diff --git a/sycl/include/CL/sycl/usm/usm_allocator.hpp b/sycl/include/CL/sycl/usm/usm_allocator.hpp index f821175205c03..3270fa1d6d67e 100644 --- a/sycl/include/CL/sycl/usm/usm_allocator.hpp +++ b/sycl/include/CL/sycl/usm/usm_allocator.hpp @@ -26,112 +26,45 @@ __SYCL_EXPORT void *aligned_alloc(size_t alignment, size_t size, usm::alloc kind); __SYCL_EXPORT void free(void *ptr, const context &ctxt); -template +template class usm_allocator { public: using value_type = T; - using pointer = T *; - using const_pointer = const T *; - using reference = T &; - using const_reference = const T &; + using propagate_on_container_copy_assignment = std::true_type; + using propagate_on_container_move_assignment = std::true_type; + using propagate_on_container_swap = std::true_type; public: template struct rebind { typedef usm_allocator other; }; - usm_allocator() = delete; - usm_allocator(const context &Ctxt, const device &Dev) + static_assert( + AllocKind != usm::alloc::device, + "usm_allocator does not support AllocKind == usm::alloc::device"); + + usm_allocator() noexcept = delete; + usm_allocator(const context &Ctxt, const device &Dev) noexcept : MContext(Ctxt), MDevice(Dev) {} - usm_allocator(const queue &Q) + usm_allocator(const queue &Q) noexcept : MContext(Q.get_context()), MDevice(Q.get_device()) {} - usm_allocator(const usm_allocator &Other) - : MContext(Other.MContext), MDevice(Other.MDevice) {} - - /// Constructs an object on memory pointed by Ptr. - /// - /// Note: AllocKind == alloc::device is not allowed. - /// - /// \param Ptr is a pointer to memory that will be used to construct the - /// object. - /// \param Val is a value to initialize the newly constructed object. - template < - usm::alloc AllocT = AllocKind, - typename std::enable_if::type = 0> - void construct(pointer Ptr, const_reference Val) { - new (Ptr) value_type(Val); - } - - template < - usm::alloc AllocT = AllocKind, - typename std::enable_if::type = 0> - void construct(pointer, const_reference) { - throw feature_not_supported( - "Device pointers do not support construct on host", - PI_INVALID_OPERATION); - } + usm_allocator(const usm_allocator &) noexcept = default; + usm_allocator(usm_allocator &&) noexcept = default; + usm_allocator &operator=(const usm_allocator &) = delete; + usm_allocator &operator=(usm_allocator &&) = default; - /// Destroys an object. - /// - /// Note:: AllocKind == alloc::device is not allowed - /// - /// \param Ptr is a pointer to memory where the object resides. - template < - usm::alloc AllocT = AllocKind, - typename std::enable_if::type = 0> - void destroy(pointer Ptr) { - Ptr->~value_type(); - } - - template < - usm::alloc AllocT = AllocKind, - typename std::enable_if::type = 0> - void destroy(pointer) { - // This method must be a NOP for device pointers. - } - - /// Note:: AllocKind == alloc::device is not allowed. - /// - /// \param Val is a reference to object. - /// \return an address of the object referenced by Val. - template < - usm::alloc AllocT = AllocKind, - typename std::enable_if::type = 0> - pointer address(reference Val) const { - return &Val; - } - - template < - usm::alloc AllocT = AllocKind, - typename std::enable_if::type = 0> - pointer address(reference) const { - throw feature_not_supported( - "Device pointers do not support address on host", PI_INVALID_OPERATION); - } - - template < - usm::alloc AllocT = AllocKind, - typename std::enable_if::type = 0> - const_pointer address(const_reference Val) const { - return &Val; - } - - template < - usm::alloc AllocT = AllocKind, - typename std::enable_if::type = 0> - const_pointer address(const_reference) const { - throw feature_not_supported( - "Device pointers do not support address on host", PI_INVALID_OPERATION); - } + template + usm_allocator(const usm_allocator &Other) noexcept + : MContext(Other.MContext), MDevice(Other.MDevice) {} /// Allocates memory. /// /// \param NumberOfElements is a count of elements to allocate memory for. - pointer allocate(size_t NumberOfElements) { + T *allocate(size_t NumberOfElements) { - auto Result = reinterpret_cast( + auto Result = reinterpret_cast( aligned_alloc(getAlignment(), NumberOfElements * sizeof(value_type), - MDevice, MContext, AllocKind)); + MDevice, MContext, AllocKind)); if (!Result) { throw memory_allocation_error(); } @@ -142,24 +75,32 @@ class usm_allocator { /// /// \param Ptr is a pointer to memory being deallocated. /// \param Size is a number of elements previously passed to allocate. - void deallocate(pointer Ptr, size_t) { + void deallocate(T *Ptr, size_t) { if (Ptr) { free(Ptr, MContext); } } -private: - constexpr size_t getAlignment() const { - /* - // This form might be preferable if the underlying implementation - // doesn't do the right thing when given 0 for alignment - return ((Alignment == 0) - ? alignof(value_type) - : Alignment); - */ - return Alignment; + template + friend bool operator==(const usm_allocator &One, + const usm_allocator &Two) { + return ((AllocKind == AllocKindU) && (One.MContext == Two.MContext) && + (One.MDevice == Two.MDevice)); + } + + template + friend bool operator!=(const usm_allocator &One, + const usm_allocator &Two) { + return !((AllocKind == AllocKindU) && (One.MContext == Two.MContext) && + (One.MDevice == Two.MDevice)); } +private: + constexpr size_t getAlignment() const { return Alignment; } + + template + friend class usm_allocator; + const context MContext; const device MDevice; }; diff --git a/sycl/test/usm/allocator_equal.cpp b/sycl/test/usm/allocator_equal.cpp new file mode 100644 index 0000000000000..e02040fe16c28 --- /dev/null +++ b/sycl/test/usm/allocator_equal.cpp @@ -0,0 +1,55 @@ +// piextUSM*Alloc functions for CUDA are not behaving as described in +// https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/USM/USM.adoc +// https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/USM/cl_intel_unified_shared_memory.asciidoc +// +// RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple %s -o %t1.out +// RUN: env SYCL_DEVICE_TYPE=HOST %t1.out +// RUN: %CPU_RUN_PLACEHOLDER %t1.out +// RUN: %GPU_RUN_PLACEHOLDER %t1.out + +//==---------- allocator_equal.cpp - Allocator Equality test ---------------==// +// +// 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 + +#include + +using namespace cl::sycl; + +int main() { + queue q; + auto dev = q.get_device(); + auto ctxt = q.get_context(); + + queue q2; + auto dev2 = q2.get_device(); + auto ctxt2 = q2.get_context(); + + // Test allocator equality + if (dev.get_info()) { + usm_allocator alloc1(ctxt, dev); + usm_allocator alloc2(q); + + assert((alloc1 == alloc2) && "Allocators should be equal."); + + usm_allocator alloc3(ctxt, dev); + usm_allocator alloc4(q); + + assert((alloc1 == alloc2) && "Allocators should be equal."); + } + + if (dev.get_info() && + dev.get_info()) { + usm_allocator alloc1(ctxt, dev); + usm_allocator alloc2(ctxt, dev); + + assert((alloc1 != alloc2) && "Allocators should NOT be equal."); + } + + return 0; +} diff --git a/sycl/test/usm/allocator_shared.cpp b/sycl/test/usm/allocator_shared.cpp new file mode 100644 index 0000000000000..2dbc0fe57bd6f --- /dev/null +++ b/sycl/test/usm/allocator_shared.cpp @@ -0,0 +1,49 @@ +// RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple %s -o %t1.out +// RUN: env SYCL_DEVICE_TYPE=HOST %t1.out +// RUN: %CPU_RUN_PLACEHOLDER %t1.out +// RUN: %GPU_RUN_PLACEHOLDER %t1.out + +//==-------- allocator_shared.cpp - Allocate Shared test -------------------==// +// +// 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 + +#include +#include + +using namespace cl::sycl; + +int main() { + queue q; + auto dev = q.get_device(); + auto ctxt = q.get_context(); + + // Test ability to create a shared pointer. + if (dev.get_info()) { + usm_allocator alloc(ctxt, dev); + auto ptr1 = std::allocate_shared(alloc); + + // Test construction + auto ptr2 = std::allocate_shared(alloc, 42); + assert((*ptr2 == 42) && "Host construct passed."); + } + + if (dev.get_info()) { + usm_allocator alloc(ctxt, dev); + auto ptr1 = std::allocate_shared(alloc); + + // Test construction + auto ptr2 = std::allocate_shared(alloc, 42); + assert((*ptr2 == 42) && "Shared construct passed."); + } + + // Device allocations are not supported due to how allocated_shared is + // written. + + return 0; +} diff --git a/sycl/test/usm/allocator_vector.cpp b/sycl/test/usm/allocator_vector.cpp index 265c071e1cf0e..8f0dcaa62055a 100644 --- a/sycl/test/usm/allocator_vector.cpp +++ b/sycl/test/usm/allocator_vector.cpp @@ -1,8 +1,3 @@ -// XFAIL: cuda || level0 -// piextUSM*Alloc functions for CUDA are not behaving as described in -// https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/USM/USM.adoc -// https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/USM/cl_intel_unified_shared_memory.asciidoc -// // RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple %s -o %t1.out // RUN: env SYCL_DEVICE_TYPE=HOST %t1.out // RUN: %CPU_RUN_PLACEHOLDER %t1.out @@ -88,43 +83,5 @@ int main() { return -1; } - if (dev.get_info()) { - usm_allocator alloc(ctxt, dev); - - std::vector vec(alloc); - vec.resize(N); - - int *res = &vec[0]; - int *vals = &vec[0]; - - auto e0 = q.submit([=](handler &h) { - h.single_task([=]() { - res[0] = 0; - for (int i = 0; i < N; i++) { - vals[i] = i; - } - }); - }); - - auto e1 = q.submit([=](handler &h) { - h.depends_on(e0); - h.single_task([=]() { - for (int i = 1; i < N; i++) { - res[0] += vals[i]; - } - }); - }); - - e1.wait(); - - int answer = (N * (N - 1)) / 2; - int result; - q.memcpy(&result, res, sizeof(int)); - q.wait(); - - if (result != answer) - return -1; - } - return 0; } diff --git a/sycl/test/usm/allocator_vector_fail.cpp b/sycl/test/usm/allocator_vector_fail.cpp deleted file mode 100644 index 8c0e176eaa411..0000000000000 --- a/sycl/test/usm/allocator_vector_fail.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// XFAIL: cuda -// piextUSM*Alloc functions for CUDA are not behaving as described in -// https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/USM/USM.adoc -// https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/USM/cl_intel_unified_shared_memory.asciidoc -// -// RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple %s -o %t1.out -// RUN: env SYCL_DEVICE_TYPE=HOST %t1.out -// RUN: %CPU_RUN_PLACEHOLDER %t1.out -// RUN: %GPU_RUN_PLACEHOLDER %t1.out - -//==-- allocator_vector_fail.cpp - Device Memory Allocator fail test -------==// -// -// 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 - -#include - -using namespace cl::sycl; - -const int N = 8; - -class foo; -int main() { - queue q; - auto dev = q.get_device(); - auto ctxt = q.get_context(); - - if (dev.get_info()) { - try { - usm_allocator alloc(ctxt, dev); - std::vector vec(alloc); - - // This statement should throw an exception since - // device pointers may not be accessed on the host. - vec.assign(N, 42); - } catch (feature_not_supported) { - return 0; - } - - return -1; - } - return 0; -} diff --git a/sycl/test/usm/allocatorll.cpp b/sycl/test/usm/allocatorll.cpp deleted file mode 100644 index 323dc0d75a1c1..0000000000000 --- a/sycl/test/usm/allocatorll.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// XFAIL: cuda -// piextUSM*Alloc functions for CUDA are not behaving as described in -// https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/USM/USM.adoc -// https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/USM/cl_intel_unified_shared_memory.asciidoc -// -// RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple %s -o %t1.out -// RUN: env SYCL_DEVICE_TYPE=HOST %t1.out -// RUN: %CPU_RUN_PLACEHOLDER %t1.out -// RUN: %GPU_RUN_PLACEHOLDER %t1.out - -//==---- allocatorll.cpp - Device Memory Linked List Allocator test --------==// -// -// 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 - -using namespace cl::sycl; - -int numNodes = 4; - -struct Node { - Node() : pNext(nullptr), Num(0xDEADBEEF) {} - - Node *pNext; - uint32_t Num; -}; - -class foo; -int main() { - queue q; - auto dev = q.get_device(); - auto ctxt = q.get_context(); - - if (!dev.get_info()) - return 0; - - usm_allocator alloc(ctxt, dev); - Node h_cur; - - Node *d_head = alloc.allocate(1); - Node *d_cur = d_head; - - for (int i = 0; i < numNodes; i++) { - h_cur.Num = i * 2; - - if (i != (numNodes - 1)) { - h_cur.pNext = alloc.allocate(1); - } else { - h_cur.pNext = nullptr; - } - - event e0 = q.memcpy(d_cur, &h_cur, sizeof(Node)); - e0.wait(); - - d_cur = h_cur.pNext; - } - - auto e1 = q.submit([=](handler &cgh) { - cgh.single_task([=]() { - Node *pHead = d_head; - while (pHead) { - pHead->Num = pHead->Num * 2 + 1; - pHead = pHead->pNext; - } - }); - }); - - e1.wait(); - - d_cur = d_head; - for (int i = 0; i < numNodes; i++) { - event c = q.memcpy(&h_cur, d_cur, sizeof(Node)); - c.wait(); - alloc.deallocate(d_cur, 1); - - const int want = i * 4 + 1; - if (h_cur.Num != want) { - return -2; - } - d_cur = h_cur.pNext; - } - - return 0; -}