forked from oneapi-src/SYCLomatic
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[SYCLomatic oneapi-src#1165] Add malloc, free, and temporary allocati…
…on tests (oneapi-src#426) Signed-off-by: Matthew Michel <[email protected]>
- Loading branch information
Showing
3 changed files
with
333 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
// ====------ onedpl_test_malloc_free.cpp---------- -*- C++ -* ----===//// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
// | ||
// ===----------------------------------------------------------------------===// | ||
|
||
#include "oneapi/dpl/algorithm" | ||
#include "oneapi/dpl/execution" | ||
|
||
#include "dpct/dpct.hpp" | ||
#include "dpct/dpl_utils.hpp" | ||
|
||
#include <iostream> | ||
#include <vector> | ||
|
||
template <typename String, typename _T1, typename _T2> | ||
int ASSERT_EQUAL(String msg, _T1 &&X, _T2 &&Y) { | ||
if (X != Y) { | ||
std::cout << "FAIL: " << msg << " - (" << X << "," << Y << ")" << std::endl; | ||
return 1; | ||
} | ||
return 0; | ||
} | ||
|
||
int test_passed(int failing_elems, std::string test_name) { | ||
if (failing_elems == 0) { | ||
std::cout << "PASS: " << test_name << std::endl; | ||
return 0; | ||
} | ||
return 1; | ||
} | ||
|
||
template <typename T, typename PolicyOrTag, typename TestVoidMalloc> | ||
int test_malloc_free_on_device(sycl::queue q, PolicyOrTag policy_or_tag, | ||
std::string test_name, std::size_t num_elements, | ||
TestVoidMalloc) { | ||
using alloc_t = std::conditional_t<TestVoidMalloc::value, void, T>; | ||
int failed_tests = 0; | ||
dpct::tagged_pointer<dpct::device_sys_tag, alloc_t> ptr; | ||
if constexpr (TestVoidMalloc::value) { | ||
ptr = dpct::malloc(policy_or_tag, num_elements * sizeof(T)); | ||
} else { | ||
ptr = dpct::malloc<T>(policy_or_tag, num_elements); | ||
} | ||
std::vector<T> num_data(num_elements); | ||
std::iota(num_data.begin(), num_data.end(), 0); | ||
std::vector<T> out_num_data(num_elements); | ||
q.submit([&](sycl::handler &h) { | ||
h.memcpy(ptr, num_data.data(), sizeof(T) * num_elements); | ||
}) | ||
.wait(); | ||
for (std::size_t i = 0; i != num_elements; ++i) { | ||
if constexpr (TestVoidMalloc::value) | ||
failed_tests += ASSERT_EQUAL(test_name, static_cast<T *>(ptr)[i], | ||
static_cast<T>(i)); | ||
else | ||
failed_tests += ASSERT_EQUAL(test_name, ptr[i], static_cast<T>(i)); | ||
} | ||
q.submit([&](sycl::handler &h) { | ||
h.memcpy(out_num_data.data(), ptr, num_elements * sizeof(T)); | ||
}) | ||
.wait(); | ||
for (std::size_t i = 0; i != num_elements; ++i) | ||
failed_tests += ASSERT_EQUAL(test_name, out_num_data[i], static_cast<T>(i)); | ||
|
||
test_passed(failed_tests, test_name); | ||
dpct::free(policy_or_tag, ptr); | ||
|
||
return failed_tests; | ||
} | ||
|
||
template <typename T, typename PolicyOrTag, typename TestVoidMalloc> | ||
int test_malloc_free_on_host(PolicyOrTag policy_or_tag, std::string test_name, | ||
std::size_t num_elements, TestVoidMalloc) { | ||
using alloc_t = std::conditional_t<TestVoidMalloc::value, void, T>; | ||
dpct::tagged_pointer<dpct::host_sys_tag, alloc_t> ptr; | ||
if constexpr (TestVoidMalloc::value) { | ||
ptr = dpct::malloc(policy_or_tag, num_elements * sizeof(T)); | ||
} else { | ||
ptr = dpct::malloc<T>(policy_or_tag, num_elements); | ||
} | ||
int failed_tests = 0; | ||
std::vector<T> num_data(num_elements); | ||
std::iota(num_data.begin(), num_data.end(), 0); | ||
std::vector<T> out_num_data(num_elements); | ||
::std::memcpy(ptr, num_data.data(), num_elements * sizeof(T)); | ||
for (std::size_t i = 0; i != num_elements; ++i) | ||
failed_tests += ASSERT_EQUAL(test_name, static_cast<T *>(ptr)[i], | ||
static_cast<T>(i)); | ||
::std::memcpy(out_num_data.data(), ptr, num_elements * sizeof(T)); | ||
for (std::size_t i = 0; i != num_elements; ++i) | ||
failed_tests += ASSERT_EQUAL(test_name, static_cast<T *>(ptr)[i], | ||
static_cast<T>(i)); | ||
test_passed(failed_tests, test_name); | ||
dpct::free(policy_or_tag, ptr); | ||
|
||
return failed_tests; | ||
} | ||
|
||
int main() { | ||
int failed_tests = 0; | ||
|
||
// Test One, test normal calls for dpct::malloc and dpct::free by allocating a | ||
// certain number of bytes on device. | ||
{ | ||
dpct::device_sys_tag device_exec; | ||
std::string test_name = | ||
"malloc and free byte array allocation - device memory with tag"; | ||
failed_tests += test_malloc_free_on_device<double>( | ||
dpct::get_default_queue(), device_exec, test_name, 5, std::true_type{}); | ||
} | ||
|
||
// Test Two, test normal calls for dpct::malloc and dpct::free by allocating a | ||
// certain number of bytes on host. | ||
{ | ||
dpct::host_sys_tag host_exec; | ||
std::string test_name = | ||
"malloc and free byte array allocation - host memory with tag"; | ||
failed_tests += test_malloc_free_on_host<double>(host_exec, test_name, 5, | ||
std::true_type{}); | ||
} | ||
|
||
// Test three, dpct::malloc and dpct::free allocation for a certain number of | ||
// int64_t elements on device | ||
{ | ||
dpct::device_sys_tag device_exec; | ||
std::string test_name = | ||
"malloc and free int64_t array allocation - device memory with tag"; | ||
failed_tests += test_malloc_free_on_device<int64_t>( | ||
dpct::get_default_queue(), device_exec, test_name, 10, | ||
std::false_type{}); | ||
} | ||
|
||
// Test four, dpct::malloc and dpct::free allocation for a certain number of | ||
// int64_t elements on host | ||
{ | ||
dpct::host_sys_tag host_exec; | ||
std::string test_name = | ||
"malloc and free int64_t array allocation - host memory with tag"; | ||
failed_tests += test_malloc_free_on_host<int64_t>(host_exec, test_name, 10, | ||
std::false_type{}); | ||
} | ||
|
||
// Test five, dpct::malloc and dpct::free allocation for a certain number of | ||
// int64_t elements on device. oneDPL device policy passed as location | ||
{ | ||
sycl::queue q = dpct::get_default_queue(); | ||
auto policy = oneapi::dpl::execution::make_device_policy(q); | ||
std::string test_name = | ||
"malloc and free int64_t array allocation - device memory with policy"; | ||
failed_tests += test_malloc_free_on_device<int64_t>(q, policy, test_name, | ||
10, std::false_type{}); | ||
} | ||
|
||
// Test six, dpct::malloc and dpct::free allocation for a certain number of | ||
// int64_t elements on device. oneDPL host policy passed as location | ||
{ | ||
std::string test_name = | ||
"malloc and free int64_t array allocation - host memory with policy"; | ||
failed_tests += test_malloc_free_on_host<int64_t>( | ||
oneapi::dpl::execution::seq, test_name, 10, std::false_type{}); | ||
} | ||
|
||
// Test seven, ensure functionality of dpct::internal::malloc_base internal | ||
// utility. | ||
{ | ||
std::size_t num_bytes = sizeof(int64_t) * 10; | ||
int64_t *ptr = static_cast<int64_t *>( | ||
dpct::internal::malloc_base(dpct::host_sys_tag{}, num_bytes)); | ||
std::iota(ptr, ptr + 10, 0); | ||
std::string test_name = "internal::malloc_base utility with host tag"; | ||
|
||
for (int i = 0; i < 10; ++i) | ||
failed_tests += ASSERT_EQUAL(test_name, ptr[i], i); | ||
std::free(ptr); | ||
} | ||
|
||
std::cout << std::endl | ||
<< failed_tests << " failing test(s) detected." << std::endl; | ||
if (failed_tests == 0) { | ||
return 0; | ||
} | ||
return 1; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
// ====------ onedpl_test_temporary_allocation.cpp---------- -*- C++ -* | ||
// ----===//// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
// | ||
// ===----------------------------------------------------------------------===// | ||
|
||
#include "oneapi/dpl/algorithm" | ||
#include "oneapi/dpl/execution" | ||
|
||
#include "dpct/dpct.hpp" | ||
#include "dpct/dpl_utils.hpp" | ||
|
||
#include <iostream> | ||
|
||
template <typename String, typename _T1, typename _T2> | ||
int ASSERT_EQUAL(String msg, _T1 &&X, _T2 &&Y) { | ||
if (X != Y) { | ||
std::cout << "FAIL: " << msg << " - (" << X << "," << Y << ")" << std::endl; | ||
return 1; | ||
} | ||
return 0; | ||
} | ||
|
||
int test_passed(int failing_elems, std::string test_name) { | ||
if (failing_elems == 0) { | ||
std::cout << "PASS: " << test_name << std::endl; | ||
return 0; | ||
} | ||
return 1; | ||
} | ||
|
||
template <typename T, typename PolicyOrTag> | ||
int test_temporary_allocation_on_device(sycl::queue q, | ||
PolicyOrTag policy_or_tag, | ||
std::string test_name, | ||
std::size_t num_elements) { | ||
int failed_tests = 0; | ||
// TODO: Use structured bindings when we switch to C++20 and can capture the | ||
// variables in lambda capture clause. | ||
auto ret_tup = dpct::get_temporary_allocation<T>(policy_or_tag, num_elements); | ||
auto ptr = std::get<0>(ret_tup); | ||
auto num_allocated = std::get<1>(ret_tup); | ||
std::vector<T> num_data(num_elements); | ||
std::iota(num_data.begin(), num_data.end(), 0); | ||
std::vector<T> out_num_data(num_elements); | ||
q.submit([&](sycl::handler &h) { | ||
h.memcpy(ptr, num_data.data(), sizeof(T) * num_elements); | ||
}) | ||
.wait(); | ||
for (std::size_t i = 0; i != num_elements; ++i) { | ||
failed_tests += ASSERT_EQUAL(test_name, ptr[i], static_cast<T>(i)); | ||
} | ||
q.submit([&](sycl::handler &h) { | ||
h.memcpy(out_num_data.data(), ptr, num_elements * sizeof(T)); | ||
}) | ||
.wait(); | ||
for (std::size_t i = 0; i != num_elements; ++i) | ||
failed_tests += ASSERT_EQUAL(test_name, out_num_data[i], static_cast<T>(i)); | ||
|
||
failed_tests += (num_allocated != num_elements); | ||
test_passed(failed_tests, test_name); | ||
dpct::release_temporary_allocation(policy_or_tag, ptr); | ||
|
||
return failed_tests; | ||
} | ||
|
||
template <typename T, typename PolicyOrTag> | ||
int test_temporary_allocation_on_host(PolicyOrTag policy_or_tag, | ||
std::string test_name, | ||
std::size_t num_elements) { | ||
int failed_tests = 0; | ||
// TODO: Use structured bindings when we switch to C++20 and can capture the | ||
// variables in lambda capture clause. | ||
auto ret_tup = dpct::get_temporary_allocation<T>(policy_or_tag, num_elements); | ||
auto ptr = std::get<0>(ret_tup); | ||
auto num_allocated = std::get<1>(ret_tup); | ||
std::vector<T> num_data(num_elements); | ||
std::iota(num_data.begin(), num_data.end(), 0); | ||
std::vector<T> out_num_data(num_elements); | ||
::std::memcpy(ptr, num_data.data(), num_elements * sizeof(T)); | ||
for (std::size_t i = 0; i != num_elements; ++i) | ||
failed_tests += ASSERT_EQUAL(test_name, ptr[i], static_cast<T>(i)); | ||
::std::memcpy(out_num_data.data(), ptr, num_elements * sizeof(T)); | ||
for (std::size_t i = 0; i != num_elements; ++i) | ||
failed_tests += ASSERT_EQUAL(test_name, ptr[i], static_cast<T>(i)); | ||
|
||
failed_tests += (num_allocated != num_elements); | ||
test_passed(failed_tests, test_name); | ||
dpct::release_temporary_allocation(policy_or_tag, ptr); | ||
|
||
return failed_tests; | ||
} | ||
|
||
int main() { | ||
// used to detect failures | ||
int failed_tests = 0; | ||
|
||
// Test One, temporary allocation with device tag. | ||
{ | ||
dpct::device_sys_tag device_sys; | ||
std::string test_name = | ||
"get and release temporary allocation - device memory with tag"; | ||
failed_tests += test_temporary_allocation_on_device<int64_t>( | ||
dpct::get_default_queue(), device_sys, test_name, 10); | ||
} | ||
|
||
// Test Two, temporary allocation with host tag. | ||
{ | ||
dpct::host_sys_tag host_sys; | ||
std::string test_name = | ||
"get and release temporary allocation - host memory with tag"; | ||
failed_tests += | ||
test_temporary_allocation_on_host<int64_t>(host_sys, test_name, 10); | ||
} | ||
|
||
// Test Three, temporary allocation with device policy. | ||
{ | ||
sycl::queue q = dpct::get_default_queue(); | ||
auto policy = oneapi::dpl::execution::make_device_policy(q); | ||
std::string test_name = | ||
"get and release temporary allocation - device memory with policy"; | ||
failed_tests += | ||
test_temporary_allocation_on_device<int64_t>(q, policy, test_name, 10); | ||
} | ||
|
||
// Test Four, temporary allocation with host policy. | ||
{ | ||
std::string test_name = | ||
"get and release temporary allocation - host memory with policy"; | ||
failed_tests += test_temporary_allocation_on_host<int64_t>( | ||
oneapi::dpl::execution::par_unseq, test_name, 10); | ||
} | ||
|
||
std::cout << std::endl | ||
<< failed_tests << " failing test(s) detected." << std::endl; | ||
if (failed_tests == 0) { | ||
return 0; | ||
} | ||
return 1; | ||
} |