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
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