| //===------- Offload API tests - olMemPrefetch ----------------------------===// |
| // |
| // 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 "../common/Fixtures.hpp" |
| #include <OffloadAPI.h> |
| #include <gtest/gtest.h> |
| |
| using olMemPrefetchTest = OffloadQueueTest; |
| OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olMemPrefetchTest); |
| |
| TEST_P(olMemPrefetchTest, SuccessHostToDevice) { |
| constexpr size_t Size = 1024; |
| void *Alloc; |
| ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED, Size, &Alloc)); |
| |
| std::memset(Alloc, 0x42, Size); |
| |
| const void *Mems[] = {Alloc}; |
| const size_t Sizes[] = {Size}; |
| ASSERT_SUCCESS(olMemPrefetch(Queue, 1, Mems, Sizes, |
| OL_MEM_MIGRATION_FLAG_HOST_TO_DEVICE)); |
| ASSERT_SUCCESS(olSyncQueue(Queue)); |
| |
| for (size_t I = 0; I < Size; I++) |
| ASSERT_EQ(static_cast<uint8_t *>(Alloc)[I], 0x42); |
| |
| ASSERT_SUCCESS(olMemFree(Alloc)); |
| } |
| |
| TEST_P(olMemPrefetchTest, SuccessDeviceToHost) { |
| constexpr size_t Size = 1024; |
| void *Alloc; |
| ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED, Size, &Alloc)); |
| |
| std::memset(Alloc, 0x21, Size); |
| |
| const void *Mems[] = {Alloc}; |
| const size_t Sizes[] = {Size}; |
| // Migrate to the device first, then bring it back. |
| ASSERT_SUCCESS(olMemPrefetch(Queue, 1, Mems, Sizes, |
| OL_MEM_MIGRATION_FLAG_HOST_TO_DEVICE)); |
| ASSERT_SUCCESS(olMemPrefetch(Queue, 1, Mems, Sizes, |
| OL_MEM_MIGRATION_FLAG_DEVICE_TO_HOST)); |
| ASSERT_SUCCESS(olSyncQueue(Queue)); |
| |
| for (size_t I = 0; I < Size; I++) |
| ASSERT_EQ(static_cast<uint8_t *>(Alloc)[I], 0x21); |
| |
| ASSERT_SUCCESS(olMemFree(Alloc)); |
| } |
| |
| TEST_P(olMemPrefetchTest, SuccessMultiple) { |
| constexpr size_t NumAllocs = 3; |
| constexpr size_t Size = 1024; |
| void *Allocs[NumAllocs]; |
| const void *Mems[NumAllocs]; |
| size_t Sizes[NumAllocs]; |
| for (size_t I = 0; I < NumAllocs; I++) { |
| ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED, Size, &Allocs[I])); |
| std::memset(Allocs[I], static_cast<int>(0x10 + I), Size); |
| Mems[I] = Allocs[I]; |
| Sizes[I] = Size; |
| } |
| |
| ASSERT_SUCCESS(olMemPrefetch(Queue, NumAllocs, Mems, Sizes, |
| OL_MEM_MIGRATION_FLAG_HOST_TO_DEVICE)); |
| ASSERT_SUCCESS(olSyncQueue(Queue)); |
| |
| for (size_t I = 0; I < NumAllocs; I++) { |
| for (size_t J = 0; J < Size; J++) |
| ASSERT_EQ(static_cast<uint8_t *>(Allocs[I])[J], |
| static_cast<uint8_t>(0x10 + I)); |
| ASSERT_SUCCESS(olMemFree(Allocs[I])); |
| } |
| } |
| |
| TEST_P(olMemPrefetchTest, SuccessZeroCount) { |
| ASSERT_SUCCESS(olMemPrefetch(Queue, 0, nullptr, nullptr, |
| OL_MEM_MIGRATION_FLAG_HOST_TO_DEVICE)); |
| ASSERT_SUCCESS(olSyncQueue(Queue)); |
| } |
| |
| TEST_P(olMemPrefetchTest, SuccessZeroSize) { |
| constexpr size_t Size = 1024; |
| void *Alloc; |
| ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED, Size, &Alloc)); |
| |
| const void *Mems[] = {Alloc}; |
| const size_t Sizes[] = {0}; |
| ASSERT_SUCCESS(olMemPrefetch(Queue, 1, Mems, Sizes, |
| OL_MEM_MIGRATION_FLAG_HOST_TO_DEVICE)); |
| ASSERT_SUCCESS(olSyncQueue(Queue)); |
| |
| ASSERT_SUCCESS(olMemFree(Alloc)); |
| } |
| |
| TEST_P(olMemPrefetchTest, SuccessUnsupportedAllocType) { |
| // Prefetching a non-managed allocation is not meaningful, but per the API |
| // contract the hint must be silently ignored and the call must still succeed. |
| constexpr size_t Size = 1024; |
| void *Alloc; |
| ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_DEVICE, Size, &Alloc)); |
| |
| const void *Mems[] = {Alloc}; |
| const size_t Sizes[] = {Size}; |
| ASSERT_SUCCESS(olMemPrefetch(Queue, 1, Mems, Sizes, |
| OL_MEM_MIGRATION_FLAG_HOST_TO_DEVICE)); |
| ASSERT_SUCCESS(olSyncQueue(Queue)); |
| |
| ASSERT_SUCCESS(olMemFree(Alloc)); |
| } |
| |
| TEST_P(olMemPrefetchTest, InvalidFlags) { |
| constexpr size_t Size = 1024; |
| void *Alloc; |
| ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED, Size, &Alloc)); |
| |
| const void *Mems[] = {Alloc}; |
| const size_t Sizes[] = {Size}; |
| ASSERT_ERROR(OL_ERRC_INVALID_ENUMERATION, |
| olMemPrefetch(Queue, 1, Mems, Sizes, 0xdeadbeef)); |
| |
| ASSERT_SUCCESS(olMemFree(Alloc)); |
| } |
| |
| TEST_P(olMemPrefetchTest, InvalidNullMems) { |
| const size_t Sizes[] = {0}; |
| ASSERT_ERROR(OL_ERRC_INVALID_NULL_POINTER, |
| olMemPrefetch(Queue, 1, nullptr, Sizes, |
| OL_MEM_MIGRATION_FLAG_HOST_TO_DEVICE)); |
| } |
| |
| TEST_P(olMemPrefetchTest, InvalidNullSizes) { |
| constexpr size_t Size = 1024; |
| void *Alloc; |
| ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_MANAGED, Size, &Alloc)); |
| |
| const void *Mems[] = {Alloc}; |
| ASSERT_ERROR(OL_ERRC_INVALID_NULL_POINTER, |
| olMemPrefetch(Queue, 1, Mems, nullptr, |
| OL_MEM_MIGRATION_FLAG_HOST_TO_DEVICE)); |
| |
| ASSERT_SUCCESS(olMemFree(Alloc)); |
| } |