mirror of
https://github.com/ROCm/composable_kernel.git
synced 2026-05-17 03:19:48 +00:00
Update test CMakeLists to add new tests automatically and add Jenkins stage for tests (#88)
* add docker file and make default target buildable
* add Jenkinsfile
* remove empty env block
* fix package stage
* remove render group from docker run
* clean up Jenkins file
* add cppcheck as dev dependency
* update cmake file
* Add profiler build stage
* add hip_version config file for reduction operator
* correct jenkins var name
* Build release instead of debug
* Update test CMakeLists.txt
reorg test dir
add test stage
* reduce compile threads to prevent compiler crash
* add optional debug stage, update second test
* remove old test target
* fix tests to return proper results and self review
* Fix package name and make test run without args
* change Dockerfile to ues rocm4.3.1
* remove parallelism from build
* Lower paralellism
Co-authored-by: Chao Liu <chao.liu2@amd.com>
[ROCm/composable_kernel commit: 992f71e371]
This commit is contained in:
@@ -13,40 +13,24 @@ include_directories(BEFORE
|
||||
${PROJECT_SOURCE_DIR}/test/include
|
||||
)
|
||||
|
||||
# test_magic_number_division
|
||||
set(MAGIC_NUMBER_DIVISISON_SOURCE magic_number_division/main.cpp)
|
||||
add_executable(test_magic_number_division ${MAGIC_NUMBER_DIVISISON_SOURCE})
|
||||
target_link_libraries(test_magic_number_division PRIVATE host_tensor)
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C ${CMAKE_CFG_INTDIR})
|
||||
add_custom_target(tests)
|
||||
|
||||
function(add_test_executeable TEST_NAME)
|
||||
add_executable(${TEST_NAME} ${ARGN})
|
||||
target_link_libraries(${TEST_NAME} PRIVATE host_tensor)
|
||||
target_link_libraries(${TEST_NAME} PRIVATE device_gemm_instance)
|
||||
target_link_libraries(${TEST_NAME} PRIVATE device_conv2d_fwd_instance)
|
||||
add_test(NAME ${TEST_NAME} COMMAND $<TARGET_FILE:${TEST_NAME}> )
|
||||
add_dependencies(tests ${TEST_NAME})
|
||||
add_dependencies(check ${TEST_NAME})
|
||||
endfunction(add_test_executeable TEST_NAME)
|
||||
|
||||
|
||||
set(CONV2D_FWD_SOURCE conv2d_fwd/main.cpp)
|
||||
file(GLOB TESTS *.cpp)
|
||||
|
||||
add_executable(test_conv2d_fwd ${CONV2D_FWD_SOURCE})
|
||||
target_link_libraries(test_conv2d_fwd PRIVATE host_tensor)
|
||||
target_link_libraries(test_conv2d_fwd PRIVATE device_conv2d_fwd_instance)
|
||||
|
||||
# test_split_k
|
||||
set(SPLIT_K_SOURCE split_k/main.cpp)
|
||||
add_executable(test_split_k ${SPLIT_K_SOURCE})
|
||||
target_link_libraries(test_split_k PRIVATE host_tensor)
|
||||
target_link_libraries(test_split_k PRIVATE device_gemm_instance)
|
||||
|
||||
# test_conv_util
|
||||
set(CONV_UTIL_SOURCE conv_util/main.cpp)
|
||||
add_executable(test_conv_util ${CONV_UTIL_SOURCE})
|
||||
target_link_libraries(test_conv_util PRIVATE host_tensor)
|
||||
|
||||
# test_reference_conv_fwd
|
||||
set(REFERENCE_CONV_FWD_SOURCE reference_conv_fwd/main.cpp)
|
||||
add_executable(test_reference_conv_fwd ${REFERENCE_CONV_FWD_SOURCE})
|
||||
target_link_libraries(test_reference_conv_fwd PRIVATE host_tensor)
|
||||
|
||||
# test_convnd_fwd_xdl
|
||||
set(CONVND_FWD_XDL_SOURCE convnd_fwd_xdl/main.cpp)
|
||||
add_executable(test_convnd_fwd_xdl ${CONVND_FWD_XDL_SOURCE})
|
||||
target_link_libraries(test_convnd_fwd_xdl PRIVATE host_tensor)
|
||||
|
||||
# test space_filling_curve_
|
||||
set(SPACE_FILLING_CURVE_SOURCE space_filling_curve/space_filling_curve.cpp)
|
||||
add_executable(space_filling_curve ${SPACE_FILLING_CURVE_SOURCE})
|
||||
target_link_libraries(space_filling_curve PRIVATE host_tensor)
|
||||
foreach(TEST ${TESTS})
|
||||
get_filename_component(BASE_NAME ${TEST} NAME_WE)
|
||||
message("adding test ${BASE_NAME}")
|
||||
add_test_executeable(test_${BASE_NAME} ${TEST})
|
||||
endforeach(TEST ${TESTS})
|
||||
|
||||
@@ -75,8 +75,12 @@ int main(int argc, char* argv[])
|
||||
ck::index_t in_left_pad_w = 1;
|
||||
ck::index_t in_right_pad_h = 1;
|
||||
ck::index_t in_right_pad_w = 1;
|
||||
|
||||
if(argc == 3)
|
||||
if(argc == 1)
|
||||
{
|
||||
init_method = 1;
|
||||
data_type = 0;
|
||||
}
|
||||
else if(argc == 3)
|
||||
{
|
||||
data_type = std::stoi(argv[1]);
|
||||
init_method = std::stoi(argv[2]);
|
||||
@@ -275,33 +279,31 @@ int main(int argc, char* argv[])
|
||||
if(success)
|
||||
{
|
||||
std::cout << "test conv2d fwd : Pass" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "test conv2d fwd: Fail " << std::endl;
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
int res = -1;
|
||||
if(data_type == 0)
|
||||
{
|
||||
Run(float(), float(), float());
|
||||
res = Run(float(), float(), float());
|
||||
}
|
||||
else if(data_type == 1)
|
||||
{
|
||||
Run(ck::half_t(), ck::half_t(), ck::half_t());
|
||||
res = Run(ck::half_t(), ck::half_t(), ck::half_t());
|
||||
}
|
||||
else if(data_type == 2)
|
||||
{
|
||||
Run(ushort(), ushort(), ushort());
|
||||
res = Run(ushort(), ushort(), ushort());
|
||||
}
|
||||
else if(data_type == 3)
|
||||
{
|
||||
Run(int8_t(), int8_t(), int8_t());
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
res = Run(int8_t(), int8_t(), int8_t());
|
||||
}
|
||||
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
@@ -161,11 +161,12 @@ int main(int, char*[])
|
||||
if(pass)
|
||||
{
|
||||
std::cout << "test magic number division: Pass" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "test magic number division: Fail" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -57,32 +57,24 @@ static bool check_out(const Tensor<T>& ref, const Tensor<T>& result)
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
struct gemmArgs
|
||||
{
|
||||
if(argc != 9)
|
||||
{
|
||||
printf("arg1: matrix layout (0: A[m, k] * B[k, n] = C[m, n];\n");
|
||||
printf(" 1: A[m, k] * B[n, k] = C[m, n];\n");
|
||||
printf(" 2: A[k, m] * B[k, n] = C[m, n];\n");
|
||||
printf(" 3: A[k, m] * B[n, k] = C[m, n])\n");
|
||||
printf("arg2 to 7: M, N, K, StrideA, StrideB, StrideC KBatch\n");
|
||||
return 1;
|
||||
}
|
||||
int layout;
|
||||
int M;
|
||||
int N;
|
||||
int K;
|
||||
int StrideA;
|
||||
int StrideB;
|
||||
int StrideC;
|
||||
int KBatch;
|
||||
};
|
||||
|
||||
const int layout = static_cast<GemmMatrixLayout>(std::stoi(argv[1]));
|
||||
|
||||
const int M = std::stoi(argv[2]);
|
||||
const int N = std::stoi(argv[3]);
|
||||
const int K = std::stoi(argv[4]);
|
||||
|
||||
const int StrideA = std::stoi(argv[5]);
|
||||
const int StrideB = std::stoi(argv[6]);
|
||||
const int StrideC = std::stoi(argv[7]);
|
||||
const int KBatch = std::stoi(argv[8]);
|
||||
|
||||
int test_gemm(const gemmArgs& args)
|
||||
{
|
||||
bool a_row_major, b_row_major, c_row_major;
|
||||
|
||||
switch(layout)
|
||||
switch(args.layout)
|
||||
{
|
||||
case GemmMatrixLayout::MK_KN_MN:
|
||||
a_row_major = true;
|
||||
@@ -121,10 +113,10 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
};
|
||||
|
||||
Tensor<float> a_m_k(f_host_tensor_descriptor(M, K, StrideA, a_row_major));
|
||||
Tensor<float> b_k_n(f_host_tensor_descriptor(K, N, StrideB, b_row_major));
|
||||
Tensor<float> c_m_n_host_result(f_host_tensor_descriptor(M, N, StrideC, c_row_major));
|
||||
Tensor<float> c_m_n_device_result(f_host_tensor_descriptor(M, N, StrideC, c_row_major));
|
||||
Tensor<float> a_m_k(f_host_tensor_descriptor(args.M, args.K, args.StrideA, a_row_major));
|
||||
Tensor<float> b_k_n(f_host_tensor_descriptor(args.K, args.N, args.StrideB, b_row_major));
|
||||
Tensor<float> c_m_n_host_result(f_host_tensor_descriptor(args.M, args.N, args.StrideC, c_row_major));
|
||||
Tensor<float> c_m_n_device_result(f_host_tensor_descriptor(args.M, args.N, args.StrideC, c_row_major));
|
||||
|
||||
// init data
|
||||
std::size_t num_thread = std::thread::hardware_concurrency();
|
||||
@@ -151,17 +143,17 @@ int main(int argc, char* argv[])
|
||||
// add device GEMM instances
|
||||
std::vector<DeviceGemmNoOpPtr> gemm_ptrs;
|
||||
|
||||
if(layout == GemmMatrixLayout::MK_KN_MN)
|
||||
if(args.layout == GemmMatrixLayout::MK_KN_MN)
|
||||
{
|
||||
ck::tensor_operation::device::device_gemm_instance::
|
||||
add_device_gemm_xdl_splitk_f32_f32_f32_mk_kn_mn_instances(gemm_ptrs);
|
||||
}
|
||||
else if(layout == GemmMatrixLayout::MK_NK_MN)
|
||||
else if(args.layout == GemmMatrixLayout::MK_NK_MN)
|
||||
{
|
||||
ck::tensor_operation::device::device_gemm_instance::
|
||||
add_device_gemm_xdl_splitk_f32_f32_f32_mk_nk_mn_instances(gemm_ptrs);
|
||||
}
|
||||
else if(layout == GemmMatrixLayout::KM_KN_MN)
|
||||
else if(args.layout == GemmMatrixLayout::KM_KN_MN)
|
||||
{
|
||||
ck::tensor_operation::device::device_gemm_instance::
|
||||
add_device_gemm_xdl_splitk_f32_f32_f32_km_kn_mn_instances(gemm_ptrs);
|
||||
@@ -179,16 +171,16 @@ int main(int argc, char* argv[])
|
||||
gemm_ptr->MakeArgumentPointer(static_cast<float*>(a_device_buf.GetDeviceBuffer()),
|
||||
static_cast<float*>(b_device_buf.GetDeviceBuffer()),
|
||||
static_cast<float*>(c_device_buf.GetDeviceBuffer()),
|
||||
M,
|
||||
N,
|
||||
K,
|
||||
StrideA,
|
||||
StrideB,
|
||||
StrideC,
|
||||
args.M,
|
||||
args.N,
|
||||
args.K,
|
||||
args.StrideA,
|
||||
args.StrideB,
|
||||
args.StrideC,
|
||||
ck::tensor_operation::element_wise::PassThrough{},
|
||||
ck::tensor_operation::element_wise::PassThrough{},
|
||||
ck::tensor_operation::element_wise::PassThrough{},
|
||||
KBatch);
|
||||
args.KBatch);
|
||||
|
||||
auto invoker_ptr = gemm_ptr->MakeInvokerPointer();
|
||||
|
||||
@@ -205,7 +197,7 @@ int main(int argc, char* argv[])
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
auto error_code = 0;
|
||||
if(success)
|
||||
{
|
||||
std::cout << "test split k : Pass" << std::endl;
|
||||
@@ -213,6 +205,49 @@ int main(int argc, char* argv[])
|
||||
else
|
||||
{
|
||||
std::cout << "test split k: Fail " << std::endl;
|
||||
error_code = -1; // test needs to report failure
|
||||
}
|
||||
return error_code;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
std::vector<gemmArgs> test_cases;
|
||||
if(argc == 1)
|
||||
{
|
||||
test_cases = {{0, 3, 3, 3, 3, 3, 3, 1}};
|
||||
// JD: Populate with more and meaningful
|
||||
return 0;
|
||||
}
|
||||
else if(argc == 9)
|
||||
{
|
||||
const int layout = static_cast<GemmMatrixLayout>(std::stoi(argv[1]));
|
||||
|
||||
const int M = std::stoi(argv[2]);
|
||||
const int N = std::stoi(argv[3]);
|
||||
const int K = std::stoi(argv[4]);
|
||||
|
||||
const int StrideA = std::stoi(argv[5]);
|
||||
const int StrideB = std::stoi(argv[6]);
|
||||
const int StrideC = std::stoi(argv[7]);
|
||||
const int KBatch = std::stoi(argv[8]);
|
||||
test_cases = {{layout, M, N, K, StrideA, StrideB, StrideC, KBatch}};
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("arg1: matrix layout (0: A[m, k] * B[k, n] = C[m, n];\n");
|
||||
printf(" 1: A[m, k] * B[n, k] = C[m, n];\n");
|
||||
printf(" 2: A[k, m] * B[k, n] = C[m, n];\n");
|
||||
printf(" 3: A[k, m] * B[n, k] = C[m, n])\n");
|
||||
printf("arg2 to 7: M, N, K, StrideA, StrideB, StrideC KBatch\n");
|
||||
return -1;
|
||||
}
|
||||
for(const auto& kinder: test_cases)
|
||||
{
|
||||
const auto res = test_gemm(kinder);
|
||||
if(!res)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user