CUTLASS 3.5.0 (#1411)
This commit is contained in:
@@ -42,8 +42,8 @@
|
||||
#include "cutlass/profiler/rank_2k_operation_profiler.h"
|
||||
#include "cutlass/profiler/trmm_operation_profiler.h"
|
||||
#include "cutlass/profiler/symm_operation_profiler.h"
|
||||
#include "cutlass/profiler/conv2d_operation_profiler.h"
|
||||
#include "cutlass/profiler/conv3d_operation_profiler.h"
|
||||
#include "cutlass/profiler/conv2d_operation_profiler.h"
|
||||
#include "cutlass/profiler/conv3d_operation_profiler.h"
|
||||
#include "cutlass/profiler/sparse_gemm_operation_profiler.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -55,7 +55,7 @@ namespace profiler {
|
||||
|
||||
CutlassProfiler::CutlassProfiler(
|
||||
Options const &options
|
||||
):
|
||||
):
|
||||
options_(options) {
|
||||
|
||||
operation_profilers_.emplace_back(new GemmOperationProfiler(options));
|
||||
@@ -145,7 +145,6 @@ int CutlassProfiler::profile_() {
|
||||
|
||||
int result = 0;
|
||||
DeviceContext device_context;
|
||||
|
||||
// For all profilers
|
||||
for (auto & profiler : operation_profilers_) {
|
||||
|
||||
@@ -193,8 +192,8 @@ void CutlassProfiler::print_usage_(std::ostream &out) {
|
||||
<< " $ cutlass_profiler --operation=RankK --help\n\n"
|
||||
<< " $ cutlass_profiler --operation=Trmm --help\n\n"
|
||||
<< " $ cutlass_profiler --operation=Symm --help\n\n"
|
||||
<< " $ cutlass_profiler --operation=Conv3d --help\n\n"
|
||||
<< " $ cutlass_profiler --operation=Conv2d --help\n\n"
|
||||
<< " $ cutlass_profiler --operation=Conv3d --help\n\n"
|
||||
<< " $ cutlass_profiler --operation=Conv2d --help\n\n"
|
||||
<< " $ cutlass_profiler --operation=SparseGemm --help\n\n"
|
||||
;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <stdexcept>
|
||||
#include <iomanip>
|
||||
#include <ios>
|
||||
#include <vector>
|
||||
|
||||
#include "cutlass/core_io.h"
|
||||
|
||||
@@ -167,7 +168,7 @@ Status GemmOperationProfiler::GemmProblem::parse(
|
||||
// default value
|
||||
this->k = 1024;
|
||||
}
|
||||
|
||||
|
||||
if (!arg_as_SplitKModeID(this->split_k_mode, "split_k_mode", problem_space, problem)) {
|
||||
// default value
|
||||
this->split_k_mode = library::SplitKMode::kSerial;
|
||||
@@ -421,6 +422,7 @@ void GemmOperationProfiler::initialize_result_(
|
||||
bool GemmOperationProfiler::initialize_reduction_configuration_(
|
||||
library::Operation const *operation,
|
||||
ProblemSpace::Problem const &problem) {
|
||||
|
||||
library::GemmDescription const &gemm_desc =
|
||||
static_cast<library::GemmDescription const&>(operation->description());
|
||||
|
||||
@@ -577,7 +579,6 @@ Status GemmOperationProfiler::initialize_workspace(
|
||||
if (options.profiling.provider_enabled(library::Provider::kCUTLASS)) {
|
||||
|
||||
if (options.execution_mode != ExecutionMode::kDryRun) {
|
||||
|
||||
uint64_t workspace_size = underlying_operation->get_host_workspace_size(&gemm_workspace_.configuration);
|
||||
gemm_workspace_.host_workspace.resize(workspace_size, 0);
|
||||
|
||||
@@ -620,7 +621,6 @@ Status GemmOperationProfiler::initialize_workspace(
|
||||
results_.back().verification_map[provider] = Disposition::kNotRun;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -794,7 +794,6 @@ bool GemmOperationProfiler::verify_with_cublas_(
|
||||
ProblemSpace const &problem_space,
|
||||
ProblemSpace::Problem const &problem) {
|
||||
|
||||
|
||||
#if CUTLASS_ENABLE_CUBLAS
|
||||
|
||||
library::GemmDescription const &gemm_desc =
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
#include "cutlass/profiler/operation_profiler.h"
|
||||
#include "cutlass/profiler/gpu_timer.h"
|
||||
|
||||
#include "cutlass/trace.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace cutlass {
|
||||
@@ -66,7 +68,7 @@ OperationProfiler::OperationProfiler(
|
||||
library::OperationKind kind,
|
||||
ArgumentDescriptionVector const &arguments,
|
||||
ProviderVector const & verification_providers
|
||||
):
|
||||
):
|
||||
kind_(kind), arguments_(arguments) {
|
||||
|
||||
ArgumentDescriptionVector tile_description_arguments{
|
||||
@@ -93,8 +95,8 @@ OperationProfiler::OperationProfiler(
|
||||
|
||||
for (auto provider : verification_providers) {
|
||||
if (std::find(
|
||||
options.verification.providers.begin(),
|
||||
options.verification.providers.end(),
|
||||
options.verification.providers.begin(),
|
||||
options.verification.providers.end(),
|
||||
provider) != options.verification.providers.end()) {
|
||||
|
||||
verification_providers_.push_back(provider);
|
||||
@@ -118,14 +120,14 @@ void OperationProfiler::print_usage(std::ostream &out) const {
|
||||
size_t const kAliasStart = 10;
|
||||
|
||||
size_t columns = 0;
|
||||
|
||||
|
||||
std::string type_str = to_string(desc.type);
|
||||
columns += type_str.size();
|
||||
|
||||
out << " [" << type_str << "]";
|
||||
|
||||
if (columns < kAliasStart) {
|
||||
out << std::string(kAliasStart - columns, ' ');
|
||||
out << std::string(kAliasStart - columns, ' ');
|
||||
}
|
||||
|
||||
columns = 0;
|
||||
@@ -161,7 +163,6 @@ bool OperationProfiler::satisfies(
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t int_value;
|
||||
|
||||
if (arg_as_int(int_value, "inst_m", problem_space, problem)) {
|
||||
@@ -252,14 +253,79 @@ bool OperationProfiler::satisfies(
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined(CUTLASS_DEBUG_TRACE_LEVEL) && (CUTLASS_DEBUG_TRACE_LEVEL > 1)
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, library::Provider provider) {
|
||||
if (provider == library::Provider::kNone) {
|
||||
out << "kNone";
|
||||
}
|
||||
else if (provider == library::Provider::kCUTLASS) {
|
||||
out << "kCUTLASS";
|
||||
}
|
||||
else if (provider == library::Provider::kReferenceHost) {
|
||||
out << "kReferenceHost";
|
||||
}
|
||||
else if (provider == library::Provider::kReferenceDevice) {
|
||||
out << "kReferenceDevice";
|
||||
}
|
||||
else if (provider == library::Provider::kCUBLAS) {
|
||||
out << "kCUBLAS";
|
||||
}
|
||||
else if (provider == library::Provider::kCUDNN) {
|
||||
out << "kCUDNN";
|
||||
}
|
||||
else {
|
||||
out << "kInvalid";
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, library::OperationKind provider) {
|
||||
if (provider == library::OperationKind::kGemm) {
|
||||
out << "kGemm";
|
||||
}
|
||||
else if (provider == library::OperationKind::kRankK) {
|
||||
out << "kRankK";
|
||||
}
|
||||
else if (provider == library::OperationKind::kRank2K) {
|
||||
out << "kRank2K";
|
||||
}
|
||||
else if (provider == library::OperationKind::kTrmm) {
|
||||
out << "kTrmm";
|
||||
}
|
||||
else if (provider == library::OperationKind::kSymm) {
|
||||
out << "kSymm";
|
||||
}
|
||||
else if (provider == library::OperationKind::kConv2d) {
|
||||
out << "kConv2d";
|
||||
}
|
||||
else if (provider == library::OperationKind::kConv3d) {
|
||||
out << "kConv3d";
|
||||
}
|
||||
else if (provider == library::OperationKind::kEqGemm) {
|
||||
out << "kEqGemm";
|
||||
}
|
||||
else if (provider == library::OperationKind::kSparseGemm) {
|
||||
out << "kSparseGemm";
|
||||
}
|
||||
else if (provider == library::OperationKind::kReduction) {
|
||||
out << "kReduction";
|
||||
}
|
||||
else {
|
||||
out << "kInvalid";
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif // defined(CUTLASS_DEBUG_TRACE_LEVEL) && (CUTLASS_DEBUG_TRACE_LEVEL > 1)
|
||||
|
||||
/// Entry point to profile all operations in the manifest
|
||||
int OperationProfiler::profile_all(
|
||||
Options const &options,
|
||||
library::Manifest const &manifest,
|
||||
Options const &options,
|
||||
library::Manifest const &manifest,
|
||||
DeviceContext &device_context) {
|
||||
|
||||
ProblemSpace problem_space(arguments_, options.cmdline);
|
||||
|
||||
// 1. Construct performance report
|
||||
@@ -282,13 +348,45 @@ int OperationProfiler::profile_all(
|
||||
for (auto const& operation_ptr : manifest) {
|
||||
|
||||
library::Operation const *operation = operation_ptr.get();
|
||||
#if defined(CUTLASS_DEBUG_TRACE_LEVEL) && (CUTLASS_DEBUG_TRACE_LEVEL > 1)
|
||||
std::cerr << " Operation: " << typeid(*operation).name() << "\n"
|
||||
<< " name: " << operation->description().name << "\n"
|
||||
<< " kind: " << operation->description().kind << "\n"
|
||||
<< " provider: " << operation->description().provider << "\n";
|
||||
#endif // CUTLASS_DEBUG_TRACE_LEVEL
|
||||
|
||||
auto min_cc = operation->description().tile_description.minimum_compute_capability;
|
||||
auto max_cc = operation->description().tile_description.maximum_compute_capability;
|
||||
|
||||
#if defined(CUTLASS_DEBUG_TRACE_LEVEL) && (CUTLASS_DEBUG_TRACE_LEVEL > 1)
|
||||
std::cerr << " min_cc: " << min_cc << "\n";
|
||||
std::cerr << " max_cc: " << min_cc << "\n";
|
||||
#endif
|
||||
|
||||
// Clear named allocations
|
||||
device_context.free();
|
||||
|
||||
#if defined(CUTLASS_DEBUG_TRACE_LEVEL) && (CUTLASS_DEBUG_TRACE_LEVEL > 1)
|
||||
if (operation->description().kind != kind_) {
|
||||
std::cerr << " @ kind " << operation->description().kind
|
||||
<< " != kind_ " << kind_ << "\n";
|
||||
}
|
||||
if (operation->description().provider != library::Provider::kCUTLASS) {
|
||||
std::cerr << " @ provider " << operation->description().provider
|
||||
<< " != library::Provider::kCUTLASS\n";
|
||||
}
|
||||
if (options.device.compute_capability() < min_cc) {
|
||||
std::cerr << " @ compute_capability "
|
||||
<< options.device.compute_capability()
|
||||
<< " < min_cc " << min_cc << "\n";
|
||||
}
|
||||
if (options.device.compute_capability() > max_cc) {
|
||||
std::cerr << " @ compute_capability "
|
||||
<< options.device.compute_capability()
|
||||
<< " > max_cc " << max_cc << "\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
// Execute compatible cutlass operations if they satisfy the current device's compute capability
|
||||
if (operation->description().kind == kind_ &&
|
||||
operation->description().provider == library::Provider::kCUTLASS &&
|
||||
@@ -296,17 +394,16 @@ int OperationProfiler::profile_all(
|
||||
options.device.compute_capability() <= max_cc) {
|
||||
|
||||
std::string operation_name(operation->description().name);
|
||||
|
||||
// Filter kernels by name
|
||||
bool filtered_by_name = options.operation_names.empty();
|
||||
if (!filtered_by_name) {
|
||||
|
||||
|
||||
for (auto const & op_name : options.operation_names) {
|
||||
if (find_string_matches_(op_name, operation_name)) {
|
||||
filtered_by_name = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto const & op_name : options.excluded_operation_names) {
|
||||
@@ -333,10 +430,10 @@ int OperationProfiler::profile_all(
|
||||
problem);
|
||||
|
||||
if (status == Status::kErrorInternal) {
|
||||
|
||||
|
||||
// If there was an internal error, consume the CUDA error and move to the next operation.
|
||||
(void)cudaGetLastError();
|
||||
|
||||
|
||||
report.append_results(results_);
|
||||
continue;
|
||||
}
|
||||
@@ -385,9 +482,9 @@ int OperationProfiler::profile_all(
|
||||
|
||||
continue_profiling = this->verify_cutlass(
|
||||
options,
|
||||
report,
|
||||
device_context,
|
||||
operation,
|
||||
report,
|
||||
device_context,
|
||||
operation,
|
||||
problem_space,
|
||||
problem);
|
||||
|
||||
@@ -419,10 +516,10 @@ int OperationProfiler::profile_all(
|
||||
if (continue_profiling && options.profiling.enabled) {
|
||||
|
||||
continue_profiling = this->profile(
|
||||
options,
|
||||
report,
|
||||
device_context,
|
||||
operation,
|
||||
options,
|
||||
report,
|
||||
device_context,
|
||||
operation,
|
||||
problem_space,
|
||||
problem);
|
||||
}
|
||||
@@ -459,7 +556,7 @@ void OperationProfiler::sleep(int sleep_duration) {
|
||||
SleepEx(sleep_duration, false);
|
||||
#else
|
||||
// sleep not supported
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -485,7 +582,7 @@ Disposition OperationProfiler::compare_tensors(
|
||||
|
||||
// bit-level equality
|
||||
passed = DeviceAllocation::block_compare_equal(
|
||||
experimental.type(),
|
||||
experimental.type(),
|
||||
experimental.data(),
|
||||
reference.data(),
|
||||
count);
|
||||
@@ -494,7 +591,7 @@ Disposition OperationProfiler::compare_tensors(
|
||||
|
||||
// relative error function
|
||||
passed = DeviceAllocation::block_compare_relatively_equal(
|
||||
experimental.type(),
|
||||
experimental.type(),
|
||||
experimental.data(),
|
||||
reference.data(),
|
||||
count,
|
||||
@@ -516,7 +613,7 @@ void OperationProfiler::save_workspace(
|
||||
for (auto const & named_allocation : device_context) {
|
||||
|
||||
DeviceAllocation *allocation = named_allocation.second;
|
||||
|
||||
|
||||
std::stringstream filename;
|
||||
|
||||
filename << desc.name << "_" << library::to_string(provider) << "_";
|
||||
@@ -535,7 +632,7 @@ void OperationProfiler::save_workspace(
|
||||
if (options.report.verbose) {
|
||||
std::cout << "wrote '" << filename.str() << "'" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -575,7 +672,7 @@ Status OperationProfiler::profile_cutlass_(
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Initialize GPU timer
|
||||
//
|
||||
@@ -590,7 +687,7 @@ Status OperationProfiler::profile_cutlass_(
|
||||
|
||||
int iteration = 0;
|
||||
for (; iteration < Iterations; ++iteration) {
|
||||
|
||||
|
||||
status = operation->run(
|
||||
arguments,
|
||||
host_workspace,
|
||||
@@ -610,7 +707,7 @@ Status OperationProfiler::profile_cutlass_(
|
||||
//
|
||||
// Update performance result
|
||||
//
|
||||
|
||||
|
||||
runtime = timer.duration(iteration);
|
||||
|
||||
return status;
|
||||
@@ -618,7 +715,7 @@ Status OperationProfiler::profile_cutlass_(
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Sets operation description
|
||||
/// Sets operation description
|
||||
void OperationProfiler::initialize_result_(
|
||||
PerformanceResult &result,
|
||||
library::OperationDescription const &operation_desc,
|
||||
@@ -657,7 +754,7 @@ void OperationProfiler::set_argument(
|
||||
result.arguments.at(problem_space.argument_index(name)) = make_pair(std::string(name), value);
|
||||
}
|
||||
|
||||
void OperationProfiler::set_argument(
|
||||
void OperationProfiler::set_argument(
|
||||
PerformanceResult &result,
|
||||
char const *name,
|
||||
ProblemSpace const &problem_space,
|
||||
@@ -669,12 +766,12 @@ void OperationProfiler::set_argument(
|
||||
|
||||
/// finds string matches filter_string in operation_name
|
||||
bool OperationProfiler::find_string_matches_(
|
||||
std::string const &filter_string,
|
||||
std::string const &filter_string,
|
||||
std::string const &operation_name) {
|
||||
// Returns true if all substrings appear in the operation_name in order
|
||||
|
||||
|
||||
// Split filter_string of the format "gemm*f32*nt" to tokens ["gemm", "f32", "nt"]
|
||||
std::string item;
|
||||
std::string item;
|
||||
std::istringstream iss(filter_string);
|
||||
std::vector<std::string> filter_tokens;
|
||||
while (std::getline(iss, item, '*')) {
|
||||
@@ -692,7 +789,7 @@ bool OperationProfiler::find_string_matches_(
|
||||
return false;
|
||||
}
|
||||
}
|
||||
start += (idx + token.length());
|
||||
start += (idx + token.length());
|
||||
}
|
||||
|
||||
// All tokens in filter_string found in operation_name
|
||||
|
||||
@@ -234,7 +234,7 @@ Status SymmOperationProfiler::SymmProblem::parse(
|
||||
|
||||
/// Total number of bytes loaded
|
||||
int64_t SymmOperationProfiler::SymmProblem::bytes(library::SymmDescription const &operation_desc) const {
|
||||
int64_t bytes;
|
||||
int64_t bytes = 0;
|
||||
// Input bytes read and Output bytes written for the gemm problem
|
||||
// Half matrix including the diagonal will have (X*(X+1))/2 elements
|
||||
if (operation_desc.side_mode == SideMode::kLeft) {
|
||||
|
||||
Reference in New Issue
Block a user