/* * Copyright (c) Advanced Micro Devices, Inc., or its affiliates. * * SPDX-License-Identifier: MIT */ #include #include static constexpr auto NUM_W{10}; static constexpr auto NUM_H{10}; /* * This Scenario Verifies hipMemcpy2DToArray API by copying the * data from pinned host memory to device from Peer GPU. * Device Memory is allocated in GPU 0 and the API is trigerred from GPU1 * INPUT: Copying Host variable E_h(Initialized with value 10+i(numelements)) * --> A_d device variable * whose memory is allocated in GPU 0 * OUTPUT: For validating the result,Copying A_d device variable * --> A_h host variable * and verifying A_h with E_h[0]+i(i.e., 10+i) */ HIP_TEST_CASE(Unit_hipMemcpy2DToArrayAsync_multiDevicePinnedHostMem) { CHECK_IMAGE_SUPPORT int numDevices = 0; constexpr auto def_val{10}; HIP_CHECK(hipGetDeviceCount(&numDevices)); if (numDevices > 1) { int canAccessPeer = 0; HIP_CHECK(hipDeviceCanAccessPeer(&canAccessPeer, 0, 1)); if (canAccessPeer) { HIP_CHECK(hipSetDevice(0)); hipArray_t A_d{nullptr}; size_t width{sizeof(float) * NUM_W}; float *A_h{nullptr}, *E_h{nullptr}; hipStream_t stream; HIP_CHECK(hipStreamCreate(&stream)); // Initialization of variables HipTest::initArrays(nullptr, nullptr, nullptr, &A_h, nullptr, nullptr, width * NUM_H, false); hipChannelFormatDesc desc = hipCreateChannelDesc(); HIP_CHECK(hipMallocArray(&A_d, &desc, NUM_W, NUM_H, hipArrayDefault)); HipTest::setDefaultData(width * NUM_H, A_h, nullptr, nullptr); HIP_CHECK(hipSetDevice(1)); HIP_CHECK(hipHostMalloc(reinterpret_cast(&E_h), width * NUM_H)); for (int i = 0; i < NUM_W * NUM_H; i++) { E_h[i] = def_val + i; } HIP_CHECK(hipMemcpy2DToArrayAsync(A_d, 0, 0, E_h, width, width, NUM_H, hipMemcpyHostToDevice, stream)); HIP_CHECK(hipStreamSynchronize(stream)); HIP_CHECK(hipSetDevice(0)); HIP_CHECK(hipMemcpy2DFromArray(A_h, width, A_d, 0, 0, width, NUM_H, hipMemcpyDeviceToHost)); REQUIRE(HipTest::checkArray(A_h, E_h, NUM_W, NUM_H) == true); // Cleaning the memory HIP_CHECK(hipFreeArray(A_d)); HIP_CHECK(hipHostFree(E_h)); HIP_CHECK(hipStreamDestroy(stream)); HipTest::freeArrays(nullptr, nullptr, nullptr, A_h, nullptr, nullptr, false); } else { HIP_SKIP_TEST(HipTest::SkipReason::kPeerAccessUnavailable); } } else { HIP_SKIP_TEST(HipTest::SkipReason::kFewerThanTwoGpus); } } /* * This scenario verifies the hipMemcpy2DToArray API in case of device * context change. * Memory is allocated in GPU-0 and the API is triggered from GPU-1 * INPUT: Copying Host variable hData(Initial value Phi) * --> A_d device variable * whose memory is allocated in GPU 0 * OUTPUT: For validating the result,Copying A_d device variable * --> A_h host variable * and verifying A_h with Phi * */ HIP_TEST_CASE(Unit_hipMemcpy2DToArrayAsync_multiDeviceDeviceContextChange) { CHECK_IMAGE_SUPPORT int numDevices = 0; HIP_CHECK(hipGetDeviceCount(&numDevices)); if (numDevices > 1) { int canAccessPeer = 0; HIP_CHECK(hipDeviceCanAccessPeer(&canAccessPeer, 0, 1)); if (canAccessPeer) { HIP_CHECK(hipSetDevice(0)); hipArray_t A_d{nullptr}; size_t width{sizeof(float) * NUM_W}; float *A_h{nullptr}, *hData{nullptr}; hipStream_t stream; // Initialization of variables HipTest::initArrays(nullptr, nullptr, nullptr, &A_h, &hData, nullptr, width * NUM_H, false); hipChannelFormatDesc desc = hipCreateChannelDesc(); HIP_CHECK(hipMallocArray(&A_d, &desc, NUM_W, NUM_H, hipArrayDefault)); HipTest::setDefaultData(width * NUM_H, A_h, hData, nullptr); HIP_CHECK(hipSetDevice(1)); HIP_CHECK(hipStreamCreate(&stream)); HIP_CHECK(hipMemcpy2DToArrayAsync(A_d, 0, 0, hData, width, width, NUM_H, hipMemcpyHostToDevice, stream)); HIP_CHECK(hipStreamSynchronize(stream)); HIP_CHECK(hipMemcpy2DFromArray(A_h, width, A_d, 0, 0, width, NUM_H, hipMemcpyDeviceToHost)); REQUIRE(HipTest::checkArray(A_h, hData, NUM_W, NUM_H) == true); // Cleaning the memory HIP_CHECK(hipFreeArray(A_d)); HIP_CHECK(hipStreamDestroy(stream)); HipTest::freeArrays(nullptr, nullptr, nullptr, A_h, hData, nullptr, false); } else { HIP_SKIP_TEST(HipTest::SkipReason::kPeerAccessUnavailable); } } else { HIP_SKIP_TEST(HipTest::SkipReason::kFewerThanTwoGpus); } }