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:
@@ -0,0 +1,60 @@
|
||||
/***************************************************************************************************
|
||||
* 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 Defines tags for architecture-specific configurations.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace cutlass {
|
||||
namespace arch {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
struct Sm50 {
|
||||
static int const kMinComputeCapability = 50;
|
||||
};
|
||||
struct Sm60 {
|
||||
static int const kMinComputeCapability = 60;
|
||||
};
|
||||
struct Sm61 {
|
||||
static int const kMinComputeCapability = 61;
|
||||
};
|
||||
struct Sm70 {
|
||||
static int const kMinComputeCapability = 70;
|
||||
};
|
||||
struct Sm72 {
|
||||
static int const kMinComputeCapability = 72;
|
||||
};
|
||||
struct Sm75 {
|
||||
static int const kMinComputeCapability = 75;
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespace arch
|
||||
} // namespace cutlass
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -0,0 +1,45 @@
|
||||
/***************************************************************************************************
|
||||
* 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 Architecture-specific operators on memory
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace cutlass {
|
||||
namespace arch {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespace arch
|
||||
} // namespace cutlass
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "memory_sm75.h"
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -0,0 +1,231 @@
|
||||
/***************************************************************************************************
|
||||
* 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 Architecture-specific operators on memory added for SM75
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cutlass/array.h"
|
||||
#include "cutlass/layout/matrix.h"
|
||||
|
||||
namespace cutlass {
|
||||
namespace arch {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <
|
||||
/// Layout of destination matrix (column-major implies transpose)
|
||||
typename Layout,
|
||||
/// .x1, .x2, or .x4
|
||||
int MatrixCount
|
||||
>
|
||||
inline __device__ void ldsm(Array<unsigned, MatrixCount> & D, void const* ptr);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Specializations
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if (__CUDACC_VER_MAJOR__ == 10) && (__CUDACC_VER_MINOR__ == 2)
|
||||
#define CUDA_NVVM_GET_SHARED_POINTER_SUPPORTED 1
|
||||
#else
|
||||
#define CUDA_NVVM_GET_SHARED_POINTER_SUPPORTED 0
|
||||
#endif
|
||||
|
||||
#if ! defined(CUDA_NVVM_GET_SHARED_POINTER_ENABLED)
|
||||
#define CUDA_NVVM_GET_SHARED_POINTER_ENABLED (CUDA_NVVM_GET_SHARED_POINTER_SUPPORTED)
|
||||
#endif
|
||||
|
||||
#if ! defined(CUDA_LDMATRIX_SUPPORTED)
|
||||
#define CUDA_LDMATRIX_SUPPORTED ((__CUDACC_VER_MAJOR__ == 10) && (__CUDACC_VER_MINOR__ >= 2))
|
||||
#endif
|
||||
|
||||
#if ! defined(CUDA_LDMATRIX_ENABLED)
|
||||
#define CUDA_LDMATRIX_ENABLED (CUDA_LDMATRIX_SUPPORTED)
|
||||
#endif
|
||||
|
||||
#if (CUDA_LDMATRIX_ENABLED && defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 750))
|
||||
#define CUDA_LDMATRIX_ACTIVATED 1
|
||||
#else
|
||||
#define CUDA_LDMATRIX_ACTIVATED 0
|
||||
#endif
|
||||
|
||||
#if defined(CUTLASS_GET_SMEM_POINTER)
|
||||
// Use the existing implementation
|
||||
#elif CUDA_NVVM_GET_SHARED_POINTER_ENABLED
|
||||
#if ! defined(NVVM_GET_SMEM_POINTER)
|
||||
#define NVVM_GET_SMEM_POINTER
|
||||
extern "C" {
|
||||
//
|
||||
// This NVVM intrinsic is subject to change in future versions of CUDA.
|
||||
// Clients should not call it directly. Rather, they should use the
|
||||
// cutlass::arch::ldsm<>() template.
|
||||
//
|
||||
__device__ uint32_t __nvvm_get_smem_pointer(void*);
|
||||
}
|
||||
#endif
|
||||
#define CUTLASS_GET_SMEM_POINTER(ptr) __nvvm_get_smem_pointer((void*)ptr)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <>
|
||||
inline __device__ void ldsm<layout::RowMajor, 1>(
|
||||
Array<unsigned, 1> & D,
|
||||
void const* ptr) {
|
||||
|
||||
#if CUDA_LDMATRIX_ACTIVATED
|
||||
|
||||
unsigned addr = CUTLASS_GET_SMEM_POINTER(ptr);
|
||||
|
||||
int x;
|
||||
asm volatile ("ldmatrix.sync.aligned.x1.m8n8.shared.b16 {%0}, [%1];" : "=r"(x) : "r"(addr));
|
||||
reinterpret_cast<int &>(D) = x;
|
||||
|
||||
#else
|
||||
|
||||
assert(0);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <>
|
||||
inline __device__ void ldsm<layout::RowMajor, 2>(
|
||||
Array<unsigned, 2> & D,
|
||||
void const* ptr) {
|
||||
|
||||
#if CUDA_LDMATRIX_ACTIVATED
|
||||
|
||||
unsigned addr = CUTLASS_GET_SMEM_POINTER(ptr);
|
||||
|
||||
int x, y;
|
||||
asm volatile ("ldmatrix.sync.aligned.x2.m8n8.shared.b16 {%0, %1}, [%2];" : "=r"(x), "=r"(y) : "r"(addr));
|
||||
reinterpret_cast<int2 &>(D) = make_int2(x, y);
|
||||
|
||||
#else
|
||||
|
||||
assert(0);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <>
|
||||
inline __device__ void ldsm<layout::RowMajor, 4>(
|
||||
Array<unsigned, 4> & D,
|
||||
void const* ptr) {
|
||||
|
||||
#if CUDA_LDMATRIX_ACTIVATED
|
||||
|
||||
unsigned addr = CUTLASS_GET_SMEM_POINTER(ptr);
|
||||
|
||||
int x, y, z, w;
|
||||
asm volatile ("ldmatrix.sync.aligned.x4.m8n8.shared.b16 {%0, %1, %2, %3}, [%4];" : "=r"(x), "=r"(y), "=r"(z), "=r"(w) : "r"(addr));
|
||||
reinterpret_cast<int4 &>(D) = make_int4(x, y, z, w);
|
||||
|
||||
#else
|
||||
|
||||
assert(0);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Transpose on 16b granularity
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <>
|
||||
inline __device__ void ldsm<layout::ColumnMajor, 1>(
|
||||
Array<unsigned, 1> & D,
|
||||
void const* ptr) {
|
||||
#if CUDA_LDMATRIX_ACTIVATED
|
||||
|
||||
unsigned addr = CUTLASS_GET_SMEM_POINTER(ptr);
|
||||
|
||||
int x;
|
||||
asm volatile ("ldmatrix.sync.aligned.x1.trans.m8n8.shared.b16 {%0}, [%1];" : "=r"(x) : "r"(addr));
|
||||
reinterpret_cast<int &>(D) = x;
|
||||
|
||||
#else
|
||||
|
||||
assert(0);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <>
|
||||
inline __device__ void ldsm<layout::ColumnMajor, 2>(
|
||||
Array<unsigned, 2> & D,
|
||||
void const* ptr) {
|
||||
|
||||
#if CUDA_LDMATRIX_ACTIVATED
|
||||
|
||||
unsigned addr = CUTLASS_GET_SMEM_POINTER(ptr);
|
||||
|
||||
int x, y;
|
||||
asm volatile ("ldmatrix.sync.aligned.x2.trans.m8n8.shared.b16 {%0, %1}, [%2];" : "=r"(x), "=r"(y) : "r"(addr));
|
||||
reinterpret_cast<int2 &>(D) = make_int2(x, y);
|
||||
|
||||
#else
|
||||
|
||||
assert(0);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <>
|
||||
inline __device__ void ldsm<layout::ColumnMajor, 4>(
|
||||
Array<unsigned, 4> & D,
|
||||
void const* ptr) {
|
||||
|
||||
#if CUDA_LDMATRIX_ACTIVATED
|
||||
|
||||
unsigned addr = CUTLASS_GET_SMEM_POINTER(ptr);
|
||||
|
||||
int x, y, z, w;
|
||||
asm volatile ("ldmatrix.sync.aligned.x4.trans.m8n8.shared.b16 {%0, %1, %2, %3}, [%4];" : "=r"(x), "=r"(y), "=r"(z), "=r"(w) : "r"(addr));
|
||||
reinterpret_cast<int4 &>(D) = make_int4(x, y, z, w);
|
||||
|
||||
#else
|
||||
|
||||
assert(0);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
} // namespace arch
|
||||
} // namespace cutlass
|
||||
@@ -0,0 +1,145 @@
|
||||
/***************************************************************************************************
|
||||
* 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 Templates exposing architecture support for multiply-add operations
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cutlass/array.h"
|
||||
#include "cutlass/numeric_types.h"
|
||||
#include "cutlass/gemm/gemm.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace cutlass {
|
||||
namespace arch {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Tag indicating the operation implied by MMA.
|
||||
struct OpMultiplyAdd;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Tag indicating the result is saturated to MAX_FLOAT|MIN_FLOAT or MAX_INT|MIN_INT
|
||||
struct OpMultiplyAddSaturate;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Tag indicating the inner product is defined by (XOR, POPC)
|
||||
struct OpXorPopc;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Tag classifying math operators as thread-level operations.
|
||||
struct OpClassSimt;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Tag classifing operators as Tensor Core operations.
|
||||
struct OpClassTensorOp;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Tag classifing operators as WMMA Tensor Core operations
|
||||
struct OpClassWmmaTensorOp;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Matrix multiply-add operation
|
||||
template <
|
||||
/// Size of the matrix product (concept: GemmShape)
|
||||
typename Shape_,
|
||||
/// Number of threads participating
|
||||
int kThreads_,
|
||||
/// Data type of A elements
|
||||
typename ElementA,
|
||||
/// Layout of A matrix (concept: MatrixLayout)
|
||||
typename LayoutA,
|
||||
/// Data type of B elements
|
||||
typename ElementB,
|
||||
/// Layout of B matrix (concept: MatrixLayout)
|
||||
typename LayoutB,
|
||||
/// Element type of C matrix
|
||||
typename ElementC,
|
||||
/// Layout of C matrix (concept: MatrixLayout)
|
||||
typename LayoutC,
|
||||
/// Inner product operator
|
||||
typename Operator
|
||||
>
|
||||
struct Mma;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Matrix multiply-add operation - specialized for 1x1x1x1 matrix multiply operation
|
||||
template <
|
||||
/// Data type of A elements
|
||||
typename ElementA,
|
||||
/// Layout of A matrix (concept: MatrixLayout)
|
||||
typename LayoutA,
|
||||
/// Data type of B elements
|
||||
typename ElementB,
|
||||
/// Layout of B matrix (concept: MatrixLayout)
|
||||
typename LayoutB,
|
||||
/// Element type of C matrix
|
||||
typename ElementC,
|
||||
/// Layout of C matrix (concept: MatrixLayout)
|
||||
typename LayoutC,
|
||||
/// Inner product operator
|
||||
typename Operator
|
||||
>
|
||||
struct Mma<gemm::GemmShape<1, 1, 1>, 1, ElementA, LayoutA, ElementB, LayoutB, ElementC, LayoutC, Operator> {
|
||||
|
||||
using Shape = gemm::GemmShape<1, 1, 1>;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
Array<ElementC, 1> &d,
|
||||
Array<ElementA, 1> const &a,
|
||||
Array<ElementB, 1> const &b,
|
||||
Array<ElementC, 1> const &c
|
||||
) {
|
||||
|
||||
d[0] = a[0] * b[0] + c[0];
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespace arch
|
||||
} // namespace cutlass
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Specializations for each compute capability
|
||||
//
|
||||
|
||||
#include "cutlass/arch/mma_sm50.h"
|
||||
#include "cutlass/arch/mma_sm60.h"
|
||||
#include "cutlass/arch/mma_sm61.h"
|
||||
#include "cutlass/arch/mma_sm70.h"
|
||||
#include "cutlass/arch/mma_sm75.h"
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -0,0 +1,373 @@
|
||||
/***************************************************************************************************
|
||||
* 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 Matrix multiply
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cutlass/arch/mma.h"
|
||||
#include "cutlass/complex.h"
|
||||
|
||||
#include "cutlass/layout/matrix.h"
|
||||
#include "cutlass/gemm/gemm.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace cutlass {
|
||||
namespace arch {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Matrix multiply-add operation
|
||||
template <
|
||||
/// Layout of A matrix
|
||||
typename LayoutA,
|
||||
/// Layout of B matrix
|
||||
typename LayoutB,
|
||||
/// Layout of C matrix
|
||||
typename LayoutC
|
||||
>
|
||||
struct Mma<gemm::GemmShape<1, 1, 1>, 1, float, LayoutA, float, LayoutB, float, LayoutC, OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<1, 1, 1>;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
Array<float, 1> &d,
|
||||
Array<float, 1> const &a,
|
||||
Array<float, 1> const &b,
|
||||
Array<float, 1> const &c
|
||||
) {
|
||||
d[0] = a[0] * b[0] + c[0];
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Matrix multiply-add operation
|
||||
template <
|
||||
/// Layout of A matrix
|
||||
typename LayoutA,
|
||||
/// Layout of B matrix
|
||||
typename LayoutB,
|
||||
/// Layout of C matrix
|
||||
typename LayoutC
|
||||
>
|
||||
struct Mma<gemm::GemmShape<1, 1, 1>, 1, double, LayoutA, double, LayoutB, double, LayoutC, OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<1, 1, 1>;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
Array<double, 1> &d,
|
||||
Array<double, 1> const &a,
|
||||
Array<double, 1> const &b,
|
||||
Array<double, 1> const &c
|
||||
) {
|
||||
|
||||
d[0] = a[0] * b[0] + c[0];
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Matrix multiply-add operation
|
||||
template <
|
||||
/// Layout of A matrix
|
||||
typename LayoutA,
|
||||
/// Layout of B matrix
|
||||
typename LayoutB,
|
||||
/// Layout of C matrix
|
||||
typename LayoutC
|
||||
>
|
||||
struct Mma<gemm::GemmShape<1, 1, 1>, 1, int, LayoutA, int, LayoutB, int, LayoutC, OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<1, 1, 1>;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
Array<int, 1> &d,
|
||||
Array<int, 1> const &a,
|
||||
Array<int, 1> const &b,
|
||||
Array<int, 1> const &c
|
||||
) {
|
||||
|
||||
d[0] = a[0] * b[0] + c[0];
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Matrix multiply-add operation
|
||||
template <
|
||||
/// Layout of A matrix
|
||||
typename LayoutA,
|
||||
/// Layout of B matrix
|
||||
typename LayoutB,
|
||||
/// Layout of C matrix
|
||||
typename LayoutC
|
||||
>
|
||||
struct Mma<
|
||||
gemm::GemmShape<1, 1, 1>,
|
||||
1,
|
||||
complex<float>,
|
||||
LayoutA,
|
||||
complex<float>,
|
||||
LayoutB,
|
||||
complex<float>,
|
||||
LayoutC,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<1, 1, 1>;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
Array<complex<float>, 1> &d,
|
||||
Array<complex<float>, 1> const &a,
|
||||
Array<complex<float>, 1> const &b,
|
||||
Array<complex<float>, 1> const &c
|
||||
) {
|
||||
|
||||
d[0].real() = a[0].real() * b[0].real() + c[0].real();
|
||||
d[0].imag() = a[0].imag() * b[0].real() + c[0].imag();
|
||||
d[0].real() = -a[0].imag() * b[0].imag() + d[0].real();
|
||||
d[0].imag() = a[0].real() * b[0].imag() + d[0].imag();
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Matrix multiply-add operation
|
||||
template <
|
||||
/// Layout of A matrix
|
||||
typename LayoutA,
|
||||
/// Layout of B matrix
|
||||
typename LayoutB,
|
||||
/// Layout of C matrix
|
||||
typename LayoutC
|
||||
>
|
||||
struct Mma<
|
||||
gemm::GemmShape<1, 1, 1>,
|
||||
1,
|
||||
complex<float>,
|
||||
LayoutA,
|
||||
float,
|
||||
LayoutB,
|
||||
complex<float>,
|
||||
LayoutC,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<1, 1, 1>;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
Array<complex<float>, 1> &d,
|
||||
Array<complex<float>, 1> const &a,
|
||||
Array<float, 1> const &b,
|
||||
Array<complex<float>, 1> const &c
|
||||
) {
|
||||
|
||||
d[0].real() = a[0].real() * b[0] + c[0].real();
|
||||
d[0].imag() = a[0].imag() * b[0] + c[0].imag();
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Matrix multiply-add operation
|
||||
template <
|
||||
/// Layout of A matrix
|
||||
typename LayoutA,
|
||||
/// Layout of B matrix
|
||||
typename LayoutB,
|
||||
/// Layout of C matrix
|
||||
typename LayoutC
|
||||
>
|
||||
struct Mma<
|
||||
gemm::GemmShape<1, 1, 1>,
|
||||
1,
|
||||
float,
|
||||
LayoutA,
|
||||
complex<float>,
|
||||
LayoutB,
|
||||
complex<float>,
|
||||
LayoutC,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<1, 1, 1>;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
Array<complex<float>, 1> &d,
|
||||
Array<float, 1> const &a,
|
||||
Array<complex<float>, 1> const &b,
|
||||
Array<complex<float>, 1> const &c
|
||||
) {
|
||||
|
||||
d[0].real() = a[0] * b[0].real() + c[0].real();
|
||||
d[0].imag() = a[0] * b[0].imag() + d[0].imag();
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Matrix multiply-add operation
|
||||
template <
|
||||
/// Layout of A matrix
|
||||
typename LayoutA,
|
||||
/// Layout of B matrix
|
||||
typename LayoutB,
|
||||
/// Layout of C matrix
|
||||
typename LayoutC
|
||||
>
|
||||
struct Mma<
|
||||
gemm::GemmShape<1, 1, 1>,
|
||||
1,
|
||||
complex<double>,
|
||||
LayoutA,
|
||||
complex<double>,
|
||||
LayoutB,
|
||||
complex<double>,
|
||||
LayoutC,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<1, 1, 1>;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
Array<complex<double>, 1> &d,
|
||||
Array<complex<double>, 1> const &a,
|
||||
Array<complex<double>, 1> const &b,
|
||||
Array<complex<double>, 1> const &c
|
||||
) {
|
||||
|
||||
d[0].real() = a[0].real() * b[0].real() + c[0].real();
|
||||
d[0].imag() = a[0].imag() * b[0].real() + c[0].imag();
|
||||
d[0].real() = -a[0].imag() * b[0].imag() + d[0].real();
|
||||
d[0].imag() = a[0].real() * b[0].imag() + d[0].imag();
|
||||
}
|
||||
};
|
||||
|
||||
/// Matrix multiply-add operation
|
||||
template <
|
||||
/// Layout of A matrix
|
||||
typename LayoutA,
|
||||
/// Layout of B matrix
|
||||
typename LayoutB,
|
||||
/// Layout of C matrix
|
||||
typename LayoutC
|
||||
>
|
||||
struct Mma<
|
||||
gemm::GemmShape<1, 1, 1>,
|
||||
1,
|
||||
complex<double>,
|
||||
LayoutA,
|
||||
double,
|
||||
LayoutB,
|
||||
complex<double>,
|
||||
LayoutC,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<1, 1, 1>;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
Array<complex<double>, 1> &d,
|
||||
Array<complex<double>, 1> const &a,
|
||||
Array<double, 1> const &b,
|
||||
Array<complex<double>, 1> const &c
|
||||
) {
|
||||
|
||||
d[0].real() = a[0].real() * b[0] + c[0].real();
|
||||
d[0].imag() = a[0].imag() * b[0] + c[0].imag();
|
||||
}
|
||||
};
|
||||
|
||||
/// Matrix multiply-add operation
|
||||
template <
|
||||
/// Layout of A matrix
|
||||
typename LayoutA,
|
||||
/// Layout of B matrix
|
||||
typename LayoutB,
|
||||
/// Layout of C matrix
|
||||
typename LayoutC
|
||||
>
|
||||
struct Mma<
|
||||
gemm::GemmShape<1, 1, 1>,
|
||||
1,
|
||||
double,
|
||||
LayoutA,
|
||||
complex<double>,
|
||||
LayoutB,
|
||||
complex<double>,
|
||||
LayoutC,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<1, 1, 1>;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
Array<complex<double>, 1> &d,
|
||||
Array<double, 1> const &a,
|
||||
Array<complex<double>, 1> const &b,
|
||||
Array<complex<double>, 1> const &c
|
||||
) {
|
||||
|
||||
d[0].real() = a[0] * b[0].real() + c[0].real();
|
||||
d[0].imag() = a[0] * b[0].imag() + d[0].imag();
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Matrix multiply-add operation
|
||||
template <
|
||||
/// Layout of A matrix
|
||||
typename LayoutA,
|
||||
/// Layout of B matrix
|
||||
typename LayoutB,
|
||||
/// Layout of C matrix
|
||||
typename LayoutC
|
||||
>
|
||||
struct Mma<gemm::GemmShape<1, 1, 1>, 1, half_t, LayoutA, half_t, LayoutB, float, LayoutC, OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<1, 1, 1>;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
Array<float, 1> &d,
|
||||
Array<half_t, 1> const &a,
|
||||
Array<half_t, 1> const &b,
|
||||
Array<float, 1> const &c
|
||||
) {
|
||||
d[0] = float(a[0]) * float(b[0]) + c[0];
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
/***************************************************************************************************
|
||||
* 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 Matrix multiply
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cuda_fp16.h>
|
||||
|
||||
#include "cutlass/arch/mma.h"
|
||||
|
||||
#include "cutlass/layout/matrix.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace cutlass {
|
||||
namespace arch {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Matrix multiply-add operation
|
||||
template <typename LayoutA, typename LayoutB, typename LayoutC>
|
||||
struct Mma<
|
||||
gemm::GemmShape<2,1,1>,
|
||||
1,
|
||||
half_t,
|
||||
LayoutA,
|
||||
half_t,
|
||||
LayoutB,
|
||||
half_t,
|
||||
LayoutC,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<2, 1, 1>;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
Array<half_t, 2> &d,
|
||||
Array<half_t, 2> const &a,
|
||||
Array<half_t, 1> const &b,
|
||||
Array<half_t, 2> const &c
|
||||
) {
|
||||
|
||||
#if (defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 600))
|
||||
|
||||
__half2 const & A = reinterpret_cast<__half2 const &>(a);
|
||||
__half2 B = __half2half2(reinterpret_cast<__half const &>(b));
|
||||
__half2 const & C = reinterpret_cast<__half2 const &>(c);
|
||||
|
||||
__half2 D = __hfma2(A, B, C);
|
||||
|
||||
d = reinterpret_cast<Array<half_t, 2> &>(D);
|
||||
|
||||
#else
|
||||
CUTLASS_PRAGMA_UNROLL
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
d[i] = a[i] * b[0] + c[i];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Matrix multiply-add operation
|
||||
template <typename LayoutA, typename LayoutB>
|
||||
struct Mma<
|
||||
gemm::GemmShape<1,2,1>,
|
||||
1,
|
||||
half_t,
|
||||
LayoutA,
|
||||
half_t,
|
||||
LayoutB,
|
||||
half_t,
|
||||
layout::RowMajor,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<1, 2, 1>;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
Array<half_t, 2> &d,
|
||||
Array<half_t, 1> const &a,
|
||||
Array<half_t, 2> const &b,
|
||||
Array<half_t, 2> const &c
|
||||
) {
|
||||
|
||||
#if (defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 600))
|
||||
|
||||
__half2 const & A = __half2half2(reinterpret_cast<__half const &>(a));
|
||||
__half2 B = reinterpret_cast<__half2 const &>(b);
|
||||
__half2 const & C = reinterpret_cast<__half2 const &>(c);
|
||||
|
||||
__half2 D = __hfma2(A, B, C);
|
||||
|
||||
d = reinterpret_cast<Array<half_t, 2> &>(D);
|
||||
|
||||
#else
|
||||
CUTLASS_PRAGMA_UNROLL
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
d[i] = a[0] * b[i] + c[i];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Matrix multiply-add operation
|
||||
template <>
|
||||
struct Mma <
|
||||
gemm::GemmShape<2, 2, 1>,
|
||||
1,
|
||||
half_t,
|
||||
layout::ColumnMajor,
|
||||
half_t,
|
||||
layout::RowMajor,
|
||||
half_t,
|
||||
layout::ColumnMajor,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<2, 2, 1>;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
Array<half_t, 4> &d,
|
||||
Array<half_t, 2> const &a,
|
||||
Array<half_t, 2> const &b,
|
||||
Array<half_t, 4> const &c
|
||||
) {
|
||||
|
||||
#if (defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 600))
|
||||
|
||||
__half2 const & A = reinterpret_cast<__half2 const &>(a);
|
||||
__half2 Blo = __low2half2(reinterpret_cast<__half2 const &>(b));
|
||||
__half2 Bhi = __high2half2(reinterpret_cast<__half2 const &>(b));
|
||||
|
||||
__half2 const *C = reinterpret_cast<__half2 const *>(&c);
|
||||
|
||||
__half2 Dlo = __hfma2(A, Blo, C[0]);
|
||||
__half2 Dhi = __hfma2(A, Bhi, C[1]);
|
||||
|
||||
Array<half_t, 2> * D = reinterpret_cast<Array<half_t, 2> *>(&d);
|
||||
|
||||
D[0] = reinterpret_cast<Array<half_t, 2> const &>(Dlo);
|
||||
D[1] = reinterpret_cast<Array<half_t, 2> const &>(Dhi);
|
||||
|
||||
#else
|
||||
CUTLASS_PRAGMA_UNROLL
|
||||
for (int j = 0; j < 2; ++j) {
|
||||
CUTLASS_PRAGMA_UNROLL
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
d[i + 2 * j] = a[i] * b[j] + c[i + 2 * j];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Matrix multiply-add operation
|
||||
template <>
|
||||
struct Mma<
|
||||
gemm::GemmShape<2, 2, 1>,
|
||||
1,
|
||||
half_t,
|
||||
layout::ColumnMajor,
|
||||
half_t,
|
||||
layout::RowMajor,
|
||||
half_t,
|
||||
layout::RowMajor,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<2, 2, 1>;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
Array<half_t, 4> &d,
|
||||
Array<half_t, 2> const &a,
|
||||
Array<half_t, 2> const &b,
|
||||
Array<half_t, 4> const &c
|
||||
) {
|
||||
|
||||
#if (defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 600))
|
||||
|
||||
__half2 Alo = __low2half2(reinterpret_cast<__half2 const &>(a));
|
||||
__half2 Ahi = __high2half2(reinterpret_cast<__half2 const &>(a));
|
||||
__half2 const & B = reinterpret_cast<__half2 const &>(b);
|
||||
|
||||
__half2 const *C = reinterpret_cast<__half2 const *>(&c);
|
||||
|
||||
__half2 Dlo = __hfma2(Alo, B, C[0]);
|
||||
__half2 Dhi = __hfma2(Ahi, B, C[0]);
|
||||
|
||||
Array<half_t, 2> * D = reinterpret_cast<Array<half_t, 2> *>(&d);
|
||||
|
||||
D[0] = reinterpret_cast<Array<half_t, 2> &>(Dlo);
|
||||
D[1] = reinterpret_cast<Array<half_t, 2> &>(Dhi);
|
||||
#else
|
||||
CUTLASS_PRAGMA_UNROLL
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
CUTLASS_PRAGMA_UNROLL
|
||||
for (int j = 0; j < 2; ++j) {
|
||||
d[i * 2 + j] = a[i] * b[j] + c[i * 2 + j];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
/***************************************************************************************************
|
||||
* 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 Matrix multiply
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cutlass/layout/matrix.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace cutlass {
|
||||
namespace arch {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Matrix multiply-add operation
|
||||
template <typename LayoutA, typename LayoutB, typename LayoutC>
|
||||
struct Mma<
|
||||
gemm::GemmShape<1,1,4>,
|
||||
1,
|
||||
int8_t,
|
||||
LayoutA,
|
||||
int8_t,
|
||||
LayoutB,
|
||||
int,
|
||||
LayoutC,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<1, 1, 4>;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
Array<int, 1> &d,
|
||||
Array<int8_t, 4> const &a,
|
||||
Array<int8_t, 4> const &b,
|
||||
Array<int, 1> const &c
|
||||
) {
|
||||
|
||||
#if (defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 610))
|
||||
|
||||
unsigned const &A = reinterpret_cast<unsigned const &>(a);
|
||||
unsigned const &B = reinterpret_cast<unsigned const &>(b);
|
||||
|
||||
asm volatile("dp4a.s32.s32 %0, %1, %2, %3;"
|
||||
: "=r"(d[0])
|
||||
: "r"(A), "r"(B), "r"(c[0]));
|
||||
|
||||
#else
|
||||
|
||||
d[0] = c[0];
|
||||
|
||||
CUTLASS_PRAGMA_UNROLL
|
||||
for (int k = 0; k < 4; ++k) {
|
||||
d[0] += a[k] * b[k];
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Matrix multiply-add operation
|
||||
template <typename LayoutC>
|
||||
struct Mma<
|
||||
gemm::GemmShape<1, 1, 2>,
|
||||
1,
|
||||
int16_t,
|
||||
layout::RowMajor,
|
||||
int16_t,
|
||||
layout::ColumnMajor,
|
||||
int,
|
||||
LayoutC,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<1, 1, 2>;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
Array<int, 1> &d,
|
||||
Array<int16_t, 2> const &a,
|
||||
Array<int16_t, 2> const &b,
|
||||
Array<int, 1> const &c
|
||||
) {
|
||||
|
||||
#if (defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 610))
|
||||
|
||||
unsigned const &A = reinterpret_cast<unsigned const &>(a);
|
||||
unsigned const &B = reinterpret_cast<unsigned const &>(b);
|
||||
|
||||
asm volatile("dp2a.s32.s32 %0, %1, %2, %3;"
|
||||
: "=r"(d[0])
|
||||
: "r"(A), "r"(B), "r"(c[0]));
|
||||
#else
|
||||
d[0] = c[0];
|
||||
|
||||
CUTLASS_PRAGMA_UNROLL
|
||||
for (int k = 0; k < 2; ++k) {
|
||||
d[0] += a[k] * b[k];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,623 @@
|
||||
/***************************************************************************************************
|
||||
* 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 Matrix multiply
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "mma.h"
|
||||
#include "cutlass/layout/matrix.h"
|
||||
#include "cutlass/numeric_types.h"
|
||||
|
||||
#if ((__CUDACC_VER_MAJOR__ > 10) || (__CUDACC_VER_MAJOR__ == 10 && __CUDACC_VER_MINOR__ >= 1))
|
||||
#define CUTLASS_ARCH_MMA_SM70_SUPPORTED
|
||||
#endif
|
||||
|
||||
#if (defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 700))
|
||||
|
||||
#if ((__CUDACC_VER_MAJOR__ > 10) || (__CUDACC_VER_MAJOR__ == 10 &&__CUDACC_VER_MINOR__ >= 1))
|
||||
#define CUTLASS_ARCH_MMA_SM70_ENABLED
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace cutlass {
|
||||
namespace arch {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Matrix multiply accumulate 884 - FP16 accumulation
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Matrix multiply-add operation: F16 = F16 * F16 + F16
|
||||
template <>
|
||||
struct Mma<
|
||||
gemm::GemmShape<8,8,4>,
|
||||
8,
|
||||
half_t,
|
||||
layout::ColumnMajor,
|
||||
half_t,
|
||||
layout::ColumnMajor,
|
||||
half_t,
|
||||
layout::RowMajor,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<8, 8, 4>;
|
||||
|
||||
using ElementA = half_t;
|
||||
using LayoutA = layout::ColumnMajor;
|
||||
using FragmentA = Array<half_t, 4>;
|
||||
|
||||
using ElementB = half_t;
|
||||
using LayoutB = layout::ColumnMajor;
|
||||
using FragmentB = Array<half_t, 4>;
|
||||
|
||||
using ElementC = half_t;
|
||||
using LayoutC = layout::RowMajor;
|
||||
using FragmentC = Array<half_t, 8>;
|
||||
|
||||
using Operator = OpMultiplyAdd;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
FragmentC &d,
|
||||
FragmentA const &a,
|
||||
FragmentB const &b,
|
||||
FragmentC const &c
|
||||
) {
|
||||
|
||||
#if defined(CUTLASS_ARCH_MMA_SM70_ENABLED)
|
||||
|
||||
unsigned const *A = reinterpret_cast<unsigned const *>(&a);
|
||||
unsigned const *B = reinterpret_cast<unsigned const *>(&b);
|
||||
unsigned const *C = reinterpret_cast<unsigned const *>(&c);
|
||||
unsigned *D = reinterpret_cast<unsigned *>(&d);
|
||||
|
||||
asm volatile("mma.sync.aligned.m8n8k4.col.col.f16.f16.f16.f16 {%0,%1,%2,%3}, {%4,%5}, {%6,%7}, {%8,%9,%10,%11};\n"
|
||||
: "=r"(D[0]), "=r"(D[1]), "=r"(D[2]), "=r"(D[3])
|
||||
: "r"(A[0]), "r"(A[1]), "r"(B[0]), "r"(B[1]), "r"(C[0]), "r"(C[1]), "r"(C[2]), "r"(C[3])
|
||||
);
|
||||
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
/// Matrix multiply-add operation: F16 = F16 * F16 + F16
|
||||
template <>
|
||||
struct Mma<
|
||||
gemm::GemmShape<8, 8, 4>,
|
||||
8,
|
||||
half_t,
|
||||
layout::ColumnMajor,
|
||||
half_t,
|
||||
layout::RowMajor,
|
||||
half_t,
|
||||
layout::RowMajor,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<8, 8, 4>;
|
||||
|
||||
using ElementA = half_t;
|
||||
using LayoutA = layout::ColumnMajor;
|
||||
using FragmentA = Array<half_t, 4>;
|
||||
|
||||
using ElementB = half_t;
|
||||
using LayoutB = layout::RowMajor;
|
||||
using FragmentB = Array<half_t, 4>;
|
||||
|
||||
using ElementC = half_t;
|
||||
using LayoutC = layout::RowMajor;
|
||||
using FragmentC = Array<half_t, 8>;
|
||||
|
||||
using Operator = OpMultiplyAdd;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
FragmentC &d,
|
||||
FragmentA const &a,
|
||||
FragmentB const &b,
|
||||
FragmentC const &c
|
||||
) {
|
||||
|
||||
#if defined(CUTLASS_ARCH_MMA_SM70_ENABLED)
|
||||
|
||||
unsigned const *A = reinterpret_cast<unsigned const *>(&a);
|
||||
unsigned const *B = reinterpret_cast<unsigned const *>(&b);
|
||||
unsigned const *C = reinterpret_cast<unsigned const *>(&c);
|
||||
unsigned *D = reinterpret_cast<unsigned *>(&d);
|
||||
|
||||
asm volatile("mma.sync.aligned.m8n8k4.col.row.f16.f16.f16.f16 {%0,%1,%2,%3}, {%4,%5}, {%6,%7}, {%8,%9,%10,%11};\n"
|
||||
: "=r"(D[0]), "=r"(D[1]), "=r"(D[2]), "=r"(D[3])
|
||||
: "r"(A[0]), "r"(A[1]), "r"(B[0]), "r"(B[1]), "r"(C[0]), "r"(C[1]), "r"(C[2]), "r"(C[3])
|
||||
);
|
||||
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
/// Matrix multiply-add operation: F16 = F16 * F16 + F16
|
||||
template <>
|
||||
struct Mma<
|
||||
gemm::GemmShape<8, 8, 4>,
|
||||
8,
|
||||
half_t,
|
||||
layout::RowMajor,
|
||||
half_t,
|
||||
layout::ColumnMajor,
|
||||
half_t,
|
||||
layout::RowMajor,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<8, 8, 4>;
|
||||
|
||||
using ElementA = half_t;
|
||||
using LayoutA = layout::RowMajor;
|
||||
using FragmentA = Array<half_t, 4>;
|
||||
|
||||
using ElementB = half_t;
|
||||
using LayoutB = layout::ColumnMajor;
|
||||
using FragmentB = Array<half_t, 4>;
|
||||
|
||||
using ElementC = half_t;
|
||||
using LayoutC = layout::RowMajor;
|
||||
using FragmentC = Array<half_t, 8>;
|
||||
|
||||
using Operator = OpMultiplyAdd;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
FragmentC &d,
|
||||
FragmentA const &a,
|
||||
FragmentB const &b,
|
||||
FragmentC const &c
|
||||
) {
|
||||
|
||||
#if defined(CUTLASS_ARCH_MMA_SM70_ENABLED)
|
||||
|
||||
unsigned const *A = reinterpret_cast<unsigned const *>(&a);
|
||||
unsigned const *B = reinterpret_cast<unsigned const *>(&b);
|
||||
unsigned const *C = reinterpret_cast<unsigned const *>(&c);
|
||||
unsigned *D = reinterpret_cast<unsigned *>(&d);
|
||||
|
||||
asm volatile("mma.sync.aligned.m8n8k4.row.col.f16.f16.f16.f16 {%0,%1,%2,%3}, {%4,%5}, {%6,%7}, {%8,%9,%10,%11};\n"
|
||||
: "=r"(D[0]), "=r"(D[1]), "=r"(D[2]), "=r"(D[3])
|
||||
: "r"(A[0]), "r"(A[1]), "r"(B[0]), "r"(B[1]), "r"(C[0]), "r"(C[1]), "r"(C[2]), "r"(C[3])
|
||||
);
|
||||
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
/// Matrix multiply-add operation: F16 = F16 * F16 + F16
|
||||
template <>
|
||||
struct Mma<
|
||||
gemm::GemmShape<8, 8, 4>,
|
||||
8,
|
||||
half_t,
|
||||
layout::RowMajor,
|
||||
half_t,
|
||||
layout::RowMajor,
|
||||
half_t,
|
||||
layout::RowMajor,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<8, 8, 4>;
|
||||
|
||||
using ElementA = half_t;
|
||||
using LayoutA = layout::RowMajor;
|
||||
using FragmentA = Array<half_t, 4>;
|
||||
|
||||
using ElementB = half_t;
|
||||
using LayoutB = layout::RowMajor;
|
||||
using FragmentB = Array<half_t, 4>;
|
||||
|
||||
using ElementC = half_t;
|
||||
using LayoutC = layout::RowMajor;
|
||||
using FragmentC = Array<half_t, 8>;
|
||||
|
||||
using Operator = OpMultiplyAdd;
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
FragmentC &d,
|
||||
FragmentA const &a,
|
||||
FragmentB const &b,
|
||||
FragmentC const &c
|
||||
) {
|
||||
|
||||
#if defined(CUTLASS_ARCH_MMA_SM70_ENABLED)
|
||||
|
||||
unsigned const *A = reinterpret_cast<unsigned const *>(&a);
|
||||
unsigned const *B = reinterpret_cast<unsigned const *>(&b);
|
||||
unsigned const *C = reinterpret_cast<unsigned const *>(&c);
|
||||
unsigned *D = reinterpret_cast<unsigned *>(&d);
|
||||
|
||||
asm volatile("mma.sync.aligned.m8n8k4.row.row.f16.f16.f16.f16 {%0,%1,%2,%3}, {%4,%5}, {%6,%7}, {%8,%9,%10,%11};\n"
|
||||
: "=r"(D[0]), "=r"(D[1]), "=r"(D[2]), "=r"(D[3])
|
||||
: "r"(A[0]), "r"(A[1]), "r"(B[0]), "r"(B[1]), "r"(C[0]), "r"(C[1]), "r"(C[2]), "r"(C[3])
|
||||
);
|
||||
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Matrix multiply accumulate 884 - FP32 accumulation
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Matrix multiply-add operation: F32 = F16 * F16 + F32
|
||||
template <>
|
||||
struct Mma<
|
||||
gemm::GemmShape<8, 8, 4>,
|
||||
8,
|
||||
half_t,
|
||||
layout::ColumnMajor,
|
||||
half_t,
|
||||
layout::ColumnMajor,
|
||||
float,
|
||||
layout::RowMajor,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<8, 8, 4>;
|
||||
|
||||
using ElementA = half_t;
|
||||
using LayoutA = layout::ColumnMajor;
|
||||
using FragmentA = Array<half_t, 4>;
|
||||
|
||||
using ElementB = half_t;
|
||||
using LayoutB = layout::ColumnMajor;
|
||||
using FragmentB = Array<half_t, 4>;
|
||||
|
||||
using ElementC = float;
|
||||
using LayoutC = layout::RowMajor;
|
||||
using FragmentC = Array<float, 8>;
|
||||
|
||||
using Operator = OpMultiplyAdd;
|
||||
|
||||
/// Multiply-add
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
FragmentC &d,
|
||||
FragmentA const &a,
|
||||
FragmentB const &b,
|
||||
FragmentC const &c
|
||||
) {
|
||||
|
||||
#if defined(CUTLASS_ARCH_MMA_SM70_ENABLED)
|
||||
|
||||
unsigned const *A = reinterpret_cast<unsigned const *>(&a);
|
||||
unsigned const *B = reinterpret_cast<unsigned const *>(&b);
|
||||
float const *C = reinterpret_cast<float const *>(&c);
|
||||
float *D = reinterpret_cast<float *>(&d);
|
||||
|
||||
asm volatile("mma.sync.aligned.m8n8k4.col.col.f32.f16.f16.f32 {%0,%1,%2,%3,%4,%5,%6,%7}, {%8,%9}, {%10,%11}, "
|
||||
"{%12,%13,%14,%15,%16,%17,%18,%19};\n"
|
||||
: "=f"(D[0]),
|
||||
"=f"(D[1]),
|
||||
"=f"(D[2]),
|
||||
"=f"(D[3]),
|
||||
"=f"(D[4]),
|
||||
"=f"(D[5]),
|
||||
"=f"(D[6]),
|
||||
"=f"(D[7])
|
||||
: "r"(A[0]),
|
||||
"r"(A[1]),
|
||||
"r"(B[0]),
|
||||
"r"(B[1]),
|
||||
"f"(C[0]),
|
||||
"f"(C[1]),
|
||||
"f"(C[2]),
|
||||
"f"(C[3]),
|
||||
"f"(C[4]),
|
||||
"f"(C[5]),
|
||||
"f"(C[6]),
|
||||
"f"(C[7])
|
||||
);
|
||||
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
/// Matrix multiply-add operation: F32 = F16 * F16 + F32
|
||||
template <>
|
||||
struct Mma<
|
||||
gemm::GemmShape<8, 8, 4>,
|
||||
8,
|
||||
half_t,
|
||||
layout::ColumnMajor,
|
||||
half_t,
|
||||
layout::RowMajor,
|
||||
float,
|
||||
layout::RowMajor,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<8, 8, 4>;
|
||||
|
||||
using ElementA = half_t;
|
||||
using LayoutA = layout::ColumnMajor;
|
||||
using FragmentA = Array<half_t, 4>;
|
||||
|
||||
using ElementB = half_t;
|
||||
using LayoutB = layout::RowMajor;
|
||||
using FragmentB = Array<half_t, 4>;
|
||||
|
||||
using ElementC = float;
|
||||
using LayoutC = layout::RowMajor;
|
||||
using FragmentC = Array<float, 8>;
|
||||
|
||||
using Operator = OpMultiplyAdd;
|
||||
|
||||
/// Multiply-add
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
FragmentC &d,
|
||||
FragmentA const &a,
|
||||
FragmentB const &b,
|
||||
FragmentC const &c
|
||||
) {
|
||||
|
||||
#if defined(CUTLASS_ARCH_MMA_SM70_ENABLED)
|
||||
|
||||
unsigned const *A = reinterpret_cast<unsigned const *>(&a);
|
||||
unsigned const *B = reinterpret_cast<unsigned const *>(&b);
|
||||
float const *C = reinterpret_cast<float const *>(&c);
|
||||
float *D = reinterpret_cast<float *>(&d);
|
||||
|
||||
asm volatile("mma.sync.aligned.m8n8k4.col.row.f32.f16.f16.f32 {%0,%1,%2,%3,%4,%5,%6,%7}, {%8,%9}, {%10,%11}, "
|
||||
"{%12,%13,%14,%15,%16,%17,%18,%19};\n"
|
||||
: "=f"(D[0]),
|
||||
"=f"(D[1]),
|
||||
"=f"(D[2]),
|
||||
"=f"(D[3]),
|
||||
"=f"(D[4]),
|
||||
"=f"(D[5]),
|
||||
"=f"(D[6]),
|
||||
"=f"(D[7])
|
||||
: "r"(A[0]),
|
||||
"r"(A[1]),
|
||||
"r"(B[0]),
|
||||
"r"(B[1]),
|
||||
"f"(C[0]),
|
||||
"f"(C[1]),
|
||||
"f"(C[2]),
|
||||
"f"(C[3]),
|
||||
"f"(C[4]),
|
||||
"f"(C[5]),
|
||||
"f"(C[6]),
|
||||
"f"(C[7])
|
||||
);
|
||||
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
/// Matrix multiply-add operation: F32 = F16 * F16 + F32
|
||||
template <>
|
||||
struct Mma<
|
||||
gemm::GemmShape<8, 8, 4>,
|
||||
8,
|
||||
half_t,
|
||||
layout::RowMajor,
|
||||
half_t,
|
||||
layout::ColumnMajor,
|
||||
float,
|
||||
layout::RowMajor,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<8, 8, 4>;
|
||||
|
||||
using ElementA = half_t;
|
||||
using LayoutA = layout::RowMajor;
|
||||
using FragmentA = Array<half_t, 4>;
|
||||
|
||||
using ElementB = half_t;
|
||||
using LayoutB = layout::ColumnMajor;
|
||||
using FragmentB = Array<half_t, 4>;
|
||||
|
||||
using ElementC = float;
|
||||
using LayoutC = layout::RowMajor;
|
||||
using FragmentC = Array<float, 8>;
|
||||
|
||||
using Operator = OpMultiplyAdd;
|
||||
|
||||
/// Multiply-add
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
FragmentC &d,
|
||||
FragmentA const &a,
|
||||
FragmentB const &b,
|
||||
FragmentC const &c
|
||||
) {
|
||||
|
||||
#if defined(CUTLASS_ARCH_MMA_SM70_ENABLED)
|
||||
|
||||
unsigned const *A = reinterpret_cast<unsigned const *>(&a);
|
||||
unsigned const *B = reinterpret_cast<unsigned const *>(&b);
|
||||
float const *C = reinterpret_cast<float const *>(&c);
|
||||
float *D = reinterpret_cast<float *>(&d);
|
||||
|
||||
asm volatile("mma.sync.aligned.m8n8k4.row.col.f32.f16.f16.f32 {%0,%1,%2,%3,%4,%5,%6,%7}, {%8,%9}, {%10,%11}, "
|
||||
"{%12,%13,%14,%15,%16,%17,%18,%19};\n"
|
||||
: "=f"(D[0]),
|
||||
"=f"(D[1]),
|
||||
"=f"(D[2]),
|
||||
"=f"(D[3]),
|
||||
"=f"(D[4]),
|
||||
"=f"(D[5]),
|
||||
"=f"(D[6]),
|
||||
"=f"(D[7])
|
||||
: "r"(A[0]),
|
||||
"r"(A[1]),
|
||||
"r"(B[0]),
|
||||
"r"(B[1]),
|
||||
"f"(C[0]),
|
||||
"f"(C[1]),
|
||||
"f"(C[2]),
|
||||
"f"(C[3]),
|
||||
"f"(C[4]),
|
||||
"f"(C[5]),
|
||||
"f"(C[6]),
|
||||
"f"(C[7])
|
||||
);
|
||||
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
/// Matrix multiply-add operation: F32 = F16 * F16 + F32
|
||||
template <>
|
||||
struct Mma<
|
||||
gemm::GemmShape<8, 8, 4>,
|
||||
8,
|
||||
half_t,
|
||||
layout::RowMajor,
|
||||
half_t,
|
||||
layout::RowMajor,
|
||||
float,
|
||||
layout::RowMajor,
|
||||
OpMultiplyAdd> {
|
||||
|
||||
using Shape = gemm::GemmShape<8, 8, 4>;
|
||||
|
||||
using ElementA = half_t;
|
||||
using LayoutA = layout::RowMajor;
|
||||
using FragmentA = Array<half_t, 4>;
|
||||
|
||||
using ElementB = half_t;
|
||||
using LayoutB = layout::RowMajor;
|
||||
using FragmentB = Array<half_t, 4>;
|
||||
|
||||
using ElementC = float;
|
||||
using LayoutC = layout::RowMajor;
|
||||
using FragmentC = Array<float, 8>;
|
||||
|
||||
using Operator = OpMultiplyAdd;
|
||||
|
||||
/// Multiply-add
|
||||
CUTLASS_HOST_DEVICE
|
||||
void operator()(
|
||||
FragmentC &d,
|
||||
FragmentA const &a,
|
||||
FragmentB const &b,
|
||||
FragmentC const &c
|
||||
) {
|
||||
|
||||
#if defined(CUTLASS_ARCH_MMA_SM70_ENABLED)
|
||||
|
||||
unsigned const *A = reinterpret_cast<unsigned const *>(&a);
|
||||
unsigned const *B = reinterpret_cast<unsigned const *>(&b);
|
||||
float const *C = reinterpret_cast<float const *>(&c);
|
||||
float *D = reinterpret_cast<float *>(&d);
|
||||
|
||||
asm volatile("mma.sync.aligned.m8n8k4.row.row.f32.f16.f16.f32 {%0,%1,%2,%3,%4,%5,%6,%7}, {%8,%9}, {%10,%11}, "
|
||||
"{%12,%13,%14,%15,%16,%17,%18,%19};\n"
|
||||
: "=f"(D[0]),
|
||||
"=f"(D[1]),
|
||||
"=f"(D[2]),
|
||||
"=f"(D[3]),
|
||||
"=f"(D[4]),
|
||||
"=f"(D[5]),
|
||||
"=f"(D[6]),
|
||||
"=f"(D[7])
|
||||
: "r"(A[0]),
|
||||
"r"(A[1]),
|
||||
"r"(B[0]),
|
||||
"r"(B[1]),
|
||||
"f"(C[0]),
|
||||
"f"(C[1]),
|
||||
"f"(C[2]),
|
||||
"f"(C[3]),
|
||||
"f"(C[4]),
|
||||
"f"(C[5]),
|
||||
"f"(C[6]),
|
||||
"f"(C[7])
|
||||
);
|
||||
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Matrix multiply-add operation specialized for the entire warp
|
||||
template <
|
||||
typename LayoutA,
|
||||
typename LayoutB,
|
||||
typename ElementC,
|
||||
typename LayoutC,
|
||||
typename Operator
|
||||
>
|
||||
struct Mma<
|
||||
gemm::GemmShape<16, 16, 4>,
|
||||
32,
|
||||
half_t,
|
||||
LayoutA,
|
||||
half_t,
|
||||
LayoutB,
|
||||
ElementC,
|
||||
LayoutC,
|
||||
Operator
|
||||
> :
|
||||
public Mma<
|
||||
gemm::GemmShape<8, 8, 4>,
|
||||
8,
|
||||
half_t,
|
||||
LayoutA,
|
||||
half_t,
|
||||
LayoutB,
|
||||
ElementC,
|
||||
LayoutC,
|
||||
Operator> {
|
||||
|
||||
using Shape = gemm::GemmShape<16, 16, 4>;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespace arch
|
||||
} // namespace cutlass
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,119 @@
|
||||
/***************************************************************************************************
|
||||
* 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 Templates exposing SIMD operators
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../array.h"
|
||||
#include "../numeric_types.h"
|
||||
|
||||
namespace cutlass {
|
||||
namespace arch {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Element-wise operators
|
||||
//
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <typename T, int N>
|
||||
Array<T, N> operator*(Array<T, N> const &a, Array<T, N> const &b) {
|
||||
Array<T, N> d;
|
||||
CUTLASS_PRAGMA_UNROLL
|
||||
for (int i = 0; i < N; ++i) {
|
||||
d[i] = a[i] * b[i];
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <typename T, int N>
|
||||
Array<T, N> operator+(Array<T, N> const &a, Array<T, N> const &b) {
|
||||
Array<T, N> d;
|
||||
CUTLASS_PRAGMA_UNROLL
|
||||
for (int i = 0; i < N; ++i) {
|
||||
d[i] = a[i] + b[i];
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <typename T, int N>
|
||||
Array<T, N> operator-(Array<T, N> const &a, Array<T, N> const &b) {
|
||||
Array<T, N> d;
|
||||
CUTLASS_PRAGMA_UNROLL
|
||||
for (int i = 0; i < N; ++i) {
|
||||
d[i] = a[i] - b[i];
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Multiply-accumulate operators
|
||||
//
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <typename T, int N>
|
||||
Array<T, N> mac(Array<T, N> const &a, Array<T, N> const &b, Array<T, N> const &c) {
|
||||
Array<T, N> d;
|
||||
CUTLASS_PRAGMA_UNROLL
|
||||
for (int i = 0; i < N; ++i) {
|
||||
d[i] = a[i] * b[i] + c;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Dot product operator
|
||||
//
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <typename Element, typename Accumulator, int N>
|
||||
Accumulator dot(Array<T, N> const &a, Array<T, N> const &b, Accumulator accum) {
|
||||
CUTLASS_PRAGMA_UNROLL
|
||||
for (int i = 0; i < N; ++i) {
|
||||
accum += a[i] * b[i];
|
||||
}
|
||||
return accum;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespace arch
|
||||
} // namespace cutlass
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "simd_sm60.h"
|
||||
#include "simd_sm61.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -0,0 +1,110 @@
|
||||
/***************************************************************************************************
|
||||
* 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 Templates exposing SIMD operators for SM60
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "simd.h"
|
||||
|
||||
namespace cutlass {
|
||||
namespace arch {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Element-wise operators - specialized for half_t x 2
|
||||
//
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <>
|
||||
Array<half_t, 2> operator*(Array<half_t, 2> const &a, Array<half_t, 2> const &b) {
|
||||
Array<half_t, 2> d;
|
||||
|
||||
// TODO
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <>
|
||||
Array<half_t, 2> operator+(AArray<half_t, 2> const &a, Array<half_t, 2> const &b) {
|
||||
Array<half_t, 2> d;
|
||||
|
||||
// TODO
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <>
|
||||
Array<half_t, 2> operator-(Array<half_t, 2> const &a, Array<half_t, 2> const &b) {
|
||||
Array<T, N> d;
|
||||
|
||||
// TODO
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Multiply-accumulate operators - specialized for half_t x 2
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <>
|
||||
Array<half_t, 2> mac(Array<half_t, 2> const &a, Array<half_t, 2> const &b, Array<half_t, 2> const &c) {
|
||||
Array<half_t, 2> d;
|
||||
|
||||
// TODO
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Dot product operator - specialized for half_t <- (half_t * half_t) x 2 + half_t
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <>
|
||||
half_t dot(Array<half_t, 2> const &a, Array<half_t, 2> const &b, half_t accum) {
|
||||
|
||||
// TODO
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
/// Dot product operator - specialized for float <- (half_t * half_t) x 2 + float
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <>
|
||||
float dot(Array<half_t, 2> const &a, Array<half_t, 2> const &b, float accum) {
|
||||
|
||||
// TODO
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespace arch
|
||||
} // namespace cutlass
|
||||
@@ -0,0 +1,141 @@
|
||||
/***************************************************************************************************
|
||||
* 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 Templates exposing SIMD operators for SM60
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "simd.h"
|
||||
|
||||
namespace cutlass {
|
||||
namespace arch {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Dot product operator - specialized for int32_t <- (int8_t * int8_t) x 4 + int32_t
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <>
|
||||
int32_t dot(Array<int8_t, 4> const &a, Array<int8_t, 4> const &b, int32_t accum) {
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
/// Dot product operator - specialized for int32_t <- (uint8_t * int8_t) x 4 + int32_t
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <>
|
||||
int32_t dot(Array<uint8_t, 4> const &a, Array<int8_t, 4> const &b, int32_t accum) {
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
/// Dot product operator - specialized for int32_t <- (int8_t * uint8_t) x 4 + int32_t
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <>
|
||||
int32_t dot(Array<int8_t, 4> const &a, Array<uint8_t, 4> const &b, int32_t accum) {
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
/// Dot product operator - specialized for int32_t <- (uint8_t * uint8_t) x 4 + int32_t
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <>
|
||||
int32_t dot(Array<uint8_t, 4> const &a, Array<uint8_t, 4> const &b, int32_t accum) {
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Dot product operator - specialized for int32_t <- (int16_t * int8_t) x 2 + int32_t
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <>
|
||||
int32_t dot(Array<int16_t, 2> const &a, Array<int8_t, 2> const &b, int32_t accum) {
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
/// Dot product operator - specialized for int32_t <- (uint16_t * int8_t) x 2 + int32_t
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <>
|
||||
int32_t dot(Array<uint16_t, 2> const &a, Array<int8_t, 2> const &b, int32_t accum) {
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
/// Dot product operator - specialized for int32_t <- (int16_t * int8_t) x 2 + int32_t
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <>
|
||||
int32_t dot(Array<int16_t, 2> const &a, Array<uint8_t, 2> const &b, int32_t accum) {
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
/// Dot product operator - specialized for int32_t <- (uint16_t * int8_t) x 2 + int32_t
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <>
|
||||
int32_t dot(Array<uint16_t, 2> const &a, Array<uint8_t, 2> const &b, int32_t accum) {
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Dot product operator - specialized for int32_t <- (int16_t * int16_t) x 2 + int32_t
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <>
|
||||
int32_t dot(Array<int16_t, 2> const &a, Array<int16_t, 2> const &b, int32_t accum) {
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
/// Dot product operator - specialized for int32_t <- (uint16_t * int16_t) x 2 + int32_t
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <>
|
||||
int32_t dot(Array<uint16_t, 2> const &a, Array<int16_t, 2> const &b, int32_t accum) {
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
/// Dot product operator - specialized for int32_t <- (int16_t * int16_t) x 2 + int32_t
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <>
|
||||
int32_t dot(Array<int16_t, 2> const &a, Array<uint16_t, 2> const &b, int32_t accum) {
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
/// Dot product operator - specialized for int32_t <- (uint16_t * int16_t) x 2 + int32_t
|
||||
CUTLASS_HOST_DEVICE
|
||||
template <>
|
||||
int32_t dot(Array<uint16_t, 2> const &a, Array<uint16_t, 2> const &b, int32_t accum) {
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespace arch
|
||||
} // namespace cutlass
|
||||
@@ -0,0 +1,222 @@
|
||||
/***************************************************************************************************
|
||||
* 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 Templates exposing architecture support for warp matrix multiply-add (WMMA) operations
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// CUTLASS WMMA does not support clang at present.
|
||||
#if !defined(__clang__)
|
||||
|
||||
#if (__CUDACC_VER_MAJOR__ >= 9)
|
||||
#if (!defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 700))
|
||||
#define CUTLASS_ARCH_WMMA_ENABLED
|
||||
#define CUTLASS_ARCH_WMMA_SM70_ENABLED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (__CUDACC_VER_MAJOR__ >= 10)
|
||||
#if (!defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 720))
|
||||
#define CUTLASS_ARCH_INTEGER_MATRIX_MULTIPLY_ENABLED
|
||||
#define CUTLASS_ARCH_WMMA_SM72_ENABLED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (__CUDACC_VER_MAJOR__ >= 10)
|
||||
#if (!defined(__CUDA_ARCH__) || (__CUDA_ARCH__ >= 750))
|
||||
#define CUTLASS_SUBBYTE_INTEGER_MATRIX_MULTIPLY_ENABLED
|
||||
#define CUTLASS_ARCH_WMMA_SM75_ENABLED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif //__clang__
|
||||
|
||||
#if defined(CUTLASS_ARCH_WMMA_ENABLED)
|
||||
|
||||
#include <mma.h>
|
||||
#include "cutlass/arch/mma.h"
|
||||
#include "cutlass/array.h"
|
||||
#include "cutlass/numeric_types.h"
|
||||
#include "cutlass/gemm/gemm.h"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace cutlass {
|
||||
namespace arch {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// MemoryKind class (Shared vs. Global memory)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
enum class MemoryKind {
|
||||
kShared, // Data resides in shared memory
|
||||
kGlobal // Data resides in global memory
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// WarpParams holds architecture-specific constants
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
struct WarpParams {
|
||||
static int const kThreadsPerWarp = 32;
|
||||
static int const kQuadsPerWarp = 8;
|
||||
static int const kThreadsPerQuad = 4;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Statically maps cutlass data types => nvcuda::wmma data types
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename Type_>
|
||||
struct CutlassToWmmaDataType{
|
||||
using Type = Type_;
|
||||
};
|
||||
|
||||
/// Statically maps cutlass::half_t => __half
|
||||
template<>
|
||||
struct CutlassToWmmaDataType<cutlass::half_t> {
|
||||
using Type = __half;
|
||||
};
|
||||
|
||||
|
||||
/// Statically maps int8_t => char
|
||||
template<>
|
||||
struct CutlassToWmmaDataType<int8_t> {
|
||||
using Type = signed char;
|
||||
};
|
||||
|
||||
/// Statically maps uint8_t => char
|
||||
template<>
|
||||
struct CutlassToWmmaDataType<uint8_t> {
|
||||
using Type = unsigned char;
|
||||
};
|
||||
|
||||
/// Statically maps int32_t => int
|
||||
template<>
|
||||
struct CutlassToWmmaDataType<int32_t> {
|
||||
using Type = int;
|
||||
};
|
||||
|
||||
#if defined(CUTLASS_SUBBYTE_INTEGER_MATRIX_MULTIPLY_ENABLED)
|
||||
/// Statically maps cutlass::int4b_t => experimental::precision::s4
|
||||
template<>
|
||||
struct CutlassToWmmaDataType<cutlass::int4b_t> {
|
||||
using Type = nvcuda::wmma::experimental::precision::s4;
|
||||
};
|
||||
|
||||
/// Statically maps cutlass::uint4b_t => experimental::precision::s4
|
||||
template<>
|
||||
struct CutlassToWmmaDataType<cutlass::uint4b_t> {
|
||||
using Type = nvcuda::wmma::experimental::precision::u4;
|
||||
};
|
||||
|
||||
/// Statically maps cutlass::uint1b_t => experimental::precision::b1
|
||||
template<>
|
||||
struct CutlassToWmmaDataType<cutlass::uint1b_t> {
|
||||
using Type = nvcuda::wmma::experimental::precision::b1;
|
||||
};
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Statically maps cutlass::layout => nvcuda::wmma layout tags
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename Layout_>
|
||||
struct CutlassToWmmaLayout {
|
||||
};
|
||||
|
||||
/// Statically maps cutlass::layout::RowMajor => nvcuda::wmma::row_major layout tags
|
||||
template <>
|
||||
struct CutlassToWmmaLayout<cutlass::layout::RowMajor> {
|
||||
using Layout = nvcuda::wmma::row_major;
|
||||
static nvcuda::wmma::layout_t const value = nvcuda::wmma::layout_t::mem_row_major;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Statically maps cutlass::layout::RowMajor => nvcuda::wmma::row_major layout tags
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <>
|
||||
struct CutlassToWmmaLayout<cutlass::layout::ColumnMajor> {
|
||||
using Layout = nvcuda::wmma::col_major;
|
||||
static nvcuda::wmma::layout_t const value = nvcuda::wmma::layout_t::mem_col_major;
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Statically maps nvcuda::wmma data types => cutlass data types
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename Type_>
|
||||
struct WmmaToCutlassDataType{
|
||||
using Type = Type_;
|
||||
};
|
||||
|
||||
/// Statically maps __half => cutlass::half_t
|
||||
template<>
|
||||
struct WmmaToCutlassDataType<__half> {
|
||||
using Type = cutlass::half_t;
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// WMMA template structure defines nvcuda::wmma::fragments and static assertion chaeks
|
||||
// for a specific template paramterized data type (Element[A|B|C]), layout (Layout[A|B|C]),
|
||||
// and native wmma size (Shape)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Shape_, ///< Size of the matrix product (concept: GemmShape)
|
||||
typename ElementA_, ///< Data type of A elements
|
||||
typename LayoutA_, ///< Layout of A matrix (concept: MatrixLayout)
|
||||
typename ElementB_, ///< Data type of B elements
|
||||
typename LayoutB_, ///< Layout of B matrix (concept: MatrixLayout)
|
||||
typename ElementC_, ///< Element type of C matrix
|
||||
typename LayoutC_, /// Layout of C matrix (concept: MatrixLayout)
|
||||
typename Operator_ = cutlass::arch::OpMultiplyAdd ///< Inner product operator (multiply-add, xor.popc)
|
||||
>
|
||||
struct Wmma;
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
} // namespace arch
|
||||
} // namespace cutlass
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Specializations for each compute capability
|
||||
//
|
||||
#ifdef CUTLASS_ARCH_WMMA_SM70_ENABLED
|
||||
#include "cutlass/arch/wmma_sm70.h"
|
||||
#endif
|
||||
|
||||
#ifdef CUTLASS_ARCH_WMMA_SM72_ENABLED
|
||||
#include "cutlass/arch/wmma_sm72.h"
|
||||
#endif
|
||||
|
||||
#ifdef CUTLASS_ARCH_WMMA_SM75_ENABLED
|
||||
#include "cutlass/arch/wmma_sm75.h"
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif //CUTLASS_ARCH_WMMA_ENABLED
|
||||
@@ -0,0 +1,105 @@
|
||||
/***************************************************************************************************
|
||||
* 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 Templates exposing warp matrix multiply-add (WMMA) operations
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "cutlass/arch/wmma.h"
|
||||
|
||||
namespace cutlass {
|
||||
namespace arch {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// WMMA structures to enclose * PTX * instruction string
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// WMMA PTX string load for A, B, and C matrices
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Shape_, ///< Size of the matrix product (concept: GemmShape)
|
||||
typename Element_, ///< Data type of elements
|
||||
typename Layout_, ///< Layout of matrix (concept: MatrixLayout)
|
||||
MemoryKind Memory = MemoryKind::kShared ///< Data resides in shared or global memory
|
||||
>
|
||||
struct PtxWmmaLoadA;
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <
|
||||
typename Shape_, ///< Size of the matrix product (concept: GemmShape)
|
||||
typename Element_, ///< Data type of elements
|
||||
typename Layout_, ///< Layout of matrix (concept: MatrixLayout)
|
||||
MemoryKind Memory = MemoryKind::kShared ///< Data resides in shared or global memory
|
||||
>
|
||||
struct PtxWmmaLoadB;
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <
|
||||
typename Shape_, ///< Size of the matrix product (concept: GemmShape)
|
||||
typename Element_, ///< Data type of elements
|
||||
typename Layout_, ///< Layout of matrix (concept: MatrixLayout)
|
||||
MemoryKind Memory = MemoryKind::kShared ///< Data resides in shared or global memory
|
||||
>
|
||||
struct PtxWmmaLoadC;
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// WMMA Matrix multiply-add operation
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Shape_, ///< Size of the matrix product (concept: GemmShape)
|
||||
typename ElementA_, ///< Data type of A elements
|
||||
typename LayoutA_, ///< Layout of A matrix (concept: MatrixLayout)
|
||||
typename ElementB_, ///< Data type of B elements
|
||||
typename LayoutB_, ///< Layout of B matrix (concept: MatrixLayout)
|
||||
typename ElementC_, ///< Element type of C matrix
|
||||
typename LayoutC_, /// Layout of C matrix (concept: MatrixLayout)
|
||||
typename Operator = cutlass::arch::OpMultiplyAdd ///< Inner product operator (multiply-add, xor.popc)
|
||||
>
|
||||
struct PtxWmma;
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// WMMA store for matrix D
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Shape_, ///< Size of the matrix product (concept: GemmShape)
|
||||
typename Element_, ///< Data type of elements
|
||||
typename Layout_, ///< Layout of matrix (concept: MatrixLayout)
|
||||
MemoryKind Memory = MemoryKind::kShared ///< Data resides in shared or global memory
|
||||
>
|
||||
struct PtxWmmaStoreD;
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespace arch
|
||||
} // namespace cutlass
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -0,0 +1,125 @@
|
||||
/***************************************************************************************************
|
||||
* 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 Matrix multiply
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include "cutlass/layout/matrix.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace cutlass {
|
||||
namespace arch {
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// WMMA template structure defines nvcuda::wmma::fragments and static assert for
|
||||
// wmma native instruction sizes supported for half
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Shape_,
|
||||
typename LayoutA_,
|
||||
typename LayoutB_,
|
||||
typename ElementC_,
|
||||
typename LayoutC_>
|
||||
struct Wmma<
|
||||
Shape_, ///< Size of the matrix product (concept: GemmShape)
|
||||
cutlass::half_t, ///< ElementA
|
||||
LayoutA_, ///< LayoutA
|
||||
cutlass::half_t, ///< ElementB
|
||||
LayoutB_, ///< LayoutB
|
||||
ElementC_, ///< ElementC
|
||||
LayoutC_, ///< LayoutC
|
||||
cutlass::arch::OpMultiplyAdd ///< Operator (multiply-add, xor.popc)
|
||||
> {
|
||||
|
||||
#if defined(CUTLASS_ARCH_WMMA_SM70_ENABLED)
|
||||
using Shape = Shape_;
|
||||
using ElementA = cutlass::half_t;
|
||||
using LayoutA = LayoutA_;
|
||||
using ElementB = cutlass::half_t;
|
||||
using LayoutB = LayoutB_;
|
||||
using ElementC = ElementC_;
|
||||
using LayoutC = LayoutC_;
|
||||
using Operator = cutlass::arch::OpMultiplyAdd;
|
||||
|
||||
// check supported wmma shape for the given multiplicand data types
|
||||
static_assert(
|
||||
platform::is_same<cutlass::gemm::GemmShape<16, 16, 16>, Shape>::value ||
|
||||
platform::is_same<cutlass::gemm::GemmShape< 8, 32, 16>, Shape>::value ||
|
||||
platform::is_same<cutlass::gemm::GemmShape<32, 8, 16>, Shape>::value,
|
||||
"Supported list of wmma operator shape for f16 multiplicands are: 16x16x16, 8x328x16, and 32x8x16");
|
||||
|
||||
// check supported wmma output data type for the given multiplicand data types
|
||||
static_assert(
|
||||
platform::is_same<cutlass::half_t, ElementC>::value || platform::is_same<float, ElementC>::value,
|
||||
"Supported of wmma output data type for f16 multiplicands are: f16 and f32");
|
||||
|
||||
// Wmma Fragment
|
||||
using FragmentA = nvcuda::wmma::fragment<
|
||||
nvcuda::wmma::matrix_a,
|
||||
Shape::kM,
|
||||
Shape::kN,
|
||||
Shape::kK,
|
||||
typename CutlassToWmmaDataType<ElementA>::Type,
|
||||
typename CutlassToWmmaLayout<LayoutA>::Layout>;
|
||||
|
||||
using FragmentB = nvcuda::wmma::fragment<
|
||||
nvcuda::wmma::matrix_b,
|
||||
Shape::kM,
|
||||
Shape::kN,
|
||||
Shape::kK,
|
||||
typename CutlassToWmmaDataType<ElementB>::Type,
|
||||
typename CutlassToWmmaLayout<LayoutB>::Layout>;
|
||||
|
||||
using FragmentC = nvcuda::wmma::fragment<
|
||||
nvcuda::wmma::accumulator,
|
||||
Shape::kM,
|
||||
Shape::kN,
|
||||
Shape::kK,
|
||||
typename CutlassToWmmaDataType<ElementC>::Type>;
|
||||
|
||||
/// Performs a nvcuda::wmma matrix multiply-accumulate operation
|
||||
CUTLASS_DEVICE
|
||||
void operator()(
|
||||
FragmentC &D,
|
||||
FragmentA const &A,
|
||||
FragmentB const &B,
|
||||
FragmentC const &C) const {
|
||||
|
||||
nvcuda::wmma::mma_sync(D, A, B, C);
|
||||
}
|
||||
#else
|
||||
static_assert(false, "wmma.mma.sync for floating point multiplicands is avialable only for SM70 and beyond");
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
} // namespace arch
|
||||
} // namespace cutlass
|
||||
@@ -0,0 +1,198 @@
|
||||
/***************************************************************************************************
|
||||
* 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 Matrix multiply
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include "cutlass/layout/matrix.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace cutlass {
|
||||
namespace arch {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// WMMA template structure defines nvcuda::wmma::fragments and static assert for
|
||||
// wmma native instruction sizes supported for int8_t
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Shape_,
|
||||
typename LayoutA_,
|
||||
typename LayoutB_,
|
||||
typename LayoutC_>
|
||||
struct Wmma<
|
||||
Shape_, ///< Size of the matrix product (concept: GemmShape)
|
||||
int8_t, ///< ElementA
|
||||
LayoutA_, ///< LayoutA
|
||||
int8_t, ///< ElementB
|
||||
LayoutB_, ///< LayoutB
|
||||
int32_t, ///< ElementC
|
||||
LayoutC_, ///< LayoutC
|
||||
cutlass::arch::OpMultiplyAdd ///< Operator (multiply-add, xor.popc)
|
||||
> {
|
||||
#if defined(CUTLASS_ARCH_WMMA_SM72_ENABLED)
|
||||
using Shape = Shape_;
|
||||
using ElementA = int8_t;
|
||||
using LayoutA = LayoutA_;
|
||||
using ElementB = int8_t;
|
||||
using LayoutB = LayoutB_;
|
||||
using ElementC = int32_t;
|
||||
using LayoutC = LayoutC_;
|
||||
using Operator = cutlass::arch::OpMultiplyAdd;
|
||||
|
||||
// check supported wmma shape for the given multiplicand data types
|
||||
static_assert(
|
||||
platform::is_same<cutlass::gemm::GemmShape<16, 16, 16>, Shape>::value ||
|
||||
platform::is_same<cutlass::gemm::GemmShape< 8, 32, 16>, Shape>::value ||
|
||||
platform::is_same<cutlass::gemm::GemmShape<32, 8, 16>, Shape>::value,
|
||||
"Supported list of wmma operator shape for s8 multiplicands are: 16x16x16, 8x328x16, and 32x8x16");
|
||||
|
||||
|
||||
// Wmma Fragment
|
||||
using FragmentA = nvcuda::wmma::fragment<
|
||||
nvcuda::wmma::matrix_a,
|
||||
Shape::kM,
|
||||
Shape::kN,
|
||||
Shape::kK,
|
||||
typename CutlassToWmmaDataType<ElementA>::Type,
|
||||
typename CutlassToWmmaLayout<LayoutA>::Layout>;
|
||||
|
||||
using FragmentB = nvcuda::wmma::fragment<
|
||||
nvcuda::wmma::matrix_b,
|
||||
Shape::kM,
|
||||
Shape::kN,
|
||||
Shape::kK,
|
||||
typename CutlassToWmmaDataType<ElementB>::Type,
|
||||
typename CutlassToWmmaLayout<LayoutB>::Layout>;
|
||||
|
||||
using FragmentC = nvcuda::wmma::fragment<
|
||||
nvcuda::wmma::accumulator,
|
||||
Shape::kM,
|
||||
Shape::kN,
|
||||
Shape::kK,
|
||||
typename CutlassToWmmaDataType<ElementC>::Type>;
|
||||
|
||||
/// Performs a nvcuda::wmma matrix multiply-accumulate operation
|
||||
CUTLASS_DEVICE
|
||||
void operator()(
|
||||
FragmentC &D,
|
||||
FragmentA const &A,
|
||||
FragmentB const &B,
|
||||
FragmentC const &C) const {
|
||||
|
||||
nvcuda::wmma::mma_sync(D, A, B, C);
|
||||
}
|
||||
|
||||
#else
|
||||
static_assert(false, "wmma.mma.sync interger type multiplicands is avialable only for SM72 and beyond");
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// WMMA template structure defines nvcuda::wmma::fragments and static assert for
|
||||
// wmma native instruction sizes supported for uint8_t
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Shape_,
|
||||
typename LayoutA_,
|
||||
typename LayoutB_,
|
||||
typename LayoutC_>
|
||||
struct Wmma<
|
||||
Shape_, ///< Size of the matrix product (concept: GemmShape)
|
||||
uint8_t, ///< ElementA
|
||||
LayoutA_, ///< LayoutA
|
||||
uint8_t, ///< ElementB
|
||||
LayoutB_, ///< LayoutB
|
||||
int32_t, ///< ElementC
|
||||
LayoutC_, ///< LayoutC
|
||||
cutlass::arch::OpMultiplyAdd ///< Operator (multiply-add, xor.popc)
|
||||
> {
|
||||
#if defined(CUTLASS_ARCH_WMMA_SM72_ENABLED)
|
||||
using Shape = Shape_;
|
||||
using ElementA = uint8_t;
|
||||
using LayoutA = LayoutA_;
|
||||
using ElementB = uint8_t;
|
||||
using LayoutB = LayoutB_;
|
||||
using ElementC = int32_t;
|
||||
using LayoutC = LayoutC_;
|
||||
using Operator = cutlass::arch::OpMultiplyAdd;
|
||||
|
||||
// check supported wmma shape for the given multiplicand data types
|
||||
static_assert(
|
||||
platform::is_same<cutlass::gemm::GemmShape<16, 16, 16>, Shape>::value ||
|
||||
platform::is_same<cutlass::gemm::GemmShape< 8, 32, 16>, Shape>::value ||
|
||||
platform::is_same<cutlass::gemm::GemmShape<32, 8, 16>, Shape>::value,
|
||||
"Supported list of wmma operator shape for u8 multiplicands are: 16x16x16, 8x328x16, and 32x8x16");
|
||||
|
||||
// Wmma Fragment
|
||||
using FragmentA = nvcuda::wmma::fragment<
|
||||
nvcuda::wmma::matrix_a,
|
||||
Shape::kM,
|
||||
Shape::kN,
|
||||
Shape::kK,
|
||||
typename CutlassToWmmaDataType<ElementA>::Type,
|
||||
typename CutlassToWmmaLayout<LayoutA>::Layout>;
|
||||
|
||||
using FragmentB = nvcuda::wmma::fragment<
|
||||
nvcuda::wmma::matrix_b,
|
||||
Shape::kM,
|
||||
Shape::kN,
|
||||
Shape::kK,
|
||||
typename CutlassToWmmaDataType<ElementB>::Type,
|
||||
typename CutlassToWmmaLayout<LayoutB>::Layout>;
|
||||
|
||||
using FragmentC = nvcuda::wmma::fragment<
|
||||
nvcuda::wmma::accumulator,
|
||||
Shape::kM,
|
||||
Shape::kN,
|
||||
Shape::kK,
|
||||
typename CutlassToWmmaDataType<ElementC>::Type>;
|
||||
|
||||
/// Performs a nvcuda::wmma matrix multiply-accumulate operation
|
||||
CUTLASS_DEVICE
|
||||
void operator()(
|
||||
FragmentC &D,
|
||||
FragmentA const &A,
|
||||
FragmentB const &B,
|
||||
FragmentC const &C) const {
|
||||
|
||||
nvcuda::wmma::mma_sync(D, A, B, C);
|
||||
}
|
||||
|
||||
#else
|
||||
static_assert(false, "wmma.mma.sync interger type multiplicands is avialable only for SM72 and beyond");
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
} // namespace arch
|
||||
} // namespace cutlass
|
||||
@@ -0,0 +1,196 @@
|
||||
/***************************************************************************************************
|
||||
* 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 Matrix multiply
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include "cutlass/layout/matrix.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
namespace cutlass {
|
||||
namespace arch {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// WMMA template structure defines nvcuda::wmma::fragments and static assert for
|
||||
// wmma native instruction sizes supported for cutlass::int4b_t (experimental::s4).
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Shape_,
|
||||
typename LayoutA_,
|
||||
typename LayoutB_,
|
||||
typename LayoutC_>
|
||||
struct Wmma<
|
||||
Shape_, ///< Size of the matrix product (concept: GemmShape)
|
||||
cutlass::int4b_t, ///< ElementA
|
||||
LayoutA_, ///< LayoutA
|
||||
cutlass::int4b_t, ///< ElementB
|
||||
LayoutB_, ///< LayoutB
|
||||
int32_t, ///< ElementC
|
||||
LayoutC_, ///< LayoutC
|
||||
cutlass::arch::OpMultiplyAdd ///< Operator (multiply-add, xor.popc)
|
||||
> {
|
||||
#if defined(CUTLASS_ARCH_WMMA_SM75_ENABLED)
|
||||
using Shape = Shape_;
|
||||
using ElementA = cutlass::int4b_t;
|
||||
using LayoutA = LayoutA_;
|
||||
using ElementB = cutlass::int4b_t;
|
||||
using LayoutB = LayoutB_;
|
||||
using ElementC = int32_t;
|
||||
using LayoutC = LayoutC_;
|
||||
using Operator = cutlass::arch::OpMultiplyAdd;
|
||||
|
||||
// check supported wmma shape for the given multiplicand data types
|
||||
static_assert(
|
||||
platform::is_same<cutlass::gemm::GemmShape<8, 8, 32>, Shape>::value,
|
||||
"Supported list of wmma operator shape for s8 multiplicands is: 8x8x32");
|
||||
|
||||
|
||||
// Wmma Fragment
|
||||
using FragmentA = nvcuda::wmma::fragment<
|
||||
nvcuda::wmma::matrix_a,
|
||||
Shape::kM,
|
||||
Shape::kN,
|
||||
Shape::kK,
|
||||
typename CutlassToWmmaDataType<ElementA>::Type,
|
||||
typename CutlassToWmmaLayout<LayoutA>::Layout>;
|
||||
|
||||
using FragmentB = nvcuda::wmma::fragment<
|
||||
nvcuda::wmma::matrix_b,
|
||||
Shape::kM,
|
||||
Shape::kN,
|
||||
Shape::kK,
|
||||
typename CutlassToWmmaDataType<ElementB>::Type,
|
||||
typename CutlassToWmmaLayout<LayoutB>::Layout>;
|
||||
|
||||
using FragmentC = nvcuda::wmma::fragment<
|
||||
nvcuda::wmma::accumulator,
|
||||
Shape::kM,
|
||||
Shape::kN,
|
||||
Shape::kK,
|
||||
typename CutlassToWmmaDataType<ElementC>::Type>;
|
||||
|
||||
/// Performs a nvcuda::wmma matrix multiply-accumulate operation
|
||||
CUTLASS_DEVICE
|
||||
void operator()(
|
||||
FragmentC &D,
|
||||
FragmentA const &A,
|
||||
FragmentB const &B,
|
||||
FragmentC const &C) const {
|
||||
nvcuda::wmma::mma_sync(D, A, B, C);
|
||||
}
|
||||
|
||||
#else
|
||||
static_assert(false, "wmma.mma.sync interger type multiplicands is avialable only for SM75 and beyond");
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// WMMA template structure defines nvcuda::wmma::fragments and static assert for
|
||||
// wmma native instruction sizes supported for cutlass::uint1b_t (experimental::b1)
|
||||
// (nvcuda::wmma targetting SASS instruction BMMA)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Shape_,
|
||||
typename LayoutA_,
|
||||
typename LayoutB_,
|
||||
typename LayoutC_>
|
||||
struct Wmma<
|
||||
Shape_, ///< Size of the matrix product (concept: GemmShape)
|
||||
cutlass::uint1b_t, ///< ElementA
|
||||
LayoutA_, ///< LayoutA
|
||||
cutlass::uint1b_t, ///< ElementB
|
||||
LayoutB_, ///< LayoutB
|
||||
int32_t, ///< ElementC
|
||||
LayoutC_, ///< LayoutC
|
||||
cutlass::arch::OpXorPopc ///< Operator (multiply-add, xor.popc)
|
||||
> {
|
||||
#if defined(CUTLASS_ARCH_WMMA_SM75_ENABLED)
|
||||
using Shape = Shape_;
|
||||
using ElementA = cutlass::uint1b_t;
|
||||
using LayoutA = LayoutA_;
|
||||
using ElementB = cutlass::uint1b_t;
|
||||
using LayoutB = LayoutB_;
|
||||
using ElementC = int32_t;
|
||||
using LayoutC = LayoutC_;
|
||||
using Operator = cutlass::arch::OpXorPopc;
|
||||
|
||||
// check supported wmma shape for the given multiplicand data types
|
||||
static_assert(
|
||||
platform::is_same<cutlass::gemm::GemmShape<8, 8, 128>, Shape>::value,
|
||||
"Supported list of wmma operator shape for b1 multiplicands is: 8x8x128");
|
||||
|
||||
|
||||
// Wmma Fragment
|
||||
using FragmentA = nvcuda::wmma::fragment<
|
||||
nvcuda::wmma::matrix_a,
|
||||
Shape::kM,
|
||||
Shape::kN,
|
||||
Shape::kK,
|
||||
typename CutlassToWmmaDataType<ElementA>::Type,
|
||||
typename CutlassToWmmaLayout<LayoutA>::Layout>;
|
||||
|
||||
using FragmentB = nvcuda::wmma::fragment<
|
||||
nvcuda::wmma::matrix_b,
|
||||
Shape::kM,
|
||||
Shape::kN,
|
||||
Shape::kK,
|
||||
typename CutlassToWmmaDataType<ElementB>::Type,
|
||||
typename CutlassToWmmaLayout<LayoutB>::Layout>;
|
||||
|
||||
using FragmentC = nvcuda::wmma::fragment<
|
||||
nvcuda::wmma::accumulator,
|
||||
Shape::kM,
|
||||
Shape::kN,
|
||||
Shape::kK,
|
||||
typename CutlassToWmmaDataType<ElementC>::Type>;
|
||||
|
||||
/// Performs a nvcuda::wmma matrix multiply-accumulate operation
|
||||
CUTLASS_DEVICE
|
||||
void operator()(
|
||||
FragmentC &D,
|
||||
FragmentA const &A,
|
||||
FragmentB const &B,
|
||||
FragmentC const &C) const {
|
||||
|
||||
nvcuda::wmma::bmma_sync(D, A, B, C, nvcuda::wmma::experimental::bmmaBitOpXOR,
|
||||
nvcuda::wmma::experimental::bmmaAccumulateOpPOPC);
|
||||
}
|
||||
|
||||
#else
|
||||
static_assert(false, "wmma.mma.sync interger type multiplicands is avialable only for SM75 and beyond");
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
} // namespace arch
|
||||
} // namespace cutlass
|
||||
Reference in New Issue
Block a user