diff --git a/Code_Exercises/Advanced_Data_Flow/solution.cpp b/Code_Exercises/Advanced_Data_Flow/solution.cpp index a539366a..ab02e562 100644 --- a/Code_Exercises/Advanced_Data_Flow/solution.cpp +++ b/Code_Exercises/Advanced_Data_Flow/solution.cpp @@ -67,9 +67,7 @@ void test_buffer() { std::cout << "Exception caught: " << e.what() << std::endl; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(out[i] == i * 4.0f); - } + SYCLACADEMY_ASSERT_EQUAL(out, [](size_t i) { return i * 4.0f; }); } void test_usm() { @@ -118,9 +116,7 @@ void test_usm() { std::cout << "Exception caught: " << e.what() << std::endl; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(out[i] == i * 4.0f); - } + SYCLACADEMY_ASSERT_EQUAL(out, [](size_t i) { return i * 4.0f; }); } int main() { diff --git a/Code_Exercises/Advanced_Data_Flow/source.cpp b/Code_Exercises/Advanced_Data_Flow/source.cpp index bef37cba..b060937e 100644 --- a/Code_Exercises/Advanced_Data_Flow/source.cpp +++ b/Code_Exercises/Advanced_Data_Flow/source.cpp @@ -73,7 +73,5 @@ int main() { out[i] = tmp[i] / 2.0f; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(out[i] == i * 4.0f); - } + SYCLACADEMY_ASSERT_EQUAL(out, [](size_t i) { return i * 4.0f; }); } diff --git a/Code_Exercises/Asynchronous_Execution/solution.cpp b/Code_Exercises/Asynchronous_Execution/solution.cpp index 0aa163cb..f7d0d926 100644 --- a/Code_Exercises/Asynchronous_Execution/solution.cpp +++ b/Code_Exercises/Asynchronous_Execution/solution.cpp @@ -61,9 +61,7 @@ void test_buffer_event_wait() { std::cout << "Exception caught: " << e.what() << std::endl; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(r[i] == i * 2); - } + SYCLACADEMY_ASSERT_EQUAL(r, [](size_t i) { return i * 2; }); } void test_buffer_queue_wait() { @@ -98,9 +96,7 @@ void test_buffer_queue_wait() { std::cout << "Exception caught: " << e.what() << std::endl; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(r[i] == i * 2); - } + SYCLACADEMY_ASSERT_EQUAL(r, [](size_t i) { return i * 2; }); } void test_buffer_buffer_destruction() { @@ -137,9 +133,7 @@ void test_buffer_buffer_destruction() { std::cout << "Exception caught: " << e.what() << std::endl; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(r[i] == i * 2); - } + SYCLACADEMY_ASSERT_EQUAL(r, [](size_t i) { return i * 2; }); } void test_usm_event_wait() { @@ -189,9 +183,7 @@ void test_usm_event_wait() { std::cout << "Exception caught: " << e.what() << std::endl; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(r[i] == i * 2); - } + SYCLACADEMY_ASSERT_EQUAL(r, [](size_t i) { return i * 2; }); } void test_usm_queue_wait() { @@ -239,9 +231,7 @@ void test_usm_queue_wait() { std::cout << "Exception caught: " << e.what() << std::endl; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(r[i] == i * 2); - } + SYCLACADEMY_ASSERT_EQUAL(r, [](size_t i) { return i * 2; }); } void test_buffer_host_accessor() { @@ -277,9 +267,7 @@ void test_buffer_host_accessor() { { auto hostAccR = bufR.get_host_access(sycl::read_only); // Copy-to-host - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(hostAccR[i] == i * 2); - } + SYCLACADEMY_ASSERT_EQUAL(hostAccR, [](size_t i) { return i * 2; }); } } // Copy-back diff --git a/Code_Exercises/Asynchronous_Execution/source.cpp b/Code_Exercises/Asynchronous_Execution/source.cpp index 962b0960..aae18d21 100644 --- a/Code_Exercises/Asynchronous_Execution/source.cpp +++ b/Code_Exercises/Asynchronous_Execution/source.cpp @@ -48,12 +48,12 @@ void test_usm() { // Use your code from the "Data Parallelism" exercise to start - SYCLACADEMY_ASSERT(true); + SYCLACADEMY_ASSERT_EQUAL(/*output data*/ 0, /*expected data*/ 0); } void test_buffer() { // Use your code from the "Data Parallelism" exercise to start - SYCLACADEMY_ASSERT(true); + SYCLACADEMY_ASSERT_EQUAL(/*output data*/ 0, /*expected data*/ 0); } int main() { diff --git a/Code_Exercises/Data_Parallelism/solution.cpp b/Code_Exercises/Data_Parallelism/solution.cpp index 14146188..2c4a17eb 100644 --- a/Code_Exercises/Data_Parallelism/solution.cpp +++ b/Code_Exercises/Data_Parallelism/solution.cpp @@ -48,7 +48,5 @@ int main() { std::cout << "Exception caught: " << e.what() << std::endl; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(r[i] == static_cast(i) * 2.0f); - } + SYCLACADEMY_ASSERT_EQUAL(r, [](size_t i) { return i * 2.0f; }); } diff --git a/Code_Exercises/Data_Parallelism/source.cpp b/Code_Exercises/Data_Parallelism/source.cpp index 98b9e2c8..323e7527 100644 --- a/Code_Exercises/Data_Parallelism/source.cpp +++ b/Code_Exercises/Data_Parallelism/source.cpp @@ -56,7 +56,5 @@ int main() { r[i] = a[i] + b[i]; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(r[i] == static_cast(i) * 2.0f); - } + SYCLACADEMY_ASSERT_EQUAL(r, [](size_t i) { return i * 2.0f; }); } diff --git a/Code_Exercises/Data_and_Dependencies/solution.cpp b/Code_Exercises/Data_and_Dependencies/solution.cpp index 0dcad731..032bbea5 100644 --- a/Code_Exercises/Data_and_Dependencies/solution.cpp +++ b/Code_Exercises/Data_and_Dependencies/solution.cpp @@ -89,9 +89,7 @@ void test_buffer() { std::cout << "Exception caught: " << e.what() << std::endl; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(out[i] == i * 2.0f); - } + SYCLACADEMY_ASSERT_EQUAL(out, [](size_t i) { return i * 2.0f; }); } void test_usm() { @@ -156,9 +154,7 @@ void test_usm() { std::cout << "Exception caught: " << e.what() << std::endl; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(out[i] == i * 2.0f); - } + SYCLACADEMY_ASSERT_EQUAL(out, [](size_t i) { return i * 2.0f; }); } int main() { diff --git a/Code_Exercises/Data_and_Dependencies/source.cpp b/Code_Exercises/Data_and_Dependencies/source.cpp index 25b442d7..a335ecfe 100644 --- a/Code_Exercises/Data_and_Dependencies/source.cpp +++ b/Code_Exercises/Data_and_Dependencies/source.cpp @@ -87,7 +87,5 @@ int main() { out[i] = inB[i] + inC[i]; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(out[i] == i * 2.0f); - } + SYCLACADEMY_ASSERT_EQUAL(out, [](size_t i) { return i * 2.0f; }); } diff --git a/Code_Exercises/Device_Discovery/solution.cpp b/Code_Exercises/Device_Discovery/solution.cpp index 884b01d0..fa65a828 100644 --- a/Code_Exercises/Device_Discovery/solution.cpp +++ b/Code_Exercises/Device_Discovery/solution.cpp @@ -68,5 +68,5 @@ int main() { std::cout << "Exception caught: " << e.what() << std::endl; } - SYCLACADEMY_ASSERT(r == 42); + SYCLACADEMY_ASSERT_EQUAL(r, 42); } diff --git a/Code_Exercises/Device_Discovery/source.cpp b/Code_Exercises/Device_Discovery/source.cpp index 30b54d15..2043f8d9 100644 --- a/Code_Exercises/Device_Discovery/source.cpp +++ b/Code_Exercises/Device_Discovery/source.cpp @@ -83,5 +83,5 @@ int main() { std::cout << "Exception caught: " << e.what() << std::endl; } - SYCLACADEMY_ASSERT(r == 42); + SYCLACADEMY_ASSERT_EQUAL(r, 42); } diff --git a/Code_Exercises/In_Order_Queue/solution_vector_add.cpp b/Code_Exercises/In_Order_Queue/solution_vector_add.cpp index 16523777..f45d1e24 100644 --- a/Code_Exercises/In_Order_Queue/solution_vector_add.cpp +++ b/Code_Exercises/In_Order_Queue/solution_vector_add.cpp @@ -89,9 +89,7 @@ void test_buffer() { std::cout << "Exception caught: " << e.what() << std::endl; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(out[i] == i * 2.0f); - } + SYCLACADEMY_ASSERT_EQUAL(out, [](size_t i) { return i * 2.0f; }); } void test_usm() { @@ -160,9 +158,7 @@ void test_usm() { std::cout << "Exception caught: " << e.what() << std::endl; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(out[i] == i * 2.0f); - } + SYCLACADEMY_ASSERT_EQUAL(out, [](size_t i) { return i * 2.0f; }); } int main() { diff --git a/Code_Exercises/In_Order_Queue/source_vector_add.cpp b/Code_Exercises/In_Order_Queue/source_vector_add.cpp index 02572b58..b254155e 100644 --- a/Code_Exercises/In_Order_Queue/source_vector_add.cpp +++ b/Code_Exercises/In_Order_Queue/source_vector_add.cpp @@ -59,5 +59,5 @@ int main() { // Use the "Data and Dependencies" exercise solution to start - SYCLACADEMY_ASSERT(true); + SYCLACADEMY_ASSERT_EQUAL(/*output data*/ 0, /*expected data*/ 0); } diff --git a/Code_Exercises/Managing_Data/solution.cpp b/Code_Exercises/Managing_Data/solution.cpp index 6160fbe1..9410247c 100644 --- a/Code_Exercises/Managing_Data/solution.cpp +++ b/Code_Exercises/Managing_Data/solution.cpp @@ -40,7 +40,7 @@ void test_usm() { sycl::free(dev_B, defaultQueue); sycl::free(dev_R, defaultQueue); - SYCLACADEMY_ASSERT(r == 42); + SYCLACADEMY_ASSERT_EQUAL(r, 42); } void test_buffer() { @@ -65,7 +65,7 @@ void test_buffer() { .wait(); } - SYCLACADEMY_ASSERT(r == 42); + SYCLACADEMY_ASSERT_EQUAL(r, 42); } int main() { diff --git a/Code_Exercises/Managing_Data/source.cpp b/Code_Exercises/Managing_Data/source.cpp index 13b1272d..2b081eef 100644 --- a/Code_Exercises/Managing_Data/source.cpp +++ b/Code_Exercises/Managing_Data/source.cpp @@ -53,7 +53,7 @@ void test_usm() { // Task: Compute a+b on the SYCL device using USM r = a + b; - SYCLACADEMY_ASSERT(r == 42); + SYCLACADEMY_ASSERT_EQUAL(r, 42); } void test_buffer() { @@ -63,7 +63,7 @@ void test_buffer() { // accessor memory model r = a + b; - SYCLACADEMY_ASSERT(r == 42); + SYCLACADEMY_ASSERT_EQUAL(r, 42); } int main() { diff --git a/Code_Exercises/Matrix_Transpose/solution.cpp b/Code_Exercises/Matrix_Transpose/solution.cpp index 3eff37ea..19631332 100644 --- a/Code_Exercises/Matrix_Transpose/solution.cpp +++ b/Code_Exercises/Matrix_Transpose/solution.cpp @@ -139,7 +139,5 @@ int main() { std::cout << "Exception caught: " << e.what() << std::endl; } - for (auto i = 0; i < N * N; ++i) { - SYCLACADEMY_ASSERT(A_T[i] == A_T_comparison[i]); - } + SYCLACADEMY_ASSERT_EQUAL(A_T, A_T_comparison); } diff --git a/Code_Exercises/Matrix_Transpose/source.cpp b/Code_Exercises/Matrix_Transpose/source.cpp index fde56ca0..e1d7326c 100644 --- a/Code_Exercises/Matrix_Transpose/source.cpp +++ b/Code_Exercises/Matrix_Transpose/source.cpp @@ -82,7 +82,5 @@ int main() { std::cout << "Exception caught: " << e.what() << std::endl; } - for (auto i = 0; i < N * N; ++i) { - SYCLACADEMY_ASSERT(A_T[i] == A_T_comparison[i]); - } + SYCLACADEMY_ASSERT_EQUAL(A_T, A_T_comparison); } diff --git a/Code_Exercises/Multiple_Devices/solution.cpp b/Code_Exercises/Multiple_Devices/solution.cpp index 37358218..0012ec95 100644 --- a/Code_Exercises/Multiple_Devices/solution.cpp +++ b/Code_Exercises/Multiple_Devices/solution.cpp @@ -88,7 +88,5 @@ int main() { std::cout << "Exception caught: " << e.what() << std::endl; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(r[i] == static_cast(i) * 2.0f); - } + SYCLACADEMY_ASSERT_EQUAL(r, [](size_t i) { return i * 2.0f; }); } diff --git a/Code_Exercises/Multiple_Devices/source.cpp b/Code_Exercises/Multiple_Devices/source.cpp index dbcea392..a7e627d3 100644 --- a/Code_Exercises/Multiple_Devices/source.cpp +++ b/Code_Exercises/Multiple_Devices/source.cpp @@ -71,7 +71,5 @@ int main() { r[dataSizeFirst + i] = a[dataSizeFirst + i] + b[dataSizeFirst + i]; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(r[i] == static_cast(i) * 2.0f); - } + SYCLACADEMY_ASSERT_EQUAL(r, [](size_t i) { return i * 2.0f; }); } diff --git a/Code_Exercises/ND_Range_Kernel/solution.cpp b/Code_Exercises/ND_Range_Kernel/solution.cpp index 48da20a2..24f1c746 100644 --- a/Code_Exercises/ND_Range_Kernel/solution.cpp +++ b/Code_Exercises/ND_Range_Kernel/solution.cpp @@ -49,9 +49,7 @@ void test_item() { std::cout << "Exception caught: " << e.what() << std::endl; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(r[i] == i * 2); - } + SYCLACADEMY_ASSERT_EQUAL(r, [](size_t i) { return i * 2; }); } void test_nd_item() { @@ -91,9 +89,7 @@ void test_nd_item() { std::cout << "Exception caught: " << e.what() << std::endl; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(r[i] == i * 2); - } + SYCLACADEMY_ASSERT_EQUAL(r, [](size_t i) { return i * 2; }); } int main() { diff --git a/Code_Exercises/ND_Range_Kernel/source.cpp b/Code_Exercises/ND_Range_Kernel/source.cpp index 4e12f649..7ce162ea 100644 --- a/Code_Exercises/ND_Range_Kernel/source.cpp +++ b/Code_Exercises/ND_Range_Kernel/source.cpp @@ -71,7 +71,5 @@ int main() { r[i] = a[i] + b[i]; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(r[i] == i * 2); - } + SYCLACADEMY_ASSERT_EQUAL(r, [](size_t i) { return i * 2; }); } diff --git a/Code_Exercises/Using_USM/solution.cpp b/Code_Exercises/Using_USM/solution.cpp index d37f5b5a..3c56d3be 100644 --- a/Code_Exercises/Using_USM/solution.cpp +++ b/Code_Exercises/Using_USM/solution.cpp @@ -62,7 +62,5 @@ int main() { std::cout << "Exception caught: " << e.what() << std::endl; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(r[i] == i * 2); - } + SYCLACADEMY_ASSERT_EQUAL(r, [](size_t i) { return i * 2.0f; }); } diff --git a/Code_Exercises/Using_USM/source.cpp b/Code_Exercises/Using_USM/source.cpp index d70dc70d..43c23f09 100644 --- a/Code_Exercises/Using_USM/source.cpp +++ b/Code_Exercises/Using_USM/source.cpp @@ -26,7 +26,5 @@ int main() { r[i] = a[i] + b[i]; } - for (int i = 0; i < dataSize; ++i) { - SYCLACADEMY_ASSERT(r[i] == i * 2); - } + SYCLACADEMY_ASSERT_EQUAL(r, [](size_t i) { return i * 2.0f; }); } diff --git a/Code_Exercises/helpers.hpp b/Code_Exercises/helpers.hpp index 42ab463c..63366b42 100644 --- a/Code_Exercises/helpers.hpp +++ b/Code_Exercises/helpers.hpp @@ -11,16 +11,108 @@ #pragma once #include // for size_t +#include +#include #ifndef __SYCL_DEVICE_ONLY__ #include // fprintf #include // abort -#define SYCLACADEMY_ASSERT(cond) \ - if (!(cond)) { \ - std::fprintf(stderr, "%s failed in %s:%d:%s\nExiting\n", #cond, \ - __BASE_FILE__, __LINE__, __FUNCTION__); \ - std::abort(); \ - } +#define SYCLACADEMY_ASSERT(cond) \ + do { \ + if (!(cond)) { \ + std::fprintf(stderr, "[FAILURE] %s failed in %s:%d:%s\nExiting\n", \ + #cond, __BASE_FILE__, __LINE__, __FUNCTION__); \ + std::abort(); \ + } else { \ + std::printf("[SUCCESS] Test passed\n"); \ + } \ + } while (false) #else -#define SYCLACADEMY_ASSERT(cond) void(0); +#define SYCLACADEMY_ASSERT(cond) void(0) #endif + +#define SYCLACADEMY_ASSERT_EQUAL(lhs, rhs) \ + SYCLACADEMY_ASSERT(SYCLAcademy::equal(lhs, rhs)) + +namespace SYCLAcademy { + +template +struct is_vector : std::false_type {}; + +template +struct is_vector()[size_t{}])>, + std::void_t().size())> > + : std::true_type {}; + +template +constexpr bool is_vector_v = is_vector::value; + +template +constexpr size_t get_size(T&& container) { + using TT = std::remove_reference_t; + if constexpr (std::is_array_v) { + return std::extent_v; + } else if constexpr (is_vector_v) { + return container.size(); + } + return 0; +} + +/** + * @brief Generic equality comparison + * + * Pointer types are not allowed. + * + * @param lhs can be a fundamental type, an object, an array or a vector-like + * type (has operator[] and method size()) + * @param rhs allowed types depend on lhs type; it can be always a fundamental + * type or an object; if lhs is an array or vector-like type then it can be an + * array or vector-like type (for element-wise comparison) or a lambda taking + * size_t index as parameter (for element-wise comparison to the return value + * of lambda(index)) + */ +template +constexpr bool equal(T&& lhs, U&& rhs) { + using TT = std::remove_reference_t; + using UU = std::remove_reference_t; + static_assert(!std::is_pointer_v && !std::is_pointer_v); + if constexpr (std::is_array_v || is_vector_v) { + const size_t lhs_size{get_size(std::forward(lhs))}; + if constexpr (std::is_array_v || is_vector_v) { + // + // Compare array/vector to array/vector element-wise + // + const size_t rhs_size{get_size(std::forward(rhs))}; + if (lhs_size < 1 || lhs_size != rhs_size) { + return false; + } + for (size_t i{0}; i < lhs_size; ++i) { + if (lhs[i] != rhs[i]) return false; + } + return true; + } else if constexpr (std::is_invocable_v) { + // + // Compare array/vector to lambda(index) element-wise + // + for (size_t i{0}; i < lhs_size; ++i) { + if (lhs[i] != rhs(i)) return false; + } + return true; + } else { + // + // Compare all elements of an array/vector to a single value + // + for (size_t i{0}; i < lhs_size; ++i) { + if (lhs[i] != rhs) return false; + } + return true; + } + } else { + // + // Single value comparison + // + static_assert(!std::is_array_v && !is_vector_v); + return lhs == rhs; + } +} +} // namespace SYCLAcademy