|
| 1 | +#include <algorithm> |
| 2 | +#include <cstdlib>t |
| 3 | +#include <hip/hip_runtime.h> |
| 4 | +#include <iostream> |
| 5 | +#include <map> |
| 6 | +#include <string> |
| 7 | +#include <type_traits> |
| 8 | +#include <typeinfo> |
| 9 | + |
| 10 | +// Convert typeid name to C++ type name |
| 11 | +std::string demangle(const char *name) { |
| 12 | + static const std::map<char, std::string> demangleMap = { |
| 13 | + {'i', "int"}, {'f', "float"}, |
| 14 | + {'d', "double"}, {'j', "unsigned int"}, |
| 15 | + {'l', "long"}, {'m', "unsigned long"}, |
| 16 | + {'x', "long long"}, {'y', "unsigned long long"}}; |
| 17 | + |
| 18 | + auto it = demangleMap.find(name[0]); |
| 19 | + if (it != demangleMap.end()) { |
| 20 | + return it->second; |
| 21 | + } else { |
| 22 | + return std::string(name); |
| 23 | + } |
| 24 | +} |
| 25 | + |
| 26 | +void checkHipCall(hipError_t status, const char *msg) { |
| 27 | + if (status != hipSuccess) { |
| 28 | + std::cerr << "HIP Error: " << msg << " - " << hipGetErrorString(status) |
| 29 | + << std::endl; |
| 30 | + std::abort(); |
| 31 | + } |
| 32 | +} |
| 33 | + |
| 34 | +template <typename T1, typename T2> |
| 35 | +void compareResults(T1 hipResult, T2 stdResult, const std::string &testName) { |
| 36 | + using CommonType = typename std::common_type<T1, T2>::type; |
| 37 | + if (static_cast<CommonType>(hipResult) != |
| 38 | + static_cast<CommonType>(stdResult)) { |
| 39 | + std::cerr << testName << " mismatch: HIP result " << hipResult << " (" |
| 40 | + << demangle(typeid(hipResult).name()) << "), std result " |
| 41 | + << stdResult << " (" << demangle(typeid(stdResult).name()) << ")" |
| 42 | + << std::endl; |
| 43 | + std::abort(); |
| 44 | + } |
| 45 | +} |
| 46 | + |
| 47 | +template <typename T1, typename T2> void runTest(T1 a, T2 b) { |
| 48 | + std::cout << "\nTesting with values: " << a << " (" |
| 49 | + << demangle(typeid(a).name()) << ") and " << b << " (" |
| 50 | + << demangle(typeid(b).name()) << ")" << std::endl; |
| 51 | + |
| 52 | + // Using std::min and std::max as reference |
| 53 | + // The two arguments are converted to std::common_type first then passed |
| 54 | + // to std::min/max. This assumes compatiblity with CUDA. |
| 55 | + using CommonType = typename std::common_type<T1, T2>::type; |
| 56 | + CommonType stdMinResult = std::min<CommonType>(a, b); |
| 57 | + CommonType stdMaxResult = std::max<CommonType>(a, b); |
| 58 | + std::cout << "Host std::min result: " << stdMinResult |
| 59 | + << " (Type: " << demangle(typeid(stdMinResult).name()) << ")" |
| 60 | + << std::endl; |
| 61 | + std::cout << "Host std::max result: " << stdMaxResult |
| 62 | + << " (Type: " << demangle(typeid(stdMaxResult).name()) << ")" |
| 63 | + << std::endl; |
| 64 | + |
| 65 | + // Using HIP's global min/max functions |
| 66 | + CommonType hipMinResult = min(a, b); |
| 67 | + CommonType hipMaxResult = max(a, b); |
| 68 | + std::cout << "Host HIP min result: " << hipMinResult |
| 69 | + << " (Type: " << demangle(typeid(hipMinResult).name()) << ")" |
| 70 | + << std::endl; |
| 71 | + std::cout << "Host HIP max result: " << hipMaxResult |
| 72 | + << " (Type: " << demangle(typeid(hipMaxResult).name()) << ")" |
| 73 | + << std::endl; |
| 74 | + |
| 75 | + // Ensure the host HIP and std results match |
| 76 | + compareResults(hipMinResult, stdMinResult, "HIP vs std min"); |
| 77 | + compareResults(hipMaxResult, stdMaxResult, "HIP vs std max"); |
| 78 | +} |
| 79 | + |
| 80 | +int main() { |
| 81 | + checkHipCall(hipSetDevice(0), "hipSetDevice failed"); |
| 82 | + |
| 83 | + // For mixed signed/unsigned integer arguments, assuming CUDA compatibility, |
| 84 | + // i.e. the signed integer is implicitly converted to unsigned type and then |
| 85 | + // compared. |
| 86 | + runTest(10uLL, -5LL); // Testing with unsigned int and long long |
| 87 | + runTest(-15, 20u); // Testing with int and unsigned int |
| 88 | + runTest(2147483647, 2147483648u); // Testing with int and unsigned int |
| 89 | + runTest( |
| 90 | + -922337203685477580LL, |
| 91 | + 922337203685477580uLL); // Testing with long long and unsigned long long |
| 92 | + runTest(2.5f, 3.14159); // Testing with float and double |
| 93 | + |
| 94 | + std::cout << "\nPass\n"; |
| 95 | + return 0; |
| 96 | +} |
0 commit comments