CUTLASS 3.8 Release (#2059)
* CUTLASS 3.8 Release * update * Update README.md * Revert "Update README.md" This reverts commit b353e36fe83e0815f99b44e46c0c95494c44726b. * update * update --------- Co-authored-by: Haicheng Wu <57973641+hwu36@users.noreply.github.com> Co-authored-by: Haicheng Wu <haichengw@nvidia.com>
This commit is contained in:
co-authored by
Haicheng Wu
Haicheng Wu
parent
9eb01fa0b0
commit
389e493055
@@ -46,6 +46,7 @@ set(CUTLASS_TOOLS_PROFILER_SOURCES
|
||||
src/problem_space.cpp
|
||||
src/operation_profiler.cu
|
||||
src/gemm_operation_profiler.cu
|
||||
src/block_scaled_gemm_operation_profiler.cu
|
||||
src/rank_k_operation_profiler.cu
|
||||
src/rank_2k_operation_profiler.cu
|
||||
src/trmm_operation_profiler.cu
|
||||
@@ -101,6 +102,7 @@ if (CUDA_VERSION VERSION_GREATER_EQUAL 12.3 AND CUDA_VERSION VERSION_LESS 12.4 A
|
||||
set(CUTLASS_PROFILER_TEST_COMMAND_OPTIONS_GEMM --operation=Gemm --providers=cutlass --verification-providers=cublas,host --junit-output=test_cutlass_profiler_gemm --print-kernel-before-running=true)
|
||||
else()
|
||||
set(CUTLASS_PROFILER_TEST_COMMAND_OPTIONS_GEMM --operation=Gemm --providers=cutlass --verification-providers=cublas,device --junit-output=test_cutlass_profiler_gemm --print-kernel-before-running=true)
|
||||
set(CUTLASS_PROFILER_TEST_COMMAND_OPTIONS_GEMM --operation=BlockScaledGemm --providers=cutlass --verification-providers=cublas,device --junit-output=test_cutlass_profiler_gemm --print-kernel-before-running=true)
|
||||
endif()
|
||||
|
||||
set(CUTLASS_PROFILER_TEST_COMMAND_OPTIONS_CONV2D --operation=Conv2d --providers=cutlass --verification-providers=cudnn,device --junit-output=test_cutlass_profiler_conv2d --print-kernel-before-running=true)
|
||||
|
||||
@@ -0,0 +1,290 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright (c) 2017 - 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
**************************************************************************************************/
|
||||
/* \file
|
||||
\brief Blockscale Gemm Profiler
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
|
||||
// CUTLASS Library includes
|
||||
#include "cutlass/library/library.h"
|
||||
#include "cutlass/library/util.h"
|
||||
#include "cutlass/library/manifest.h"
|
||||
|
||||
// Profiler includes
|
||||
#include "options.h"
|
||||
#include "device_context.h"
|
||||
#include "operation_profiler.h"
|
||||
#include "performance_result.h"
|
||||
#include "problem_space.h"
|
||||
#include "reduction_operation_profiler.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace cutlass {
|
||||
namespace profiler {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Abstract base class for each math function
|
||||
class BlockScaledGemmOperationProfiler : public OperationProfiler {
|
||||
public:
|
||||
|
||||
/// Problem structure obtained from problem space
|
||||
struct GemmProblem {
|
||||
|
||||
cutlass::library::GemmUniversalMode mode{library::GemmUniversalMode::kGemm};
|
||||
|
||||
int64_t m{16};
|
||||
int64_t n{16};
|
||||
int64_t k{16};
|
||||
|
||||
|
||||
int cluster_m{1};
|
||||
int cluster_n{1};
|
||||
int cluster_k{1};
|
||||
int cluster_m_fallback{1};
|
||||
int cluster_n_fallback{1};
|
||||
int cluster_k_fallback{1};
|
||||
|
||||
|
||||
int64_t lda{0};
|
||||
int64_t ldb{0};
|
||||
int64_t ldc{0};
|
||||
std::vector<uint8_t> alpha;
|
||||
std::vector<uint8_t> beta;
|
||||
|
||||
cutlass::library::SplitKMode split_k_mode{library::SplitKMode::kNone};
|
||||
int split_k_slices{1};
|
||||
int batch_count{1};
|
||||
|
||||
cutlass::library::RasterOrder raster_order{cutlass::library::RasterOrder::kHeuristic};
|
||||
int swizzle_size{1};
|
||||
|
||||
|
||||
cutlass::library::RuntimeDatatype runtime_input_datatype_a{};
|
||||
cutlass::library::RuntimeDatatype runtime_input_datatype_b{};
|
||||
|
||||
|
||||
// gemm with parallel interleaved reduction
|
||||
// gemm epilogue (alpha, beta) = (1.0, 0.0)
|
||||
// reduction epilogue (alpha, beta) = (GemmProblem::alpha, GemmProblem::beta)
|
||||
std::vector<uint8_t> alpha_one;
|
||||
std::vector<uint8_t> beta_zero;
|
||||
|
||||
bool use_pdl{false};
|
||||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
/// Parses the problem
|
||||
Status parse(
|
||||
library::BlockScaledGemmDescription const &operation_desc,
|
||||
ProblemSpace const &problem_space,
|
||||
ProblemSpace::Problem const &problem);
|
||||
|
||||
/// Total number of bytes loaded
|
||||
int64_t bytes(library::BlockScaledGemmDescription const &operation_desc) const;
|
||||
|
||||
/// Total number of flops computed
|
||||
int64_t flops(library::BlockScaledGemmDescription const &operation_desc) const;
|
||||
|
||||
/// Initializes a performance result
|
||||
void initialize_result(
|
||||
PerformanceResult &result,
|
||||
library::BlockScaledGemmDescription const &operation_desc,
|
||||
ProblemSpace const &problem_space);
|
||||
};
|
||||
|
||||
/// Workspace used
|
||||
struct GemmWorkspace {
|
||||
|
||||
DeviceAllocation *A{nullptr};
|
||||
DeviceAllocation *SFA{nullptr};
|
||||
DeviceAllocation *B{nullptr};
|
||||
DeviceAllocation *SFB{nullptr};
|
||||
DeviceAllocation *C{nullptr};
|
||||
DeviceAllocation *Computed{nullptr};
|
||||
DeviceAllocation *Reference{nullptr};
|
||||
DeviceAllocation *Computed_SFD{nullptr};
|
||||
DeviceAllocation *Reference_SFD{nullptr};
|
||||
DeviceAllocation *Norm_constant{nullptr};
|
||||
|
||||
/// Number of copies of the problem workspace which are visited sequentially during
|
||||
/// profiling to avoid camping in the last level cache.
|
||||
int problem_count{1};
|
||||
|
||||
library::GemmUniversalConfiguration configuration;
|
||||
library::BlockScaledGemmArguments arguments;
|
||||
|
||||
/// Buffer used for the operation's host workspace
|
||||
std::vector<uint8_t> host_workspace;
|
||||
|
||||
/// Buffer used for the operations' device workspace
|
||||
DeviceAllocation device_workspace;
|
||||
|
||||
/// Library configuration and arguments for reduction operator
|
||||
library::ReductionConfiguration reduction_configuration;
|
||||
library::ReductionArguments reduction_arguments;
|
||||
|
||||
/// Buffer used for the cutlass reduction operations' host workspace
|
||||
std::vector<uint8_t> reduction_host_workspace;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
//
|
||||
// Data members
|
||||
//
|
||||
|
||||
/// GEMM problem obtained from problem space
|
||||
GemmProblem problem_;
|
||||
|
||||
/// Device memory allocations
|
||||
GemmWorkspace gemm_workspace_;
|
||||
|
||||
/// CUTLASS parallel reduction operation to follow this* gemm operation
|
||||
library::Operation const *reduction_op_;
|
||||
|
||||
public:
|
||||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
/// Ctor
|
||||
BlockScaledGemmOperationProfiler(Options const &options);
|
||||
|
||||
/// Destructor
|
||||
virtual ~BlockScaledGemmOperationProfiler();
|
||||
|
||||
GemmProblem const& problem() const { return problem_; }
|
||||
|
||||
/// Prints usage statement for the math function
|
||||
virtual void print_usage(std::ostream &out) const;
|
||||
|
||||
/// Prints examples
|
||||
virtual void print_examples(std::ostream &out) const;
|
||||
|
||||
/// Extracts the problem dimensions
|
||||
virtual Status initialize_configuration(
|
||||
Options const &options,
|
||||
PerformanceReport &report,
|
||||
DeviceContext &device_context,
|
||||
library::Operation const *operation,
|
||||
ProblemSpace const &problem_space,
|
||||
ProblemSpace::Problem const &problem);
|
||||
|
||||
/// Initializes workspace
|
||||
virtual Status initialize_workspace(
|
||||
Options const &options,
|
||||
PerformanceReport &report,
|
||||
DeviceContext &device_context,
|
||||
library::Operation const *operation,
|
||||
ProblemSpace const &problem_space,
|
||||
ProblemSpace::Problem const &problem);
|
||||
|
||||
/// Verifies CUTLASS against references
|
||||
virtual bool verify_cutlass(
|
||||
Options const &options,
|
||||
PerformanceReport &report,
|
||||
DeviceContext &device_context,
|
||||
library::Operation const *operation,
|
||||
ProblemSpace const &problem_space,
|
||||
ProblemSpace::Problem const &problem);
|
||||
|
||||
/// Measures performance results
|
||||
virtual bool profile(
|
||||
Options const &options,
|
||||
PerformanceReport &report,
|
||||
DeviceContext &device_context,
|
||||
library::Operation const *operation,
|
||||
ProblemSpace const &problem_space,
|
||||
ProblemSpace::Problem const &problem);
|
||||
|
||||
protected:
|
||||
|
||||
/// Initializes the performance result
|
||||
void initialize_result_(
|
||||
PerformanceResult &result,
|
||||
Options const &options,
|
||||
library::BlockScaledGemmDescription const &operation_desc,
|
||||
ProblemSpace const &problem_space);
|
||||
|
||||
/// Verifies CUTLASS against references
|
||||
bool verify_with_cublas_(
|
||||
Options const &options,
|
||||
PerformanceReport &report,
|
||||
DeviceContext &device_context,
|
||||
library::Operation const *operation,
|
||||
ProblemSpace const &problem_space,
|
||||
ProblemSpace::Problem const &problem);
|
||||
|
||||
/// Verifies CUTLASS against host and device references
|
||||
bool verify_with_reference_(
|
||||
Options const &options,
|
||||
PerformanceReport &report,
|
||||
DeviceContext &device_context,
|
||||
library::Operation const *operation,
|
||||
ProblemSpace const &problem_space,
|
||||
ProblemSpace::Problem const &problem,
|
||||
cutlass::library::NumericTypeID element_A,
|
||||
cutlass::library::NumericTypeID element_B);
|
||||
|
||||
/// Method to profile a CUTLASS Operation
|
||||
Status profile_cutlass_(
|
||||
PerformanceResult &result,
|
||||
Options const &options,
|
||||
library::Operation const *operation,
|
||||
void *arguments,
|
||||
void *host_workspace,
|
||||
void *device_workspace);
|
||||
|
||||
/// Initialize reduction problem dimensions and library::Operation
|
||||
bool initialize_reduction_configuration_(
|
||||
library::Operation const *operation,
|
||||
ProblemSpace::Problem const &problem);
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespace profiler
|
||||
} // namespace cutlass
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -73,6 +73,15 @@ public:
|
||||
int64_t n{16};
|
||||
int64_t k{16};
|
||||
|
||||
|
||||
int cluster_m{1};
|
||||
int cluster_n{1};
|
||||
int cluster_k{1};
|
||||
int cluster_m_fallback{1};
|
||||
int cluster_n_fallback{1};
|
||||
int cluster_k_fallback{1};
|
||||
|
||||
|
||||
int64_t lda{0};
|
||||
int64_t ldb{0};
|
||||
int64_t ldc{0};
|
||||
@@ -86,6 +95,11 @@ public:
|
||||
cutlass::library::RasterOrder raster_order{cutlass::library::RasterOrder::kHeuristic};
|
||||
int swizzle_size{1};
|
||||
|
||||
|
||||
cutlass::library::RuntimeDatatype runtime_input_datatype_a{};
|
||||
cutlass::library::RuntimeDatatype runtime_input_datatype_b{};
|
||||
|
||||
|
||||
// gemm with parallel interleaved reduction
|
||||
// gemm epilogue (alpha, beta) = (1.0, 0.0)
|
||||
// reduction epilogue (alpha, beta) = (GemmProblem::alpha, GemmProblem::beta)
|
||||
|
||||
@@ -942,6 +942,18 @@ bool arg_as_IteratorAlgorithmID(
|
||||
ProblemSpace const &problem_space,
|
||||
ProblemSpace::Problem const &problem);
|
||||
|
||||
|
||||
/// Lexically casts an argument to an int64 if it is defined. Returns true if not null.
|
||||
bool arg_as_RuntimeDatatype(library::RuntimeDatatype &runtime_datatype, KernelArgument::Value const *value_ptr);
|
||||
|
||||
/// Lexically casts an argument to an int64 if it is defined. Returns true if not null.
|
||||
bool arg_as_RuntimeDatatype(
|
||||
library::RuntimeDatatype &runtime_datatype,
|
||||
char const *name,
|
||||
ProblemSpace const &problem_space,
|
||||
ProblemSpace::Problem const &problem);
|
||||
|
||||
|
||||
/// Lexically casts an argument to an int64 if it is defined. Returns true if not null.
|
||||
bool arg_as_RasterOrder(library::RasterOrder &raster_order, KernelArgument::Value const *value_ptr);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -38,6 +38,7 @@
|
||||
// Profiler includes
|
||||
#include "cutlass/profiler/cutlass_profiler.h"
|
||||
#include "cutlass/profiler/gemm_operation_profiler.h"
|
||||
#include "cutlass/profiler/block_scaled_gemm_operation_profiler.h"
|
||||
#include "cutlass/profiler/rank_k_operation_profiler.h"
|
||||
#include "cutlass/profiler/rank_2k_operation_profiler.h"
|
||||
#include "cutlass/profiler/trmm_operation_profiler.h"
|
||||
@@ -60,6 +61,8 @@ CutlassProfiler::CutlassProfiler(
|
||||
|
||||
operation_profilers_.emplace_back(new GemmOperationProfiler(options));
|
||||
|
||||
operation_profilers_.emplace_back(new BlockScaledGemmOperationProfiler(options));
|
||||
|
||||
operation_profilers_.emplace_back(new SparseGemmOperationProfiler(options));
|
||||
|
||||
operation_profilers_.emplace_back(new Conv2dOperationProfiler(options));
|
||||
|
||||
@@ -616,6 +616,48 @@ void DeviceAllocation::initialize_random_device(int seed, Distribution dist) {
|
||||
dist
|
||||
);
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kFUE4M3:
|
||||
cutlass::reference::device::BlockFillRandom<cutlass::float_ue4m3_t>(
|
||||
reinterpret_cast<cutlass::float_ue4m3_t *>(pointer_),
|
||||
capacity_,
|
||||
seed,
|
||||
dist
|
||||
);
|
||||
break;
|
||||
case library::NumericTypeID::kFUE8M0:
|
||||
cutlass::reference::device::BlockFillRandom<cutlass::float_ue8m0_t>(
|
||||
reinterpret_cast<cutlass::float_ue8m0_t *>(pointer_),
|
||||
capacity_,
|
||||
seed,
|
||||
dist
|
||||
);
|
||||
break;
|
||||
case library::NumericTypeID::kFE2M3:
|
||||
cutlass::reference::device::BlockFillRandom<cutlass::float_e2m3_t>(
|
||||
reinterpret_cast<cutlass::float_e2m3_t *>(pointer_),
|
||||
capacity_,
|
||||
seed,
|
||||
dist
|
||||
);
|
||||
break;
|
||||
case library::NumericTypeID::kFE3M2:
|
||||
cutlass::reference::device::BlockFillRandom<cutlass::float_e3m2_t>(
|
||||
reinterpret_cast<cutlass::float_e3m2_t *>(pointer_),
|
||||
capacity_,
|
||||
seed,
|
||||
dist
|
||||
);
|
||||
break;
|
||||
case library::NumericTypeID::kFE2M1:
|
||||
cutlass::reference::device::BlockFillRandom<cutlass::float_e2m1_t>(
|
||||
reinterpret_cast<cutlass::float_e2m1_t *>(pointer_),
|
||||
capacity_,
|
||||
seed,
|
||||
dist
|
||||
);
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kF64:
|
||||
cutlass::reference::device::BlockFillRandom<double>(
|
||||
reinterpret_cast<double *>(pointer_),
|
||||
@@ -771,6 +813,50 @@ void DeviceAllocation::initialize_random_host(int seed, Distribution dist) {
|
||||
dist
|
||||
);
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kFUE4M3:
|
||||
cutlass::reference::host::BlockFillRandom<cutlass::float_ue4m3_t>(
|
||||
reinterpret_cast<cutlass::float_ue4m3_t *>(host_data.data()),
|
||||
capacity_,
|
||||
seed,
|
||||
dist
|
||||
);
|
||||
break;
|
||||
|
||||
|
||||
case library::NumericTypeID::kFE2M3:
|
||||
cutlass::reference::host::BlockFillRandom<cutlass::float_e2m3_t>(
|
||||
reinterpret_cast<cutlass::float_e2m3_t *>(host_data.data()),
|
||||
capacity_,
|
||||
seed,
|
||||
dist
|
||||
);
|
||||
break;
|
||||
case library::NumericTypeID::kFE3M2:
|
||||
cutlass::reference::host::BlockFillRandom<cutlass::float_e3m2_t>(
|
||||
reinterpret_cast<cutlass::float_e3m2_t *>(host_data.data()),
|
||||
capacity_,
|
||||
seed,
|
||||
dist
|
||||
);
|
||||
break;
|
||||
case library::NumericTypeID::kFE2M1:
|
||||
cutlass::reference::host::BlockFillRandom<cutlass::float_e2m1_t>(
|
||||
reinterpret_cast<cutlass::float_e2m1_t *>(host_data.data()),
|
||||
capacity_,
|
||||
seed,
|
||||
dist
|
||||
);
|
||||
break;
|
||||
case library::NumericTypeID::kFUE8M0:
|
||||
cutlass::reference::host::BlockFillRandom<cutlass::float_ue8m0_t>(
|
||||
reinterpret_cast<cutlass::float_ue8m0_t *>(host_data.data()),
|
||||
capacity_,
|
||||
seed,
|
||||
dist
|
||||
);
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kF16:
|
||||
cutlass::reference::host::BlockFillRandom<cutlass::half_t>(
|
||||
reinterpret_cast<cutlass::half_t *>(host_data.data()),
|
||||
@@ -990,6 +1076,50 @@ void DeviceAllocation::initialize_sequential_device(Distribution dist) {
|
||||
static_cast<cutlass::float_e5m2_t>(dist.sequential.start)
|
||||
);
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kFUE4M3:
|
||||
cutlass::reference::device::BlockFillSequential<cutlass::float_ue4m3_t>(
|
||||
reinterpret_cast<cutlass::float_ue4m3_t *>(pointer_),
|
||||
capacity_,
|
||||
static_cast<cutlass::float_ue4m3_t>(dist.sequential.delta),
|
||||
static_cast<cutlass::float_ue4m3_t>(dist.sequential.start)
|
||||
);
|
||||
break;
|
||||
|
||||
|
||||
case library::NumericTypeID::kFE2M3:
|
||||
cutlass::reference::device::BlockFillSequential<cutlass::float_e2m3_t>(
|
||||
reinterpret_cast<cutlass::float_e2m3_t *>(pointer_),
|
||||
capacity_,
|
||||
static_cast<cutlass::float_e2m3_t>(dist.sequential.delta),
|
||||
static_cast<cutlass::float_e2m3_t>(dist.sequential.start)
|
||||
);
|
||||
break;
|
||||
case library::NumericTypeID::kFE3M2:
|
||||
cutlass::reference::device::BlockFillSequential<cutlass::float_e3m2_t>(
|
||||
reinterpret_cast<cutlass::float_e3m2_t *>(pointer_),
|
||||
capacity_,
|
||||
static_cast<cutlass::float_e3m2_t>(dist.sequential.delta),
|
||||
static_cast<cutlass::float_e3m2_t>(dist.sequential.start)
|
||||
);
|
||||
break;
|
||||
case library::NumericTypeID::kFE2M1:
|
||||
cutlass::reference::device::BlockFillSequential<cutlass::float_e2m1_t>(
|
||||
reinterpret_cast<cutlass::float_e2m1_t *>(pointer_),
|
||||
capacity_,
|
||||
static_cast<cutlass::float_e2m1_t>(dist.sequential.delta),
|
||||
static_cast<cutlass::float_e2m1_t>(dist.sequential.start)
|
||||
);
|
||||
break;
|
||||
case library::NumericTypeID::kFUE8M0:
|
||||
cutlass::reference::device::BlockFillSequential<cutlass::float_ue8m0_t>(
|
||||
reinterpret_cast<cutlass::float_ue8m0_t *>(pointer_),
|
||||
capacity_,
|
||||
static_cast<cutlass::float_ue8m0_t>(dist.sequential.delta),
|
||||
static_cast<cutlass::float_ue8m0_t>(dist.sequential.start)
|
||||
);
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kF16:
|
||||
cutlass::reference::device::BlockFillSequential<cutlass::half_t>(
|
||||
reinterpret_cast<cutlass::half_t *>(pointer_),
|
||||
@@ -1220,6 +1350,50 @@ void DeviceAllocation::initialize_sequential_host(Distribution dist) {
|
||||
static_cast<cutlass::float_e5m2_t>(dist.sequential.start)
|
||||
);
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kFUE4M3:
|
||||
cutlass::reference::host::BlockFillSequential<cutlass::float_ue4m3_t>(
|
||||
reinterpret_cast<cutlass::float_ue4m3_t *>(host_data.data()),
|
||||
capacity_,
|
||||
static_cast<cutlass::float_ue4m3_t>(dist.sequential.delta),
|
||||
static_cast<cutlass::float_ue4m3_t>(dist.sequential.start)
|
||||
);
|
||||
break;
|
||||
|
||||
|
||||
case library::NumericTypeID::kFE2M3:
|
||||
cutlass::reference::host::BlockFillSequential<cutlass::float_e2m3_t>(
|
||||
reinterpret_cast<cutlass::float_e2m3_t *>(host_data.data()),
|
||||
capacity_,
|
||||
static_cast<cutlass::float_e2m3_t>(dist.sequential.delta),
|
||||
static_cast<cutlass::float_e2m3_t>(dist.sequential.start)
|
||||
);
|
||||
break;
|
||||
case library::NumericTypeID::kFE3M2:
|
||||
cutlass::reference::host::BlockFillSequential<cutlass::float_e3m2_t>(
|
||||
reinterpret_cast<cutlass::float_e3m2_t *>(host_data.data()),
|
||||
capacity_,
|
||||
static_cast<cutlass::float_e3m2_t>(dist.sequential.delta),
|
||||
static_cast<cutlass::float_e3m2_t>(dist.sequential.start)
|
||||
);
|
||||
break;
|
||||
case library::NumericTypeID::kFE2M1:
|
||||
cutlass::reference::host::BlockFillSequential<cutlass::float_e2m1_t>(
|
||||
reinterpret_cast<cutlass::float_e2m1_t *>(host_data.data()),
|
||||
capacity_,
|
||||
static_cast<cutlass::float_e2m1_t>(dist.sequential.delta),
|
||||
static_cast<cutlass::float_e2m1_t>(dist.sequential.start)
|
||||
);
|
||||
break;
|
||||
case library::NumericTypeID::kFUE8M0:
|
||||
cutlass::reference::host::BlockFillSequential<cutlass::float_ue8m0_t>(
|
||||
reinterpret_cast<cutlass::float_ue8m0_t *>(host_data.data()),
|
||||
capacity_,
|
||||
static_cast<cutlass::float_ue8m0_t>(dist.sequential.delta),
|
||||
static_cast<cutlass::float_ue8m0_t>(dist.sequential.start)
|
||||
);
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kF16:
|
||||
cutlass::reference::host::BlockFillSequential<cutlass::half_t>(
|
||||
reinterpret_cast<cutlass::half_t *>(host_data.data()),
|
||||
@@ -1516,6 +1690,34 @@ bool DeviceAllocation::block_compare_equal(
|
||||
reinterpret_cast<float_e5m2_t const *>(ptr_A),
|
||||
reinterpret_cast<float_e5m2_t const *>(ptr_B),
|
||||
capacity);
|
||||
|
||||
case library::NumericTypeID::kFUE4M3:
|
||||
return reference::device::BlockCompareEqual<float_ue4m3_t>(
|
||||
reinterpret_cast<float_ue4m3_t const *>(ptr_A),
|
||||
reinterpret_cast<float_ue4m3_t const *>(ptr_B),
|
||||
capacity);
|
||||
case library::NumericTypeID::kFUE8M0:
|
||||
return reference::device::BlockCompareEqual<float_ue8m0_t>(
|
||||
reinterpret_cast<float_ue8m0_t const *>(ptr_A),
|
||||
reinterpret_cast<float_ue8m0_t const *>(ptr_B),
|
||||
capacity);
|
||||
case library::NumericTypeID::kFE2M3:
|
||||
return reference::device::BlockCompareEqual<float_e2m3_t>(
|
||||
reinterpret_cast<float_e2m3_t const *>(ptr_A),
|
||||
reinterpret_cast<float_e2m3_t const *>(ptr_B),
|
||||
capacity);
|
||||
|
||||
case library::NumericTypeID::kFE3M2:
|
||||
return reference::device::BlockCompareEqual<float_e3m2_t>(
|
||||
reinterpret_cast<float_e3m2_t const *>(ptr_A),
|
||||
reinterpret_cast<float_e3m2_t const *>(ptr_B),
|
||||
capacity);
|
||||
case library::NumericTypeID::kFE2M1:
|
||||
return reference::device::BlockCompareEqual<float_e2m1_t>(
|
||||
reinterpret_cast<float_e2m1_t const *>(ptr_A),
|
||||
reinterpret_cast<float_e2m1_t const *>(ptr_B),
|
||||
capacity);
|
||||
|
||||
case library::NumericTypeID::kF16:
|
||||
return reference::device::BlockCompareEqual<half_t>(
|
||||
reinterpret_cast<half_t const *>(ptr_A),
|
||||
@@ -1684,6 +1886,46 @@ bool DeviceAllocation::block_compare_relatively_equal(
|
||||
capacity,
|
||||
static_cast<float_e5m2_t>(epsilon),
|
||||
static_cast<float_e5m2_t>(nonzero_floor));
|
||||
|
||||
case library::NumericTypeID::kFUE4M3:
|
||||
return reference::device::BlockCompareRelativelyEqual<float_ue4m3_t>(
|
||||
reinterpret_cast<float_ue4m3_t const *>(ptr_A),
|
||||
reinterpret_cast<float_ue4m3_t const *>(ptr_B),
|
||||
capacity,
|
||||
static_cast<float_ue4m3_t>(epsilon),
|
||||
static_cast<float_ue4m3_t>(nonzero_floor));
|
||||
case library::NumericTypeID::kFUE8M0:
|
||||
return reference::device::BlockCompareRelativelyEqual<float_ue8m0_t>(
|
||||
reinterpret_cast<float_ue8m0_t const *>(ptr_A),
|
||||
reinterpret_cast<float_ue8m0_t const *>(ptr_B),
|
||||
capacity,
|
||||
static_cast<float_ue8m0_t>(epsilon),
|
||||
static_cast<float_ue8m0_t>(nonzero_floor));
|
||||
|
||||
case library::NumericTypeID::kFE2M3:
|
||||
return reference::device::BlockCompareRelativelyEqual<float_e2m3_t>(
|
||||
reinterpret_cast<float_e2m3_t const *>(ptr_A),
|
||||
reinterpret_cast<float_e2m3_t const *>(ptr_B),
|
||||
capacity,
|
||||
static_cast<float_e2m3_t>(epsilon),
|
||||
static_cast<float_e2m3_t>(nonzero_floor));
|
||||
|
||||
case library::NumericTypeID::kFE3M2:
|
||||
return reference::device::BlockCompareRelativelyEqual<float_e3m2_t>(
|
||||
reinterpret_cast<float_e3m2_t const *>(ptr_A),
|
||||
reinterpret_cast<float_e3m2_t const *>(ptr_B),
|
||||
capacity,
|
||||
static_cast<float_e3m2_t>(epsilon),
|
||||
static_cast<float_e3m2_t>(nonzero_floor));
|
||||
|
||||
case library::NumericTypeID::kFE2M1:
|
||||
return reference::device::BlockCompareRelativelyEqual<float_e2m1_t>(
|
||||
reinterpret_cast<float_e2m1_t const *>(ptr_A),
|
||||
reinterpret_cast<float_e2m1_t const *>(ptr_B),
|
||||
capacity,
|
||||
static_cast<float_e2m1_t>(epsilon),
|
||||
static_cast<float_e2m1_t>(nonzero_floor));
|
||||
|
||||
case library::NumericTypeID::kF16:
|
||||
return reference::device::BlockCompareRelativelyEqual<half_t>(
|
||||
reinterpret_cast<half_t const *>(ptr_A),
|
||||
@@ -2026,6 +2268,27 @@ void DeviceAllocation::write_tensor_csv(
|
||||
case library::NumericTypeID::kFE5M2:
|
||||
write_tensor_csv_static_type<float_e5m2_t>(out, *this);
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kFUE4M3:
|
||||
write_tensor_csv_static_type<float_ue4m3_t>(out, *this);
|
||||
break;
|
||||
|
||||
|
||||
case library::NumericTypeID::kFE2M3:
|
||||
write_tensor_csv_static_type<float_e2m3_t>(out, *this);
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kFE3M2:
|
||||
write_tensor_csv_static_type<float_e3m2_t>(out, *this);
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kFE2M1:
|
||||
write_tensor_csv_static_type<float_e2m1_t>(out, *this);
|
||||
break;
|
||||
case library::NumericTypeID::kFUE8M0:
|
||||
write_tensor_csv_static_type<float_ue8m0_t>(out, *this);
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kF16:
|
||||
write_tensor_csv_static_type<half_t>(out, *this);
|
||||
break;
|
||||
@@ -2193,6 +2456,27 @@ void DeviceAllocation::fill_device(double val = 0.0) {
|
||||
case library::NumericTypeID::kFE5M2:
|
||||
tensor_fill<float_e5m2_t>(*this, static_cast<float_e5m2_t>(val));
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kFUE4M3:
|
||||
tensor_fill<float_ue4m3_t>(*this, static_cast<float_ue4m3_t>(val));
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kFUE8M0:
|
||||
tensor_fill<float_ue8m0_t>(*this, static_cast<float_ue8m0_t>(val));
|
||||
break;
|
||||
case library::NumericTypeID::kFE2M3:
|
||||
tensor_fill<float_e2m3_t>(*this, static_cast<float_e2m3_t>(val));
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kFE3M2:
|
||||
tensor_fill<float_e3m2_t>(*this, static_cast<float_e3m2_t>(val));
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kFE2M1:
|
||||
tensor_fill<float_e2m1_t>(*this, static_cast<float_e2m1_t>(val));
|
||||
break;
|
||||
|
||||
|
||||
case library::NumericTypeID::kF16:
|
||||
tensor_fill<half_t>(*this, static_cast<half_t>(val));
|
||||
break;
|
||||
@@ -2288,6 +2572,47 @@ void DeviceAllocation::fill_host(double val = 0.0) {
|
||||
std::vector<uint8_t> host_data(bytes());
|
||||
|
||||
switch (this->type()) {
|
||||
|
||||
case library::NumericTypeID::kFUE4M3:
|
||||
cutlass::reference::host::BlockFill<float_ue4m3_t>(
|
||||
reinterpret_cast<float_ue4m3_t *>(host_data.data()),
|
||||
capacity_,
|
||||
static_cast<float_ue4m3_t>(val)
|
||||
);
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kFUE8M0:
|
||||
cutlass::reference::host::BlockFill<float_ue8m0_t>(
|
||||
reinterpret_cast<float_ue8m0_t *>(host_data.data()),
|
||||
capacity_,
|
||||
static_cast<float_ue8m0_t>(val)
|
||||
);
|
||||
break;
|
||||
case library::NumericTypeID::kFE2M3:
|
||||
cutlass::reference::host::BlockFill<float_e2m3_t>(
|
||||
reinterpret_cast<float_e2m3_t *>(host_data.data()),
|
||||
capacity_,
|
||||
static_cast<float_e2m3_t>(val)
|
||||
);
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kFE3M2:
|
||||
cutlass::reference::host::BlockFill<float_e3m2_t>(
|
||||
reinterpret_cast<float_e3m2_t *>(host_data.data()),
|
||||
capacity_,
|
||||
static_cast<float_e3m2_t>(val)
|
||||
);
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kFE2M1:
|
||||
cutlass::reference::host::BlockFill<float_e2m1_t>(
|
||||
reinterpret_cast<float_e2m1_t *>(host_data.data()),
|
||||
capacity_,
|
||||
static_cast<float_e2m1_t>(val)
|
||||
);
|
||||
break;
|
||||
|
||||
|
||||
case library::NumericTypeID::kFE4M3:
|
||||
cutlass::reference::host::BlockFill<float_e4m3_t>(
|
||||
reinterpret_cast<float_e4m3_t *>(host_data.data()),
|
||||
|
||||
@@ -104,6 +104,25 @@ DeviceAllocation *DeviceContext::allocate_and_initialize_tensor(
|
||||
case library::NumericTypeID::kFE5M2:
|
||||
data_distribution.set_uniform(-1, 1, 0);
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kFE2M3:
|
||||
data_distribution.set_uniform(-2, 2, 0);
|
||||
break;
|
||||
case library::NumericTypeID::kFE3M2:
|
||||
data_distribution.set_uniform(-2, 2, 0);
|
||||
break;
|
||||
case library::NumericTypeID::kFE2M1:
|
||||
data_distribution.set_uniform(-2, 2, 0);
|
||||
break;
|
||||
case library::NumericTypeID::kFUE8M0:
|
||||
data_distribution.set_uniform(1, 4, 0);
|
||||
break;
|
||||
|
||||
case library::NumericTypeID::kFUE4M3:
|
||||
data_distribution.set_uniform(1, 4, 0);
|
||||
break;
|
||||
|
||||
|
||||
case library::NumericTypeID::kF16:
|
||||
data_distribution.set_uniform(-3, 3, 0);
|
||||
break;
|
||||
|
||||
@@ -76,6 +76,8 @@ GemmOperationProfiler::GemmOperationProfiler(Options const &options):
|
||||
{ArgumentTypeID::kInteger, {"split_k_slices", "split-k-slices"}, "Number of partitions of K dimension"},
|
||||
{ArgumentTypeID::kInteger, {"batch_count", "batch-count"}, "Number of GEMMs computed in one batch"},
|
||||
{ArgumentTypeID::kEnumerated, {"raster_order", "raster-order"}, "Raster order (heuristic, along_n, along_m)"},
|
||||
{ArgumentTypeID::kEnumerated, {"runtime_input_datatype_a", "runtime-input-datatype::a"}, "Runtime datatype (e4m3, e5m2, e3m2, e2m3, e2m1)"},
|
||||
{ArgumentTypeID::kEnumerated, {"runtime_input_datatype_b", "runtime-input-datatype::b"}, "Runtime datatype (e4m3, e5m2, e3m2, e2m3, e2m1)"},
|
||||
{ArgumentTypeID::kInteger, {"use_pdl", "use-pdl"}, "Use PDL (true, false)"},
|
||||
{ArgumentTypeID::kInteger, {"swizzle_size", "swizzle-size"}, "Size to swizzle"},
|
||||
},
|
||||
@@ -172,6 +174,38 @@ Status GemmOperationProfiler::GemmProblem::parse(
|
||||
this->k = 1024;
|
||||
}
|
||||
|
||||
|
||||
if (!arg_as_int(this->cluster_m, "cluster_m", problem_space, problem)) {
|
||||
// default value
|
||||
this->cluster_m = 1;
|
||||
}
|
||||
|
||||
if (!arg_as_int(this->cluster_n, "cluster_n", problem_space, problem)) {
|
||||
// default value
|
||||
this->cluster_n = 1;
|
||||
}
|
||||
|
||||
if (!arg_as_int(this->cluster_k, "cluster_k", problem_space, problem)) {
|
||||
// default value
|
||||
this->cluster_k = 1;
|
||||
}
|
||||
|
||||
if (!arg_as_int(this->cluster_m_fallback, "cluster_m_fallback", problem_space, problem)) {
|
||||
// default value
|
||||
this->cluster_m_fallback = 0;
|
||||
}
|
||||
|
||||
if (!arg_as_int(this->cluster_n_fallback, "cluster_n_fallback", problem_space, problem)) {
|
||||
// default value
|
||||
this->cluster_n_fallback = 0;
|
||||
}
|
||||
|
||||
if (!arg_as_int(this->cluster_k_fallback, "cluster_k_fallback", problem_space, problem)) {
|
||||
// default value
|
||||
this->cluster_k_fallback = 0;
|
||||
}
|
||||
|
||||
|
||||
if (!arg_as_bool(this->use_pdl, "use_pdl", problem_space, problem)) {
|
||||
// default value
|
||||
this->use_pdl = false;
|
||||
@@ -192,6 +226,18 @@ Status GemmOperationProfiler::GemmProblem::parse(
|
||||
this->split_k_slices = 1;
|
||||
}
|
||||
|
||||
|
||||
if (!arg_as_RuntimeDatatype(this->runtime_input_datatype_a, "runtime_input_datatype_a", problem_space, problem)) {
|
||||
// default value
|
||||
this->runtime_input_datatype_a = cutlass::library::RuntimeDatatype::kStatic;
|
||||
}
|
||||
|
||||
if (!arg_as_RuntimeDatatype(this->runtime_input_datatype_b, "runtime_input_datatype_b", problem_space, problem)) {
|
||||
// default value
|
||||
this->runtime_input_datatype_b = cutlass::library::RuntimeDatatype::kStatic;
|
||||
}
|
||||
|
||||
|
||||
if (!arg_as_int(this->batch_count, "batch_count", problem_space, problem)) {
|
||||
// default value
|
||||
this->batch_count = 1;
|
||||
@@ -338,6 +384,15 @@ void GemmOperationProfiler::GemmProblem::initialize_result(
|
||||
set_argument(result, "n", problem_space, n);
|
||||
set_argument(result, "k", problem_space, k);
|
||||
|
||||
|
||||
set_argument(result, "cluster_m", problem_space, cluster_m);
|
||||
set_argument(result, "cluster_n", problem_space, cluster_n);
|
||||
set_argument(result, "cluster_k", problem_space, cluster_k);
|
||||
set_argument(result, "cluster_m_fallback", problem_space, cluster_m_fallback);
|
||||
set_argument(result, "cluster_n_fallback", problem_space, cluster_n_fallback);
|
||||
set_argument(result, "cluster_k_fallback", problem_space, cluster_k_fallback);
|
||||
|
||||
|
||||
set_argument(result, "split_k_mode", problem_space, library::to_string(split_k_mode));
|
||||
set_argument(result, "split_k_slices", problem_space, split_k_slices);
|
||||
set_argument(result, "batch_count", problem_space, batch_count);
|
||||
@@ -345,6 +400,11 @@ void GemmOperationProfiler::GemmProblem::initialize_result(
|
||||
set_argument(result, "swizzle_size", problem_space, swizzle_size);
|
||||
set_argument(result, "use_pdl", problem_space, library::to_string(use_pdl));
|
||||
|
||||
|
||||
set_argument(result, "runtime_input_datatype_a", problem_space, library::to_string(runtime_input_datatype_a));
|
||||
set_argument(result, "runtime_input_datatype_b", problem_space, library::to_string(runtime_input_datatype_b));
|
||||
|
||||
|
||||
set_argument(result, "alpha", problem_space,
|
||||
library::lexical_cast(alpha, operation_desc.element_epilogue));
|
||||
|
||||
@@ -388,6 +448,14 @@ Status GemmOperationProfiler::initialize_configuration(
|
||||
gemm_workspace_[i].configuration.problem_size.m() = int(problem_.m);
|
||||
gemm_workspace_[i].configuration.problem_size.n() = int(problem_.n);
|
||||
gemm_workspace_[i].configuration.problem_size.k() = int(problem_.k);
|
||||
|
||||
gemm_workspace_[i].configuration.cluster_shape.m() = int(problem_.cluster_m);
|
||||
gemm_workspace_[i].configuration.cluster_shape.n() = int(problem_.cluster_n);
|
||||
gemm_workspace_[i].configuration.cluster_shape.k() = int(problem_.cluster_k);
|
||||
gemm_workspace_[i].configuration.cluster_shape_fallback.m() = int(problem_.cluster_m_fallback);
|
||||
gemm_workspace_[i].configuration.cluster_shape_fallback.n() = int(problem_.cluster_n_fallback);
|
||||
gemm_workspace_[i].configuration.cluster_shape_fallback.k() = int(problem_.cluster_k_fallback);
|
||||
|
||||
gemm_workspace_[i].configuration.lda = problem_.lda;
|
||||
gemm_workspace_[i].configuration.ldb = problem_.ldb;
|
||||
gemm_workspace_[i].configuration.ldc = problem_.ldc;
|
||||
@@ -423,6 +491,15 @@ Status GemmOperationProfiler::initialize_configuration(
|
||||
gemm_workspace_[i].arguments.pointer_mode = library::ScalarPointerMode::kHost;
|
||||
gemm_workspace_[i].arguments.swizzle_size = problem_.swizzle_size;
|
||||
gemm_workspace_[i].arguments.raster_order = problem_.raster_order;
|
||||
gemm_workspace_[i].arguments.cluster_shape = {int(problem_.cluster_m), int(problem_.cluster_n), int(problem_.cluster_k)};
|
||||
gemm_workspace_[i].arguments.cluster_shape_fallback = {int(problem_.cluster_m_fallback), int(problem_.cluster_n_fallback), int(problem_.cluster_k_fallback)};
|
||||
gemm_workspace_[i].arguments.split_k_slices = problem_.split_k_slices;
|
||||
|
||||
|
||||
gemm_workspace_[i].arguments.runtime_input_datatype_a = problem_.runtime_input_datatype_a;
|
||||
gemm_workspace_[i].arguments.runtime_input_datatype_b = problem_.runtime_input_datatype_b;
|
||||
|
||||
|
||||
initialize_result_(this->model_result_, options, operation_desc, problem_space);
|
||||
if (const auto can_implement = operation->can_implement(&gemm_workspace_[i].configuration, &gemm_workspace_[i].arguments); can_implement != Status::kSuccess) {
|
||||
return can_implement;
|
||||
@@ -621,6 +698,9 @@ Status GemmOperationProfiler::initialize_workspace(
|
||||
if (options.execution_mode != ExecutionMode::kDryRun) {
|
||||
// NOTE: the leading non-batch strides are duplicated here for 3.0 API kernels
|
||||
gemm_workspace_[i].arguments.problem_size = {int(problem_.m), int(problem_.n), int(problem_.k)};
|
||||
gemm_workspace_[i].arguments.cluster_shape = {int(problem_.cluster_m), int(problem_.cluster_n), int(problem_.cluster_k)};
|
||||
gemm_workspace_[i].arguments.cluster_shape_fallback = {int(problem_.cluster_m_fallback), int(problem_.cluster_n_fallback), int(problem_.cluster_k_fallback)};
|
||||
gemm_workspace_[i].arguments.split_k_slices = problem_.split_k_slices;
|
||||
gemm_workspace_[i].arguments.batch_count = problem_.batch_count;
|
||||
gemm_workspace_[i].arguments.lda = problem_.lda;
|
||||
gemm_workspace_[i].arguments.ldb = problem_.ldb;
|
||||
@@ -857,12 +937,32 @@ bool GemmOperationProfiler::verify_cutlass(
|
||||
}
|
||||
#endif // #if CUTLASS_ENABLE_CUBLAS
|
||||
|
||||
|
||||
cutlass::library::RuntimeDatatype runtime_datatype_a = gemm_workspace_.front().arguments.runtime_input_datatype_a;
|
||||
cutlass::library::RuntimeDatatype runtime_datatype_b = gemm_workspace_.front().arguments.runtime_input_datatype_b;
|
||||
|
||||
bool is_runtime_datatype_a = runtime_datatype_a != cutlass::library::RuntimeDatatype::kStatic;
|
||||
bool is_runtime_datatype_b = runtime_datatype_b != cutlass::library::RuntimeDatatype::kStatic;
|
||||
|
||||
assert(is_runtime_datatype_a == is_runtime_datatype_b && "runtime datatype should be both dynamic or static.");
|
||||
|
||||
|
||||
library::GemmDescription const &gemm_desc =
|
||||
static_cast<library::GemmDescription const &>(operation->description());
|
||||
|
||||
|
||||
cutlass::library::NumericTypeID element_A = gemm_desc.A.element;
|
||||
cutlass::library::NumericTypeID element_B = gemm_desc.B.element;
|
||||
|
||||
if (is_runtime_datatype_a) {
|
||||
element_A = cutlass::library::dynamic_datatype_to_id(runtime_datatype_a);
|
||||
}
|
||||
|
||||
if (is_runtime_datatype_b) {
|
||||
element_B = cutlass::library::dynamic_datatype_to_id(runtime_datatype_b);
|
||||
}
|
||||
|
||||
|
||||
bool verification_status = verify_with_reference_(options, report, device_context, operation, problem_space, problem, element_A, element_B);
|
||||
|
||||
// Update disposition to worst case verification outcome among all
|
||||
@@ -1087,6 +1187,14 @@ bool GemmOperationProfiler::verify_with_reference_(
|
||||
gemm_workspace_[i].configuration.problem_size.m(),
|
||||
gemm_workspace_[i].configuration.problem_size.n(),
|
||||
gemm_workspace_[i].configuration.problem_size.k(),
|
||||
|
||||
gemm_workspace_[i].configuration.cluster_shape.m(),
|
||||
gemm_workspace_[i].configuration.cluster_shape.n(),
|
||||
gemm_workspace_[i].configuration.cluster_shape.k(),
|
||||
gemm_workspace_[i].configuration.cluster_shape_fallback.m(),
|
||||
gemm_workspace_[i].configuration.cluster_shape_fallback.n(),
|
||||
gemm_workspace_[i].configuration.cluster_shape_fallback.k(),
|
||||
|
||||
gemm_desc.tile_description.math_instruction.element_accumulator,
|
||||
gemm_desc.element_epilogue,
|
||||
|
||||
|
||||
@@ -91,6 +91,11 @@ OperationProfiler::OperationProfiler(
|
||||
{ArgumentTypeID::kInteger, {"cluster_m", "cluster-shape::m"}, "Cluster shape in the M dimension"},
|
||||
{ArgumentTypeID::kInteger, {"cluster_n", "cluster-shape::n"}, "Cluster shape in the N dimension"},
|
||||
{ArgumentTypeID::kInteger, {"cluster_k", "cluster-shape::k"}, "Cluster shape in the K dimension"},
|
||||
|
||||
{ArgumentTypeID::kInteger, {"cluster_m_fallback", "cluster-shape-fallback::m"}, "Fallback Cluster shape in the M dimension"},
|
||||
{ArgumentTypeID::kInteger, {"cluster_n_fallback", "cluster-shape-fallback::n"}, "Fallback Cluster shape in the N dimension"},
|
||||
{ArgumentTypeID::kInteger, {"cluster_k_fallback", "cluster-shape-fallback::k"}, "Fallback Cluster shape in the K dimension"},
|
||||
|
||||
{ArgumentTypeID::kInteger, {"stages", "threadblock-stages"}, "Number of stages of threadblock-scoped matrix multiply"},
|
||||
{ArgumentTypeID::kInteger, {"warps_m", "warp-count::m"}, "Number of warps within threadblock along the M dimension"},
|
||||
{ArgumentTypeID::kInteger, {"warps_n", "warp-count::n"}, "Number of warps within threadblock along the N dimension"},
|
||||
@@ -174,6 +179,11 @@ bool OperationProfiler::satisfies(
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool dynamic_cluster = int64_t(op_desc.tile_description.cluster_shape.m()) == 0 ||
|
||||
int64_t(op_desc.tile_description.cluster_shape.n()) == 0 ||
|
||||
int64_t(op_desc.tile_description.cluster_shape.k()) == 0;
|
||||
|
||||
int64_t int_value;
|
||||
|
||||
if (arg_as_int(int_value, "inst_m", problem_space, problem)) {
|
||||
@@ -212,6 +222,7 @@ bool OperationProfiler::satisfies(
|
||||
}
|
||||
}
|
||||
|
||||
if (!dynamic_cluster) {
|
||||
if (arg_as_int(int_value, "cluster_m", problem_space, problem)) {
|
||||
if (int64_t(op_desc.tile_description.cluster_shape.m()) != int_value) {
|
||||
return false;
|
||||
@@ -230,6 +241,7 @@ bool OperationProfiler::satisfies(
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (arg_as_int(int_value, "stages", problem_space, problem)) {
|
||||
if (int64_t(op_desc.tile_description.threadblock_stages) != int_value) {
|
||||
return false;
|
||||
@@ -296,6 +308,11 @@ std::ostream& operator<<(std::ostream& out, library::OperationKind provider) {
|
||||
if (provider == library::OperationKind::kGemm) {
|
||||
out << "kGemm";
|
||||
}
|
||||
|
||||
else if (provider == library::OperationKind::kBlockScaledGemm) {
|
||||
out << "kBlockScaledGemm";
|
||||
}
|
||||
|
||||
else if (provider == library::OperationKind::kRankK) {
|
||||
out << "kRankK";
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <set>
|
||||
|
||||
#include "cutlass/cutlass.h"
|
||||
@@ -810,16 +811,27 @@ Options::Options(cutlass::CommandLine const &cmdline):
|
||||
}
|
||||
else if (cmdline.check_cmd_line_flag("kernels")) {
|
||||
cmdline.get_cmd_line_arguments("kernels", operation_names);
|
||||
profiling.error_on_no_match = cmdline.check_cmd_line_flag("error-on-no-match");
|
||||
profiling.error_if_nothing_is_profiled = cmdline.check_cmd_line_flag("error-if-nothing-is-profiled");
|
||||
}
|
||||
|
||||
if (cmdline.check_cmd_line_flag("kernels-file")) {
|
||||
std::string filename;
|
||||
cmdline.get_cmd_line_argument("kernels-file", filename, {});
|
||||
std::ifstream input(filename);
|
||||
if (!input.good()) {
|
||||
throw std::runtime_error("failed to open: " + filename);
|
||||
}
|
||||
for (std::string line; getline(input, line);) {
|
||||
operation_names.push_back(line);
|
||||
}
|
||||
}
|
||||
|
||||
if (cmdline.check_cmd_line_flag("ignore-kernels")) {
|
||||
cmdline.get_cmd_line_arguments("ignore-kernels", excluded_operation_names);
|
||||
profiling.error_on_no_match = cmdline.check_cmd_line_flag("error-on-no-match");
|
||||
profiling.error_if_nothing_is_profiled = cmdline.check_cmd_line_flag("error-if-nothing-is-profiled");
|
||||
}
|
||||
|
||||
profiling.error_on_no_match = cmdline.check_cmd_line_flag("error-on-no-match");
|
||||
profiling.error_if_nothing_is_profiled = cmdline.check_cmd_line_flag("error-if-nothing-is-profiled");
|
||||
|
||||
// Prevent launches on the device for anything other than CUTLASS operation
|
||||
// Allow verification only on host
|
||||
if (execution_mode == ExecutionMode::kTrace) {
|
||||
@@ -856,6 +868,11 @@ void Options::print_usage(std::ostream &out) const {
|
||||
<< " (\"s1688\" and \"nt\") or (\"s844\" and \"tn\" and \"align8\") in their" << end_of_line
|
||||
<< " operation name using --kernels=\"s1688*nt, s884*tn*align8\"\n\n"
|
||||
|
||||
<< " --kernels-file=<filename> "
|
||||
<< " Same behavior as --kernels, but kernel names are specified in a file" << end_of_line
|
||||
<< " with one kernel on each line. Set of profiled kernels is the union of kernels specified" << end_of_line
|
||||
<< " here and those specified in `kernels`.\n\n"
|
||||
|
||||
<< " --ignore-kernels=<string_list> "
|
||||
<< " Excludes kernels whose names match anything in this list.\n\n"
|
||||
;
|
||||
|
||||
@@ -879,6 +879,32 @@ bool arg_as_NumericTypeID(
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/// Lexically casts an argument to an int64 if it is defined. Returns true if not null.
|
||||
bool arg_as_RuntimeDatatype(
|
||||
library::RuntimeDatatype &runtime_datatype,
|
||||
KernelArgument::Value const *value_ptr) {
|
||||
|
||||
if (value_ptr->not_null) {
|
||||
if (value_ptr->argument->description->type == ArgumentTypeID::kEnumerated) {
|
||||
|
||||
runtime_datatype = library::from_string<library::RuntimeDatatype>(
|
||||
static_cast<EnumeratedTypeArgument::EnumeratedTypeValue const *>(value_ptr)->element);
|
||||
if (runtime_datatype == library::RuntimeDatatype::kInvalid) {
|
||||
throw std::runtime_error(
|
||||
"arg_as_RuntimeDatatype() - illegal cast.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error(
|
||||
"arg_as_RuntimeDatatype() - illegal cast.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// Lexically casts an argument to an int64 if it is defined. Returns true if not null.
|
||||
bool arg_as_RasterOrder(
|
||||
library::RasterOrder &raster_order,
|
||||
@@ -945,6 +971,21 @@ bool arg_as_LayoutTypeID(
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// Lexically casts an argument to an int64 if it is defined. Returns true if not null.
|
||||
bool arg_as_RuntimeDatatype(
|
||||
library::RuntimeDatatype &runtime_datatype,
|
||||
char const *name,
|
||||
ProblemSpace const &problem_space,
|
||||
ProblemSpace::Problem const &problem) {
|
||||
|
||||
size_t idx = problem_space.argument_index(name);
|
||||
KernelArgument::Value const *value_ptr = problem.at(idx).get();
|
||||
|
||||
return arg_as_RuntimeDatatype(runtime_datatype, value_ptr);
|
||||
}
|
||||
|
||||
|
||||
/// Lexically casts an argument to an int64 if it is defined. Returns true if not null.
|
||||
bool arg_as_LayoutTypeID(
|
||||
library::LayoutTypeID &layout_type,
|
||||
|
||||
Reference in New Issue
Block a user