co-authored by
Aniket Shivam
parent
9b8166e3f0
commit
d572cc1aab
@@ -159,7 +159,7 @@ class DualGemm {
|
||||
using Mma0 = typename cutlass::gemm::threadblock::DefaultMma<
|
||||
ElementA, LayoutA, kAlignmentA, ElementB, LayoutB0, kAlignmentB,
|
||||
ElementAccumulator, layout::RowMajor, arch::OpClassTensorOp, ArchTag,
|
||||
ThreadblockShape, WarpShape,
|
||||
ThreadblockShape, WarpShape,
|
||||
InstructionShape, Stages, Operator>::ThreadblockMma;
|
||||
using Mma1 = typename cutlass::gemm::threadblock::DefaultMma<
|
||||
ElementA, LayoutA, kAlignmentA, ElementB, LayoutB1, kAlignmentB,
|
||||
@@ -348,7 +348,7 @@ public:
|
||||
ThreadblockSwizzle threadblock_swizzle;
|
||||
|
||||
cutlass::gemm::GemmCoord tiled_shape = threadblock_swizzle.get_tiled_shape(
|
||||
args.problem_size,
|
||||
args.problem_size,
|
||||
{ThreadblockShape::kM, ThreadblockShape::kN, ThreadblockShape::kK},
|
||||
args.split_k_slices);
|
||||
|
||||
|
||||
@@ -167,10 +167,10 @@ bool run_nonfused_gemm_f16_sm80() {
|
||||
std::cout << "Running Non-fused GEMMs FP16 TN GEMMs...\n";
|
||||
|
||||
bool pass = nonFusedGemm.run(
|
||||
problem_size,
|
||||
alpha0,
|
||||
beta0,
|
||||
alpha1,
|
||||
problem_size,
|
||||
alpha0,
|
||||
beta0,
|
||||
alpha1,
|
||||
beta1,
|
||||
true /* is_profiling */
|
||||
);
|
||||
@@ -248,10 +248,10 @@ bool run_fused_gemm_f16_sm80_shmem() {
|
||||
std::cout << "Running Fused FP16 TN GEMMs + Epilogue2...\n";
|
||||
|
||||
bool passed = fusedGemm.run(
|
||||
problem_size,
|
||||
alpha0,
|
||||
beta0,
|
||||
alpha1,
|
||||
problem_size,
|
||||
alpha0,
|
||||
beta0,
|
||||
alpha1,
|
||||
beta1
|
||||
);
|
||||
|
||||
@@ -301,11 +301,11 @@ bool run_batched_fused_gemm_f16_sm80_shmem() {
|
||||
std::cout << "Running Batched Fused FP16 TN GEMMs + Epilogue2...\n";
|
||||
|
||||
bool passed = fusedGemm.run(
|
||||
batch_problem_size,
|
||||
alpha0,
|
||||
beta0,
|
||||
alpha1,
|
||||
beta1,
|
||||
batch_problem_size,
|
||||
alpha0,
|
||||
beta0,
|
||||
alpha1,
|
||||
beta1,
|
||||
kBatchCount,
|
||||
false, /* broadcast_b1 */
|
||||
false /* is_profiling */
|
||||
@@ -358,11 +358,11 @@ bool run_broadcast_fused_gemm_f16_sm80_shmem() {
|
||||
std::cout << "Running Broadcast Fused FP16 TN GEMMs + Epilogue2...\n";
|
||||
|
||||
bool passed = fusedGemm.run(
|
||||
problem_size,
|
||||
alpha0,
|
||||
beta0,
|
||||
alpha1,
|
||||
beta1,
|
||||
problem_size,
|
||||
alpha0,
|
||||
beta0,
|
||||
alpha1,
|
||||
beta1,
|
||||
1, /* batch_count */
|
||||
true, /* broadcast_b1 */
|
||||
true /* is_profiling */
|
||||
@@ -415,11 +415,11 @@ bool run_batched_broadcast_fused_gemm_f16_sm80_shmem() {
|
||||
std::cout << "Running Batch Broadcast Fused FP16 TN GEMMs + Epilogue2...\n";
|
||||
|
||||
bool passed = fusedGemm.run(
|
||||
batch_problem_size,
|
||||
alpha0,
|
||||
beta0,
|
||||
alpha1,
|
||||
beta1,
|
||||
batch_problem_size,
|
||||
alpha0,
|
||||
beta0,
|
||||
alpha1,
|
||||
beta1,
|
||||
kBatchCount,
|
||||
true, /* broadcast_b1 */
|
||||
false /* is_profiling */
|
||||
@@ -444,11 +444,11 @@ int main() {
|
||||
};
|
||||
|
||||
std::string test_name = (
|
||||
"dual-gemm f16 bias=" +
|
||||
std::to_string(kUseBias) +
|
||||
" split_k_serial=" +
|
||||
"dual-gemm f16 bias=" +
|
||||
std::to_string(kUseBias) +
|
||||
" split_k_serial=" +
|
||||
std::to_string(kSplitKSerial) +
|
||||
" batch_count=" +
|
||||
" batch_count=" +
|
||||
std::to_string(kBatchCount)
|
||||
);
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "cutlass/util/reference/device/gemm.h"
|
||||
#include "cutlass/util/reference/device/tensor_relu.h"
|
||||
|
||||
#include "cutlass/platform/platform.h"
|
||||
#include "cutlass/gemm/gemm.h"
|
||||
#include "cutlass/gemm/device/gemm_universal.h"
|
||||
|
||||
@@ -356,13 +357,13 @@ struct NonFusedDualGemmRun
|
||||
|
||||
for(int i = 0; i < runs; i++) {
|
||||
status = gemm_op_0();
|
||||
|
||||
|
||||
CUTLASS_CHECK(status);
|
||||
}
|
||||
cudaEventRecord(stop1);
|
||||
for(int i = 0; i < runs; i++) {
|
||||
status = gemm_op_1();
|
||||
|
||||
|
||||
CUTLASS_CHECK(status);
|
||||
}
|
||||
|
||||
@@ -564,22 +565,22 @@ struct DualFusedGemmRun
|
||||
cutlass::HostTensor<
|
||||
typename DualGemm::ElementA,
|
||||
typename DualGemm::LayoutA> tensor_A0(
|
||||
std::is_same<typename DualGemm::LayoutA, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.m(), problem_size.k()) :
|
||||
cutlass::platform::is_same<typename DualGemm::LayoutA, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.m(), problem_size.k()) :
|
||||
cutlass::MatrixCoord(problem_size.m(), batch_count * problem_size.k()));
|
||||
|
||||
cutlass::HostTensor<
|
||||
typename DualGemm::ElementB,
|
||||
typename DualGemm::LayoutB0> tensor_B0(
|
||||
std::is_same<typename DualGemm::LayoutB0, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.k(), problem_size.n()) :
|
||||
cutlass::platform::is_same<typename DualGemm::LayoutB0, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.k(), problem_size.n()) :
|
||||
cutlass::MatrixCoord(problem_size.k(), batch_count * problem_size.n()));
|
||||
|
||||
cutlass::HostTensor<
|
||||
typename DualGemm::ElementC,
|
||||
typename DualGemm::LayoutC> tensor_C0(
|
||||
std::is_same<typename DualGemm::LayoutC, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.m(), problem_size.n()) :
|
||||
cutlass::platform::is_same<typename DualGemm::LayoutC, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.m(), problem_size.n()) :
|
||||
cutlass::MatrixCoord(problem_size.m(), batch_count * problem_size.n()));
|
||||
|
||||
cutlass::HostTensor<
|
||||
@@ -589,22 +590,22 @@ struct DualFusedGemmRun
|
||||
cutlass::HostTensor<
|
||||
typename DualGemm::ElementC,
|
||||
typename DualGemm::LayoutC> tensor_D0(
|
||||
std::is_same<typename DualGemm::LayoutC, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.m(), problem_size.n()) :
|
||||
cutlass::platform::is_same<typename DualGemm::LayoutC, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.m(), problem_size.n()) :
|
||||
cutlass::MatrixCoord(problem_size.m(), batch_count * problem_size.n()));
|
||||
|
||||
cutlass::HostTensor<
|
||||
typename DualGemm::ElementC,
|
||||
typename DualGemm::LayoutC> reference_D0(
|
||||
std::is_same<typename DualGemm::LayoutC, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.m(), problem_size.n()) :
|
||||
cutlass::platform::is_same<typename DualGemm::LayoutC, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.m(), problem_size.n()) :
|
||||
cutlass::MatrixCoord(problem_size.m(), batch_count * problem_size.n()));
|
||||
|
||||
cutlass::HostTensor<
|
||||
typename DualGemm::ElementB,
|
||||
typename DualGemm::LayoutB1> tensor_B1(
|
||||
std::is_same<typename DualGemm::LayoutB1, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.k(), problem_size.n()) :
|
||||
cutlass::platform::is_same<typename DualGemm::LayoutB1, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.k(), problem_size.n()) :
|
||||
cutlass::MatrixCoord(problem_size.k(), batch_count * problem_size.n()));
|
||||
if (broadcast_b1) {
|
||||
tensor_B1.resize({problem_size.k(), batch_count});
|
||||
@@ -613,8 +614,8 @@ struct DualFusedGemmRun
|
||||
cutlass::HostTensor<
|
||||
typename DualGemm::ElementC,
|
||||
typename DualGemm::LayoutC> tensor_C1(
|
||||
std::is_same<typename DualGemm::LayoutC, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.m(), problem_size.n()) :
|
||||
cutlass::platform::is_same<typename DualGemm::LayoutC, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.m(), problem_size.n()) :
|
||||
cutlass::MatrixCoord(problem_size.m(), batch_count * problem_size.n()));
|
||||
|
||||
cutlass::HostTensor<
|
||||
@@ -624,29 +625,29 @@ struct DualFusedGemmRun
|
||||
cutlass::HostTensor<
|
||||
typename DualGemm::ElementC,
|
||||
typename DualGemm::LayoutC> tensor_D1(
|
||||
std::is_same<typename DualGemm::LayoutC, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.m(), problem_size.n()) :
|
||||
cutlass::platform::is_same<typename DualGemm::LayoutC, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.m(), problem_size.n()) :
|
||||
cutlass::MatrixCoord(problem_size.m(), batch_count * problem_size.n()));
|
||||
|
||||
cutlass::HostTensor<
|
||||
typename DualGemm::ElementC,
|
||||
typename DualGemm::LayoutC> tensor_D2(
|
||||
std::is_same<typename DualGemm::LayoutC, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.m(), problem_size.n()) :
|
||||
cutlass::platform::is_same<typename DualGemm::LayoutC, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.m(), problem_size.n()) :
|
||||
cutlass::MatrixCoord(problem_size.m(), batch_count * problem_size.n()));
|
||||
|
||||
cutlass::HostTensor<
|
||||
typename DualGemm::ElementC,
|
||||
typename DualGemm::LayoutC> reference_D1(
|
||||
std::is_same<typename DualGemm::LayoutC, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.m(), problem_size.n()) :
|
||||
cutlass::platform::is_same<typename DualGemm::LayoutC, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.m(), problem_size.n()) :
|
||||
cutlass::MatrixCoord(problem_size.m(), batch_count * problem_size.n()));
|
||||
|
||||
cutlass::HostTensor<
|
||||
typename DualGemm::ElementC,
|
||||
typename DualGemm::LayoutC> reference_D2(
|
||||
std::is_same<typename DualGemm::LayoutC, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.m(), problem_size.n()) :
|
||||
cutlass::platform::is_same<typename DualGemm::LayoutC, cutlass::layout::RowMajor>::value ?
|
||||
cutlass::MatrixCoord(batch_count * problem_size.m(), problem_size.n()) :
|
||||
cutlass::MatrixCoord(problem_size.m(), batch_count * problem_size.n()));
|
||||
|
||||
CHECK_TRUE(initialize_tensor(tensor_A0.host_view(), init_A, seed + 2019));
|
||||
@@ -712,16 +713,16 @@ struct DualFusedGemmRun
|
||||
ref_B1 = {tensor_Bias1.device_data(), typename DualGemm::LayoutC::Stride(0)};
|
||||
}
|
||||
typename DualGemm::Arguments arguments{
|
||||
(batch_count > 1 ?
|
||||
cutlass::gemm::DualGemmMode::kBatched :
|
||||
(batch_count > 1 ?
|
||||
cutlass::gemm::DualGemmMode::kBatched :
|
||||
cutlass::gemm::DualGemmMode::kGemm),
|
||||
problem_size,
|
||||
tensor_A0.device_ref(),
|
||||
tensor_B0.device_ref(),
|
||||
ref_B0,
|
||||
DualGemm::kStoreD0 ? tensor_D0.device_ref() : nullptr_ref,
|
||||
(broadcast_b1 ?
|
||||
typename DualGemm::TensorRefB1(tensor_B1.device_data(), 0) :
|
||||
(broadcast_b1 ?
|
||||
typename DualGemm::TensorRefB1(tensor_B1.device_data(), 0) :
|
||||
tensor_B1.device_ref()),
|
||||
ref_B1,
|
||||
DualGemm::kStoreD1 ? tensor_D1.device_ref() : nullptr_ref,
|
||||
@@ -793,15 +794,15 @@ struct DualFusedGemmRun
|
||||
using GemmUniversal0 = cutlass::gemm::device::GemmUniversal<
|
||||
typename DualGemm::ElementA, typename DualGemm::LayoutA,
|
||||
typename DualGemm::ElementB, typename DualGemm::LayoutB0,
|
||||
typename DualGemm::ElementC, typename DualGemm::LayoutC,
|
||||
typename DualGemm::ElementC, typename DualGemm::LayoutC,
|
||||
ElementAccumulator
|
||||
>;
|
||||
|
||||
GemmUniversal0 reference_gemm0;
|
||||
|
||||
typename GemmUniversal0::Arguments args0 {
|
||||
(batch_count > 1 ?
|
||||
cutlass::gemm::GemmUniversalMode::kBatched :
|
||||
(batch_count > 1 ?
|
||||
cutlass::gemm::GemmUniversalMode::kBatched :
|
||||
cutlass::gemm::GemmUniversalMode::kGemm),
|
||||
problem_size,
|
||||
batch_count,
|
||||
@@ -828,15 +829,15 @@ struct DualFusedGemmRun
|
||||
using GemmUniversal1 = cutlass::gemm::device::GemmUniversal<
|
||||
typename DualGemm::ElementA, typename DualGemm::LayoutA,
|
||||
typename DualGemm::ElementB, typename DualGemm::LayoutB1,
|
||||
typename DualGemm::ElementC, typename DualGemm::LayoutC,
|
||||
typename DualGemm::ElementC, typename DualGemm::LayoutC,
|
||||
ElementAccumulator
|
||||
>;
|
||||
|
||||
GemmUniversal1 reference_gemm1;
|
||||
|
||||
typename GemmUniversal1::Arguments args1 {
|
||||
(batch_count > 1 ?
|
||||
cutlass::gemm::GemmUniversalMode::kBatched :
|
||||
(batch_count > 1 ?
|
||||
cutlass::gemm::GemmUniversalMode::kBatched :
|
||||
cutlass::gemm::GemmUniversalMode::kGemm),
|
||||
problem_size,
|
||||
batch_count,
|
||||
@@ -861,7 +862,7 @@ struct DualFusedGemmRun
|
||||
CUTLASS_CHECK(status);
|
||||
|
||||
if(relu) {
|
||||
cutlass::reference::device::TensorReLu(reference_D0.device_view());
|
||||
cutlass::reference::device::TensorReLu(reference_D0.device_view());
|
||||
cutlass::reference::device::TensorReLu(reference_D1.device_view());
|
||||
}
|
||||
|
||||
|
||||
@@ -300,7 +300,7 @@ struct DualGemm {
|
||||
int offset_k = 0;
|
||||
int problem_size_k = params.problem_size.k();
|
||||
|
||||
ElementA *ptr_A0 = static_cast<ElementA *>(params.ref_A0.data());
|
||||
ElementA *ptr_A0 = static_cast<ElementA *>(params.ref_A0.data());
|
||||
ElementB *ptr_B0 = static_cast<ElementB *>(params.ref_B0.data());
|
||||
ElementB *ptr_B1 = static_cast<ElementB *>(params.ref_B1.data());
|
||||
|
||||
@@ -309,7 +309,7 @@ struct DualGemm {
|
||||
//
|
||||
if (params.mode == DualGemmMode::kGemm) {
|
||||
if (threadblock_tile_offset.k() + 1 < params.grid_tiled_shape.k()) {
|
||||
problem_size_k = (threadblock_tile_offset.k() + 1) * params.gemm_k_size;
|
||||
problem_size_k = (threadblock_tile_offset.k() + 1) * params.gemm_k_size;
|
||||
}
|
||||
|
||||
offset_k = threadblock_tile_offset.k() * params.gemm_k_size;
|
||||
@@ -413,11 +413,11 @@ struct DualGemm {
|
||||
|
||||
int block_idx = threadblock_tile_offset.m() + threadblock_tile_offset.n() * params.grid_tiled_shape.m();
|
||||
|
||||
ElementC *ptr_C0 = static_cast<ElementC *>(params.ref_C0.data());
|
||||
ElementC *ptr_C1 = static_cast<ElementC *>(params.ref_C1.data());
|
||||
ElementC *ptr_D0 = static_cast<ElementC *>(params.ref_D0.data());
|
||||
ElementC *ptr_D1 = static_cast<ElementC *>(params.ref_D1.data());
|
||||
ElementC *ptr_D2 = static_cast<ElementC *>(params.ref_D2.data());
|
||||
ElementC *ptr_C0 = static_cast<ElementC *>(params.ref_C0.data());
|
||||
ElementC *ptr_C1 = static_cast<ElementC *>(params.ref_C1.data());
|
||||
ElementC *ptr_D0 = static_cast<ElementC *>(params.ref_D0.data());
|
||||
ElementC *ptr_D1 = static_cast<ElementC *>(params.ref_D1.data());
|
||||
ElementC *ptr_D2 = static_cast<ElementC *>(params.ref_D2.data());
|
||||
|
||||
// Construct the semaphore.
|
||||
Semaphore semaphore(params.semaphore + block_idx, thread_idx);
|
||||
@@ -425,7 +425,7 @@ struct DualGemm {
|
||||
if (params.mode == DualGemmMode::kGemm) {
|
||||
// If performing a reduction via split-K, fetch the initial synchronization
|
||||
if (kSplitKSerial && params.grid_tiled_shape.k() > 1) {
|
||||
|
||||
|
||||
// Fetch the synchronization lock initially but do not block.
|
||||
semaphore.fetch();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user