Fix typos 2 (#842)
Co-authored-by: Haicheng Wu <57973641+hwu36@users.noreply.github.com>
This commit is contained in:
co-authored by
Haicheng Wu
parent
c4f6b8c6bc
commit
7e370c9637
@@ -47,7 +47,7 @@
|
||||
or utilities within CUTLASS. Such utilities are demonstrated elsewhere in other examples and are
|
||||
prevalent in the CUTLASS unit tests.
|
||||
|
||||
This example has delibrately been kept similar to the basic_gemm example from cutass-1.3 to
|
||||
This example has delibrately been kept similar to the basic_gemm example from cutlass-1.3 to
|
||||
highlight the minimum amount of differences needed to transition to cutlass-2.0.
|
||||
|
||||
Cutlass-1.3 sgemm: https://github.com/NVIDIA/cutlass/blob/master/examples/00_basic_gemm/basic_gemm.cu
|
||||
|
||||
@@ -75,7 +75,7 @@ Now that we setup the properties of data, we have to setup properties of computa
|
||||
Second, we create template variables of tile sizes for thread-block, warp and mma-op to 128x128x32,
|
||||
64x64x32, 8x8x4 (MxNxK) respectively. When passed to instantiate CUTLASS GEMM kernel, it internally
|
||||
deduce the amount of threads needed per thread-block, amount of shared memory, storing data in
|
||||
bank-conflict free manner, and ton of other variables required to compose, intialize and launch a
|
||||
bank-conflict free manner, and ton of other variables required to compose, initialize and launch a
|
||||
high performance GEMM kernel. This is the beauty of CUTLASS, it relieves developer from
|
||||
understanding and coding complicated hardware optimizations which can easily go wrong.
|
||||
|
||||
@@ -107,7 +107,7 @@ is done which threadblock launched on an SM, CUDA SM architecture of GPU you wan
|
||||
These are all put together to create a template variable which describes CUTLASS GEMM kernel using
|
||||
cutlass::gemm::device::Gemm template.
|
||||
|
||||
The next step is to intialize physical data, instantiate and initialize CUTLASS kernel and run it.
|
||||
The next step is to initialize physical data, instantiate and initialize CUTLASS kernel and run it.
|
||||
We use CUTLASS utilities to initialize, fill, compare matrices as they are simple and doesn't come
|
||||
in the way of learning CUTLASS.
|
||||
|
||||
@@ -115,7 +115,7 @@ Once all the matrices are initialized and filled with data, create arguments tup
|
||||
kernel which takes problem size (M = 5120, N = 4096 and K = 4096), matrices, alpha, beta and the
|
||||
important one, split k-dimension factor. Along with that, we query CUTLASS if any scratch-space
|
||||
memory required by the kernel we instantiated. If yes, we create it and pass it along with other
|
||||
arguments created to intialize CUTLASS kernel then, the kernel is launched.
|
||||
arguments created to initialize CUTLASS kernel then, the kernel is launched.
|
||||
|
||||
In this example, we later on launch a reference gemm kernel (from CUTLASS utilities) to compare if
|
||||
the output from CUTLASS kernel is same as reference GEMM kernel.
|
||||
|
||||
@@ -74,7 +74,7 @@ Now that we setup the properties of data, we have to setup properties of computa
|
||||
Second, we create template variables of tile sizes for thread-block, warp and mma-op to 128x256x64,
|
||||
64x64x16, 8x8x16 (MxNxK) respectively. When passed to instantiate CUTLASS GEMM kernel, it internally
|
||||
deduce the amount of threads needed per thread-block, amount of shared memory, storing data in
|
||||
bank-conflict free manner, and ton of other variables required to compose, intialize and launch a
|
||||
bank-conflict free manner, and ton of other variables required to compose, initialize and launch a
|
||||
high performance GEMM kernel. This is the beauty of CUTLASS, it relieves developer from
|
||||
understanding and coding complicated hardware optimizations which can easily go wrong.
|
||||
|
||||
@@ -106,7 +106,7 @@ is done which threadblock launched on an SM, CUDA SM architecture of GPU you wan
|
||||
These are all put together to create a template variable which describes CUTLASS GEMM kernel using
|
||||
cutlass::gemm::device::Gemm template.
|
||||
|
||||
The next step is to intialize physical data, instantiate and initialize CUTLASS kernel and run it.
|
||||
The next step is to initialize physical data, instantiate and initialize CUTLASS kernel and run it.
|
||||
We use CUTLASS utilities to initialize, fill, compare matrices as they are simple and doesn't come
|
||||
in the way of learning CUTLASS.
|
||||
|
||||
@@ -114,7 +114,7 @@ Once all the matrices are initialized and filled with data, create arguments tup
|
||||
kernel which takes problem size (M = 5120, N = 4096 and K = 4096), matrices, alpha, beta and the
|
||||
important one, split k-dimension factor. Along with that, we query CUTLASS if any scratch-space
|
||||
memory required by the kernel we instantiated. If yes, we create it and pass it along with other
|
||||
arguments created to intialize CUTLASS kernel then, the kernel is launched.
|
||||
arguments created to initialize CUTLASS kernel then, the kernel is launched.
|
||||
|
||||
In this example, we later on launch a reference gemm kernel (from CUTLASS utilities) to compare if
|
||||
the output from CUTLASS kernel is same as reference GEMM kernel.
|
||||
|
||||
@@ -76,7 +76,7 @@ Now that we setup the properties of data, we have to setup properties of computa
|
||||
Second, we create template variables of tile sizes for thread-block, warp and mma-op to 128x128x128,
|
||||
64x64x128, 8x8x32 (MxNxK) respectively. When passed to instantiate CUTLASS Implicit GEMM kernel, it
|
||||
internally deduces the amount of threads needed per thread-block, amount of shared memory, storing
|
||||
data in bank-conflict free manner, and ton of other variables required to compose, intialize and
|
||||
data in bank-conflict free manner, and ton of other variables required to compose, initialize and
|
||||
launch a high performance Implicit GEMM kernel. This is the beauty of CUTLASS, it relieves developer
|
||||
from understanding and coding complicated hardware optimizations which can easily go wrong.
|
||||
|
||||
@@ -108,7 +108,7 @@ is done which threadblock launched on an SM, CUDA SM architecture of GPU you wan
|
||||
These are all put together to create a template variable which describes CUTLASS Implicit GEMM
|
||||
kernel using cutlass::conv::device::ImplicitGemm template.
|
||||
|
||||
The next step is to intialize physical data, instantiate and initialize CUTLASS kernel and run it.
|
||||
The next step is to initialize physical data, instantiate and initialize CUTLASS kernel and run it.
|
||||
We use CUTLASS utilities to initialize, fill, compare tensors as they are simple and doesn't come
|
||||
in the way of learning CUTLASS.
|
||||
|
||||
@@ -117,7 +117,7 @@ kernel which takes problem size (N = 1, H = 64, W = 64, C = 128), filter size (K
|
||||
R = 3, S = 3, C = 128 ), padding, strides, dilation, tensors, alpha, beta and the
|
||||
important one, split k-dimension factor. Along with that, we query CUTLASS if any scratch-space
|
||||
memory required by the kernel we instantiated. If yes, we create it and pass it along with other
|
||||
arguments created to intialize CUTLASS kernel then, the kernel is launched.
|
||||
arguments created to initialize CUTLASS kernel then, the kernel is launched.
|
||||
|
||||
In this example, we later on launch a reference convolution kernel (from CUTLASS utilities) to
|
||||
compare if the output from CUTLASS kernel is same as the reference implicit GEMM kernel.
|
||||
|
||||
@@ -321,7 +321,7 @@ public:
|
||||
int smem_write_stage_idx = 1;
|
||||
|
||||
// Issue loads during the first warp-level matrix multiply-add *AFTER* issuing
|
||||
// shared memory loads (which have the tighest latency requirement).
|
||||
// shared memory loads (which have the tightest latency requirement).
|
||||
|
||||
//
|
||||
// Mainloop
|
||||
@@ -461,7 +461,7 @@ public:
|
||||
int gemm_k_iterations_1 = FragmentIteratorA1::Policy::kIterations / Base::kWarpGemmIterations1;
|
||||
|
||||
// Issue loads during the first warp-level matrix multiply-add *AFTER* issuing
|
||||
// shared memory loads (which have the tighest latency requirement).
|
||||
// shared memory loads (which have the tightest latency requirement).
|
||||
|
||||
//
|
||||
// Mainloop
|
||||
|
||||
+1
-1
@@ -341,7 +341,7 @@ public:
|
||||
int smem_write_stage_idx = 1;
|
||||
|
||||
// Issue loads during the first warp-level matrix multiply-add *AFTER* issuing
|
||||
// shared memory loads (which have the tighest latency requirement).
|
||||
// shared memory loads (which have the tightest latency requirement).
|
||||
|
||||
//
|
||||
// Mainloop
|
||||
|
||||
@@ -325,7 +325,7 @@ public:
|
||||
iterator_B0.clear_mask(gemm_k_iterations_0 <= 1);
|
||||
|
||||
// Issue loads during the first warp-level matrix multiply-add *AFTER* issuing
|
||||
// shared memory loads (which have the tighest latency requirement).
|
||||
// shared memory loads (which have the tightest latency requirement).
|
||||
|
||||
//
|
||||
// Mainloop
|
||||
|
||||
@@ -346,7 +346,7 @@ public:
|
||||
iterator_B0.clear_mask(gemm_k_iterations_0 <= 1);
|
||||
|
||||
// Issue loads during the first warp-level matrix multiply-add *AFTER* issuing
|
||||
// shared memory loads (which have the tighest latency requirement).
|
||||
// shared memory loads (which have the tightest latency requirement).
|
||||
|
||||
//
|
||||
// Mainloop
|
||||
|
||||
@@ -73,7 +73,7 @@ Now that we setup the properties of data, we have to setup properties of computa
|
||||
Second, we create template variables of tile sizes for thread-block, warp and mma-op to 128x128x64,
|
||||
64x64x64, 16x8x16 (MxNxK) respectively. When passed to instantiate CUTLASS Implicit GEMM kernel, it
|
||||
internally deduces the amount of threads needed per thread-block, amount of shared memory, storing
|
||||
data in bank-conflict free manner, and ton of other variables required to compose, intialize and
|
||||
data in bank-conflict free manner, and ton of other variables required to compose, initialize and
|
||||
launch a high performance Implicit GEMM kernel. This is the beauty of CUTLASS, it relieves developer
|
||||
from understanding and coding complicated hardware optimizations which can easily go wrong.
|
||||
|
||||
@@ -95,7 +95,7 @@ is done which threadblock launched on an SM, CUDA SM architecture of GPU you wan
|
||||
These are all put together to create a template variable which describes CUTLASS Implicit GEMM
|
||||
kernel using cutlass::conv::device::ImplicitGemm template.
|
||||
|
||||
The next step is to intialize physical data, instantiate and initialize CUTLASS kernel and run it.
|
||||
The next step is to initialize physical data, instantiate and initialize CUTLASS kernel and run it.
|
||||
We use CUTLASS utilities to initialize, fill, compare tensors as they are simple and doesn't come
|
||||
in the way of learning CUTLASS.
|
||||
|
||||
@@ -104,7 +104,7 @@ kernel which takes problem size (N = 1, H = 64, W = 64, C = 128), filter size (K
|
||||
R = 3, S = 3, C = 128 ), padding, strides, dilation, tensors, alpha, beta and the
|
||||
important one, split k-dimension factor. Along with that, we query CUTLASS if any scratch-space
|
||||
memory required by the kernel we instantiated. If yes, we create it and pass it along with other
|
||||
arguments created to intialize CUTLASS kernel then, the kernel is launched.
|
||||
arguments created to initialize CUTLASS kernel then, the kernel is launched.
|
||||
|
||||
In this example, we later on launch a reference convolution kernel (from CUTLASS utilities) to
|
||||
compare if the output from CUTLASS kernel is same as the reference implicit GEMM kernel.
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ computing GEMM. So the output also contains either a Mx1 or 1XN vector. It onl
|
||||
core instructions.
|
||||
|
||||
Most of the reduction is done in gemm/warp level, see gemm/warp/mma_with_reduction_tensor_op.h
|
||||
A few bit of reduction is done in the epilouge before storing the vector, see
|
||||
A few bit of reduction is done in the epilogue before storing the vector, see
|
||||
epilogue/threadblock/epilogue_gemm_k_reduction.h
|
||||
*/
|
||||
|
||||
|
||||
@@ -1088,7 +1088,7 @@ int main(int argc, char const **args) {
|
||||
|
||||
// Determine kernel configuration based on head size.
|
||||
// If head size is less than or equal to 64, each block operates over 64 queries and
|
||||
// 64 keys, and parital results can be stored in the register file.
|
||||
// 64 keys, and partial results can be stored in the register file.
|
||||
// If head size is greater than 64, each block operates over 32 queries and 128 keys,
|
||||
// and partial results are stored in shared memory.
|
||||
if (options.head_size_v > 64) {
|
||||
|
||||
@@ -1173,7 +1173,7 @@ int main(int argc, char const **args) {
|
||||
|
||||
// Determine kernel configuration based on head size.
|
||||
// If head size is less than or equal to 64, each block operates over 64 queries and
|
||||
// 64 keys, and parital results can be stored in the register file.
|
||||
// 64 keys, and partial results can be stored in the register file.
|
||||
// If head size is greater than 64, each block operates over 32 queries and 128 keys,
|
||||
// and partial results are stored in shared memory.
|
||||
if (options.head_size_v > 64) {
|
||||
|
||||
@@ -310,7 +310,7 @@ class CustomMmaPipelined : public CustomMmaBase<Shape_, Policy_, 2> {
|
||||
iterator_B.clear_mask(gemm_k_iterations <= 1);
|
||||
|
||||
// Issue loads during the first warp-level matrix multiply-add *AFTER*
|
||||
// issuing shared memory loads (which have the tighest latency requirement).
|
||||
// issuing shared memory loads (which have the tightest latency requirement).
|
||||
|
||||
//
|
||||
// Mainloop
|
||||
|
||||
@@ -600,7 +600,7 @@ class MmaPipelinedFromSharedMemory : public MmaBaseFromSharedMemory<
|
||||
iterator_B.clear_mask(gemm_k_iterations <= 1);
|
||||
|
||||
// Issue loads during the first warp-level matrix multiply-add *AFTER*
|
||||
// issuing shared memory loads (which have the tighest latency requirement).
|
||||
// issuing shared memory loads (which have the tightest latency requirement).
|
||||
|
||||
//
|
||||
// Mainloop
|
||||
|
||||
+1
-1
@@ -181,7 +181,7 @@ class PredicatedTileAccessIteratorResidualLast<
|
||||
BytePointer pointer_;
|
||||
|
||||
/// Below is used when Gather is turned on. We need to record strided_offset
|
||||
/// and contiguous_offset seperated to compute the offset by using
|
||||
/// and contiguous_offset separated to compute the offset by using
|
||||
///
|
||||
/// offset = contiguous_offset + indices[strided_offset]
|
||||
///
|
||||
|
||||
@@ -86,14 +86,14 @@ class gen_default_b2b_mma:
|
||||
"OperatorClass", str(stage), "Operator")
|
||||
return gen_code
|
||||
|
||||
def gen_using_FusedAddBiasEpilouge(self):
|
||||
def gen_using_FusedAddBiasEpilogue(self):
|
||||
gen_code = ""
|
||||
for i in range(self.b2b_num - 1):
|
||||
code_using = helper.var_idx("using FusedAddBiasEpilouge", i)
|
||||
epilouge_name = "typename cutlass::epilogue::threadblock::DefaultFusedBiasActEpilogueTensorOp"
|
||||
code_using = helper.var_idx("using FusedAddBiasEpilogue", i)
|
||||
epilogue_name = "typename cutlass::epilogue::threadblock::DefaultFusedBiasActEpilogueTensorOp"
|
||||
template_args = helper.var_idx("<ThreadblockShape", i) + helper.var_idx(",typename MmaCore", i) + helper.var_idx("::MmaPolicy::Operator, 1, EpilogueOutputOp", i) + ", 2>::Epilogue"
|
||||
|
||||
gen_code += code_using + " = " + epilouge_name + template_args + ";\n"
|
||||
gen_code += code_using + " = " + epilogue_name + template_args + ";\n"
|
||||
|
||||
return gen_code
|
||||
|
||||
@@ -161,12 +161,12 @@ class gen_default_b2b_mma:
|
||||
MmaPipelined_param_list += "ElementAccumulator0, layout::RowMajor, "
|
||||
|
||||
for i in range(self.b2b_num - 1):
|
||||
epilouge_name = "EpilogueOutputOp" + str(i)
|
||||
MmaPipelined_param_list += epilouge_name + ", "
|
||||
epilogue_name = "EpilogueOutputOp" + str(i)
|
||||
MmaPipelined_param_list += epilogue_name + ", "
|
||||
|
||||
for i in range(self.b2b_num - 1):
|
||||
epilouge_name = "FusedAddBiasEpilouge" + str(i)
|
||||
MmaPipelined_param_list += epilouge_name + ", "
|
||||
epilogue_name = "FusedAddBiasEpilogue" + str(i)
|
||||
MmaPipelined_param_list += epilogue_name + ", "
|
||||
|
||||
for i in range(self.b2b_num):
|
||||
MmaPolicy = "typename MmaCore" + str(i) + "::MmaPolicy"
|
||||
@@ -198,7 +198,7 @@ class gen_default_b2b_mma:
|
||||
mmacore_codebody = self.gen_using_MmaCore(2)
|
||||
iterator_codebody = self.gen_using_Iterator()
|
||||
fragment_iterator_codebody = self.gen_fragment_iterator()
|
||||
epilogue_iterator_codebody = self.gen_using_FusedAddBiasEpilouge()
|
||||
epilogue_iterator_codebody = self.gen_using_FusedAddBiasEpilogue()
|
||||
threadBlockMma = self.gen_threadblockmma()
|
||||
specialized_code = mmacore_codebody + iterator_codebody + fragment_iterator_codebody + epilogue_iterator_codebody + threadBlockMma
|
||||
|
||||
@@ -352,7 +352,7 @@ class gen_b2b_mme_pipelined:
|
||||
}\n\
|
||||
\n\
|
||||
// Issue loads during the first warp-level matrix multiply-add *AFTER* issuing \n\
|
||||
// shared memory loads (which have the tighest latency requirement).\n\
|
||||
// shared memory loads (which have the tightest latency requirement).\n\
|
||||
\n\
|
||||
//\n\
|
||||
// Mainloop\n\
|
||||
@@ -459,7 +459,7 @@ class gen_b2b_mme_pipelined:
|
||||
}\n\
|
||||
\n\
|
||||
// Issue loads during the first warp-level matrix multiply-add *AFTER* issuing \n\
|
||||
// shared memory loads (which have the tighest latency requirement).\n\
|
||||
// shared memory loads (which have the tightest latency requirement).\n\
|
||||
iterator_A.load(tb_frag_A);\n\
|
||||
\n\
|
||||
//\n\
|
||||
@@ -490,7 +490,7 @@ class gen_b2b_mme_pipelined:
|
||||
__syncthreads();\n\
|
||||
\n\
|
||||
// Issue loads during the first warp-level matrix multiply-add *AFTER* issuing \n\
|
||||
// shared memory loads (which have the tighest latency requirement).\n\
|
||||
// shared memory loads (which have the tightest latency requirement).\n\
|
||||
iterator_A.load(tb_frag_A);\n\
|
||||
\n\
|
||||
++this->smem_iterator_B0_;\n\
|
||||
@@ -549,12 +549,12 @@ class gen_b2b_mme_pipelined:
|
||||
code = "// " + str(id + 1) + " Gemm"
|
||||
code += " /// Iterator to load a warp-scoped tile of A1 operand from intermediate accumulator tile\n"
|
||||
|
||||
code += " " + helper.var_idx("FragmentC", id - 1) + helper.var_idx(" after_epilouge_accu", id - 1) + ";\n"
|
||||
code += " " + helper.var_idx("FragmentC", id - 1) + helper.var_idx(" after_epilogue_accu", id - 1) + ";\n"
|
||||
code += " " + helper.var_idx("epilogue_", id - 1) + helper.var_idx("(output_op_", id - 1) + helper.var_idx(", accum", id - 1) \
|
||||
+ helper.var_idx(", after_epilouge_accu", id - 1) + helper.var_idx(", iterator_C", id - 1) +");\n"
|
||||
+ helper.var_idx(", after_epilogue_accu", id - 1) + helper.var_idx(", iterator_C", id - 1) +");\n"
|
||||
|
||||
# FragmentIteratorA1 warp_tile_iterator_A1_(accum0);
|
||||
code += " " + helper.var_idx("FragmentIteratorA", id) + helper.var_idx(" warp_tile_iterator_A", id) +"_(" + helper.var_idx("after_epilouge_accu", id - 1) + ");\n"
|
||||
code += " " + helper.var_idx("FragmentIteratorA", id) + helper.var_idx(" warp_tile_iterator_A", id) +"_(" + helper.var_idx("after_epilogue_accu", id - 1) + ");\n"
|
||||
# FragmentB1 tb_frag_B1;
|
||||
code += " " + helper.var_idx("FragmentB", id) + " " + helper.var_idx("tb_frag_B", id) + ";\n"
|
||||
# tb_frag_B1.clear();
|
||||
@@ -990,7 +990,7 @@ class gen_threadblock:
|
||||
|
||||
|
||||
self.gen_b2b_mma_base = gen_b2b_mma_base(template_param, gen_class_name, b2b_num, cutlass_deps_root, project_root)
|
||||
self.gen_b2b_mma_piplined = gen_b2b_mme_pipelined(template_param, gen_class_name, b2b_num, cutlass_deps_root, project_root)
|
||||
self.gen_b2b_mma_pipelined = gen_b2b_mme_pipelined(template_param, gen_class_name, b2b_num, cutlass_deps_root, project_root)
|
||||
self.gen_default_b2b_mma = gen_default_b2b_mma(template_param, gen_class_name, b2b_num, cutlass_deps_root, project_root)
|
||||
|
||||
|
||||
@@ -1001,7 +1001,7 @@ class gen_threadblock:
|
||||
|
||||
with open(self.file_dir + "b2b_mma_base.h", "w+") as f:
|
||||
f.write(base_code)
|
||||
pipeline_code = self.gen_b2b_mma_piplined.gen_code(first_use_1stage = first_use_1stage)
|
||||
pipeline_code = self.gen_b2b_mma_pipelined.gen_code(first_use_1stage = first_use_1stage)
|
||||
print("[INFO]: Gen kernel code [b2b_mma_pipelined.h]output Dir: is ", self.file_dir)
|
||||
|
||||
with open(self.file_dir + "b2b_mma_pipelined.h", "w+") as f:
|
||||
|
||||
@@ -45,7 +45,7 @@ class gen_verify:
|
||||
self.user_header_file = ""
|
||||
for header in user_header_file:
|
||||
self.user_header_file += "#include \"" + header + "\"\n"
|
||||
self.seperate_cutlass = gen_basic.gen_volta_turing_fuse_act_impl(fuse_gemm_info, gen_class_name, user_header_file, output_dir)
|
||||
self.separate_cutlass = gen_basic.gen_volta_turing_fuse_act_impl(fuse_gemm_info, gen_class_name, user_header_file, output_dir)
|
||||
self.gen_params()
|
||||
self.output_dir = output_dir
|
||||
|
||||
@@ -53,14 +53,14 @@ class gen_verify:
|
||||
def gen_code(self):
|
||||
code = ""
|
||||
code += self.user_header_file
|
||||
code += self.seperate_cutlass.gen_using(False) #False -> Turing, True -> Volta
|
||||
code += self.separate_cutlass.gen_using(False) #False -> Turing, True -> Volta
|
||||
|
||||
code_body = ""
|
||||
for i in range(self.b2b_num):
|
||||
code_body += " " + helper.var_idx("Gemm", i) + helper.var_idx(" gemm_op_", i) + ";\n"
|
||||
code_body += " " + helper.var_idx("gemm_op_", i) + helper.var_idx(".initialize(Arguments_", i) + ", nullptr);\n"
|
||||
|
||||
code_body += self.seperate_cutlass.gen_run()
|
||||
code_body += self.separate_cutlass.gen_run()
|
||||
|
||||
code += ir.gen_func(self.name, self.params, code_body)
|
||||
helper.write_2_headfile("cutlass_verify.h", self.output_dir, code)
|
||||
@@ -87,6 +87,6 @@ class gen_verify:
|
||||
|
||||
def gen_initialize():
|
||||
code = ""
|
||||
initialize_code = self.seperate_cutlass.gen_initialize()
|
||||
initialize_code = self.separate_cutlass.gen_initialize()
|
||||
|
||||
code = ir.gen_func("initialize", [[]])
|
||||
|
||||
@@ -83,23 +83,23 @@ def list_2_string(input_list, ):
|
||||
return rtn_string
|
||||
|
||||
|
||||
def get_epilouge_info(layer_info):
|
||||
def get_epilogue_info(layer_info):
|
||||
return layer_info['epilogue']
|
||||
|
||||
def get_epilogue_tp(layer_info):
|
||||
epilogue_info = get_epilouge_info(layer_info)
|
||||
epilogue_info = get_epilogue_info(layer_info)
|
||||
return epilogue_info['tp']
|
||||
|
||||
def get_epilogue_add_bias_or_not(layer_info):
|
||||
epilogue_info = get_epilouge_info(layer_info)
|
||||
epilogue_info = get_epilogue_info(layer_info)
|
||||
return epilogue_info['bias']['addbias']
|
||||
|
||||
def get_epilogue_add_bias_tp(layer_info):
|
||||
epilogue_info = get_epilouge_info(layer_info)
|
||||
epilogue_info = get_epilogue_info(layer_info)
|
||||
return epilogue_info['bias']['bias_tp']
|
||||
|
||||
def get_epilogue_args(layer_info):
|
||||
epilogue_info = get_epilouge_info(layer_info)
|
||||
epilogue_info = get_epilogue_info(layer_info)
|
||||
return epilogue_info['args']
|
||||
|
||||
def get_epilogue_bias_shape(layer_info):
|
||||
|
||||
+7
-7
@@ -33,7 +33,7 @@
|
||||
\brief Hopper GEMM example leveraging collective operation builders.
|
||||
|
||||
This example showcases the use of CUTLASS's CollectiveBuilder to easily construct performant kernels
|
||||
targetting the NVIDIA Hopper architecture.
|
||||
targeting the NVIDIA Hopper architecture.
|
||||
|
||||
Background and motivation
|
||||
-------------------------
|
||||
@@ -45,7 +45,7 @@
|
||||
However, DefaultGemmConfigurations leave multiple opportunities for improvement, which are addressed
|
||||
in CUTLASS 3:
|
||||
(1) DefaultGemmConfigurations do not allow one to use a more-performant set of parameters without
|
||||
specifying every parameter. For example, the DefaultGemmConfigurations for GEMMs targetting
|
||||
specifying every parameter. For example, the DefaultGemmConfigurations for GEMMs targeting
|
||||
Ampere specify that three pipeline stages should be used regardless of the sizes of operands.
|
||||
If one wished to increase this value, one would also need to specify all other template parameters.
|
||||
This leaves a gap between a high-level ease-of-use interface and a lower-level detailed interface.
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
Alongside these opportunities for improvement, the Hopper architecture offers new features that increase
|
||||
the number of valid configurations of a kernel. In addition to the many template parameters already available
|
||||
in CUTLASS 2 kernels, CUTLASS 3 kernels targetting Hopper also have various scheduling modes to select from that control:
|
||||
in CUTLASS 2 kernels, CUTLASS 3 kernels targeting Hopper also have various scheduling modes to select from that control:
|
||||
(1) how data is to be loaded (e.g., using the Hopper TMA feature or Ampere cp.async)
|
||||
(2) how work is to be divided among warps in a thread block (e.g., whether to use "warp specialization")
|
||||
(3) whether persistent thread blocks should be used
|
||||
@@ -64,13 +64,13 @@
|
||||
Introduction to the CollectiveBuilder
|
||||
-------------------------------------
|
||||
CUTLASS 3 introduces the CollectiveBuilder to further ease the process of selecting template parameters
|
||||
for kernels targetting Hopper. Similar to the DefaultGemmConfigurations used in CUTLASS 2, the CollectiveBuilder
|
||||
for kernels targeting Hopper. Similar to the DefaultGemmConfigurations used in CUTLASS 2, the CollectiveBuilder
|
||||
takes in a small set of template parameters (e.g., the data types of operands A and B). It then automatically
|
||||
determines the data loading strategy to use depending on whether the Hopper TMA feature can be used with the provided
|
||||
parameters. If one does not indicate a particular scheduling policy or stage count to use (by using `Auto` template
|
||||
parameters), the CollectiveBuilder will also automatically select these.
|
||||
|
||||
Unlike DefaultGemmConfigurations a parital specialization of the CollectiveBuilder is not needed for many
|
||||
Unlike DefaultGemmConfigurations a partial specialization of the CollectiveBuilder is not needed for many
|
||||
configurations of operand types. Instead the CollectiveBuilder "builds" a configuration based on generic
|
||||
properties of the specified operands, layouts, and other parameters. For example, when the stage count
|
||||
is set to `Auto`, the CollectiveBuilder may automatically calculate the maximum number of stages that
|
||||
@@ -90,7 +90,7 @@
|
||||
Details of this example
|
||||
-----------------------
|
||||
This example walks through the use of the CollectiveBuilder with various schedules and stage counts specified.
|
||||
This example also illustrates how CUTLASS 3 GEMMs targetting Hopper automatically support batched GEMMs by simply
|
||||
This example also illustrates how CUTLASS 3 GEMMs targeting Hopper automatically support batched GEMMs by simply
|
||||
extending the problem size with an additional tensor rank.
|
||||
|
||||
Example usage:
|
||||
@@ -162,7 +162,7 @@ struct Options {
|
||||
|
||||
out << "49_hopper_gemm_schedules_with_collective_builder\n\n"
|
||||
<< " This example showcases the use of CUTLASS's collective operation builders to easily construct\n"
|
||||
<< " performant kernels targetting NVIDIA's Hopper architecture.\n\n"
|
||||
<< " performant kernels targeting NVIDIA's Hopper architecture.\n\n"
|
||||
<< "Options:\n\n"
|
||||
<< " --help If specified, displays this usage statement\n\n"
|
||||
<< " --m=<int> Sets the M extent of the GEMM\n"
|
||||
|
||||
Reference in New Issue
Block a user