CUTLASS 1.2
This commit is contained in:
@@ -29,6 +29,7 @@ set(CUTLASS_PERF_TEST_HEADERS
|
||||
performance_result.h
|
||||
gemm/cublas_dispatch.h
|
||||
gemm/cutlass_dispatch.h
|
||||
gemm/cutlass_dispatch_splitK_PI.h
|
||||
gemm/gemm_perf_testbed.h
|
||||
gemm/gemm_profiler.h
|
||||
)
|
||||
@@ -36,9 +37,11 @@ set(CUTLASS_PERF_TEST_HEADERS
|
||||
set(CUTLASS_PERF_TEST_SOURCES
|
||||
cutlass_perf_test.cu
|
||||
gemm/sgemm.cu
|
||||
gemm/sgemm_splitK.cu
|
||||
gemm/dgemm.cu
|
||||
gemm/hgemm.cu
|
||||
gemm/igemm.cu
|
||||
gemm/igemm_splitK.cu
|
||||
gemm/wmma_gemm.cu
|
||||
gemm/wmma_binary_gemm.cu
|
||||
gemm/wmma_integer_gemm.cu
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright (c) 2017-2018, 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 {nv-internal-release}
|
||||
|
||||
#if (defined(__CUDACC__) && (!defined(__CUDA_ARCH__) || __CUDA_ARCH__ >= 750))
|
||||
#pragma warning( disable : 4503)
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "cutlass/gemm/gemm.h"
|
||||
#include "cutlass/gemm/bmma_gemm_traits.h"
|
||||
#include "tools/test/perf/cutlass_perf_test.h"
|
||||
#include "tools/test/perf/gemm/gemm_profiler.h"
|
||||
#include "tools/test/perf/gemm/cutlass_dispatch.h"
|
||||
#include "tools/test/perf/gemm/gemm_perf_testbed.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Traits>
|
||||
struct BmmaGemmDispatch {
|
||||
|
||||
typedef cutlass::gemm::Gemm<Traits> Gemm;
|
||||
|
||||
typedef typename Gemm::Params Params;
|
||||
|
||||
/// Indicate warp-level GEMM
|
||||
static bool const kThreadMultiplyAdd = false;
|
||||
|
||||
static bool const kRunCuBLAS = false;
|
||||
|
||||
static cutlass::MatrixLayout::Kind const kLayoutA = Traits::kLayoutA;
|
||||
static cutlass::MatrixLayout::Kind const kLayoutB = Traits::kLayoutB;
|
||||
|
||||
//
|
||||
// Data members
|
||||
//
|
||||
|
||||
/// Params argument
|
||||
Params params;
|
||||
|
||||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
BmmaGemmDispatch() {}
|
||||
|
||||
/// Initializes params object
|
||||
BmmaGemmDispatch(int m, int n, int k, int alpha,
|
||||
cutlass::Vector<cutlass::bin1_t, 32> const* d_a, int lda,
|
||||
cutlass::Vector<cutlass::bin1_t, 32> const* d_b, int ldb, int beta,
|
||||
int const* d_c, int ldc, int* d_d, int ldd) {
|
||||
|
||||
params.initialize(m, n, k * 32, alpha, d_a, lda, d_b, ldb, beta, d_c, ldc, d_d, ldd);
|
||||
}
|
||||
|
||||
/// Initializes params object
|
||||
BmmaGemmDispatch(Params const& _params) : params(_params) {}
|
||||
|
||||
/// Launches kernel
|
||||
cudaError_t operator()() { return Gemm::launch(params); }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace perf {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int profile_bmma_gemm(TestbenchOutput<GemmProblem> &output, TestbenchOptions const &options, Config const &config) {
|
||||
typedef perf::GemmProfiler<cutlass::Vector<cutlass::bin1_t, 32>, cutlass::Vector<cutlass::bin1_t, 32>, int, int, int> GemmProfiler;
|
||||
|
||||
int results = 0;
|
||||
|
||||
{
|
||||
|
||||
typedef cutlass::gemm::BmmaGemmTraits<cutlass::Shape<1024, 128, 128>,
|
||||
cutlass::Shape<1024, 32, 32>,
|
||||
cutlass::MatrixLayout::kRowMajor,
|
||||
cutlass::MatrixLayout::kColumnMajor>
|
||||
BmmaGemmTraits;
|
||||
|
||||
typedef BmmaGemmDispatch<BmmaGemmTraits> Dispatch;
|
||||
|
||||
results |= profile_gemm<Dispatch, GemmProfiler>(output, "bmma_gemm_tn", options, config);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct BmmaGemmRegistrar {
|
||||
BmmaGemmRegistrar() { RegisterGemmProfileFunc(profile_bmma_gemm); }
|
||||
};
|
||||
|
||||
volatile BmmaGemmRegistrar _BmmaGemmRegistrar;
|
||||
|
||||
} // namespace perf
|
||||
|
||||
#endif // if (defined(__CUDACC__) && (!defined(__CUDA_ARCH__) || __CUDA_ARCH__ >= 750)
|
||||
@@ -89,4 +89,76 @@ struct CublasGemmDispatch {
|
||||
}
|
||||
};
|
||||
|
||||
/// Dispatcher for batched strided cuBLAS kernels
|
||||
template <typename AType, typename BType, typename CType, typename Accumulator, typename Scalar>
|
||||
struct CublasBatchedStridedGemmDispatch {
|
||||
/// Type used for device-side allocations
|
||||
typedef typename cutlass::TypeTraits<AType>::device_type ADeviceType;
|
||||
typedef typename cutlass::TypeTraits<BType>::device_type BDeviceType;
|
||||
typedef typename cutlass::TypeTraits<CType>::device_type CDeviceType;
|
||||
typedef typename cutlass::TypeTraits<Accumulator>::device_type AccumulatorDeviceType;
|
||||
typedef typename cutlass::TypeTraits<Scalar>::device_type ScalarDeviceType;
|
||||
|
||||
static cublasOperation_t convert(cutlass::MatrixLayout::Kind layout) {
|
||||
switch (layout) {
|
||||
case cutlass::MatrixLayout::kRowMajor:
|
||||
return CUBLAS_OP_T;
|
||||
case cutlass::MatrixLayout::kColumnMajor:
|
||||
return CUBLAS_OP_N;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return CUBLAS_OP_N;
|
||||
}
|
||||
|
||||
/// Launches a cuBLAS GEMM kernel
|
||||
cublasStatus_t operator()(cublasHandle_t handle,
|
||||
cutlass::MatrixLayout::Kind layout_a,
|
||||
cutlass::MatrixLayout::Kind layout_b,
|
||||
int m,
|
||||
int n,
|
||||
int k,
|
||||
Scalar alpha,
|
||||
const ADeviceType *A,
|
||||
int lda,
|
||||
long long int batch_stride_A,
|
||||
const BDeviceType *B,
|
||||
int ldb,
|
||||
long long int batch_stride_B,
|
||||
Scalar beta,
|
||||
CDeviceType *C,
|
||||
int ldc,
|
||||
long long int batch_stride_C,
|
||||
int batch_count,
|
||||
cublasGemmAlgo_t algorithm) {
|
||||
#if defined(CUDA_VERSION) && CUDA_VERSION >= 9010
|
||||
return cublasGemmStridedBatchedEx(handle,
|
||||
convert(layout_a),
|
||||
convert(layout_b),
|
||||
m,
|
||||
n,
|
||||
k,
|
||||
reinterpret_cast<ScalarDeviceType const *>(&alpha),
|
||||
A,
|
||||
cutlass::TypeTraits<ADeviceType>::cublas_type,
|
||||
lda,
|
||||
batch_stride_A,
|
||||
B,
|
||||
cutlass::TypeTraits<BDeviceType>::cublas_type,
|
||||
ldb,
|
||||
batch_stride_B,
|
||||
reinterpret_cast<ScalarDeviceType const *>(&beta),
|
||||
C,
|
||||
cutlass::TypeTraits<CDeviceType>::cublas_type,
|
||||
ldc,
|
||||
batch_stride_C,
|
||||
batch_count,
|
||||
cutlass::TypeTraits<AccumulatorDeviceType>::cublas_type,
|
||||
algorithm);
|
||||
#else
|
||||
return CUBLAS_STATUS_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace perf
|
||||
|
||||
@@ -81,6 +81,32 @@ struct CutlassDispatch {
|
||||
params.initialize(m, n, k, alpha, d_a, lda, d_b, ldb, beta, d_c, ldc, d_d, ldd);
|
||||
}
|
||||
|
||||
/// Initializes batched strided params object
|
||||
CutlassDispatch(Index m,
|
||||
Index n,
|
||||
Index k,
|
||||
ScalarEpilogue alpha,
|
||||
ScalarA const* d_a,
|
||||
Index lda,
|
||||
long long int batch_stride_A,
|
||||
ScalarB const* d_b,
|
||||
Index ldb,
|
||||
long long int batch_stride_B,
|
||||
ScalarEpilogue beta,
|
||||
ScalarC const* d_c,
|
||||
Index ldc,
|
||||
long long int batch_stride_C,
|
||||
ScalarD* d_d,
|
||||
Index ldd,
|
||||
long long int batch_stride_D,
|
||||
Index batch_count) {
|
||||
params.initialize(m, n, k, alpha, d_a, lda, batch_stride_A,
|
||||
d_b, ldb, batch_stride_B,
|
||||
beta, d_c, ldc, batch_stride_C,
|
||||
d_d, ldd, batch_stride_D,
|
||||
batch_count);
|
||||
}
|
||||
|
||||
/// Initializes params object
|
||||
CutlassDispatch(Params const& _params) : params(_params) {}
|
||||
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright (c) 2017-2018, 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.
|
||||
*
|
||||
**************************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "cutlass/matrix_traits.h"
|
||||
#include "tools/util/type_traits.h"
|
||||
#include <cuda_runtime_api.h>
|
||||
#include <assert.h>
|
||||
|
||||
namespace perf {
|
||||
|
||||
template <typename KernelClass_,
|
||||
typename Index_,
|
||||
typename ScalarA_,
|
||||
typename ScalarB_,
|
||||
typename ScalarC_,
|
||||
typename ScalarD_,
|
||||
typename Compute_,
|
||||
typename ScalarEpilogue_,
|
||||
bool ThreadMultiplyAdd_,
|
||||
bool RunCuBLAS_ = true>
|
||||
struct CutlassDispatchSplitKPIGemm {
|
||||
typedef typename KernelClass_::Params Params;
|
||||
typedef KernelClass_ KernelClass;
|
||||
typedef Index_ Index;
|
||||
typedef ScalarA_ ScalarA;
|
||||
typedef ScalarB_ ScalarB;
|
||||
typedef ScalarC_ ScalarC;
|
||||
typedef ScalarD_ ScalarD;
|
||||
typedef Compute_ Compute;
|
||||
typedef ScalarEpilogue_ ScalarEpilogue;
|
||||
|
||||
static bool const kThreadMultiplyAdd = ThreadMultiplyAdd_;
|
||||
static bool const kRunCuBLAS = RunCuBLAS_;
|
||||
|
||||
static cutlass::MatrixLayout::Kind const kLayoutA = KernelClass::Traits::kLayoutA;
|
||||
static cutlass::MatrixLayout::Kind const kLayoutB = KernelClass::Traits::kLayoutB;
|
||||
|
||||
//
|
||||
// Data members
|
||||
//
|
||||
|
||||
/// Params argument
|
||||
Params params;
|
||||
|
||||
/// splitK PI require workspace
|
||||
typename cutlass::TypeTraits<Compute>::device_type *workspace_ptr;
|
||||
|
||||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
/// Ctor Initializes params object
|
||||
CutlassDispatchSplitKPIGemm(Index m,
|
||||
Index n,
|
||||
Index k,
|
||||
ScalarEpilogue alpha,
|
||||
ScalarA const* d_a,
|
||||
Index lda,
|
||||
ScalarB const* d_b,
|
||||
Index ldb,
|
||||
ScalarEpilogue beta,
|
||||
ScalarC const* d_c,
|
||||
Index ldc,
|
||||
ScalarD* d_d,
|
||||
Index ldd) {
|
||||
params.init_problem(m, n, k);
|
||||
int workspace_size_in_byte = params.required_workspace_memory_in_byte();
|
||||
|
||||
cudaError_t workspace_err = cudaMalloc(&workspace_ptr, workspace_size_in_byte);
|
||||
if (workspace_err != cudaSuccess) {
|
||||
std::cout << "\nCUDA workspace malloc error: " << cudaGetErrorString(workspace_err)
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
params.initialize(alpha, d_a, lda, d_b, ldb, beta, d_c, ldc, d_d, ldd, workspace_ptr);
|
||||
}
|
||||
|
||||
/// Initializes batched strided params object
|
||||
CutlassDispatchSplitKPIGemm(Index m,
|
||||
Index n,
|
||||
Index k,
|
||||
ScalarEpilogue alpha,
|
||||
ScalarA const* d_a,
|
||||
Index lda,
|
||||
long long int batch_stride_A,
|
||||
ScalarB const* d_b,
|
||||
Index ldb,
|
||||
long long int batch_stride_B,
|
||||
ScalarEpilogue beta,
|
||||
ScalarC const* d_c,
|
||||
Index ldc,
|
||||
long long int batch_stride_C,
|
||||
ScalarD* d_d,
|
||||
Index ldd,
|
||||
long long int batch_stride_D,
|
||||
Index batch_count) {
|
||||
assert(0);//batched strided splitK should never be called
|
||||
}
|
||||
|
||||
/// Launches kernel
|
||||
cudaError_t operator()() { return KernelClass::launch(params); }
|
||||
|
||||
~CutlassDispatchSplitKPIGemm() {
|
||||
cudaError_t workspace_err = cudaFree(workspace_ptr);
|
||||
if (workspace_err != cudaSuccess) {
|
||||
std::cout << "\nCUDA workspace malloc error: " << cudaGetErrorString(workspace_err)
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<
|
||||
typename SplitKPIGemmTraits_
|
||||
>
|
||||
struct CutlassDispatchSplitKPIGemmBasic {
|
||||
///
|
||||
typedef SplitKPIGemmTraits_ Traits;
|
||||
|
||||
///
|
||||
typedef typename Traits::KernelClass KernelClass;
|
||||
|
||||
/// Index type
|
||||
typedef typename Traits::Index Index;
|
||||
|
||||
/// The scalar for A.
|
||||
typedef typename Traits::ScalarA ScalarA;
|
||||
/// The scalar for B.
|
||||
typedef typename Traits::ScalarB ScalarB;
|
||||
/// The scalar for C.
|
||||
typedef typename Traits::ScalarC ScalarC;
|
||||
/// The scalar for D.
|
||||
typedef typename Traits::ScalarD ScalarD;
|
||||
|
||||
// TODO - support alternative accumulator and scalar types
|
||||
typedef ScalarD Compute;
|
||||
typedef Compute ScalarEpilogue;
|
||||
|
||||
typedef CutlassDispatchSplitKPIGemm<KernelClass,
|
||||
Index,
|
||||
ScalarA,
|
||||
ScalarB,
|
||||
ScalarC,
|
||||
ScalarD,
|
||||
Compute,
|
||||
ScalarEpilogue,
|
||||
true>
|
||||
Dispatch;
|
||||
};
|
||||
} //namespace perf
|
||||
@@ -78,6 +78,7 @@ class GemmTestbed {
|
||||
|
||||
/// Dispatch object to cuBLAS GEMM
|
||||
typedef CublasGemmDispatch<AType, BType, CType, Accumulator, Scalar> CublasDispatch;
|
||||
typedef CublasBatchedStridedGemmDispatch<AType, BType, CType, Accumulator, Scalar> CublasBatchedStridedGemmDispatch;
|
||||
|
||||
//
|
||||
// Type definitions
|
||||
@@ -160,18 +161,20 @@ class GemmTestbed {
|
||||
|
||||
/// Resizes each tensor
|
||||
void resize_helper(GemmProblem const &problem) {
|
||||
resize_device_allocation(A,
|
||||
initial_distribution.dist_A,
|
||||
initial_distribution.seed,
|
||||
problem.m,
|
||||
problem.k,
|
||||
problem.layout_A);
|
||||
|
||||
resize_device_allocation(A,
|
||||
initial_distribution.dist_A,
|
||||
initial_distribution.seed,
|
||||
problem.m,
|
||||
problem.k * problem.batch_count,
|
||||
problem.layout_A);
|
||||
|
||||
|
||||
resize_device_allocation(
|
||||
B,
|
||||
initial_distribution.dist_B,
|
||||
initial_distribution.seed + 17, // compute distinct value from initial seed
|
||||
problem.k,
|
||||
problem.k * problem.batch_count,
|
||||
problem.n,
|
||||
problem.layout_B);
|
||||
|
||||
@@ -180,21 +183,21 @@ class GemmTestbed {
|
||||
initial_distribution.dist_C,
|
||||
initial_distribution.seed + 101, // compute distinct value from initial seed
|
||||
problem.m,
|
||||
problem.n,
|
||||
problem.n * problem.batch_count,
|
||||
cutlass::MatrixLayout::kColumnMajor);
|
||||
|
||||
resize_device_allocation(reference,
|
||||
cutlass::Distribution(),
|
||||
0,
|
||||
problem.m,
|
||||
problem.n,
|
||||
problem.n * problem.batch_count,
|
||||
cutlass::MatrixLayout::kColumnMajor);
|
||||
|
||||
resize_device_allocation(experimental,
|
||||
cutlass::Distribution(),
|
||||
0,
|
||||
problem.m,
|
||||
problem.n,
|
||||
problem.n * problem.batch_count,
|
||||
cutlass::MatrixLayout::kColumnMajor);
|
||||
}
|
||||
|
||||
@@ -315,24 +318,36 @@ class GemmTestbed {
|
||||
/// Inner dimension of GEMM problem
|
||||
int K() const { return problem.k; }
|
||||
|
||||
/// batch count
|
||||
int batch_count() const { return problem.batch_count; }
|
||||
|
||||
/// Returns a pointer to the A operand
|
||||
ADeviceType *ptr_A() const { return A.get(); }
|
||||
|
||||
/// Leading dimension of A
|
||||
int lda() const { return problem.lda(); }
|
||||
|
||||
///
|
||||
long long int batch_stride_a() const{ return problem.batch_stride_a(); }
|
||||
|
||||
/// Returns a pointer to the B operand
|
||||
BDeviceType *ptr_B() const { return B.get(); }
|
||||
|
||||
/// Leading dimension of B
|
||||
int ldb() const { return problem.ldb(); }
|
||||
|
||||
///
|
||||
long long int batch_stride_b() const{ return problem.batch_stride_b(); }
|
||||
|
||||
/// Returns a pointer to the initial state of the result tensor in device memory
|
||||
CDeviceType *ptr_C_initial() const { return C_initial.get(); }
|
||||
|
||||
/// Leading dimension of C
|
||||
int ldc() const { return problem.ldc(); }
|
||||
|
||||
///
|
||||
long long int batch_stride_c() const { return problem.batch_stride_c(); }
|
||||
|
||||
/// Returns a pointer to the result tensor in device memory
|
||||
CDeviceType *ptr_experimental() const { return experimental.get(); }
|
||||
|
||||
@@ -341,7 +356,7 @@ class GemmTestbed {
|
||||
|
||||
/// Returns the number of flops implied by the computation (1 multiply-accumulate = 2 flops)
|
||||
uint64_t flops() const {
|
||||
return uint64_t(problem.m) * uint64_t(problem.n) * uint64_t(problem.k) * detail::ElementCount<AType>::kValue * 2ULL;
|
||||
return uint64_t(problem.batch_count) * uint64_t(problem.m) * uint64_t(problem.n) * uint64_t(problem.k) * detail::ElementCount<AType>::kValue * 2ULL;
|
||||
}
|
||||
|
||||
/// Computes the speed of the computation in GFLOPs/s
|
||||
@@ -373,28 +388,59 @@ class GemmTestbed {
|
||||
|
||||
/// Launches the cuBLAS GEMM - does not initialize output matrix
|
||||
cublasStatus_t launch_cublas(cublasGemmAlgo_t algo) {
|
||||
CublasDispatch dispatch;
|
||||
if (problem.batch_count == 1) {
|
||||
CublasDispatch dispatch;
|
||||
|
||||
Scalar alpha(Scalar(problem.alpha));
|
||||
Scalar beta(Scalar(problem.beta));
|
||||
Scalar alpha(Scalar(problem.alpha));
|
||||
Scalar beta(Scalar(problem.beta));
|
||||
|
||||
status = dispatch(handle,
|
||||
problem.layout_A,
|
||||
problem.layout_B,
|
||||
problem.m,
|
||||
problem.n,
|
||||
problem.k,
|
||||
alpha,
|
||||
ptr_A(),
|
||||
lda(),
|
||||
ptr_B(),
|
||||
ldb(),
|
||||
beta,
|
||||
ptr_reference(),
|
||||
ldc(),
|
||||
algo);
|
||||
status = dispatch(handle,
|
||||
problem.layout_A,
|
||||
problem.layout_B,
|
||||
problem.m,
|
||||
problem.n,
|
||||
problem.k,
|
||||
alpha,
|
||||
ptr_A(),
|
||||
lda(),
|
||||
ptr_B(),
|
||||
ldb(),
|
||||
beta,
|
||||
ptr_reference(),
|
||||
ldc(),
|
||||
algo);
|
||||
|
||||
return status;
|
||||
return status;
|
||||
}
|
||||
else {
|
||||
// call batched strided cublas
|
||||
CublasBatchedStridedGemmDispatch dispatch;
|
||||
|
||||
Scalar alpha(Scalar(problem.alpha));
|
||||
Scalar beta(Scalar(problem.beta));
|
||||
|
||||
status = dispatch(handle,
|
||||
problem.layout_A,
|
||||
problem.layout_B,
|
||||
problem.m,
|
||||
problem.n,
|
||||
problem.k,
|
||||
alpha,
|
||||
ptr_A(),
|
||||
lda(),
|
||||
batch_stride_a(),
|
||||
ptr_B(),
|
||||
ldb(),
|
||||
batch_stride_b(),
|
||||
beta,
|
||||
ptr_reference(),
|
||||
ldc(),
|
||||
batch_stride_c(),
|
||||
batch_count(),
|
||||
algo);
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/// Verifies the 'test' tensor with 'ref'
|
||||
|
||||
@@ -164,24 +164,52 @@ class GemmProfiler {
|
||||
result.disposition = Disposition::Passed;
|
||||
}
|
||||
|
||||
CutlassDispatch dispatch(testbed.M(),
|
||||
testbed.N(),
|
||||
testbed.K(),
|
||||
testbed.alpha(),
|
||||
testbed.ptr_A(),
|
||||
testbed.lda(),
|
||||
testbed.ptr_B(),
|
||||
testbed.ldb(),
|
||||
testbed.beta(),
|
||||
testbed.ptr_C_initial(),
|
||||
testbed.ldc(),
|
||||
testbed.ptr_experimental(),
|
||||
testbed.ldc());
|
||||
CutlassDispatch *dispatch_ptr;
|
||||
|
||||
dispatch();
|
||||
// check to see if we need to launch batched strided gemm
|
||||
if (testbed.batch_count() == 1) {
|
||||
dispatch_ptr = new CutlassDispatch(testbed.M(),
|
||||
testbed.N(),
|
||||
testbed.K(),
|
||||
testbed.alpha(),
|
||||
testbed.ptr_A(),
|
||||
testbed.lda(),
|
||||
testbed.ptr_B(),
|
||||
testbed.ldb(),
|
||||
testbed.beta(),
|
||||
testbed.ptr_C_initial(),
|
||||
testbed.ldc(),
|
||||
testbed.ptr_experimental(),
|
||||
testbed.ldc());
|
||||
|
||||
dispatch_ptr->operator()();
|
||||
}
|
||||
else {
|
||||
dispatch_ptr = new CutlassDispatch(testbed.M(),
|
||||
testbed.N(),
|
||||
testbed.K(),
|
||||
testbed.alpha(),
|
||||
testbed.ptr_A(),
|
||||
testbed.lda(),
|
||||
testbed.batch_stride_a(),
|
||||
testbed.ptr_B(),
|
||||
testbed.ldb(),
|
||||
testbed.batch_stride_b(),
|
||||
testbed.beta(),
|
||||
testbed.ptr_C_initial(),
|
||||
testbed.ldc(),
|
||||
testbed.batch_stride_c(),
|
||||
testbed.ptr_experimental(),
|
||||
testbed.ldc(),
|
||||
testbed.batch_stride_c(),
|
||||
testbed.batch_count());
|
||||
|
||||
dispatch_ptr->operator()();
|
||||
}
|
||||
|
||||
if (cudaDeviceSynchronize() != cudaSuccess) {
|
||||
result.disposition = Disposition::Failed;
|
||||
delete dispatch_ptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -202,35 +230,40 @@ class GemmProfiler {
|
||||
}
|
||||
|
||||
// warmup launch
|
||||
dispatch();
|
||||
dispatch_ptr->operator()();
|
||||
|
||||
if (cudaDeviceSynchronize() != cudaSuccess) {
|
||||
result.disposition = Disposition::Failed;
|
||||
delete dispatch_ptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (cudaEventRecord(events[0]) != cudaSuccess) {
|
||||
result.disposition = Disposition::Failed;
|
||||
delete dispatch_ptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
for (int iter = 0; iter < options.iterations; ++iter) {
|
||||
dispatch();
|
||||
dispatch_ptr->operator()();
|
||||
}
|
||||
|
||||
if (cudaEventRecord(events[1]) != cudaSuccess) {
|
||||
result.disposition = Disposition::Failed;
|
||||
delete dispatch_ptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (cudaEventSynchronize(events[1]) != cudaSuccess) {
|
||||
result.disposition = Disposition::Failed;
|
||||
delete dispatch_ptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
float average_ms = 0;
|
||||
if (cudaEventElapsedTime(&average_ms, events[0], events[1]) != cudaSuccess) {
|
||||
result.disposition = Disposition::Failed;
|
||||
delete dispatch_ptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -242,6 +275,7 @@ class GemmProfiler {
|
||||
<< " failed with disposition: " << result.disposition << "\n";
|
||||
}
|
||||
|
||||
delete dispatch_ptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -265,7 +299,7 @@ class GemmProfiler {
|
||||
|
||||
std::vector<PerformanceResult<GemmProblem> > results;
|
||||
|
||||
results.push_back(execute_cutlass<CutlassDispatch>(problem, algorithm));
|
||||
results.push_back(execute_cutlass<CutlassDispatch>(problem, algorithm));
|
||||
// cool-down period
|
||||
if (!options.dry_run) {
|
||||
pause(options.sleep_time);
|
||||
@@ -276,28 +310,30 @@ class GemmProfiler {
|
||||
|
||||
/// Runs the test and collects performance for all results
|
||||
template <typename CutlassDispatch>
|
||||
void schmoo(Range const &M, Range const &N, Range const &K) {
|
||||
for (int m = M.start; m <= M.end; m = M.next(m)) {
|
||||
for (int n = N.start; n <= N.end; n = N.next(n)) {
|
||||
for (int k = K.start; k <= K.end; k = K.next(k)) {
|
||||
|
||||
std::vector<PerformanceResult<GemmProblem> > results =
|
||||
void schmoo(Range const &M, Range const &N, Range const &K, Range const &batch_count) {
|
||||
for (int b = batch_count.start; b <= batch_count.end; b = batch_count.next(b)) {
|
||||
for (int m = M.start; m <= M.end; m = M.next(m)) {
|
||||
for (int n = N.start; n <= N.end; n = N.next(n)) {
|
||||
for (int k = K.start; k <= K.end; k = K.next(k)) {
|
||||
std::vector<PerformanceResult<GemmProblem> > results =
|
||||
execute<CutlassDispatch>(GemmProblem(m,
|
||||
n,
|
||||
k,
|
||||
CutlassDispatch::kLayoutA,
|
||||
CutlassDispatch::kLayoutB,
|
||||
config.alpha,
|
||||
config.beta));
|
||||
n,
|
||||
k,
|
||||
CutlassDispatch::kLayoutA,
|
||||
CutlassDispatch::kLayoutB,
|
||||
config.alpha,
|
||||
config.beta,
|
||||
b));
|
||||
|
||||
for (std::vector<PerformanceResult<GemmProblem> >::const_iterator it = results.begin();
|
||||
it != results.end();
|
||||
++it) {
|
||||
output.append(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (std::vector<PerformanceResult<GemmProblem> >::const_iterator it = results.begin();
|
||||
it != results.end();
|
||||
++it) {
|
||||
output.append(*it);
|
||||
}
|
||||
}//k
|
||||
}//n
|
||||
}//m
|
||||
}//batch_count
|
||||
}
|
||||
|
||||
/// Runs the test over the problem space and reports only the best performance
|
||||
@@ -369,7 +405,7 @@ int profile_gemm(TestbenchOutput<GemmProblem> &output,
|
||||
config.problem_range.M, config.problem_range.N, config.problem_range.K);
|
||||
} else {
|
||||
perf.template schmoo<Dispatch>(
|
||||
config.problem_range.M, config.problem_range.N, config.problem_range.K);
|
||||
config.problem_range.M, config.problem_range.N, config.problem_range.K, config.problem_range.batch_count);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright (c) 2017-2018, 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.
|
||||
*
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "cutlass/gemm/gemm.h"
|
||||
#include "cutlass/gemm/igemm_traits.h"
|
||||
#include "cutlass/reduction/batched_reduction_traits.h"
|
||||
#include "cutlass/gemm/device_gemm_traits.h"
|
||||
#include "tools/test/perf/cutlass_perf_test.h"
|
||||
#include "tools/test/perf/gemm/gemm_perf_testbed.h"
|
||||
#include "tools/test/perf/gemm/gemm_profiler.h"
|
||||
#include "tools/test/perf/gemm/cutlass_dispatch.h"
|
||||
#include "tools/test/perf/gemm/cutlass_dispatch_splitK_PI.h"
|
||||
#pragma warning( disable : 4503)
|
||||
|
||||
namespace perf {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename OutputTile, int splits_count>
|
||||
int profile_igemm_splitkpi_kernel(
|
||||
TestbenchOutput<GemmProblem> &output,
|
||||
TestbenchOptions const &options,
|
||||
Config const &config,
|
||||
std::string const &name,
|
||||
std::string const &algo) {
|
||||
|
||||
typedef perf::GemmProfiler<int8_t, int8_t, int, int, int> GemmProfiler;
|
||||
|
||||
int results = 0;
|
||||
|
||||
{
|
||||
/*batched igemm traits*/
|
||||
typedef cutlass::gemm::IgemmTraits<
|
||||
cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::MatrixLayout::kColumnMajor,
|
||||
OutputTile
|
||||
> IgemmTraits;
|
||||
/*batched reduction traits*/
|
||||
typedef cutlass::reduction::BatchedReductionTraits<int,
|
||||
int,
|
||||
int,
|
||||
int,
|
||||
int, /*accumulation type*/
|
||||
splits_count,
|
||||
cutlass::Shape<1, 1, 128>,
|
||||
cutlass::Shape<1, 1, 64>,
|
||||
cutlass::Shape<1, 1, 2> >
|
||||
BatchedReductionTraits;
|
||||
|
||||
// create a device gemm
|
||||
typedef typename cutlass::gemm::SplitkPIGemmTraits<IgemmTraits, BatchedReductionTraits> deviceGemmTraits;
|
||||
typedef typename CutlassDispatchSplitKPIGemmBasic<deviceGemmTraits>::Dispatch Dispatch;
|
||||
|
||||
results |= profile_gemm<Dispatch, GemmProfiler>(output, name + "_nn", options, config, algo + "_splitk_pi");
|
||||
}
|
||||
|
||||
{
|
||||
/*batched igemm traits*/
|
||||
typedef cutlass::gemm::IgemmTraits<
|
||||
cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::MatrixLayout::kRowMajor,
|
||||
OutputTile
|
||||
> IgemmTraits;
|
||||
/*batched reduction traits*/
|
||||
typedef cutlass::reduction::BatchedReductionTraits<int,
|
||||
int,
|
||||
int,
|
||||
int,
|
||||
int, /*accumulation type*/
|
||||
splits_count,
|
||||
cutlass::Shape<1, 1, 128>,
|
||||
cutlass::Shape<1, 1, 64>,
|
||||
cutlass::Shape<1, 1, 2> >
|
||||
BatchedReductionTraits;
|
||||
|
||||
// create a device gemm
|
||||
typedef typename cutlass::gemm::SplitkPIGemmTraits<IgemmTraits, BatchedReductionTraits> deviceGemmTraits;
|
||||
typedef typename CutlassDispatchSplitKPIGemmBasic<deviceGemmTraits>::Dispatch Dispatch;
|
||||
|
||||
results |= profile_gemm<Dispatch, GemmProfiler>(output, name + "_nt", options, config, algo + "_splitk_pi");
|
||||
}
|
||||
|
||||
{
|
||||
/*batched igemm traits*/
|
||||
typedef cutlass::gemm::IgemmTraits<
|
||||
cutlass::MatrixLayout::kRowMajor,
|
||||
cutlass::MatrixLayout::kColumnMajor,
|
||||
OutputTile
|
||||
> IgemmTraits;
|
||||
/*batched reduction traits*/
|
||||
typedef cutlass::reduction::BatchedReductionTraits<int,
|
||||
int,
|
||||
int,
|
||||
int,
|
||||
int, /*accumulation type*/
|
||||
splits_count,
|
||||
cutlass::Shape<1, 1, 128>,
|
||||
cutlass::Shape<1, 1, 64>,
|
||||
cutlass::Shape<1, 1, 2> >
|
||||
BatchedReductionTraits;
|
||||
|
||||
// create a device gemm
|
||||
typedef typename cutlass::gemm::SplitkPIGemmTraits<IgemmTraits, BatchedReductionTraits> deviceGemmTraits;
|
||||
typedef typename CutlassDispatchSplitKPIGemmBasic<deviceGemmTraits>::Dispatch Dispatch;
|
||||
|
||||
results |= profile_gemm<Dispatch, GemmProfiler>(output, name + "_tn", options, config, algo + "_splitk_pi");
|
||||
}
|
||||
|
||||
{
|
||||
/*batched igemm traits*/
|
||||
typedef cutlass::gemm::IgemmTraits<
|
||||
cutlass::MatrixLayout::kRowMajor,
|
||||
cutlass::MatrixLayout::kRowMajor,
|
||||
OutputTile
|
||||
> IgemmTraits;
|
||||
/*batched reduction traits*/
|
||||
typedef cutlass::reduction::BatchedReductionTraits<int,
|
||||
int,
|
||||
int,
|
||||
int,
|
||||
int, /*accumulation type*/
|
||||
splits_count,
|
||||
cutlass::Shape<1, 1, 128>,
|
||||
cutlass::Shape<1, 1, 64>,
|
||||
cutlass::Shape<1, 1, 2> >
|
||||
BatchedReductionTraits;
|
||||
|
||||
// create a device gemm
|
||||
typedef typename cutlass::gemm::SplitkPIGemmTraits<IgemmTraits, BatchedReductionTraits> deviceGemmTraits;
|
||||
typedef typename CutlassDispatchSplitKPIGemmBasic<deviceGemmTraits>::Dispatch Dispatch;
|
||||
|
||||
results |= profile_gemm<Dispatch, GemmProfiler>(output, name + "_tt", options, config, algo + "_splitk_pi");
|
||||
}
|
||||
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// Profiles all SGEMM tile sizes
|
||||
int profile_igemm_splitkpi(TestbenchOutput<GemmProblem> &output, TestbenchOptions const &options, Config const &config) {
|
||||
int results = 0;
|
||||
/*128x128x32*/
|
||||
results |= profile_igemm_splitkpi_kernel<cutlass::Shape<32, 128, 128>, 8 >(output, options, config, "igemm_128x128x32_splitk_pi_split8", "128x128");
|
||||
results |= profile_igemm_splitkpi_kernel<cutlass::Shape<32, 128, 128>, 16 >(output, options, config, "igemm_128x128x32_splitk_pi_split16", "128x128");
|
||||
results |= profile_igemm_splitkpi_kernel<cutlass::Shape<32, 128, 128>, 32 >(output, options, config, "igemm_128x128x32_splitk_pi_split32", "128x128");
|
||||
results |= profile_igemm_splitkpi_kernel<cutlass::Shape<32, 128, 128>, 64 >(output, options, config, "igemm_128x128x32_splitk_pi_split64", "128x128");
|
||||
|
||||
/*128x64x32*/
|
||||
results |= profile_igemm_splitkpi_kernel<cutlass::Shape<32, 64, 128>, 8 >(output, options, config, "igemm_128x64x32_splitk_pi_split8", "128x64");
|
||||
results |= profile_igemm_splitkpi_kernel<cutlass::Shape<32, 64, 128>, 16 >(output, options, config, "igemm_128x64x32_splitk_pi_split16", "128x64");
|
||||
results |= profile_igemm_splitkpi_kernel<cutlass::Shape<32, 64, 128>, 20 >(output, options, config, "igemm_128x64x32_splitk_pi_split20", "128x64");
|
||||
results |= profile_igemm_splitkpi_kernel<cutlass::Shape<32, 64, 128>, 32 >(output, options, config, "igemm_128x64x32_splitk_pi_split32", "128x64");
|
||||
results |= profile_igemm_splitkpi_kernel<cutlass::Shape<32, 64, 128>, 64 >(output, options, config, "igemm_128x64x32_splitk_pi_split64", "128x64");
|
||||
|
||||
/*128x32x32*/
|
||||
results |= profile_igemm_splitkpi_kernel<cutlass::Shape<32, 32, 128>, 8 >(output, options, config, "igemm_128x32x32_splitk_pi_split8", "128x32");
|
||||
results |= profile_igemm_splitkpi_kernel<cutlass::Shape<32, 32, 128>, 16 >(output, options, config, "igemm_128x32x32_splitk_pi_split16", "128x32");
|
||||
results |= profile_igemm_splitkpi_kernel<cutlass::Shape<32, 32, 128>, 20 >(output, options, config, "igemm_128x32x32_splitk_pi_split20", "128x32");
|
||||
results |= profile_igemm_splitkpi_kernel<cutlass::Shape<32, 32, 128>, 32 >(output, options, config, "igemm_128x32x32_splitk_pi_split32", "128x32");
|
||||
results |= profile_igemm_splitkpi_kernel<cutlass::Shape<32, 32, 128>, 64 >(output, options, config, "igemm_128x32x32_splitk_pi_split64", "128x32");
|
||||
|
||||
/*64x64x32*/
|
||||
results |= profile_igemm_splitkpi_kernel<cutlass::Shape<32, 64, 64>, 8 >(output, options, config, "igemm_64x64x32_splitk_pi_split8", "64x64");
|
||||
results |= profile_igemm_splitkpi_kernel<cutlass::Shape<32, 64, 64>, 16 >(output, options, config, "igemm_64x64x32_splitk_pi_split16", "64x64");
|
||||
results |= profile_igemm_splitkpi_kernel<cutlass::Shape<32, 64, 64>, 20 >(output, options, config, "igemm_64x64x32_splitk_pi_split20", "64x64");
|
||||
results |= profile_igemm_splitkpi_kernel<cutlass::Shape<32, 64, 64>, 32 >(output, options, config, "igemm_64x64x32_splitk_pi_split32", "64x64");
|
||||
results |= profile_igemm_splitkpi_kernel<cutlass::Shape<32, 64, 64>, 64 >(output, options, config, "igemm_64x64x32_splitk_pi_split64", "64x64");
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
struct IgemmSplitKPIRegistrar {
|
||||
IgemmSplitKPIRegistrar() { RegisterGemmProfileFunc(profile_igemm_splitkpi); }
|
||||
};
|
||||
|
||||
volatile IgemmSplitKPIRegistrar _IgemmSplitKPIRegistrar;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespace perf
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,187 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright (c) 2017-2018, 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.
|
||||
*
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "cutlass/gemm/gemm.h"
|
||||
#include "cutlass/gemm/sgemm_traits.h"
|
||||
#include "cutlass/reduction/batched_reduction_traits.h"
|
||||
#include "cutlass/gemm/device_gemm_traits.h"
|
||||
#include "tools/test/perf/cutlass_perf_test.h"
|
||||
#include "tools/test/perf/gemm/gemm_perf_testbed.h"
|
||||
#include "tools/test/perf/gemm/gemm_profiler.h"
|
||||
#include "tools/test/perf/gemm/cutlass_dispatch.h"
|
||||
#include "tools/test/perf/gemm/cutlass_dispatch_splitK_PI.h"
|
||||
#pragma warning( disable : 4503)
|
||||
|
||||
namespace perf {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename OutputTile, int splits_count>
|
||||
int profile_sgemm_splitkpi_kernel(
|
||||
TestbenchOutput<GemmProblem> &output,
|
||||
TestbenchOptions const &options,
|
||||
Config const &config,
|
||||
std::string const &name,
|
||||
std::string const &algo) {
|
||||
|
||||
typedef perf::GemmProfiler<float, float, float, float, float> SGemmProfiler;
|
||||
|
||||
int results = 0;
|
||||
|
||||
{
|
||||
/*batched sgemm traits*/
|
||||
typedef cutlass::gemm::SgemmTraits<cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::MatrixLayout::kColumnMajor, OutputTile>
|
||||
SgemmTraits;
|
||||
/*batched reduction traits*/
|
||||
typedef cutlass::reduction::BatchedReductionTraits<float,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
splits_count,
|
||||
cutlass::Shape<1, 1, 128>,
|
||||
cutlass::Shape<1, 1, 64>,
|
||||
cutlass::Shape<1, 1, 2> >
|
||||
BatchedReductionTraits;
|
||||
|
||||
// create a device gemm
|
||||
typedef typename cutlass::gemm::SplitkPIGemmTraits<SgemmTraits, BatchedReductionTraits> deviceGemmTraits;
|
||||
typedef typename CutlassDispatchSplitKPIGemmBasic<deviceGemmTraits>::Dispatch Dispatch;
|
||||
|
||||
results |= profile_gemm<Dispatch, SGemmProfiler>(output, name + "_nn", options, config, algo + "_splitk_pi");
|
||||
}
|
||||
|
||||
{
|
||||
/*batched sgemm traits*/
|
||||
typedef cutlass::gemm::SgemmTraits<cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::MatrixLayout::kRowMajor, OutputTile>
|
||||
SgemmTraits;
|
||||
/*batched reduction traits*/
|
||||
typedef cutlass::reduction::BatchedReductionTraits<float,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
splits_count,
|
||||
cutlass::Shape<1, 1, 128>,
|
||||
cutlass::Shape<1, 1, 64>,
|
||||
cutlass::Shape<1, 1, 2> >
|
||||
BatchedReductionTraits;
|
||||
|
||||
// create a device gemm
|
||||
typedef typename cutlass::gemm::SplitkPIGemmTraits<SgemmTraits, BatchedReductionTraits> deviceGemmTraits;
|
||||
typedef typename CutlassDispatchSplitKPIGemmBasic<deviceGemmTraits>::Dispatch Dispatch;
|
||||
|
||||
results |= profile_gemm<Dispatch, SGemmProfiler>(output, name + "_nt", options, config, algo + "_splitk_pi");
|
||||
}
|
||||
|
||||
{
|
||||
/*batched sgemm traits*/
|
||||
typedef cutlass::gemm::SgemmTraits<cutlass::MatrixLayout::kRowMajor,
|
||||
cutlass::MatrixLayout::kColumnMajor, OutputTile>
|
||||
SgemmTraits;
|
||||
/*batched reduction traits*/
|
||||
typedef cutlass::reduction::BatchedReductionTraits<float,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
splits_count,
|
||||
cutlass::Shape<1, 1, 128>,
|
||||
cutlass::Shape<1, 1, 64>,
|
||||
cutlass::Shape<1, 1, 2> >
|
||||
BatchedReductionTraits;
|
||||
|
||||
// create a device gemm
|
||||
typedef typename cutlass::gemm::SplitkPIGemmTraits<SgemmTraits, BatchedReductionTraits> deviceGemmTraits;
|
||||
typedef typename CutlassDispatchSplitKPIGemmBasic<deviceGemmTraits>::Dispatch Dispatch;
|
||||
|
||||
results |= profile_gemm<Dispatch, SGemmProfiler>(output, name + "_tn", options, config, algo + "_splitk_pi");
|
||||
}
|
||||
|
||||
{
|
||||
/*batched sgemm traits*/
|
||||
typedef cutlass::gemm::SgemmTraits<cutlass::MatrixLayout::kRowMajor,
|
||||
cutlass::MatrixLayout::kRowMajor, OutputTile>
|
||||
SgemmTraits;
|
||||
/*batched reduction traits*/
|
||||
typedef cutlass::reduction::BatchedReductionTraits<float,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
splits_count,
|
||||
cutlass::Shape<1, 1, 128>,
|
||||
cutlass::Shape<1, 1, 64>,
|
||||
cutlass::Shape<1, 1, 2> >
|
||||
BatchedReductionTraits;
|
||||
|
||||
// create a device gemm
|
||||
typedef typename cutlass::gemm::SplitkPIGemmTraits<SgemmTraits, BatchedReductionTraits> deviceGemmTraits;
|
||||
typedef typename CutlassDispatchSplitKPIGemmBasic<deviceGemmTraits>::Dispatch Dispatch;
|
||||
|
||||
results |= profile_gemm<Dispatch, SGemmProfiler>(output, name + "_tt", options, config, algo + "_splitk_pi");
|
||||
}
|
||||
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// Profiles all SGEMM tile sizes
|
||||
int profile_sgemm_splitkpi(TestbenchOutput<GemmProblem> &output, TestbenchOptions const &options, Config const &config) {
|
||||
int results = 0;
|
||||
|
||||
results |= profile_sgemm_splitkpi_kernel<cutlass::Shape<8, 128, 128>, 32 >(output, options, config, "sgemm_128x128x8_splitk_pi_split32", "128x128");
|
||||
|
||||
/*128x64x8*/
|
||||
results |= profile_sgemm_splitkpi_kernel<cutlass::Shape<8, 64, 128>, 8 >(output, options, config, "sgemm_128x64x8_splitk_pi_split8", "128x64");
|
||||
results |= profile_sgemm_splitkpi_kernel<cutlass::Shape<8, 64, 128>, 16 >(output, options, config, "sgemm_128x64x8_splitk_pi_split16", "128x64");
|
||||
results |= profile_sgemm_splitkpi_kernel<cutlass::Shape<8, 64, 128>, 20 >(output, options, config, "sgemm_128x64x8_splitk_pi_split20", "128x64");
|
||||
results |= profile_sgemm_splitkpi_kernel<cutlass::Shape<8, 64, 128>, 24 >(output, options, config, "sgemm_128x64x8_splitk_pi_split24", "128x64");
|
||||
results |= profile_sgemm_splitkpi_kernel<cutlass::Shape<8, 64, 128>, 28 >(output, options, config, "sgemm_128x64x8_splitk_pi_split28", "128x64");
|
||||
results |= profile_sgemm_splitkpi_kernel<cutlass::Shape<8, 64, 128>, 32 >(output, options, config, "sgemm_128x64x8_splitk_pi_split32", "128x64");
|
||||
results |= profile_sgemm_splitkpi_kernel<cutlass::Shape<8, 64, 128>, 64 >(output, options, config, "sgemm_128x64x8_splitk_pi_split64", "128x64");
|
||||
/*128x32x8*/
|
||||
results |= profile_sgemm_splitkpi_kernel<cutlass::Shape<8, 32, 128>, 8 >(output, options, config, "sgemm_128x32x8_splitk_pi_split8", "128x32");
|
||||
results |= profile_sgemm_splitkpi_kernel<cutlass::Shape<8, 32, 128>, 16 >(output, options, config, "sgemm_128x32x8_splitk_pi_split16", "128x32");
|
||||
results |= profile_sgemm_splitkpi_kernel<cutlass::Shape<8, 32, 128>, 20 >(output, options, config, "sgemm_128x32x8_splitk_pi_split20", "128x32");
|
||||
results |= profile_sgemm_splitkpi_kernel<cutlass::Shape<8, 32, 128>, 24 >(output, options, config, "sgemm_128x32x8_splitk_pi_split24", "128x32");
|
||||
results |= profile_sgemm_splitkpi_kernel<cutlass::Shape<8, 32, 128>, 28 >(output, options, config, "sgemm_128x32x8_splitk_pi_split28", "128x32");
|
||||
results |= profile_sgemm_splitkpi_kernel<cutlass::Shape<8, 32, 128>, 32 >(output, options, config, "sgemm_128x32x8_splitk_pi_split32", "128x32");
|
||||
results |= profile_sgemm_splitkpi_kernel<cutlass::Shape<8, 32, 128>, 64 >(output, options, config, "sgemm_128x32x8_splitk_pi_split64", "128x32");
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
struct SgemmSplitKPIRegistrar {
|
||||
SgemmSplitKPIRegistrar() { RegisterGemmProfileFunc(profile_sgemm_splitkpi); }
|
||||
};
|
||||
|
||||
volatile SgemmSplitKPIRegistrar _SgemmSplitKPIRegistrar;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespace perf
|
||||
@@ -76,6 +76,15 @@ struct WmmaBinaryGemmDispatch {
|
||||
params.initialize(m, n, k * 32, alpha, d_a, lda, d_b, ldb, beta, d_c, ldc, d_d, ldd);
|
||||
}
|
||||
|
||||
/// batched strided bmma
|
||||
WmmaBinaryGemmDispatch(int m, int n, int k, int alpha,
|
||||
cutlass::Vector<cutlass::bin1_t, 32> const* d_a, int lda, long long int batch_stride_a,
|
||||
cutlass::Vector<cutlass::bin1_t, 32> const* d_b, int ldb, long long int batch_stride_b, int beta,
|
||||
int const* d_c, int ldc, long long int batch_stride_c, int* d_d, int ldd, long long int batch_stride_d,
|
||||
int batch_count) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/// Initializes params object
|
||||
WmmaBinaryGemmDispatch(Params const& _params) : params(_params) {}
|
||||
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright (c) 2017-2018, 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.
|
||||
*
|
||||
**************************************************************************************************/
|
||||
* Copyright (c) 2017-2018, 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.
|
||||
*
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "cutlass/wmma_matrix.h"
|
||||
#ifdef CUTLASS_USE_WMMA_API
|
||||
@@ -92,6 +92,31 @@ struct WmmaGemmDispatch {
|
||||
params.initialize(m, n, k, alpha, d_a, lda, d_b, ldb, beta, d_c, ldc, d_d, ldd);
|
||||
}
|
||||
|
||||
WmmaGemmDispatch(int m,
|
||||
int n,
|
||||
int k,
|
||||
Scalar alpha,
|
||||
ScalarA const* d_a,
|
||||
int lda,
|
||||
long long int batch_stride_A,
|
||||
ScalarB const* d_b,
|
||||
int ldb,
|
||||
long long int batch_stride_B,
|
||||
Scalar beta,
|
||||
ScalarC const* d_c,
|
||||
int ldc,
|
||||
long long int batch_stride_C,
|
||||
ScalarD* d_d,
|
||||
int ldd,
|
||||
long long int batch_stride_D,
|
||||
int batch_count) {
|
||||
params.initialize(m, n, k, alpha, d_a, lda, batch_stride_A,
|
||||
d_b, ldb, batch_stride_B,
|
||||
beta, d_c, ldc, batch_stride_C,
|
||||
d_d, ldd, batch_stride_D,
|
||||
batch_count);
|
||||
}
|
||||
|
||||
/// Initializes params object
|
||||
WmmaGemmDispatch(Params const& _params) : params(_params) {}
|
||||
|
||||
@@ -105,6 +130,7 @@ namespace perf {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename DummyT>
|
||||
int profile_wmma_gemm_f32(TestbenchOutput<GemmProblem> &output, TestbenchOptions const &options, Config const &config) {
|
||||
typedef perf::GemmProfiler<cutlass::half_t, cutlass::half_t, float, float, float> GemmProfiler;
|
||||
|
||||
@@ -112,8 +138,8 @@ int profile_wmma_gemm_f32(TestbenchOutput<GemmProblem> &output, TestbenchOptions
|
||||
|
||||
{
|
||||
typedef cutlass::gemm::WmmaGemmTraits<cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::MatrixLayout::kRowMajor>
|
||||
WmmaGemmTraits;
|
||||
cutlass::MatrixLayout::kRowMajor>
|
||||
WmmaGemmTraits;
|
||||
|
||||
typedef WmmaGemmDispatch<WmmaGemmTraits> Dispatch;
|
||||
|
||||
@@ -122,8 +148,8 @@ int profile_wmma_gemm_f32(TestbenchOutput<GemmProblem> &output, TestbenchOptions
|
||||
|
||||
{
|
||||
typedef cutlass::gemm::WmmaGemmTraits<cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::MatrixLayout::kColumnMajor>
|
||||
WmmaGemmTraits;
|
||||
cutlass::MatrixLayout::kColumnMajor>
|
||||
WmmaGemmTraits;
|
||||
|
||||
typedef WmmaGemmDispatch<WmmaGemmTraits> Dispatch;
|
||||
|
||||
@@ -132,7 +158,7 @@ int profile_wmma_gemm_f32(TestbenchOutput<GemmProblem> &output, TestbenchOptions
|
||||
|
||||
{
|
||||
typedef cutlass::gemm::WmmaGemmTraits<cutlass::MatrixLayout::kRowMajor,
|
||||
cutlass::MatrixLayout::kColumnMajor>
|
||||
cutlass::MatrixLayout::kColumnMajor>
|
||||
WmmaGemmTraits;
|
||||
|
||||
typedef WmmaGemmDispatch<WmmaGemmTraits> Dispatch;
|
||||
@@ -142,7 +168,7 @@ int profile_wmma_gemm_f32(TestbenchOutput<GemmProblem> &output, TestbenchOptions
|
||||
|
||||
{
|
||||
typedef cutlass::gemm::WmmaGemmTraits<cutlass::MatrixLayout::kRowMajor,
|
||||
cutlass::MatrixLayout::kRowMajor>
|
||||
cutlass::MatrixLayout::kRowMajor>
|
||||
WmmaGemmTraits;
|
||||
|
||||
typedef WmmaGemmDispatch<WmmaGemmTraits> Dispatch;
|
||||
@@ -155,10 +181,11 @@ int profile_wmma_gemm_f32(TestbenchOutput<GemmProblem> &output, TestbenchOptions
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename DummyT>
|
||||
int profile_wmma_gemm_f16(
|
||||
TestbenchOutput<GemmProblem> &output,
|
||||
TestbenchOptions const &options,
|
||||
Config const &config) {
|
||||
TestbenchOutput<GemmProblem> &output,
|
||||
TestbenchOptions const &options,
|
||||
Config const &config) {
|
||||
|
||||
typedef perf::GemmProfiler<
|
||||
cutlass::half_t,
|
||||
@@ -173,7 +200,7 @@ int profile_wmma_gemm_f16(
|
||||
typedef cutlass::gemm::WmmaGemmTraits<
|
||||
cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::MatrixLayout::kRowMajor,
|
||||
cutlass::Shape<32, 128, 128>,
|
||||
cutlass::Shape<32, 256, 128>,
|
||||
half,
|
||||
half,
|
||||
half,
|
||||
@@ -192,7 +219,7 @@ int profile_wmma_gemm_f16(
|
||||
typedef cutlass::gemm::WmmaGemmTraits<
|
||||
cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::Shape<32, 128, 128>,
|
||||
cutlass::Shape<32, 256, 128>,
|
||||
half,
|
||||
half,
|
||||
half,
|
||||
@@ -211,7 +238,7 @@ int profile_wmma_gemm_f16(
|
||||
typedef cutlass::gemm::WmmaGemmTraits<
|
||||
cutlass::MatrixLayout::kRowMajor,
|
||||
cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::Shape<32, 128, 128>,
|
||||
cutlass::Shape<32, 256, 128>,
|
||||
half,
|
||||
half,
|
||||
half,
|
||||
@@ -230,7 +257,7 @@ int profile_wmma_gemm_f16(
|
||||
typedef cutlass::gemm::WmmaGemmTraits<
|
||||
cutlass::MatrixLayout::kRowMajor,
|
||||
cutlass::MatrixLayout::kRowMajor,
|
||||
cutlass::Shape<32, 128, 128>,
|
||||
cutlass::Shape<32, 256, 128>,
|
||||
half,
|
||||
half,
|
||||
half,
|
||||
@@ -248,12 +275,283 @@ int profile_wmma_gemm_f16(
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
template <typename DummyT>
|
||||
int profile_wmma_4_gemm_f16(
|
||||
TestbenchOutput<GemmProblem> &output,
|
||||
TestbenchOptions const &options,
|
||||
Config const &config) {
|
||||
|
||||
typedef perf::GemmProfiler<
|
||||
cutlass::half_t,
|
||||
cutlass::half_t,
|
||||
cutlass::half_t,
|
||||
cutlass::half_t,
|
||||
cutlass::half_t> GemmProfiler;
|
||||
|
||||
int results = 0;
|
||||
|
||||
// a set of test requires leading dim to be multiple of 4 instead of 8
|
||||
|
||||
{
|
||||
typedef cutlass::gemm::WmmaGemmTraits<
|
||||
cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::MatrixLayout::kRowMajor,
|
||||
cutlass::Shape<32, 16, 16>,
|
||||
half,
|
||||
half,
|
||||
half,
|
||||
cutlass::gemm::LinearScaling<half>,
|
||||
half,
|
||||
typename cutlass::gemm::WmmaGemmAccumulatorsPerWarp<typename cutlass::Shape<32, 16, 16> >::Shape,
|
||||
typename cutlass::Shape<16, 16, 16>,
|
||||
4, /*kScalarsPerLdgA_*/
|
||||
4, /*kScalarsPerLdgB_*/
|
||||
4, /*KScalarsPerLdsA_*/
|
||||
4, /*KScalarsPerLdsB_*/
|
||||
4 / sizeof(half), /*kScalarsPerLdgCAndStgD_*/
|
||||
4 / sizeof(half), /*kScalarsPerStsD_*/
|
||||
4 / sizeof(half) /*kScalarsPerLdsD_*/
|
||||
>
|
||||
WmmaGemmTraits;
|
||||
|
||||
typedef WmmaGemmDispatch<WmmaGemmTraits> Dispatch;
|
||||
|
||||
results |= profile_gemm<Dispatch, GemmProfiler>(output, "wmma_4_gemm_f16_nt", options, config);
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::gemm::WmmaGemmTraits<
|
||||
cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::Shape<32, 16, 16>,
|
||||
half,
|
||||
half,
|
||||
half,
|
||||
cutlass::gemm::LinearScaling<half>,
|
||||
half,
|
||||
typename cutlass::gemm::WmmaGemmAccumulatorsPerWarp<typename cutlass::Shape<32, 16, 16> >::Shape,
|
||||
typename cutlass::Shape<16, 16, 16>,
|
||||
4, /*kScalarsPerLdgA_*/
|
||||
4, /*kScalarsPerLdgB_*/
|
||||
4, /*KScalarsPerLdsA_*/
|
||||
4, /*KScalarsPerLdsB_*/
|
||||
4 / sizeof(half), /*kScalarsPerLdgCAndStgD_*/
|
||||
4 / sizeof(half), /*kScalarsPerStsD_*/
|
||||
4 / sizeof(half) /*kScalarsPerLdsD_*/
|
||||
>
|
||||
WmmaGemmTraits;
|
||||
|
||||
typedef WmmaGemmDispatch<WmmaGemmTraits> Dispatch;
|
||||
|
||||
results |= profile_gemm<Dispatch, GemmProfiler>(output, "wmma_4_gemm_f16_nn", options, config);
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::gemm::WmmaGemmTraits<
|
||||
cutlass::MatrixLayout::kRowMajor,
|
||||
cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::Shape<32, 16, 16>,
|
||||
half,
|
||||
half,
|
||||
half,
|
||||
cutlass::gemm::LinearScaling<half>,
|
||||
half,
|
||||
typename cutlass::gemm::WmmaGemmAccumulatorsPerWarp<typename cutlass::Shape<32, 16, 16> >::Shape,
|
||||
typename cutlass::Shape<16, 16, 16>,
|
||||
4, /*kScalarsPerLdgA_*/
|
||||
4, /*kScalarsPerLdgB_*/
|
||||
4, /*KScalarsPerLdsA_*/
|
||||
4, /*KScalarsPerLdsB_*/
|
||||
4 / sizeof(half), /*kScalarsPerLdgCAndStgD_*/
|
||||
4 / sizeof(half), /*kScalarsPerStsD_*/
|
||||
4 / sizeof(half) /*kScalarsPerLdsD_*/
|
||||
>
|
||||
WmmaGemmTraits;
|
||||
|
||||
typedef WmmaGemmDispatch<WmmaGemmTraits> Dispatch;
|
||||
|
||||
results |= profile_gemm<Dispatch, GemmProfiler>(output, "wmma_4_gemm_f16_tn", options, config);
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::gemm::WmmaGemmTraits<
|
||||
cutlass::MatrixLayout::kRowMajor,
|
||||
cutlass::MatrixLayout::kRowMajor,
|
||||
cutlass::Shape<32, 16, 16>,
|
||||
half,
|
||||
half,
|
||||
half,
|
||||
cutlass::gemm::LinearScaling<half>,
|
||||
half,
|
||||
typename cutlass::gemm::WmmaGemmAccumulatorsPerWarp<typename cutlass::Shape<32, 16, 16> >::Shape,
|
||||
typename cutlass::Shape<16, 16, 16>,
|
||||
4, /*kScalarsPerLdgA_*/
|
||||
4, /*kScalarsPerLdgB_*/
|
||||
4, /*KScalarsPerLdsA_*/
|
||||
4, /*KScalarsPerLdsB_*/
|
||||
4 / sizeof(half), /*kScalarsPerLdgCAndStgD_*/
|
||||
4 / sizeof(half), /*kScalarsPerStsD_*/
|
||||
4 / sizeof(half) /*kScalarsPerLdsD_*/
|
||||
>
|
||||
WmmaGemmTraits;
|
||||
|
||||
typedef WmmaGemmDispatch<WmmaGemmTraits> Dispatch;
|
||||
|
||||
results |= profile_gemm<Dispatch, GemmProfiler>(output, "wmma_4_gemm_f16_tt", options, config);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
template <typename DummyT>
|
||||
int profile_wmma_4_fp16_sgemm_fp16(
|
||||
TestbenchOutput<GemmProblem> &output,
|
||||
TestbenchOptions const &options,
|
||||
Config const &config) {
|
||||
|
||||
typedef perf::GemmProfiler<
|
||||
cutlass::half_t,
|
||||
cutlass::half_t,
|
||||
cutlass::half_t,
|
||||
float,
|
||||
float> GemmProfiler;
|
||||
|
||||
int results = 0;
|
||||
|
||||
// a set of test requires leading dim to be multiple of 4 instead of 8
|
||||
|
||||
{
|
||||
typedef float accumu_type;
|
||||
typedef half c_type;
|
||||
typedef cutlass::gemm::WmmaGemmTraits<
|
||||
cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::MatrixLayout::kRowMajor,
|
||||
cutlass::Shape<32, 16, 16>,
|
||||
half,
|
||||
half,
|
||||
c_type,
|
||||
cutlass::gemm::LinearScaling<accumu_type>,
|
||||
accumu_type,
|
||||
typename cutlass::gemm::WmmaGemmAccumulatorsPerWarp<typename cutlass::Shape<32, 16, 16> >::Shape,
|
||||
typename cutlass::Shape<16, 16, 16>,
|
||||
4, /*kScalarsPerLdgA_*/
|
||||
4, /*kScalarsPerLdgB_*/
|
||||
4, /*KScalarsPerLdsA_*/
|
||||
4, /*KScalarsPerLdsB_*/
|
||||
8 / sizeof(c_type), /*kScalarsPerLdgCAndStgD_*/
|
||||
8 / sizeof(accumu_type), /*kScalarsPerStsD_*/
|
||||
8 / sizeof(accumu_type) /*kScalarsPerLdsD_*/
|
||||
>
|
||||
WmmaGemmTraits;
|
||||
|
||||
typedef WmmaGemmDispatch<WmmaGemmTraits> Dispatch;
|
||||
|
||||
results |= profile_gemm<Dispatch, GemmProfiler>(output, "wmma_4_fp16_sgemm_fp16_nt", options, config);
|
||||
}
|
||||
|
||||
{
|
||||
typedef float accumu_type;
|
||||
typedef half c_type;
|
||||
typedef cutlass::gemm::WmmaGemmTraits<
|
||||
cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::Shape<32, 16, 16>,
|
||||
half,
|
||||
half,
|
||||
c_type,
|
||||
cutlass::gemm::LinearScaling<accumu_type>,
|
||||
accumu_type,
|
||||
typename cutlass::gemm::WmmaGemmAccumulatorsPerWarp<typename cutlass::Shape<32, 16, 16> >::Shape,
|
||||
typename cutlass::Shape<16, 16, 16>,
|
||||
4, /*kScalarsPerLdgA_*/
|
||||
4, /*kScalarsPerLdgB_*/
|
||||
4, /*KScalarsPerLdsA_*/
|
||||
4, /*KScalarsPerLdsB_*/
|
||||
8 / sizeof(c_type), /*kScalarsPerLdgCAndStgD_*/
|
||||
8 / sizeof(accumu_type), /*kScalarsPerStsD_*/
|
||||
8 / sizeof(accumu_type) /*kScalarsPerLdsD_*/
|
||||
>
|
||||
WmmaGemmTraits;
|
||||
|
||||
typedef WmmaGemmDispatch<WmmaGemmTraits> Dispatch;
|
||||
|
||||
results |= profile_gemm<Dispatch, GemmProfiler>(output, "wmma_4_fp16_sgemm_fp16_nn", options, config);
|
||||
}
|
||||
|
||||
{
|
||||
typedef float accumu_type;
|
||||
typedef half c_type;
|
||||
typedef cutlass::gemm::WmmaGemmTraits<
|
||||
cutlass::MatrixLayout::kRowMajor,
|
||||
cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::Shape<32, 16, 16>,
|
||||
half,
|
||||
half,
|
||||
c_type,
|
||||
cutlass::gemm::LinearScaling<accumu_type>,
|
||||
accumu_type,
|
||||
typename cutlass::gemm::WmmaGemmAccumulatorsPerWarp<typename cutlass::Shape<32, 16, 16> >::Shape,
|
||||
typename cutlass::Shape<16, 16, 16>,
|
||||
4, /*kScalarsPerLdgA_*/
|
||||
4, /*kScalarsPerLdgB_*/
|
||||
4, /*KScalarsPerLdsA_*/
|
||||
4, /*KScalarsPerLdsB_*/
|
||||
8 / sizeof(c_type), /*kScalarsPerLdgCAndStgD_*/
|
||||
8 / sizeof(accumu_type), /*kScalarsPerStsD_*/
|
||||
8 / sizeof(accumu_type) /*kScalarsPerLdsD_*/
|
||||
>
|
||||
WmmaGemmTraits;
|
||||
|
||||
typedef WmmaGemmDispatch<WmmaGemmTraits> Dispatch;
|
||||
|
||||
results |= profile_gemm<Dispatch, GemmProfiler>(output, "wmma_4_fp16_sgemm_fp16_tn", options, config);
|
||||
}
|
||||
|
||||
{
|
||||
typedef float accumu_type;
|
||||
typedef half c_type;
|
||||
typedef cutlass::gemm::WmmaGemmTraits<
|
||||
cutlass::MatrixLayout::kRowMajor,
|
||||
cutlass::MatrixLayout::kRowMajor,
|
||||
cutlass::Shape<32, 16, 16>,
|
||||
half,
|
||||
half,
|
||||
c_type,
|
||||
cutlass::gemm::LinearScaling<accumu_type>,
|
||||
accumu_type,
|
||||
typename cutlass::gemm::WmmaGemmAccumulatorsPerWarp<typename cutlass::Shape<32, 16, 16> >::Shape,
|
||||
typename cutlass::Shape<16, 16, 16>,
|
||||
4, /*kScalarsPerLdgA_*/
|
||||
4, /*kScalarsPerLdgB_*/
|
||||
4, /*KScalarsPerLdsA_*/
|
||||
4, /*KScalarsPerLdsB_*/
|
||||
8 / sizeof(c_type), /*kScalarsPerLdgCAndStgD_*/
|
||||
8 / sizeof(accumu_type), /*kScalarsPerStsD_*/
|
||||
8 / sizeof(accumu_type) /*kScalarsPerLdsD_*/
|
||||
>
|
||||
WmmaGemmTraits;
|
||||
|
||||
typedef WmmaGemmDispatch<WmmaGemmTraits> Dispatch;
|
||||
|
||||
results |= profile_gemm<Dispatch, GemmProfiler>(output, "wmma_4_fp16_sgemm_fp16_tt", options, config);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct WmmaGemmRegistrar {
|
||||
WmmaGemmRegistrar() {
|
||||
RegisterGemmProfileFunc(profile_wmma_gemm_f32);
|
||||
RegisterGemmProfileFunc(profile_wmma_gemm_f16);
|
||||
RegisterGemmProfileFunc(profile_wmma_gemm_f32<void>);
|
||||
RegisterGemmProfileFunc(profile_wmma_gemm_f16<void>);
|
||||
|
||||
//#ifdef EXHAUSTIVE_PROF
|
||||
RegisterGemmProfileFunc(profile_wmma_4_gemm_f16<void>);
|
||||
//fp32 accum with fp16 input and output
|
||||
RegisterGemmProfileFunc(profile_wmma_4_fp16_sgemm_fp16<void>);
|
||||
//#endif // defined EXHAUSTIVE_PROF
|
||||
}
|
||||
};
|
||||
|
||||
@@ -266,3 +564,4 @@ volatile WmmaGemmRegistrar _WmmaGemmRegistrar;
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // defined CUTLASS_USE_WMMA_API
|
||||
|
||||
|
||||
@@ -74,6 +74,15 @@ struct WmmaIntegerGemmDispatch {
|
||||
params.initialize(m, n, k, alpha, d_a, lda, d_b, ldb, beta, d_c, ldc, d_d, ldd);
|
||||
}
|
||||
|
||||
///
|
||||
WmmaIntegerGemmDispatch(int m, int n, int k, int alpha,
|
||||
ScalarA const* d_a, int lda, long long int batch_stride_a,
|
||||
ScalarB const* d_b, int ldb, long long int batch_stride_b, int beta,
|
||||
int const* d_c, int ldc, long long int batch_stride_c, int* d_d, int ldd, long long int batch_stride_d,
|
||||
int batch_count) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/// Initializes params object
|
||||
WmmaIntegerGemmDispatch(Params const& _params) : params(_params) {}
|
||||
|
||||
@@ -125,6 +134,15 @@ struct WmmaIntegerGemmDispatch<Traits,
|
||||
params.initialize(m, n, k * 8, alpha, d_a, lda, d_b, ldb, beta, d_c, ldc, d_d, ldd);
|
||||
}
|
||||
|
||||
///
|
||||
WmmaIntegerGemmDispatch(int m, int n, int k, int alpha,
|
||||
ScalarA const* d_a, int lda, long long int batch_stride_a,
|
||||
ScalarB const* d_b, int ldb, long long int batch_stride_b, int beta,
|
||||
int const* d_c, int ldc, long long int batch_stride_c, int* d_d, int ldd, long long int batch_stride_d,
|
||||
int batch_count) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/// Initializes params object
|
||||
WmmaIntegerGemmDispatch(Params const& _params) : params(_params) {}
|
||||
|
||||
@@ -176,6 +194,15 @@ struct WmmaIntegerGemmDispatch<Traits,
|
||||
params.initialize(m, n, k * 8, alpha, d_a, lda, d_b, ldb, beta, d_c, ldc, d_d, ldd);
|
||||
}
|
||||
|
||||
///
|
||||
WmmaIntegerGemmDispatch(int m, int n, int k, int alpha,
|
||||
ScalarA const* d_a, int lda, long long int batch_stride_a,
|
||||
ScalarB const* d_b, int ldb, long long int batch_stride_b, int beta,
|
||||
int const* d_c, int ldc, long long int batch_stride_c, int* d_d, int ldd, long long int batch_stride_d,
|
||||
int batch_count) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/// Initializes params object
|
||||
WmmaIntegerGemmDispatch(Params const& _params) : params(_params) {}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
**************************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include "cutlass/matrix_traits.h"
|
||||
#include "tools/util/command_line.h"
|
||||
#include "tools/test/perf/provider.h"
|
||||
@@ -85,6 +85,7 @@ struct GemmProblem {
|
||||
int m;
|
||||
int n;
|
||||
int k;
|
||||
int batch_count;
|
||||
cutlass::MatrixLayout::Kind layout_A;
|
||||
cutlass::MatrixLayout::Kind layout_B;
|
||||
|
||||
@@ -96,7 +97,7 @@ struct GemmProblem {
|
||||
//
|
||||
|
||||
/// Static method to print GemmProblem headers
|
||||
static std::string header() { return "M,N,K,Layout_A,Layout_B,Beta"; }
|
||||
static std::string header() { return "M,N,K,Layout_A,Layout_B,Beta,batch_count"; }
|
||||
|
||||
//
|
||||
// Methods
|
||||
@@ -108,21 +109,24 @@ struct GemmProblem {
|
||||
cutlass::MatrixLayout::Kind _layout_A = cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::MatrixLayout::Kind _layout_B = cutlass::MatrixLayout::kRowMajor,
|
||||
double _alpha = 1,
|
||||
double _beta = 0)
|
||||
: m(_m), n(_n), k(_k), layout_A(_layout_A), layout_B(_layout_B), alpha(_alpha), beta(_beta) {}
|
||||
double _beta = 0,
|
||||
int _batch_count = 1)
|
||||
: m(_m), n(_n), k(_k), layout_A(_layout_A), layout_B(_layout_B), alpha(_alpha), beta(_beta), batch_count(_batch_count) {
|
||||
assert(batch_count >= 1);
|
||||
}
|
||||
|
||||
/// leading dimension of A
|
||||
int lda() const {
|
||||
if (layout_A == cutlass::MatrixLayout::kColumnMajor) {
|
||||
return m;
|
||||
}
|
||||
return k;
|
||||
return k * batch_count;
|
||||
}
|
||||
|
||||
/// leading dimension of B
|
||||
int ldb() const {
|
||||
if (layout_B == cutlass::MatrixLayout::kColumnMajor) {
|
||||
return k;
|
||||
return k * batch_count;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
@@ -130,10 +134,35 @@ struct GemmProblem {
|
||||
/// leading dimension of C
|
||||
int ldc() const { return m; }
|
||||
|
||||
/// batch_stride_a. only makes sense when batch_count > 1
|
||||
long long int batch_stride_a() const {
|
||||
assert(batch_count > 1);
|
||||
if (layout_A == cutlass::MatrixLayout::kColumnMajor) {
|
||||
return static_cast<long long int>(k) * static_cast<long long int>(lda());
|
||||
}
|
||||
return static_cast<long long int>(k);
|
||||
}
|
||||
|
||||
/// batch_stride_b. only makes sense when batch_count > 1
|
||||
long long int batch_stride_b() const {
|
||||
assert(batch_count > 1);
|
||||
if (layout_B == cutlass::MatrixLayout::kColumnMajor) {
|
||||
return static_cast<long long int>(k);
|
||||
}
|
||||
return static_cast<long long int>(k) * static_cast<long long int>(ldb());
|
||||
}
|
||||
|
||||
/// batch_stride_c. only makes sense when batch_count > 1
|
||||
long long int batch_stride_c() const {
|
||||
assert(batch_count > 1);
|
||||
return static_cast<long long int>(n) * static_cast<long long int>(ldc());
|
||||
}
|
||||
|
||||
|
||||
/// Pretty prints output
|
||||
std::ostream &pretty_print(std::ostream &out) const {
|
||||
out << m << "-by-" << n << "-by-" << k << ", A: " << layout_A << "-major, B: " << layout_B
|
||||
<< "-major, beta: " << beta;
|
||||
<< "-major, beta: " << beta << ", batch: " << batch_count;
|
||||
|
||||
return out;
|
||||
}
|
||||
@@ -142,7 +171,7 @@ struct GemmProblem {
|
||||
/// Prints a problem to an output stream
|
||||
inline std::ostream &operator<<(std::ostream &out, GemmProblem const &problem) {
|
||||
out << problem.m << "," << problem.n << "," << problem.k << "," << problem.layout_A << ","
|
||||
<< problem.layout_B << "," << problem.beta;
|
||||
<< problem.layout_B << "," << problem.beta << "," << problem.batch_count;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -125,13 +125,16 @@ struct GemmProblemRange {
|
||||
/// Range of sizes in GEMM K dimension
|
||||
Range K;
|
||||
|
||||
/// Range of sizes in batch dimeion
|
||||
Range batch_count;
|
||||
|
||||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
/// Constructor to define a space of probelm sizes
|
||||
GemmProblemRange(Range _M = Range(256), Range _N = Range(256), Range _K = Range(256))
|
||||
: M(_M), N(_N), K(_K) {}
|
||||
GemmProblemRange(Range _M = Range(256), Range _N = Range(256), Range _K = Range(256), Range _batch_count = Range(1))
|
||||
: M(_M), N(_N), K(_K), batch_count(_batch_count) {}
|
||||
|
||||
/// Parses a command line argument as a Range object
|
||||
static void get_range(Range &range,
|
||||
@@ -155,6 +158,7 @@ struct GemmProblemRange {
|
||||
get_range(M, args, "m", Range(10240));
|
||||
get_range(N, args, "n", Range(4096));
|
||||
get_range(K, args, "k", Range(4096));
|
||||
get_range(batch_count, args, "batch", Range(1));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -368,7 +372,7 @@ struct TestbenchOptions {
|
||||
|
||||
/// Number of iterations
|
||||
int iterations;
|
||||
|
||||
|
||||
/// Defines how to run the benchmark
|
||||
ExecutionMode::Kind execution_mode;
|
||||
|
||||
@@ -599,6 +603,9 @@ struct TestbenchOptions {
|
||||
<< " --k=<depth>[:max depth[:step]] "
|
||||
<< " Size of inner dimension of A and B. May specify a range with optional step size.\n"
|
||||
|
||||
<< " --batch=<batch> "
|
||||
<< " Number of batches for a bached gemm. "
|
||||
|
||||
<< " --kernels=<{s|d|h|i|wmma_|wmma_binary_|wmma_integer_}gemm_{nn,nt,tn,tt}>\n"
|
||||
<< " "
|
||||
<< " Select GEMM datatype and layout to use for tests\n"
|
||||
|
||||
Reference in New Issue
Block a user