CUTLASS 2.0 (#62)
CUTLASS 2.0 Substantially refactored for - Better performance, particularly for native Turing Tensor Cores - Robust and durable templates spanning the design space - Encapsulated functionality embodying modern C++11 programming techniques - Optimized containers and data types for efficient, generic, portable device code Updates to: - Quick start guide - Documentation - Utilities - CUTLASS Profiler Native Turing Tensor Cores - Efficient GEMM kernels targeting Turing Tensor Cores - Mixed-precision floating point, 8-bit integer, 4-bit integer, and binarized operands Coverage of existing CUTLASS functionality: - GEMM kernels targeting CUDA and Tensor Cores in NVIDIA GPUs - Volta Tensor Cores through native mma.sync and through WMMA API - Optimizations such as parallel reductions, threadblock rasterization, and intra-threadblock reductions - Batched GEMM operations - Complex-valued GEMMs Note: this commit and all that follow require a host compiler supporting C++11 or greater.
This commit is contained in:
302
tools/profiler/src/performance_report.cpp
Normal file
302
tools/profiler/src/performance_report.cpp
Normal file
@@ -0,0 +1,302 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright (c) 2017-2019, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
* provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
* * 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.
|
||||
* * Neither the name of the NVIDIA CORPORATION 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 NVIDIA CORPORATION 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 TOR (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 Execution environment
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <iomanip>
|
||||
|
||||
#include "performance_report.h"
|
||||
|
||||
namespace cutlass {
|
||||
namespace profiler {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__unix__)
|
||||
|
||||
#define SHELL_COLOR_BRIGHT() "\033[1;37m"
|
||||
#define SHELL_COLOR_GREEN() "\033[1;32m"
|
||||
#define SHELL_COLOR_RED() "\033[1;31m"
|
||||
#define SHELL_COLOR_END() "\033[0m"
|
||||
|
||||
#else
|
||||
|
||||
#define SHELL_COLOR_BRIGHT() ""
|
||||
#define SHELL_COLOR_GREEN() ""
|
||||
#define SHELL_COLOR_RED() ""
|
||||
#define SHELL_COLOR_END() ""
|
||||
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PerformanceReport::PerformanceReport(
|
||||
Options const &options,
|
||||
std::vector<std::string> const &argument_names
|
||||
):
|
||||
options_(options), argument_names_(argument_names), problem_index_(0), good_(true) {
|
||||
|
||||
//
|
||||
// Open output file
|
||||
//
|
||||
if (!options_.report.output_path.empty()) {
|
||||
|
||||
bool print_header = true;
|
||||
|
||||
if (options_.report.append) {
|
||||
|
||||
std::ifstream test_output_file(options_.report.output_path.c_str());
|
||||
|
||||
if (test_output_file.is_open()) {
|
||||
print_header = false;
|
||||
test_output_file.close();
|
||||
}
|
||||
|
||||
output_file_.open(options_.report.output_path.c_str(), std::ios::app);
|
||||
}
|
||||
else {
|
||||
output_file_.open(options_.report.output_path.c_str());
|
||||
}
|
||||
|
||||
if (!output_file_.good()) {
|
||||
|
||||
std::cerr << "Could not open output file at path '"
|
||||
<< options_.report.output_path << "'" << std::endl;
|
||||
|
||||
good_ = false;
|
||||
}
|
||||
|
||||
if (print_header) {
|
||||
print_csv_header_(output_file_) << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PerformanceReport::next_problem() {
|
||||
++problem_index_;
|
||||
}
|
||||
|
||||
void PerformanceReport::append_result(PerformanceResult result) {
|
||||
|
||||
result.problem_index = problem_index_;
|
||||
|
||||
if (options_.report.verbose) {
|
||||
std::cout << "\n";
|
||||
print_result_pretty_(std::cout, result) << std::flush;
|
||||
}
|
||||
|
||||
if (output_file_.is_open()) {
|
||||
print_result_csv_(output_file_, result) << std::endl;
|
||||
}
|
||||
else {
|
||||
concatenated_results_.push_back(result);
|
||||
}
|
||||
}
|
||||
|
||||
void PerformanceReport::append_results(PerformanceResultVector const &results) {
|
||||
|
||||
if (options_.report.verbose) {
|
||||
std::cout << "\n\n";
|
||||
}
|
||||
|
||||
// For each result
|
||||
for (auto const & result : results) {
|
||||
append_result(result);
|
||||
}
|
||||
}
|
||||
|
||||
void PerformanceReport::close() {
|
||||
|
||||
//
|
||||
// Output results to stdout if they were not written to a file already.
|
||||
//
|
||||
if (options_.report.verbose && !concatenated_results_.empty()) {
|
||||
|
||||
std::cout << "\n\n";
|
||||
std::cout << "=============================\n\n";
|
||||
std::cout << "CSV Results:\n\n";
|
||||
|
||||
print_csv_header_(std::cout) << std::endl;
|
||||
|
||||
for (auto const &result : concatenated_results_) {
|
||||
print_result_csv_(std::cout, result) << "\n";
|
||||
}
|
||||
}
|
||||
else if (output_file_.is_open() && options_.report.verbose) {
|
||||
std::cout << "\n\nWrote results to '" << options_.report.output_path << "'" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *disposition_status_color(Disposition disposition) {
|
||||
switch (disposition) {
|
||||
case Disposition::kPassed: return SHELL_COLOR_GREEN();
|
||||
case Disposition::kFailed: return SHELL_COLOR_RED();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return SHELL_COLOR_END();
|
||||
}
|
||||
|
||||
/// Prints the result in human readable form
|
||||
std::ostream & PerformanceReport::print_result_pretty_(
|
||||
std::ostream &out,
|
||||
PerformanceResult const &result) {
|
||||
|
||||
out << "=============================\n"
|
||||
<< " Problem ID: " << result.problem_index << "\n";
|
||||
|
||||
if (!options_.report.pivot_tags.empty()) {
|
||||
|
||||
out << " Tags: ";
|
||||
|
||||
int column_idx = 0;
|
||||
for (auto const & tag : options_.report.pivot_tags) {
|
||||
out << (column_idx++ ? "," : "") << tag.first << ":" << tag.second;
|
||||
}
|
||||
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
out
|
||||
<< "\n"
|
||||
<< " Provider: " << SHELL_COLOR_BRIGHT() << to_string(result.provider, true) << SHELL_COLOR_END() << "\n"
|
||||
<< " Operation: " << result.operation_name << "\n\n"
|
||||
<< " Disposition: " << disposition_status_color(result.disposition) << to_string(result.disposition, true) << SHELL_COLOR_END() << "\n"
|
||||
<< " Status: " << SHELL_COLOR_BRIGHT() << library::to_string(result.status, true) << SHELL_COLOR_END() << "\n";
|
||||
|
||||
out
|
||||
<< "\n Arguments: ";
|
||||
|
||||
int column_idx = 0;
|
||||
for (auto const &arg : result.arguments) {
|
||||
if (!arg.second.empty()) {
|
||||
out << " --" << arg.first << "=" << arg.second;
|
||||
column_idx += 4 + arg.first.size() + arg.second.size();
|
||||
if (column_idx > 90) {
|
||||
out << " \\\n ";
|
||||
column_idx = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
out << "\n\n";
|
||||
|
||||
out
|
||||
<< " Bytes: " << result.bytes << " bytes\n"
|
||||
<< " FLOPs: " << result.flops << " flops\n\n";
|
||||
|
||||
if (result.good()) {
|
||||
|
||||
out
|
||||
<< " Runtime: " << result.runtime << " ms\n"
|
||||
<< " Memory: " << result.gbytes_per_sec() << " GiB/s\n"
|
||||
<< "\n Math: " << result.gflops_per_sec() << " GFLOP/s\n";
|
||||
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Prints the CSV header
|
||||
std::ostream & PerformanceReport::print_csv_header_(
|
||||
std::ostream &out) {
|
||||
|
||||
int column_idx = 0;
|
||||
|
||||
// Pivot tags
|
||||
for (auto const & tag : options_.report.pivot_tags) {
|
||||
out << (column_idx++ ? "," : "") << tag.first;
|
||||
}
|
||||
|
||||
out
|
||||
<< (column_idx ? "," : "") << "Problem,Provider"
|
||||
<< ",Operation,Disposition,Status";
|
||||
|
||||
for (auto const &arg_name : argument_names_) {
|
||||
out << "," << arg_name;
|
||||
}
|
||||
|
||||
out
|
||||
<< ",Bytes"
|
||||
<< ",Flops"
|
||||
<< ",Runtime"
|
||||
<< ",GB/s"
|
||||
<< ",GFLOPs"
|
||||
;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Print the result in CSV output
|
||||
std::ostream & PerformanceReport::print_result_csv_(
|
||||
std::ostream &out,
|
||||
PerformanceResult const &result) {
|
||||
|
||||
int column_idx = 0;
|
||||
|
||||
// Pivot tags
|
||||
for (auto const & tag : options_.report.pivot_tags) {
|
||||
out << (column_idx++ ? "," : "") << tag.second;
|
||||
}
|
||||
|
||||
out
|
||||
<< (column_idx ? "," : "")
|
||||
<< result.problem_index
|
||||
<< "," << to_string(result.provider, true)
|
||||
<< "," << result.operation_name
|
||||
<< "," << to_string(result.disposition)
|
||||
<< "," << library::to_string(result.status);
|
||||
|
||||
for (auto const & arg : result.arguments) {
|
||||
out << "," << arg.second;
|
||||
}
|
||||
|
||||
out
|
||||
<< "," << result.bytes
|
||||
<< "," << result.flops
|
||||
<< "," << result.runtime;
|
||||
|
||||
if (result.good()) {
|
||||
|
||||
out
|
||||
<< "," << result.gbytes_per_sec()
|
||||
<< "," << result.gflops_per_sec()
|
||||
;
|
||||
}
|
||||
else {
|
||||
out << std::string(2
|
||||
, ','
|
||||
);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespace profiler
|
||||
} // namespace cutlass
|
||||
Reference in New Issue
Block a user