From 79100107cd51e0cddf97361105dc1b912dae462d Mon Sep 17 00:00:00 2001 From: Cong Ma <142121551+CongMa13@users.noreply.github.com> Date: Tue, 21 Jan 2025 09:14:20 -0700 Subject: [PATCH] Refactor the code that print the test output (#327) --- test/01_contraction/contraction_test.cpp | 150 +++++++++-------------- test/02_permutation/permutation_test.cpp | 101 +++++++-------- test/03_reduction/reduction_test.cpp | 103 +++++++--------- test/utils.hpp | 83 +++++++++++++ 4 files changed, 233 insertions(+), 204 deletions(-) diff --git a/test/01_contraction/contraction_test.cpp b/test/01_contraction/contraction_test.cpp index f58e53d8..789054f5 100644 --- a/test/01_contraction/contraction_test.cpp +++ b/test/01_contraction/contraction_test.cpp @@ -90,11 +90,29 @@ namespace hiptensor std::ostream& ContractionTest::printHeader(std::ostream& stream /* = std::cout */) const { - return stream << "TypeA, TypeB, TypeC, " << "TypeD, TypeCompute, " - << "Algorithm, Operator, " << "WorkSizePreference, LogLevel, " - << "Lengths, Strides, Modes, Alpha," << "Beta, elapsedMs, " - << "Problem Size(GFlops), " << "TFlops/s, " << "TotalBytes, " << "Result" - << std::endl; + // clang-format off + return stream + << "TypeA," // 1 + << "TypeB," // 2 + << "TypeC," // 3 + << "TypeD," // 4 + << "TypeCompute," // 5 + << "Algorithm," // 6 + << "Operator," // 7 + << "WorkSizePreference," // 8 + << "LogLevel," // 9 + << "Lengths," // 10 + << "Strides," // 11 + << "Modes," // 12 + << "Alpha," // 13 + << "Beta," // 14 + << "elapsedMs," // 15 + << "Problem Size(GFlops)," // 16 + << "TFlops," // 17 + << "TotalBytes," // 18 + << "Result" // 19 + << std::endl; + // clang-format on } std::ostream& ContractionTest::printKernel(std::ostream& stream) const @@ -111,96 +129,50 @@ namespace hiptensor auto alpha = std::get<8>(param); auto beta = std::get<9>(param); - stream << hipTypeToString(testType[0]) << ", " << hipTypeToString(testType[1]) << ", " - << hipTypeToString(testType[2]) << ", " << hipTypeToString(testType[3]) << ", " - << computeTypeToString(convertToComputeType(testType[4])) << ", " - << algoTypeToString(algorithm) << ", " << opTypeToString(operatorType) << ", " - << workSizePrefToString(workSizePref) << ", " << logLevelToString(logLevel) << ", ["; - - for(int i = 0; i < lengths.size(); i++) - { - if(i != 0) - { - stream << ", "; - } - stream << "["; - for(int j = 0; j < lengths[i].size(); j++) - { - if(j != 0) - { - stream << ", "; - } - stream << lengths[i][j]; - } - stream << "]"; - } - stream << "], ["; - - if(!strides.empty()) - { - for(int i = 0; i < strides.size(); i++) - { - if(i != 0) - { - stream << ", "; - } - stream << "["; - for(int j = 0; j < strides[i].size(); j++) - { - if(j != 0) - { - stream << ", "; - } - stream << strides[i][j]; - } - stream << "]"; - } - } - stream << "], ["; - - if(!modes.empty()) - { - for(int i = 0; i < modes.size(); i++) - { - if(i != 0) - { - stream << ", "; - } - stream << "["; - for(int j = 0; j < modes[i].size(); j++) - { - if(j != 0) - { - stream << ", "; - } - stream << modes[i][j]; - } - stream << "]"; - } - } - stream << "], " << alpha << ", " << beta << ", "; + // clang-format off + stream + << hipTypeToString(testType[0]) << "," // 1 + << hipTypeToString(testType[1]) << "," // 2 + << hipTypeToString(testType[2]) << "," // 3 + << hipTypeToString(testType[3]) << "," // 4 + << computeTypeToString(convertToComputeType(testType[4])) << "," // 5 + << algoTypeToString(algorithm) << "," // 6 + << opTypeToString(operatorType) << "," // 7 + << workSizePrefToString(workSizePref) << "," // 8 + << logLevelToString(logLevel) << ","; // 9 + printContainerInCsv(lengths, stream) << ","; // 10 + printContainerInCsv(strides, stream) << ","; // 11 + printContainerInCsv(modes, stream) << ","; // 12 + printContainerInCsv(alpha, stream) << ","; // 13 + printContainerInCsv(beta, stream) << ","; // 14 + // clang-format on if(!mRunFlag) { - stream << "n/a" << ", " << "n/a" << ", " << "n/a" << ", " << "n/a" << ", " << "SKIPPED" - << std::endl; + // clang-format off + stream + << "n/a" << "," // 15 + << "n/a" << "," // 16 + << "n/a" << "," // 17 + << "n/a" << "," // 18 + << "SKIPPED" // 19 + << std::endl; + // clang-format on } else { - - stream << mElapsedTimeMs << ", " << mTotalGFlops << ", " << mMeasuredTFlopsPerSec - << ", " << mTotalBytes << ", "; - - auto& testOptions = HiptensorOptions::instance(); - - if(testOptions->performValidation()) - { - stream << ((bool)mValidationResult ? "PASSED" : "FAILED") << std::endl; - } - else - { - stream << "BENCH" << std::endl; - } + auto isPerformValidation = HiptensorOptions::instance()->performValidation(); + auto result = isPerformValidation ? (mValidationResult ? "PASSED" : "FAILED") : "BENCH"; + + // clang-format off + stream + << mElapsedTimeMs << "," // 15 + << mTotalGFlops << "," // 16 + << mMeasuredTFlopsPerSec << "," // 17 + << mTotalBytes << "," // 18 + << result // 19 + << std::endl; + // clang-format on } return stream; diff --git a/test/02_permutation/permutation_test.cpp b/test/02_permutation/permutation_test.cpp index d8d54d82..1a03b522 100644 --- a/test/02_permutation/permutation_test.cpp +++ b/test/02_permutation/permutation_test.cpp @@ -79,14 +79,21 @@ namespace hiptensor std::ostream& PermutationTest::printHeader(std::ostream& stream /* = std::cout */) const { - return stream << "TypeIn, TypeCompute, " - << "Operators , LogLevel, " - << "Lengths, PermutedOrder, " - << "Alpha, elapsedMs, " - << "Problem Size(GFlops), " - << "TFlops/s, " - << "TotalBytes, " - << "Result" << std::endl; + // clang-format off + return stream << "TypeIn," // 1 + << "TypeCompute," // 2 + << "Operators," // 3 + << "LogLevel," // 4 + << "Lengths," // 5 + << "PermutedOrder," // 6 + << "Alpha," // 7 + << "ElapsedMs," // 8 + << "Problem Size(GFlops)," // 9 + << "TFlops," // 10 + << "TotalBytes," // 11 + << "Result" // 12 + << std::endl; + // clang-format on } std::ostream& PermutationTest::printKernel(std::ostream& stream) const @@ -99,62 +106,40 @@ namespace hiptensor auto alpha = std::get<4>(param); auto operators = std::get<5>(param); - stream << hipTypeToString(testType[0]) << ", " - << computeTypeToString(convertToComputeType(testType[1])) << ", " - << opTypeToString(operators[0]) << ", " << opTypeToString(operators[1]) << ", " - << logLevelToString(logLevel) << ", ["; - - for(int i = 0; i < lengths.size(); i++) - { - if(i != 0) - { - stream << ", "; - } - stream << lengths[i]; - } - stream << "], ["; - - if(!permutedDims.empty()) - { - for(int i = 0; i < permutedDims.size(); i++) - { - if(i != 0) - { - stream << ", "; - } - stream << permutedDims[i]; - } - } - stream << "], " << alpha << ", "; + // clang-format off + stream << hipTypeToString(testType[0]) << "," // 1 + << computeTypeToString(convertToComputeType(testType[1])) << "," // 2 + << "[ " << opTypeToString(operators[0]) << " " << opTypeToString(operators[1]) << "]," // 3 + << logLevelToString(logLevel) << ","; // 4 + printContainerInCsv(lengths, stream) << ","; // 5 + printContainerInCsv(permutedDims, stream) << ","; // 6 + stream << alpha << ","; // 7 + // clang-format on if(!mRunFlag) { - stream << "n/a" - << ", " - << "n/a" - << ", " - << "n/a" - << ", " - << "n/a" - << ", " - << "SKIPPED" << std::endl; + // clang-format off + stream << "n/a" << "," // 8 + << "n/a" << "," // 9 + << "n/a" << "," // 10 + << "n/a" << "," // 11 + << "SKIPPED" // 12 + << std::endl; + // clang-format on } else { - - stream << mElapsedTimeMs << ", " << mTotalGFlops << ", " << mMeasuredTFlopsPerSec - << ", " << mTotalBytes << ", "; - - auto& testOptions = HiptensorOptions::instance(); - - if(testOptions->performValidation()) - { - stream << ((bool)mValidationResult ? "PASSED" : "FAILED") << std::endl; - } - else - { - stream << "BENCH" << std::endl; - } + auto isPerformValidation = HiptensorOptions::instance()->performValidation(); + auto result = isPerformValidation ? (mValidationResult ? "PASSED" : "FAILED") : "BENCH"; + + // clang-format off + stream << mElapsedTimeMs << "," //8 + << mTotalGFlops << "," //9 + << mMeasuredTFlopsPerSec << "," //10 + << mTotalBytes << "," //11 + << result //12 + << std::endl; + // clang-format on } return stream; diff --git a/test/03_reduction/reduction_test.cpp b/test/03_reduction/reduction_test.cpp index cedcfb7c..90f2b486 100644 --- a/test/03_reduction/reduction_test.cpp +++ b/test/03_reduction/reduction_test.cpp @@ -113,14 +113,23 @@ namespace hiptensor std::ostream& ReductionTest::printHeader(std::ostream& stream /* = std::cout */) const { - return stream << "TypeIn, TypeCompute, " - << "Operator, LogLevel, " - << "Lengths, ReOrder, " - << "Alpha, Beta, elapsedMs, " - << "Problem Size(GFlops), " - << "TFlops/s, " - << "TotalBytes, " - << "Result" << std::endl; + // clang-format off + return stream + << "TypeIn," //1 + << "TypeCompute," //2 + << "Operator," //3 + << "LogLevel," //4 + << "Lengths," //5 + << "ReOrder," //6 + << "Alpha," //7 + << "Beta," //8 + << "elapsedMs," //9 + << "Problem Size(GFlops)," //10 + << "TFlops," //11 + << "TotalBytes," //12 + << "Result" //13 + << std::endl; + // clang-format on } std::ostream& ReductionTest::printKernel(std::ostream& stream) const @@ -134,61 +143,41 @@ namespace hiptensor auto beta = std::get<5>(param); auto op = std::get<6>(param); - stream << hipTypeToString(testType[0]) << ", " - << computeTypeToString(convertToComputeType(testType[1])) << ", " - << opTypeToString(op) << ", " << logLevelToString(logLevel) << ", ["; - - for(int i = 0; i < lengths.size(); i++) - { - if(i != 0) - { - stream << ", "; - } - stream << lengths[i]; - } - stream << "], ["; - - if(!outputDims.empty()) - { - for(int i = 0; i < outputDims.size(); i++) - { - if(i != 0) - { - stream << ", "; - } - stream << outputDims[i]; - } - } - stream << "], " << alpha << ", " << beta << ", "; + // clang-format off + stream << hipTypeToString(testType[0]) << "," //1 + << computeTypeToString(convertToComputeType(testType[1])) << "," //2 + << opTypeToString(op) << "," //3 + << logLevelToString(logLevel) << ","; //4 + printContainerInCsv(lengths, stream) << ","; //5 + printContainerInCsv(outputDims, stream) << ","; //6 + stream << alpha << "," //7 + << beta << ","; //8 + // clang-format on if(!mRunFlag) { - stream << "n/a" - << ", " - << "n/a" - << ", " - << "n/a" - << ", " - << "n/a" - << ", " - << "SKIPPED" << std::endl; + // clang-format off + stream << "n/a" << "," //9 + << "n/a" << "," //10 + << "n/a" << "," //11 + << "n/a" << "," //12 + << "SKIPPED" //13 + << std::endl; + // clang-format on } else { - - stream << mElapsedTimeMs << ", " << mTotalGFlops << ", " << mMeasuredTFlopsPerSec - << ", " << mTotalBytes << ", "; - - auto& testOptions = HiptensorOptions::instance(); - - if(testOptions->performValidation()) - { - stream << ((bool)mValidationResult ? "PASSED" : "FAILED") << std::endl; - } - else - { - stream << "BENCH" << std::endl; - } + auto isPerformValidation = HiptensorOptions::instance()->performValidation(); + auto result = isPerformValidation ? (mValidationResult ? "PASSED" : "FAILED") : "BENCH"; + + // clang-format off + stream << mElapsedTimeMs << "," //9 + << mTotalGFlops << "," //10 + << mMeasuredTFlopsPerSec << "," //11 + << mTotalBytes << "," //12 + << result //13 + << std::endl; + // clang-format on } return stream; diff --git a/test/utils.hpp b/test/utils.hpp index 8415ff50..358f604f 100644 --- a/test/utils.hpp +++ b/test/utils.hpp @@ -387,6 +387,89 @@ std::pair compareEqualLaunchKernel(DDataType* deviceD, return std::make_pair(retval, maxRelativeError); } +namespace hiptensor +{ + template + struct has_const_iterator + { + private: + typedef char yes; + typedef struct + { + char array[2]; + } no; + + template + static yes test(typename C::const_iterator*); + template + static no test(...); + + public: + static const bool value = sizeof(test(0)) == sizeof(yes); + typedef T type; + }; + + template + struct has_begin_end + { + template + static char (&f( + typename std::enable_if(&C::begin)), + typename C::const_iterator (C::*)() const>::value, + void>::type*))[1]; + + template + static char (&f(...))[2]; + + template + static char (&g( + typename std::enable_if(&C::end)), + typename C::const_iterator (C::*)() const>::value, + void>::type*))[1]; + + template + static char (&g(...))[2]; + + static bool const beg_value = sizeof(f(0)) == 1; + static bool const end_value = sizeof(g(0)) == 1; + }; + + template + struct is_container + : std::integral_constant::value && has_begin_end::beg_value + && has_begin_end::end_value> + { + }; + + // Write the content of arrays as value of a CSV field + // do not use ',' since it is field separator in CSV + // Example: arrays = [[1, 2], [3, 4] + // Output: '[[1 2] [3 4]]' + + // Main print function + template + std::ostream& printContainerInCsv(Container const& container, std::ostream& outStream) + { + outStream << "["; + for(const auto& element : container) + { + if constexpr(is_container::value) + { + printContainerInCsv(element, outStream); + } + else + { + outStream << element << " "; + } + } + outStream << "] "; + return outStream; + } +} + namespace std { template