1 | //===-- unittests/Runtime/CUDA/Memory.cpp -----------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "flang/Runtime/CUDA/memory.h" |
10 | #include "cuda_runtime.h" |
11 | #include "../tools.h" |
12 | #include "gtest/gtest.h" |
13 | #include "flang-rt/runtime/allocator-registry.h" |
14 | #include "flang-rt/runtime/terminator.h" |
15 | #include "flang/Runtime/CUDA/allocator.h" |
16 | #include "flang/Runtime/CUDA/common.h" |
17 | #include "flang/Runtime/CUDA/descriptor.h" |
18 | #include "flang/Runtime/allocatable.h" |
19 | #include "flang/Support/Fortran.h" |
20 | |
21 | using namespace Fortran::runtime; |
22 | using namespace Fortran::runtime::cuda; |
23 | |
24 | TEST(MemoryCUFTest, SimpleAllocTramsferFree) { |
25 | int *dev = (int *)RTNAME(CUFMemAlloc)( |
26 | sizeof(int), kMemTypeDevice, __FILE__, __LINE__); |
27 | EXPECT_TRUE(dev != 0); |
28 | int host = 42; |
29 | RTNAME(CUFDataTransferPtrPtr) |
30 | ((void *)dev, (void *)&host, sizeof(int), kHostToDevice, __FILE__, __LINE__); |
31 | host = 0; |
32 | RTNAME(CUFDataTransferPtrPtr) |
33 | ((void *)&host, (void *)dev, sizeof(int), kDeviceToHost, __FILE__, __LINE__); |
34 | EXPECT_EQ(42, host); |
35 | RTNAME(CUFMemFree)((void *)dev, kMemTypeDevice, __FILE__, __LINE__); |
36 | } |
37 | |
38 | static OwningPtr<Descriptor> createAllocatable( |
39 | Fortran::common::TypeCategory tc, int kind, int rank = 1) { |
40 | return Descriptor::Create(TypeCode{tc, kind}, kind, nullptr, rank, nullptr, |
41 | CFI_attribute_allocatable); |
42 | } |
43 | |
44 | TEST(MemoryCUFTest, CUFDataTransferDescDesc) { |
45 | using Fortran::common::TypeCategory; |
46 | RTNAME(CUFRegisterAllocator)(); |
47 | // INTEGER(4), DEVICE, ALLOCATABLE :: a(:) |
48 | auto dev{createAllocatable(TypeCategory::Integer, 4)}; |
49 | dev->SetAllocIdx(kDeviceAllocatorPos); |
50 | EXPECT_EQ((int)kDeviceAllocatorPos, dev->GetAllocIdx()); |
51 | RTNAME(AllocatableSetBounds)(*dev, 0, 1, 10); |
52 | RTNAME(AllocatableAllocate) |
53 | (*dev, /*asyncObject=*/nullptr, /*hasStat=*/false, /*errMsg=*/nullptr, |
54 | __FILE__, __LINE__); |
55 | EXPECT_TRUE(dev->IsAllocated()); |
56 | |
57 | // Create temp array to transfer to device. |
58 | auto x{MakeArray<TypeCategory::Integer, 4>(std::vector<int>{10}, |
59 | std::vector<int32_t>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})}; |
60 | RTNAME(CUFDataTransferDescDesc) |
61 | (dev.get(), x.get(), kHostToDevice, __FILE__, __LINE__); |
62 | |
63 | // Retrieve data from device. |
64 | auto host{MakeArray<TypeCategory::Integer, 4>(std::vector<int>{10}, |
65 | std::vector<int32_t>{0, 0, 0, 0, 0, 0, 0, 0, 0, 0})}; |
66 | RTNAME(CUFDataTransferDescDesc) |
67 | (host.get(), dev.get(), kDeviceToHost, __FILE__, __LINE__); |
68 | |
69 | for (unsigned i = 0; i < 10; ++i) { |
70 | EXPECT_EQ(*host->ZeroBasedIndexedElement<std::int32_t>(i), (std::int32_t)i); |
71 | } |
72 | } |
73 | |
74 | TEST(MemoryCUFTest, CUFDataTransferDescDescDstNotAllocated) { |
75 | using Fortran::common::TypeCategory; |
76 | RTNAME(CUFRegisterAllocator)(); |
77 | // INTEGER(4), DEVICE, ALLOCATABLE :: a(:) |
78 | auto dev{createAllocatable(TypeCategory::Integer, 4)}; |
79 | dev->SetAllocIdx(kDeviceAllocatorPos); |
80 | EXPECT_EQ((int)kDeviceAllocatorPos, dev->GetAllocIdx()); |
81 | EXPECT_FALSE(dev->IsAllocated()); |
82 | |
83 | // Create temp array to transfer to device. |
84 | auto x{MakeArray<TypeCategory::Integer, 4>(std::vector<int>{10}, |
85 | std::vector<int32_t>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})}; |
86 | RTNAME(CUFDataTransferDescDesc) |
87 | (dev.get(), x.get(), kHostToDevice, __FILE__, __LINE__); |
88 | |
89 | // Retrieve data from device. |
90 | auto host{MakeArray<TypeCategory::Integer, 4>(std::vector<int>{10}, |
91 | std::vector<int32_t>{0, 0, 0, 0, 0, 0, 0, 0, 0, 0})}; |
92 | RTNAME(CUFDataTransferDescDesc) |
93 | (host.get(), dev.get(), kDeviceToHost, __FILE__, __LINE__); |
94 | |
95 | for (unsigned i = 0; i < 10; ++i) { |
96 | EXPECT_EQ(*host->ZeroBasedIndexedElement<std::int32_t>(i), (std::int32_t)i); |
97 | } |
98 | } |
99 | |