CUTLASS 2.2 (#96)
Adds support for NVIDIA Ampere Architecture features. CUDA 11 Toolkit recommended.
This commit is contained in:
@@ -45,6 +45,9 @@ private:
|
||||
/// Host workspace
|
||||
static int const kHostWorkspaceSize = (4 << 10);
|
||||
|
||||
/// Provider of operations
|
||||
Provider provider_;
|
||||
|
||||
/// CUDA device properties
|
||||
cudaDeviceProp device_;
|
||||
|
||||
@@ -90,6 +93,12 @@ public:
|
||||
/// Gets the current CUDA stream
|
||||
cudaStream_t get_stream() const;
|
||||
|
||||
/// Gets the current provider
|
||||
Provider get_provider() const;
|
||||
|
||||
/// Sets the provider of operations
|
||||
void set_provider(Provider provider);
|
||||
|
||||
/// Gets the device workspace size
|
||||
size_t get_workspace_size() const;
|
||||
|
||||
@@ -149,6 +158,56 @@ public:
|
||||
void * ptr_D, /// Pointer to D matrix
|
||||
int ldd /// Leading dimension of D matrix
|
||||
);
|
||||
|
||||
/// Executes a GEMM computation: D <= alpha * A*B + beta * C.
|
||||
//
|
||||
// Supports batched-strided, batched array or split-K serial or split-K parallel.
|
||||
//
|
||||
Status gemm_universal(
|
||||
|
||||
GemmUniversalMode mode, /// indicates the mode in which the kUniversal GEMM is launched
|
||||
|
||||
int M, /// GEMM M dimension
|
||||
int N, /// GEMM N dimension
|
||||
int K, /// GEMM K dimension
|
||||
|
||||
NumericTypeID element_compute, /// Data type of internal accumulation
|
||||
|
||||
NumericTypeID element_scalar, /// Data type of alpha/beta scalars
|
||||
|
||||
void const *alpha, /// Pointer to alpha scalar
|
||||
|
||||
NumericTypeID element_A, /// Data type of A matrix elements
|
||||
LayoutTypeID layout_A, /// Layout of A matrix
|
||||
ComplexTransform transform_A, /// Complex transformation applied to A matrix - ignored for real-valued matrices
|
||||
|
||||
void const * ptr_A, /// Pointer to A matrix in Global Memory
|
||||
int lda, /// Leading dimension of A matrix
|
||||
|
||||
NumericTypeID element_B, /// Data type of B matrix elements
|
||||
LayoutTypeID layout_B, /// Layout of B matrix
|
||||
ComplexTransform transform_B, /// Complex transformation applied to B matrix - ignored for real-valued matrices
|
||||
|
||||
void const * ptr_B, /// Pointer to B matrix in Global Memory
|
||||
int ldb, /// Leading dimension of B matrix
|
||||
|
||||
void const * beta, /// Pointer to beta scalar
|
||||
|
||||
NumericTypeID element_C, /// Data type of C and D matrices
|
||||
|
||||
void const * ptr_C, /// Pointer to C matrix
|
||||
int ldc, /// Leading dimension of C matrix
|
||||
|
||||
void * ptr_D, /// Pointer to D matrix
|
||||
int ldd, /// Leading dimension of D matrix
|
||||
|
||||
int batch_count = 1, /// Batch count or number of split-K slices
|
||||
|
||||
int64_t batch_stride_A = 0, /// Batch stride of A operand
|
||||
int64_t batch_stride_B = 0, /// Batch stride of B operand
|
||||
int64_t batch_stride_C = 0, /// Batch stride of C operand
|
||||
int64_t batch_stride_D = 0 /// Batch stride of D operand
|
||||
);
|
||||
|
||||
/// Planar complex GEMM
|
||||
///
|
||||
@@ -276,7 +335,6 @@ public:
|
||||
using HandlePtr = std::unique_ptr<Handle>;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespace library
|
||||
} // namespace cutlass
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
#include "cutlass/cutlass.h"
|
||||
@@ -93,10 +94,14 @@ enum class NumericTypeID {
|
||||
kS32,
|
||||
kS64,
|
||||
kF16,
|
||||
kBF16,
|
||||
kTF32,
|
||||
kF32,
|
||||
kF64,
|
||||
kCF16,
|
||||
kCBF16,
|
||||
kCF32,
|
||||
kCTF32,
|
||||
kCF64,
|
||||
kCS4,
|
||||
kCS8,
|
||||
@@ -120,6 +125,7 @@ enum class ComplexTransform {
|
||||
|
||||
/// Providers
|
||||
enum class Provider {
|
||||
kNone,
|
||||
kCUTLASS,
|
||||
kReferenceHost,
|
||||
kReferenceDevice,
|
||||
@@ -132,6 +138,8 @@ enum class Provider {
|
||||
/// Enumeration indicating the kind of operation
|
||||
enum class OperationKind {
|
||||
kGemm,
|
||||
kEqGemm,
|
||||
kReduction,
|
||||
kInvalid
|
||||
};
|
||||
|
||||
@@ -160,9 +168,11 @@ enum class OpcodeClassID {
|
||||
};
|
||||
|
||||
enum class MathOperationID {
|
||||
kAdd,
|
||||
kMultiplyAdd,
|
||||
kMultiplyAddSaturate,
|
||||
kMultiplyAddComplex,
|
||||
kMultiplyAddGaussianComplex,
|
||||
kXorPopc,
|
||||
kInvalid
|
||||
};
|
||||
@@ -180,12 +190,17 @@ enum class GemmKind {
|
||||
kInvalid
|
||||
};
|
||||
|
||||
/// Mode of GEMM
|
||||
enum class GemmUniversalMode {
|
||||
kGemm,
|
||||
kGemmSplitKParallel,
|
||||
kBatched,
|
||||
kArray,
|
||||
/// Mode of Universal GEMM
|
||||
using GemmUniversalMode = cutlass::gemm::GemmUniversalMode;
|
||||
|
||||
enum class EpilogueKind {
|
||||
kUnknown,
|
||||
kConversion,
|
||||
kLinearCombination,
|
||||
kLinearCombinationClamp,
|
||||
kLinearCombinationPlanarComplex,
|
||||
kLinearCombinationRelu,
|
||||
kLinearCombinationSigmoid,
|
||||
kInvalid
|
||||
};
|
||||
|
||||
@@ -220,6 +235,22 @@ struct MathInstructionDescription {
|
||||
opcode_class(opcode_class),
|
||||
math_operation(math_operation) {}
|
||||
|
||||
// Equality operator
|
||||
inline
|
||||
bool operator==(MathInstructionDescription const& rhs) const{
|
||||
return (
|
||||
(instruction_shape == rhs.instruction_shape) &&
|
||||
(element_accumulator == rhs.element_accumulator) &&
|
||||
(opcode_class == rhs.opcode_class) &&
|
||||
(math_operation == rhs.math_operation));
|
||||
}
|
||||
|
||||
// Inequality operator
|
||||
inline
|
||||
bool operator!=(MathInstructionDescription const& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/// Structure describing the tiled structure of a GEMM-like computation
|
||||
@@ -261,6 +292,24 @@ struct TileDescription {
|
||||
math_instruction(math_instruction),
|
||||
minimum_compute_capability(minimum_compute_capability),
|
||||
maximum_compute_capability(maximum_compute_capability) { }
|
||||
|
||||
// Equality operator
|
||||
inline
|
||||
bool operator==(TileDescription const& rhs) const{
|
||||
return (
|
||||
(threadblock_shape == rhs.threadblock_shape) &&
|
||||
(threadblock_stages == rhs.threadblock_stages) &&
|
||||
(warp_count == rhs.warp_count) &&
|
||||
(math_instruction == rhs.math_instruction) &&
|
||||
(minimum_compute_capability == rhs.minimum_compute_capability) &&
|
||||
(maximum_compute_capability == rhs.maximum_compute_capability));
|
||||
}
|
||||
|
||||
// Inequality operator
|
||||
inline
|
||||
bool operator!=(TileDescription const& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
};
|
||||
|
||||
/// High-level description of an operation
|
||||
@@ -379,6 +428,20 @@ struct GemmDescription : public OperationDescription {
|
||||
transform_B(transform_B) {}
|
||||
};
|
||||
|
||||
|
||||
/// Description of all Reduction operations
|
||||
struct ReductionDescription : public OperationDescription {
|
||||
|
||||
/// Describes the data type of workspace
|
||||
NumericTypeID element_workspace;
|
||||
|
||||
/// Describes the data type of final output
|
||||
NumericTypeID element_output;
|
||||
|
||||
/// Describes the data type of the scalars passed to the epilogue
|
||||
NumericTypeID element_epilogue;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -549,6 +612,42 @@ struct GemmArrayArguments {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Universal GEMM supporting multiple split-K modes, multiple batched modes, real and complex
|
||||
//
|
||||
// OperationKind: Gemm
|
||||
// GemmKind: Universal
|
||||
|
||||
struct GemmUniversalConfiguration {
|
||||
|
||||
GemmUniversalMode mode;
|
||||
gemm::GemmCoord problem_size;
|
||||
int batch_count;
|
||||
|
||||
int64_t lda;
|
||||
int64_t ldb;
|
||||
int64_t ldc;
|
||||
int64_t ldd;
|
||||
};
|
||||
|
||||
struct GemmUniversalArguments {
|
||||
|
||||
void const *A;
|
||||
void const *B;
|
||||
void const *C;
|
||||
void *D;
|
||||
|
||||
void const *alpha;
|
||||
void const *beta;
|
||||
ScalarPointerMode pointer_mode;
|
||||
|
||||
int64_t batch_stride_A;
|
||||
int64_t batch_stride_B;
|
||||
int64_t batch_stride_C;
|
||||
int64_t batch_stride_D;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Complex valued GEMM in which real and imaginary parts are separated by a stride
|
||||
//
|
||||
// OperationKind: Gemm
|
||||
@@ -648,7 +747,6 @@ struct GemmPlanarComplexArrayArguments {
|
||||
ScalarPointerMode pointer_mode;
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespace library
|
||||
|
||||
@@ -45,6 +45,13 @@ namespace cutlass {
|
||||
namespace library {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Forward declaration
|
||||
class Manifest;
|
||||
|
||||
// init and insert all cutlass gemm and conv2d op in manifest object (procedurally generated using generator.py)
|
||||
void initialize_all(Manifest &manifest);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// List of operations
|
||||
using OperationVector = std::vector<std::unique_ptr<Operation>>;
|
||||
|
||||
@@ -29,24 +29,28 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
#include <iosfwd>
|
||||
#include <unordered_map>
|
||||
#include <algorithm>
|
||||
|
||||
#include "cutlass/library/library.h"
|
||||
#include "cutlass/library/manifest.h"
|
||||
|
||||
#include "cutlass/library/util.h"
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace cutlass {
|
||||
namespace library {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Data Structures for Gemm Functional Maps
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Tuple uniquely identifying functional behavior
|
||||
/// Tuple uniquely identifying Gemm functional behavior
|
||||
struct GemmFunctionalKey {
|
||||
|
||||
Provider provider;
|
||||
GemmKind gemm_kind;
|
||||
NumericTypeID element_compute;
|
||||
NumericTypeID element_scalar;
|
||||
NumericTypeID element_A;
|
||||
@@ -63,6 +67,8 @@ struct GemmFunctionalKey {
|
||||
|
||||
inline
|
||||
GemmFunctionalKey(
|
||||
Provider provider,
|
||||
GemmKind gemm_kind = GemmKind::kGemm,
|
||||
NumericTypeID element_compute = NumericTypeID::kF32,
|
||||
NumericTypeID element_scalar = NumericTypeID::kF32,
|
||||
NumericTypeID element_A = NumericTypeID::kF16,
|
||||
@@ -73,6 +79,8 @@ struct GemmFunctionalKey {
|
||||
ComplexTransform transform_B = ComplexTransform::kNone,
|
||||
NumericTypeID element_C = NumericTypeID::kF16
|
||||
):
|
||||
provider(provider),
|
||||
gemm_kind(gemm_kind),
|
||||
element_compute(element_compute),
|
||||
element_scalar(element_scalar),
|
||||
element_A(element_A),
|
||||
@@ -87,6 +95,8 @@ struct GemmFunctionalKey {
|
||||
inline
|
||||
bool operator==(GemmFunctionalKey const &rhs) const {
|
||||
return
|
||||
(provider == rhs.provider) &&
|
||||
(gemm_kind == rhs.gemm_kind) &&
|
||||
(element_compute == rhs.element_compute) &&
|
||||
(element_scalar == rhs.element_scalar) &&
|
||||
(element_A == rhs.element_A) &&
|
||||
@@ -104,6 +114,28 @@ struct GemmFunctionalKey {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
inline
|
||||
std::ostream & operator<<(std::ostream &out, cutlass::library::GemmFunctionalKey const &k) {
|
||||
|
||||
out << "{\n"
|
||||
<< " provider: " << to_string(k.provider) << "\n"
|
||||
<< " gemm_kind: " << to_string(k.gemm_kind) << "\n"
|
||||
<< " element_compute: " << to_string(k.element_compute) << "\n"
|
||||
<< " element_scalar: " << to_string(k.element_scalar) << "\n"
|
||||
<< " element_A: " << to_string(k.element_A) << "\n"
|
||||
<< " layout_A: " << to_string(k.layout_A) << "\n"
|
||||
<< " transform_A: " << to_string(k.transform_A) << "\n"
|
||||
<< " element_B: " << to_string(k.element_B) << "\n"
|
||||
<< " layout_B: " << to_string(k.layout_B) << "\n"
|
||||
<< " transform_B: " << to_string(k.transform_B) << "\n"
|
||||
<< " element_C: " << to_string(k.element_C) << "\n"
|
||||
<< "}";
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Hash function for GemmFunctionalKey
|
||||
@@ -120,15 +152,17 @@ struct GemmFunctionalKeyHasher {
|
||||
IntHash hash;
|
||||
|
||||
return
|
||||
rotl(hash(int(key.element_compute)), 2) ^
|
||||
rotl(hash(int(key.element_scalar)), 3) ^
|
||||
rotl(hash(int(key.element_A)), 4) ^
|
||||
rotl(hash(int(key.layout_A)), 5) ^
|
||||
rotl(hash(int(key.transform_A)), 6) ^
|
||||
rotl(hash(int(key.element_B)), 7) ^
|
||||
rotl(hash(int(key.layout_B)), 8) ^
|
||||
rotl(hash(int(key.transform_B)), 9) ^
|
||||
rotl(hash(int(key.element_C)), 10);
|
||||
rotl(hash(int(key.provider)), 1) ^
|
||||
rotl(hash(int(key.gemm_kind)), 2) ^
|
||||
rotl(hash(int(key.element_compute)), 3) ^
|
||||
rotl(hash(int(key.element_scalar)), 4) ^
|
||||
rotl(hash(int(key.element_A)), 5) ^
|
||||
rotl(hash(int(key.layout_A)), 6) ^
|
||||
rotl(hash(int(key.transform_A)), 7) ^
|
||||
rotl(hash(int(key.element_B)), 8) ^
|
||||
rotl(hash(int(key.layout_B)), 9) ^
|
||||
rotl(hash(int(key.transform_B)), 10) ^
|
||||
rotl(hash(int(key.element_C)), 11);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -172,6 +206,7 @@ using GemmOperationFunctionalMap = std::unordered_map<
|
||||
GemmOperationVectorMap,
|
||||
GemmFunctionalKeyHasher
|
||||
>;
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -179,15 +214,10 @@ using GemmOperationFunctionalMap = std::unordered_map<
|
||||
class OperationTable {
|
||||
public:
|
||||
|
||||
/// Map of all operations of type kGemm and gemm_kind of type kGemm
|
||||
/// Map of all operations of type kGemm
|
||||
// provider (kCUTLASS)
|
||||
GemmOperationFunctionalMap gemm_operations;
|
||||
|
||||
/// Map of all operations of type kGemm and gemm_kind of type kPlanarComplex
|
||||
GemmOperationFunctionalMap gemm_planar_complex_operations;
|
||||
|
||||
/// Map of all operations of type kGemm and gemm_kind of type kPlanarComplexArray
|
||||
GemmOperationFunctionalMap gemm_planar_complex_array_operations;
|
||||
|
||||
public:
|
||||
|
||||
void append(Manifest const &manifest);
|
||||
@@ -202,4 +232,3 @@ public:
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::ostream & operator<<(std::ostream &out, cutlass::library::GemmFunctionalKey const &k);
|
||||
|
||||
|
||||
@@ -49,6 +49,9 @@ char const *to_string(Provider provider, bool pretty = false);
|
||||
/// Parses a Provider enumerant from a string
|
||||
template <> Provider from_string<Provider>(std::string const &str);
|
||||
|
||||
/// Converts a GemmKind enumerant to a string
|
||||
char const *to_string(GemmKind type, bool pretty = false);
|
||||
|
||||
/// Converts a NumericType enumerant to a string
|
||||
char const *to_string(OperationKind type, bool pretty = false);
|
||||
|
||||
@@ -111,6 +114,14 @@ char const *to_string(ComplexTransform type, bool pretty = false);
|
||||
template <>
|
||||
ComplexTransform from_string<ComplexTransform>(std::string const &str);
|
||||
|
||||
|
||||
/// Converts a SplitKMode enumerant to a string
|
||||
char const *to_string(SplitKMode split_k_mode, bool pretty = false);
|
||||
|
||||
/// Converts a SplitKMode enumerant from a string
|
||||
template <>
|
||||
SplitKMode from_string<SplitKMode>(std::string const &str);
|
||||
|
||||
/// Lexical cast from int64_t to string
|
||||
std::string lexical_cast(int64_t int_value);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user