Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

309 lines
11 KiB
C++

// Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "rng/common.hpp"
#include "rng/config_types.hpp"
#include "test_common.hpp"
#include <gtest/gtest.h>
__global__
void write_target_arch([[maybe_unused]] rocrand_impl::host::target_arch host_arch,
int* __restrict__ result)
{
#if !defined(__SPIRV__)
constexpr auto arch = rocrand_impl::host::get_device_arch();
*result = arch == host_arch;
#else
*result = -1;
#endif
}
static constexpr rocrand_rng_type dummy_rng_type = rocrand_rng_type(0);
namespace rocrand_impl::host
{
template<class T>
struct generator_config_defaults<dummy_rng_type, T>
{
static constexpr inline unsigned int threads = 256;
static constexpr inline unsigned int blocks = 1;
};
template<>
struct generator_config_defaults<dummy_rng_type, double>
{
static constexpr inline unsigned int threads = 512;
static constexpr inline unsigned int blocks = 2;
};
template<>
struct generator_config_defaults<dummy_rng_type, half>
{
static constexpr inline unsigned int threads = 512;
static constexpr inline unsigned int blocks = 7;
};
} // namespace rocrand_impl::host
template<class T,
unsigned int BlockSize = rocrand_impl::host::default_config_provider<
dummy_rng_type>::template device_config<T>(true)
.threads>
__global__ __launch_bounds__(BlockSize)
void write_config(unsigned int* block_size, unsigned int* grid_size)
{
if(blockIdx.x == 0 && threadIdx.x == 0 && BlockSize == blockDim.x)
{
*block_size = blockDim.x;
*grid_size = gridDim.x;
}
}
TEST(rocrand_config_dispatch_tests, host_matches_device)
{
const hipStream_t stream = 0;
rocrand_impl::host::target_arch host_arch;
HIP_CHECK(rocrand_impl::host::get_device_arch(stream, host_arch));
int* result_ptr = nullptr;
HIP_CHECK(hipMallocHelper(&result_ptr, sizeof(result_ptr)));
hipLaunchKernelGGL(write_target_arch, dim3(1), dim3(1), 0, stream, host_arch, result_ptr);
HIP_CHECK(hipGetLastError());
int result = -1;
HIP_CHECK(hipMemcpy(&result, result_ptr, sizeof(result), hipMemcpyDeviceToHost));
if(result != -1)
{
ASSERT_NE(host_arch, rocrand_impl::host::target_arch::invalid);
ASSERT_EQ(result, 1);
}
else
{
GTEST_SKIP() << "SPIR-V build: result is null; skipping arch match assertion.";
}
HIP_CHECK(hipFree(result_ptr));
}
TEST(rocrand_config_dispatch_tests, parse_common_architectures)
{
using rocrand_impl::host::parse_gcn_arch;
using rocrand_impl::host::target_arch;
ASSERT_EQ(parse_gcn_arch(""), target_arch::unknown);
ASSERT_EQ(parse_gcn_arch("not a gfx arch"), target_arch::unknown);
ASSERT_EQ(parse_gcn_arch(":"), target_arch::unknown);
ASSERT_EQ(parse_gcn_arch("g:"), target_arch::unknown);
ASSERT_EQ(parse_gcn_arch("gfx900:sramecc+"), target_arch::gfx900);
ASSERT_EQ(parse_gcn_arch("gfx906:::"), target_arch::gfx906);
ASSERT_EQ(parse_gcn_arch("gfx908:"), target_arch::gfx908);
ASSERT_EQ(parse_gcn_arch("gfx90a:sramecc+:xnack-"), target_arch::gfx90a);
}
TEST(rocrand_config_dispatch_tests, get_config_on_host_and_device)
{
using T = unsigned int;
const hipStream_t stream = 0;
unsigned int *d_block_size{}, *d_grid_size{};
HIP_CHECK(hipMallocHelper(&d_block_size, sizeof(*d_block_size)));
HIP_CHECK(hipMallocHelper(&d_grid_size, sizeof(*d_grid_size)));
rocrand_impl::host::generator_config config{};
const hipError_t err = rocrand_impl::host::get_generator_config<dummy_rng_type, T>(
stream,
ROCRAND_ORDERING_PSEUDO_DEFAULT,
config);
HIP_CHECK(err);
hipLaunchKernelGGL(write_config<T>,
dim3(config.blocks),
dim3(config.threads),
0,
stream,
d_block_size,
d_grid_size);
HIP_CHECK(hipGetLastError());
unsigned int block_size{}, grid_size{};
HIP_CHECK(hipMemcpy(&block_size, d_block_size, sizeof(block_size), hipMemcpyDeviceToHost));
HIP_CHECK(hipMemcpy(&grid_size, d_grid_size, sizeof(grid_size), hipMemcpyDeviceToHost));
HIP_CHECK(hipFree(d_block_size));
HIP_CHECK(hipFree(d_grid_size));
ASSERT_EQ(block_size, config.threads);
ASSERT_EQ(grid_size, config.blocks);
}
#if USE_DEVICE_DISPATCH
TEST(rocrand_config_dispatch_tests, device_id_from_stream)
{
using rocrand_impl::host::get_device_from_stream;
hipDevice_t device_id;
HIP_CHECK(hipGetDevice(&device_id));
int result;
static constexpr hipStream_t default_stream = 0;
HIP_CHECK(get_device_from_stream(default_stream, result));
ASSERT_EQ(result, device_id);
HIP_CHECK(get_device_from_stream(hipStreamPerThread, result));
ASSERT_EQ(result, device_id);
hipStream_t stream;
HIP_CHECK(hipStreamCreate(&stream));
HIP_CHECK(get_device_from_stream(stream, result));
HIP_CHECK(hipStreamDestroy(stream));
ASSERT_EQ(result, device_id);
HIP_CHECK(hipStreamCreateWithFlags(&stream, hipStreamNonBlocking));
HIP_CHECK(get_device_from_stream(stream, result));
HIP_CHECK(hipStreamDestroy(stream));
ASSERT_EQ(result, device_id);
}
template<class ConfigProvider>
__global__
void least_common_grid_size_kernel(unsigned int* least_common_grid_size, rocrand_ordering order)
{
*least_common_grid_size
= rocrand_impl::host::get_least_common_grid_size<ConfigProvider,
rocrand_impl::host::target_arch{}>(
rocrand_impl::host::is_ordering_dynamic(order));
}
TEST(rocrand_config_dispatch_tests, default_config_provider)
{
using config_provider = rocrand_impl::host::default_config_provider<dummy_rng_type>;
static constexpr hipStream_t default_stream = 0;
static constexpr rocrand_ordering ordering = ROCRAND_ORDERING_PSEUDO_DEFAULT;
rocrand_impl::host::generator_config config{};
ASSERT_EQ(config_provider::host_config<unsigned int>(default_stream, ordering, config),
hipSuccess);
ASSERT_EQ(config.blocks, 1);
ASSERT_EQ(config.threads, 256);
config = {};
ASSERT_EQ(config_provider::host_config<double>(default_stream, ordering, config), hipSuccess);
ASSERT_EQ(config.blocks, 2);
ASSERT_EQ(config.threads, 512);
unsigned int least_common_grid_size{};
ASSERT_EQ(
rocrand_impl::host::get_least_common_grid_size<config_provider>(default_stream,
ordering,
least_common_grid_size),
hipSuccess);
ASSERT_EQ(least_common_grid_size, 512 * 2 * 7);
unsigned int* d_least_common_grid_size{};
HIP_CHECK(hipMalloc(&d_least_common_grid_size, sizeof(*d_least_common_grid_size)));
hipLaunchKernelGGL(HIP_KERNEL_NAME(least_common_grid_size_kernel<config_provider>),
1,
1,
0,
default_stream,
d_least_common_grid_size,
ordering);
unsigned int h_least_common_grid_size{};
HIP_CHECK(hipMemcpy(&h_least_common_grid_size,
d_least_common_grid_size,
sizeof(h_least_common_grid_size),
hipMemcpyDeviceToHost));
HIP_CHECK(hipFree(d_least_common_grid_size));
ASSERT_EQ(least_common_grid_size, h_least_common_grid_size);
}
template<class ConfigProvider>
__global__
void config_selector_kernel(unsigned int* output)
{
if(threadIdx.x == 0 && blockIdx.x == 0)
{
output[0] = ConfigProvider::template device_config<unsigned short>(true).blocks;
output[1] = ConfigProvider::template device_config<unsigned short>(true).threads;
}
}
namespace rocrand_impl::host
{
template<>
struct generator_config_selector<dummy_rng_type, unsigned short>
{
__host__ __device__
static constexpr unsigned int get_threads(const target_arch arch)
{
if(arch == target_arch::gfx906)
return 64;
return generator_config_defaults<dummy_rng_type, unsigned short>::threads;
}
__host__ __device__
static constexpr unsigned int get_blocks(const target_arch /*arch*/)
{
return generator_config_defaults<dummy_rng_type, unsigned short>::blocks;
}
};
} // namespace rocrand_impl::host
TEST(rocrand_config_dispatch_tests, config_selection)
{
unsigned int* d_output{};
constexpr std::size_t size = 2;
HIP_CHECK(hipMallocHelper(&d_output, size * sizeof(*d_output)));
using config_provider_t = rocrand_impl::host::default_config_provider<dummy_rng_type>;
config_provider_t config_provider{};
rocrand_impl::host::generator_config config{};
static constexpr hipStream_t default_stream = 0;
static constexpr rocrand_ordering ordering = ROCRAND_ORDERING_PSEUDO_DYNAMIC;
HIP_CHECK(config_provider.host_config<unsigned short>(default_stream, ordering, config));
hipLaunchKernelGGL(HIP_KERNEL_NAME(config_selector_kernel<config_provider_t>),
config.blocks,
config.threads,
0,
default_stream,
d_output);
HIP_CHECK(hipGetLastError());
std::array<unsigned int, 2> h_output{};
HIP_CHECK(
hipMemcpy(h_output.data(), d_output, size * sizeof(*d_output), hipMemcpyDeviceToHost));
HIP_CHECK(hipFree(d_output));
ASSERT_EQ(config.blocks, h_output[0]);
ASSERT_EQ(config.threads, h_output[1]);
}
#endif // USE_DEVICE_DISPATCH