Add 'projects/rocshmem/' from commit '0496586829058af5cfd7f23acda2a6d0040da584'
git-subtree-dir: projects/rocshmem git-subtree-mainline:5fd976da70git-subtree-split:0496586829
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
###############################################################################
|
||||
# Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# 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.
|
||||
###############################################################################
|
||||
|
||||
IF (BUILD_FUNCTIONAL_TESTS)
|
||||
add_subdirectory(functional_tests)
|
||||
ENDIF()
|
||||
|
||||
IF (BUILD_UNIT_TESTS)
|
||||
add_subdirectory(unit_tests)
|
||||
ENDIF()
|
||||
@@ -0,0 +1,108 @@
|
||||
###############################################################################
|
||||
# Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# 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.
|
||||
###############################################################################
|
||||
|
||||
cmake_minimum_required(VERSION 3.16.3 FATAL_ERROR)
|
||||
|
||||
###############################################################################
|
||||
# PROJECT
|
||||
###############################################################################
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/setup_project.cmake)
|
||||
project(rocshmem_functional_tests VERSION 1.0.0 LANGUAGES CXX)
|
||||
|
||||
###############################################################################
|
||||
# SOURCES
|
||||
###############################################################################
|
||||
add_executable(${PROJECT_NAME} "")
|
||||
|
||||
target_include_directories(
|
||||
${PROJECT_NAME}
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
target_sources(
|
||||
${PROJECT_NAME}
|
||||
PRIVATE
|
||||
barrier_all_tester.cpp
|
||||
sync_all_tester.cpp
|
||||
test_driver.cpp
|
||||
tester.cpp
|
||||
tester_arguments.cpp
|
||||
ping_pong_tester.cpp
|
||||
ping_all_tester.cpp
|
||||
primitive_tester.cpp
|
||||
primitive_mr_tester.cpp
|
||||
default_ctx_primitive_tester.cpp
|
||||
team_ctx_primitive_tester.cpp
|
||||
team_ctx_infra_tester.cpp
|
||||
amo_bitwise_tester.cpp
|
||||
amo_extended_tester.cpp
|
||||
amo_standard_tester.cpp
|
||||
random_access_tester.cpp
|
||||
shmem_ptr_tester.cpp
|
||||
signaling_operations_tester.cpp
|
||||
signaling_operations_tester.hpp
|
||||
workgroup_primitives.cpp
|
||||
empty_tester.cpp
|
||||
wavefront_primitives.cpp
|
||||
flood_tester.cpp
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
# ROCSHMEM
|
||||
###############################################################################
|
||||
if (BUILD_TESTS_ONLY)
|
||||
#TODO these find_packages should be performed as-needed in rocshmem-config.cmake
|
||||
find_package(hip REQUIRED PATHS /opt/rocm)
|
||||
find_package(MPI)
|
||||
find_package(Threads REQUIRED)
|
||||
find_package(rocshmem REQUIRED PATHS /opt/rocm)
|
||||
|
||||
target_include_directories(
|
||||
${PROJECT_NAME}
|
||||
PRIVATE
|
||||
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../src>
|
||||
)
|
||||
endif()
|
||||
|
||||
find_package(PMIx)
|
||||
|
||||
target_compile_definitions(
|
||||
${PROJECT_NAME}
|
||||
PRIVATE
|
||||
$<$<TARGET_EXISTS:PMIx::pmix>:HAVE_PMIX=1>
|
||||
)
|
||||
|
||||
configure_file(../../scripts/functional_tests/driver.sh rocshmem_functional_driver.sh COPYONLY)
|
||||
rocm_install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/rocshmem_functional_driver.sh COMPONENT tests DESTINATION ${CMAKE_INSTALL_DATADIR}/rocshmem)
|
||||
rocm_install(TARGETS rocshmem_functional_tests COMPONENT tests)
|
||||
|
||||
target_link_libraries(
|
||||
${PROJECT_NAME}
|
||||
PRIVATE
|
||||
roc::rocshmem
|
||||
$<TARGET_NAME_IF_EXISTS:MPI::MPI_CXX>
|
||||
$<TARGET_NAME_IF_EXISTS:PMIx::pmix>
|
||||
)
|
||||
@@ -0,0 +1,302 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "amo_bitwise_tester.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/* Declare the global kernel template with a generic implementation */
|
||||
template <typename T>
|
||||
__global__ void AMOBitwiseTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, T *dest, T *ret_val,
|
||||
AddrMode addr_mode, TestType type,
|
||||
ShmemContextType ctx_type) {
|
||||
return;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__device__ inline T* compute_target_ptr(T* base_ptr, AddrMode addr_mode,
|
||||
int wg_idx, int itr, int n_wgs) {
|
||||
// PerBlock: element = wg_idx, with n_wgs elements per loop
|
||||
// PerGrid : single element shared by the whole grid per loop
|
||||
if (addr_mode == AddrMode::PerBlock) {
|
||||
size_t offset = wg_idx + itr * n_wgs;
|
||||
return base_ptr + offset;
|
||||
} else { // PerGrid
|
||||
return base_ptr + itr;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
template <typename T>
|
||||
AMOBitwiseTester<T>::AMOBitwiseTester(TesterArguments args) : Tester(args) {
|
||||
n_out = (args.addr_mode == AddrMode::PerBlock) ? args.num_wgs : 1;
|
||||
n_in = args.num_wgs * args.wg_size;
|
||||
n_loops = args.loop + args.skip;
|
||||
|
||||
// One return per *thread* per loop
|
||||
CHECK_HIP(hipMalloc((void **)&ret_val, args.max_msg_size * n_in * n_loops));
|
||||
|
||||
dest = (T *)rocshmem_malloc(args.max_msg_size * n_out * n_loops);
|
||||
if (dest == nullptr) {
|
||||
std::cerr << "Error allocating memory from symmetric heap" << std::endl;
|
||||
std::cerr << "dest: " << (void*)dest << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
AMOBitwiseTester<T>::~AMOBitwiseTester() {
|
||||
CHECK_HIP(hipFree(ret_val));
|
||||
rocshmem_free(dest);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AMOBitwiseTester<T>::resetBuffers(size_t size) {
|
||||
memset(ret_val, 0, args.max_msg_size * n_in * n_loops);
|
||||
memset(dest, 0, args.max_msg_size * n_out * n_loops);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AMOBitwiseTester<T>::launchKernel(dim3 gridsize, dim3 blocksize, int loop,
|
||||
size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
hipLaunchKernelGGL(AMOBitwiseTest, gridsize, blocksize, shared_bytes, stream,
|
||||
args.loop, args.skip, start_time, end_time, dest,
|
||||
ret_val, args.addr_mode, _type, _shmem_context);
|
||||
|
||||
num_msgs = n_loops * gridsize.x * blocksize.x;
|
||||
num_timed_msgs = args.loop * gridsize.x * blocksize.x;
|
||||
}
|
||||
|
||||
template <typename G>
|
||||
void fail_eq(const G& got, const G& exp) {
|
||||
std::cerr << "data validation error\n"
|
||||
<< "got " << got << ", expected " << exp << std::endl;
|
||||
std::exit(-1);
|
||||
}
|
||||
|
||||
// Map (loop, elem_idx) -> dest[] index for current address mode.
|
||||
template <typename T>
|
||||
int AMOBitwiseTester<T>::destIndex(int l, int elem_idx) const {
|
||||
return (args.addr_mode == AddrMode::PerBlock)
|
||||
? l * static_cast<int>(args.num_wgs) + elem_idx
|
||||
: l; // PerGrid has a single element per loop
|
||||
}
|
||||
|
||||
// Number of output elements to check per loop for current address mode.
|
||||
template <typename T>
|
||||
int AMOBitwiseTester<T>::numElems() const {
|
||||
return (args.addr_mode == AddrMode::PerBlock)
|
||||
? static_cast<int>(args.num_wgs)
|
||||
: 1; // PerGrid
|
||||
}
|
||||
|
||||
// Return pointer to the start of the ret_val “chunk” for (loop, elem_idx)
|
||||
// plus the chunk length for this address mode.
|
||||
template <typename T>
|
||||
std::pair<T*, int> AMOBitwiseTester<T>::retChunk(int l, int elem_idx) const {
|
||||
if (args.addr_mode == AddrMode::PerBlock) {
|
||||
// One chunk per element (workgroup): wg_size returns
|
||||
T* p = ret_val + l * n_in + elem_idx * args.wg_size;
|
||||
int sz = static_cast<int>(args.wg_size);
|
||||
return {p, sz};
|
||||
}
|
||||
// PerGrid: one big chunk per loop (all threads)
|
||||
T* p = ret_val + l * n_in;
|
||||
int sz = static_cast<int>(n_in);
|
||||
return {p, sz};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AMOBitwiseTester<T>::verifyDestValues() {
|
||||
const int loops = static_cast<int>(n_loops);
|
||||
const int n_elems = numElems();
|
||||
|
||||
auto check_equal_all = [&](T expected) {
|
||||
for (int l = 0; l < loops; ++l) {
|
||||
for (int elem = 0; elem < n_elems; ++elem) {
|
||||
const int idx = destIndex(l, elem);
|
||||
if (dest[idx] != expected) fail_eq(dest[idx], expected);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Use all-ones mask for type T
|
||||
const T MASK = static_cast<T>(~T{0});
|
||||
|
||||
switch (_type) {
|
||||
case AMO_AndTestType:
|
||||
case AMO_FetchAndTestType: {
|
||||
// Start at 0; 0 & MASK == 0 regardless of writer count.
|
||||
check_equal_all(static_cast<T>(0));
|
||||
break;
|
||||
}
|
||||
case AMO_OrTestType:
|
||||
case AMO_FetchOrTestType: {
|
||||
// final value is MASK.
|
||||
check_equal_all(MASK);
|
||||
break;
|
||||
}
|
||||
case AMO_XorTestType:
|
||||
case AMO_FetchXorTestType: {
|
||||
// PerBlock: K = wg_size; PerGrid: K = num_wgs * wg_size
|
||||
const int K = (args.addr_mode == AddrMode::PerBlock)
|
||||
? static_cast<int>(args.wg_size)
|
||||
: static_cast<int>(args.num_wgs * args.wg_size);
|
||||
const T expected = (K & 1) ? MASK : static_cast<T>(0);
|
||||
check_equal_all(expected);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AMOBitwiseTester<T>::verifyReturnValues() {
|
||||
// Only “fetch-*” types produce return values to validate.
|
||||
if (_type == AMO_AndTestType || _type == AMO_OrTestType ||
|
||||
_type == AMO_XorTestType) return;
|
||||
|
||||
const int loops = static_cast<int>(n_loops);
|
||||
const int n_elems = numElems();
|
||||
const T MASK = static_cast<T>(~T{0});
|
||||
|
||||
for (int l = 0; l < loops; ++l) {
|
||||
for (int elem = 0; elem < n_elems; ++elem) {
|
||||
auto [p, cnt] = retChunk(l, elem);
|
||||
|
||||
// Count distribution of observed old values in this chunk
|
||||
int zeros = 0, masks = 0;
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
zeros += (p[i] == static_cast<T>(0));
|
||||
masks += (p[i] == MASK);
|
||||
}
|
||||
if (zeros + masks != cnt) {
|
||||
fail_eq(zeros + masks, cnt); // unexpected values present
|
||||
}
|
||||
|
||||
switch (_type) {
|
||||
case AMO_FetchAndTestType:
|
||||
// Old value is 0 (dest stays 0)
|
||||
if (!(zeros == cnt && masks == 0)) fail_eq(zeros, cnt);
|
||||
break;
|
||||
|
||||
case AMO_FetchOrTestType:
|
||||
// Exactly one 0 (the first OR), rest MASK
|
||||
if (!(zeros == 1 && masks == cnt - 1)) fail_eq(zeros, 1);
|
||||
break;
|
||||
|
||||
case AMO_FetchXorTestType: {
|
||||
// returns multiset = { ceil(K/2) zeros, floor(K/2) MASKs }
|
||||
const int exp_zeros = (cnt + 1) / 2; // ceil(cnt/2)
|
||||
const int exp_masks = cnt / 2; // floor(cnt/2)
|
||||
if (!(zeros == exp_zeros && masks == exp_masks)) {
|
||||
fail_eq(zeros, exp_zeros);
|
||||
}
|
||||
// cross-check
|
||||
if ((cnt & 1) && zeros != masks + 1) fail_eq(zeros, masks + 1);
|
||||
if (!(cnt & 1) && zeros != masks) fail_eq(zeros, masks);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AMOBitwiseTester<T>::verifyResults(size_t size) {
|
||||
// PE 0 checks returns; target PE checks dest.
|
||||
if (args.myid) {
|
||||
verifyDestValues();
|
||||
} else {
|
||||
verifyReturnValues();
|
||||
}
|
||||
}
|
||||
|
||||
#define AMO_BITWISE_DEF_GEN(T, TNAME) \
|
||||
template <> \
|
||||
__global__ void AMOBitwiseTest<T>( \
|
||||
int loop, int skip, long long int *start_time, \
|
||||
long long int *end_time, T *dest, T *ret_val, \
|
||||
AddrMode addr_mode, TestType type, ShmemContextType ctx_type) { \
|
||||
__shared__ rocshmem_ctx_t ctx; \
|
||||
int wg_id = get_flat_grid_id(); \
|
||||
int global_id = get_flat_id(); \
|
||||
int n_threads = get_flat_grid_size(); \
|
||||
int n_wgs = get_grid_num_blocks(); \
|
||||
rocshmem_wg_ctx_create(ctx_type, &ctx); \
|
||||
for (int i = 0; i < loop + skip; i++) { \
|
||||
T *ptr = compute_target_ptr<T>(dest, addr_mode, wg_id, i, n_wgs); \
|
||||
T ret = 0; \
|
||||
if (i == skip) { \
|
||||
start_time[wg_id] = wall_clock64(); \
|
||||
} \
|
||||
switch (type) { \
|
||||
case AMO_FetchAndTestType: \
|
||||
ret = rocshmem_ctx_##TNAME##_atomic_fetch_and(ctx, ptr, \
|
||||
(T)~(T)0, 1); \
|
||||
break; \
|
||||
case AMO_AndTestType: \
|
||||
rocshmem_ctx_##TNAME##_atomic_and(ctx, ptr, (T)~(T)0, 1); \
|
||||
break; \
|
||||
case AMO_FetchOrTestType: \
|
||||
ret = rocshmem_ctx_##TNAME##_atomic_fetch_or(ctx, ptr, \
|
||||
(T)~(T)0, 1); \
|
||||
break; \
|
||||
case AMO_OrTestType: \
|
||||
rocshmem_ctx_##TNAME##_atomic_or(ctx, ptr, (T)~(T)0, 1); \
|
||||
break; \
|
||||
case AMO_FetchXorTestType: \
|
||||
ret = rocshmem_ctx_##TNAME##_atomic_fetch_xor(ctx, ptr, \
|
||||
(T)~(T)0, 1); \
|
||||
break; \
|
||||
case AMO_XorTestType: \
|
||||
rocshmem_ctx_##TNAME##_atomic_xor(ctx, ptr, (T)~(T)0, 1); \
|
||||
break; \
|
||||
default: \
|
||||
break; \
|
||||
} \
|
||||
ret_val[global_id + i * n_threads] = ret; \
|
||||
} \
|
||||
rocshmem_ctx_quiet(ctx); \
|
||||
end_time[wg_id] = wall_clock64(); \
|
||||
__syncthreads(); \
|
||||
rocshmem_wg_ctx_destroy(&ctx); \
|
||||
} \
|
||||
template class AMOBitwiseTester<T>;
|
||||
|
||||
AMO_BITWISE_DEF_GEN(unsigned int, uint)
|
||||
AMO_BITWISE_DEF_GEN(unsigned long, ulong)
|
||||
AMO_BITWISE_DEF_GEN(unsigned long long, ulonglong)
|
||||
AMO_BITWISE_DEF_GEN(int32_t, int32)
|
||||
AMO_BITWISE_DEF_GEN(int64_t, int64)
|
||||
@@ -0,0 +1,62 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _AMO_BITWISE_TESTER_HPP_
|
||||
#define _AMO_BITWISE_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
template <typename T>
|
||||
class AMOBitwiseTester : public Tester {
|
||||
public:
|
||||
explicit AMOBitwiseTester(TesterArguments args);
|
||||
virtual ~AMOBitwiseTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
void verifyDestValues();
|
||||
void verifyReturnValues();
|
||||
|
||||
int destIndex(int l, int elem_idx) const;
|
||||
int numElems() const;
|
||||
std::pair<T*, int> retChunk(int l, int elem_idx) const;
|
||||
|
||||
T* dest{nullptr}; // symmetric target buffer [loop][elem]
|
||||
T* ret_val{nullptr}; // device returns [loop][thread]
|
||||
|
||||
size_t n_in{0}; // num_wgs * wg_size
|
||||
size_t n_out{0}; // elements per loop: PerBlock->num_wgs, PerGrid->1
|
||||
size_t n_loops{0}; // loop + skip
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,268 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "amo_extended_tester.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/* Declare the global kernel template with a generic implementation */
|
||||
template <typename T>
|
||||
__global__ void AMOExtendedTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, T *dest, T *ret_val,
|
||||
AddrMode addr_mode, TestType type,
|
||||
ShmemContextType ctx_type) {
|
||||
return;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__device__ inline T* compute_target_ptr(T* base_ptr, AddrMode addr_mode,
|
||||
int wg_idx, int itr, int n_wgs) {
|
||||
// PerBlock: element = wg_idx, with n_wgs elements per loop
|
||||
// PerGrid : single element shared by the whole grid per loop
|
||||
if (addr_mode == AddrMode::PerBlock) {
|
||||
size_t offset = wg_idx + itr * n_wgs;
|
||||
return base_ptr + offset;
|
||||
} else { // PerGrid
|
||||
return base_ptr + itr;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
template <typename T>
|
||||
AMOExtendedTester<T>::AMOExtendedTester(TesterArguments args) : Tester(args) {
|
||||
n_out = (args.addr_mode == AddrMode::PerBlock) ? args.num_wgs : 1;
|
||||
n_in = args.num_wgs * args.wg_size;
|
||||
n_loops = args.loop + args.skip;
|
||||
|
||||
// One return per *thread* per loop
|
||||
CHECK_HIP(hipMalloc((void **)&ret_val, args.max_msg_size * n_in * n_loops));
|
||||
|
||||
dest = (T *)rocshmem_malloc(args.max_msg_size * n_out * n_loops);
|
||||
if (dest == nullptr) {
|
||||
std::cerr << "Error allocating memory from symmetric heap" << std::endl;
|
||||
std::cerr << "dest: " << (void*)dest << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
AMOExtendedTester<T>::~AMOExtendedTester() {
|
||||
CHECK_HIP(hipFree(ret_val));
|
||||
rocshmem_free(dest);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AMOExtendedTester<T>::resetBuffers(size_t size) {
|
||||
memset(ret_val, 0, args.max_msg_size * n_in * n_loops);
|
||||
memset(dest, 0, args.max_msg_size * n_out * n_loops);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AMOExtendedTester<T>::launchKernel(dim3 gridsize, dim3 blocksize, int loop,
|
||||
size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
hipLaunchKernelGGL(AMOExtendedTest, gridsize, blocksize, shared_bytes, stream,
|
||||
args.loop, args.skip, start_time, end_time, dest,
|
||||
ret_val, args.addr_mode, _type, _shmem_context);
|
||||
|
||||
num_msgs = n_loops * gridsize.x * blocksize.x;
|
||||
num_timed_msgs = args.loop * gridsize.x * blocksize.x;
|
||||
}
|
||||
|
||||
template <typename G>
|
||||
void fail_eq(const G& got, const G& exp) {
|
||||
std::cerr << "data validation error\n"
|
||||
<< "got " << got << ", expected " << exp << std::endl;
|
||||
std::exit(-1);
|
||||
}
|
||||
|
||||
// Map (loop, elem_idx) -> dest[] index for current address mode.
|
||||
template <typename T>
|
||||
int AMOExtendedTester<T>::destIndex(int l, int elem_idx) const {
|
||||
return (args.addr_mode == AddrMode::PerBlock)
|
||||
? l * static_cast<int>(args.num_wgs) + elem_idx
|
||||
: l; // PerGrid has a single element per loop
|
||||
}
|
||||
|
||||
// Number of output elements to check per loop for current address mode.
|
||||
template <typename T>
|
||||
int AMOExtendedTester<T>::numElems() const {
|
||||
return (args.addr_mode == AddrMode::PerBlock)
|
||||
? static_cast<int>(args.num_wgs)
|
||||
: 1; // PerGrid
|
||||
}
|
||||
|
||||
// Return pointer to the start of the ret_val “chunk” for (loop, elem_idx)
|
||||
// plus the chunk length for this address mode.
|
||||
template <typename T>
|
||||
std::pair<T*, int> AMOExtendedTester<T>::retChunk(int l, int elem_idx) const {
|
||||
if (args.addr_mode == AddrMode::PerBlock) {
|
||||
// One chunk per element (workgroup): wg_size returns
|
||||
T* p = ret_val + l * n_in + elem_idx * args.wg_size;
|
||||
int sz = static_cast<int>(args.wg_size);
|
||||
return {p, sz};
|
||||
}
|
||||
// PerGrid: one big chunk per loop (all threads)
|
||||
T* p = ret_val + l * n_in;
|
||||
int sz = static_cast<int>(n_in);
|
||||
return {p, sz};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AMOExtendedTester<T>::verifyDestValues() {
|
||||
const int loops = static_cast<int>(n_loops);
|
||||
const int n_elems = numElems();
|
||||
|
||||
auto check_equal_all = [&](T expected) {
|
||||
for (int l = 0; l < loops; ++l) {
|
||||
for (int elem = 0; elem < n_elems; ++elem) {
|
||||
const int idx = destIndex(l, elem);
|
||||
if (dest[idx] != expected) fail_eq(dest[idx], expected);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto check_nonzero_all = [&]() {
|
||||
for (int l = 0; l < loops; ++l) {
|
||||
for (int elem = 0; elem < n_elems; ++elem) {
|
||||
const int idx = destIndex(l, elem);
|
||||
if (dest[idx] == T{0}) fail_eq(dest[idx], T{1});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
switch (_type) {
|
||||
case AMO_FetchTestType:
|
||||
// fetch does not modify dest -> stays 0
|
||||
check_equal_all(T{0});
|
||||
break;
|
||||
|
||||
case AMO_SetTestType:
|
||||
// set writes a constant (17)
|
||||
check_equal_all(static_cast<T>(17));
|
||||
break;
|
||||
|
||||
case AMO_SwapTestType:
|
||||
// swap writes non-zero values -> final must be non-zero
|
||||
check_nonzero_all();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AMOExtendedTester<T>::verifyReturnValues() {
|
||||
// Only fetch/swap produce return values to validate
|
||||
if (_type == AMO_SetTestType) return;
|
||||
|
||||
const int loops = static_cast<int>(n_loops);
|
||||
const int n_elems = numElems();
|
||||
|
||||
for (int l = 0; l < loops; ++l) {
|
||||
for (int elem = 0; elem < n_elems; ++elem) {
|
||||
auto [p, cnt] = retChunk(l, elem);
|
||||
|
||||
int zeros = 0;
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
zeros += (p[i] == T{0});
|
||||
}
|
||||
|
||||
if (_type == AMO_FetchTestType) {
|
||||
// fetch returns the current value (initially 0), dest unchanged
|
||||
if (zeros != cnt) fail_eq(zeros, cnt);
|
||||
} else { // AMO_SwapTestType
|
||||
// For a single element per (loop,elem), exactly one atomic_swap
|
||||
// observes old==0 (the first arriving swap). The rest see non-zero.
|
||||
if (zeros != 1) fail_eq(zeros, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AMOExtendedTester<T>::verifyResults(size_t /*size*/) {
|
||||
// PE 0 checks returns; target PE checks dest.
|
||||
if (args.myid) {
|
||||
verifyDestValues();
|
||||
} else {
|
||||
verifyReturnValues();
|
||||
}
|
||||
}
|
||||
|
||||
#define AMO_EXTENDED_DEF_GEN(T, TNAME) \
|
||||
template <> \
|
||||
__global__ void AMOExtendedTest<T>( \
|
||||
int loop, int skip, long long int *start_time, \
|
||||
long long int *end_time, T *dest, T *ret_val, \
|
||||
AddrMode addr_mode, TestType type, ShmemContextType ctx_type) { \
|
||||
__shared__ rocshmem_ctx_t ctx; \
|
||||
int wg_id = get_flat_grid_id(); \
|
||||
int global_id = get_flat_id(); \
|
||||
int t_id = get_flat_block_id(); \
|
||||
int n_threads = get_flat_grid_size(); \
|
||||
int n_wgs = get_grid_num_blocks(); \
|
||||
rocshmem_wg_ctx_create(ctx_type, &ctx); \
|
||||
for (int i = 0; i < loop + skip; i++) { \
|
||||
T *ptr = compute_target_ptr<T>(dest, addr_mode, wg_id, i, n_wgs); \
|
||||
T ret = 0; \
|
||||
if (i == skip) { \
|
||||
start_time[wg_id] = wall_clock64(); \
|
||||
} \
|
||||
switch (type) { \
|
||||
case AMO_FetchTestType: \
|
||||
ret = rocshmem_ctx_##TNAME##_atomic_fetch(ctx, ptr, 1); \
|
||||
break; \
|
||||
case AMO_SetTestType: \
|
||||
rocshmem_ctx_##TNAME##_atomic_set(ctx, ptr, (T)17, 1); \
|
||||
break; \
|
||||
case AMO_SwapTestType: \
|
||||
ret = rocshmem_ctx_##TNAME##_atomic_swap(ctx, ptr, (T)(t_id + 1),1);\
|
||||
break; \
|
||||
default: \
|
||||
break; \
|
||||
} \
|
||||
ret_val[global_id + i * n_threads] = ret; \
|
||||
} \
|
||||
rocshmem_ctx_quiet(ctx); \
|
||||
end_time[wg_id] = wall_clock64(); \
|
||||
__syncthreads(); \
|
||||
rocshmem_wg_ctx_destroy(&ctx); \
|
||||
} \
|
||||
template class AMOExtendedTester<T>;
|
||||
|
||||
AMO_EXTENDED_DEF_GEN(float, float)
|
||||
AMO_EXTENDED_DEF_GEN(double, double)
|
||||
AMO_EXTENDED_DEF_GEN(int, int)
|
||||
AMO_EXTENDED_DEF_GEN(long, long)
|
||||
AMO_EXTENDED_DEF_GEN(long long, longlong)
|
||||
AMO_EXTENDED_DEF_GEN(unsigned int, uint)
|
||||
AMO_EXTENDED_DEF_GEN(unsigned long, ulong)
|
||||
AMO_EXTENDED_DEF_GEN(unsigned long long, ulonglong)
|
||||
@@ -0,0 +1,62 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _AMO_EXTENDED_TESTER_HPP_
|
||||
#define _AMO_EXTENDED_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
template <typename T>
|
||||
class AMOExtendedTester : public Tester {
|
||||
public:
|
||||
explicit AMOExtendedTester(TesterArguments args);
|
||||
virtual ~AMOExtendedTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
void verifyDestValues();
|
||||
void verifyReturnValues();
|
||||
|
||||
int destIndex(int l, int elem_idx) const;
|
||||
int numElems() const;
|
||||
std::pair<T*, int> retChunk(int l, int elem_idx) const;
|
||||
|
||||
T* dest{nullptr}; // symmetric target buffer [loop][elem]
|
||||
T* ret_val{nullptr}; // device returns [loop][thread]
|
||||
|
||||
size_t n_in{0}; // num_wgs * wg_size
|
||||
size_t n_out{0}; // elements per loop: PerBlock->num_wgs, PerGrid->1
|
||||
size_t n_loops{0}; // loop + skip
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,304 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "amo_standard_tester.hpp"
|
||||
#include "tester.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/* Declare the global kernel template with a generic implementation */
|
||||
template <typename T>
|
||||
__global__ void AMOStandardTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, T *dest,
|
||||
T *ret_val, AddrMode addr_mode,
|
||||
TestType type, ShmemContextType ctx_type) {
|
||||
return;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__device__ inline T* compute_target_ptr(T* base_ptr, AddrMode addr_mode,
|
||||
int wg_idx, int itr, int n_wgs) {
|
||||
// PerBlock: element = wg_idx, with n_wgs elements per loop
|
||||
// PerGrid : single element shared by the whole grid per loop
|
||||
if (addr_mode == AddrMode::PerBlock) {
|
||||
size_t offset = wg_idx + itr * n_wgs;
|
||||
return base_ptr + offset;
|
||||
} else { // PerGrid
|
||||
return base_ptr + itr;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
template <typename T>
|
||||
AMOStandardTester<T>::AMOStandardTester(TesterArguments args) : Tester(args) {
|
||||
n_out = (args.addr_mode == AddrMode::PerBlock) ? args.num_wgs : 1;
|
||||
n_in = args.num_wgs * args.wg_size;
|
||||
n_loops = args.loop + args.skip;
|
||||
|
||||
// One return per *thread* per loop
|
||||
CHECK_HIP(hipMalloc((void **)&ret_val, args.max_msg_size * n_in * n_loops));
|
||||
|
||||
dest = (T *)rocshmem_malloc(args.max_msg_size * n_out * n_loops);
|
||||
if (dest == nullptr) {
|
||||
std::cerr << "Error allocating memory from symmetric heap" << std::endl;
|
||||
std::cerr << "dest: " << dest << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
AMOStandardTester<T>::~AMOStandardTester() {
|
||||
CHECK_HIP(hipFree(ret_val));
|
||||
rocshmem_free(dest);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AMOStandardTester<T>::resetBuffers(size_t size) {
|
||||
memset(ret_val, 0, args.max_msg_size * n_in * n_loops);
|
||||
memset(dest, 0, args.max_msg_size * n_out * n_loops);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AMOStandardTester<T>::launchKernel(dim3 gridsize, dim3 blocksize, int loop,
|
||||
size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
hipLaunchKernelGGL(AMOStandardTest, gridsize, blocksize, shared_bytes, stream,
|
||||
args.loop, args.skip, start_time, end_time, dest, ret_val,
|
||||
args.addr_mode, _type, _shmem_context);
|
||||
|
||||
num_msgs = n_loops * gridsize.x * blocksize.x;
|
||||
num_timed_msgs = args.loop * gridsize.x * blocksize.x;
|
||||
}
|
||||
|
||||
|
||||
template <typename G>
|
||||
void fail_eq(const G& got, const G& exp) {
|
||||
std::cerr << "data validation error\n"
|
||||
<< "got " << got << ", expected " << exp << std::endl;
|
||||
std::exit(-1);
|
||||
}
|
||||
|
||||
template <typename G>
|
||||
void fail_nonzero(const G& got) {
|
||||
std::cerr << "data validation error\n"
|
||||
<< "got " << got << ", expected non-zero" << std::endl;
|
||||
std::exit(-1);
|
||||
}
|
||||
|
||||
// Map (loop, elem_idx) -> dest[] index for current address mode.
|
||||
template <typename T>
|
||||
int AMOStandardTester<T>::destIndex(int l, int elem_idx) const {
|
||||
return (args.addr_mode == AddrMode::PerBlock)
|
||||
? l * args.num_wgs + elem_idx
|
||||
: l; // PerGrid has a single element per loop
|
||||
}
|
||||
|
||||
// Number of output elements to check per loop for current address mode.
|
||||
template <typename T>
|
||||
int AMOStandardTester<T>::numElems() const {
|
||||
return (args.addr_mode == AddrMode::PerBlock)
|
||||
? static_cast<int>(args.num_wgs)
|
||||
: 1; // PerGrid
|
||||
}
|
||||
|
||||
// Return pointer to the start of the ret_val “chunk” for (loop, elem_idx)
|
||||
// plus the chunk length for this address mode.
|
||||
template <typename T>
|
||||
std::pair<T*, int> AMOStandardTester<T>::retChunk(int l, int elem_idx) const {
|
||||
if (args.addr_mode == AddrMode::PerBlock) {
|
||||
// One chunk per element (workgroup): wg_size returns
|
||||
T* p = ret_val + l * n_in + elem_idx * args.wg_size;
|
||||
int sz = static_cast<int>(args.wg_size);
|
||||
return {p, sz};
|
||||
}
|
||||
// PerGrid: one big chunk per loop
|
||||
T* p = ret_val + l * n_in;
|
||||
int sz = static_cast<int>(n_in);
|
||||
return {p, sz};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AMOStandardTester<T>::verifyDestValues() {
|
||||
const int loops = static_cast<int>(n_loops);
|
||||
const int n_elems = numElems();
|
||||
|
||||
auto check_equal_all = [&](T expected) {
|
||||
for (int l = 0; l < loops; ++l) {
|
||||
for (int elem = 0; elem < n_elems; ++elem) {
|
||||
const int idx = destIndex(l, elem);
|
||||
if (dest[idx] != expected) fail_eq(dest[idx], expected);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto check_nonzero_all = [&]() {
|
||||
for (int l = 0; l < loops; ++l) {
|
||||
for (int elem = 0; elem < n_elems; ++elem) {
|
||||
const int idx = destIndex(l, elem);
|
||||
if (dest[idx] == T{0}) fail_nonzero(dest[idx]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
switch (_type) {
|
||||
case AMO_AddTestType:
|
||||
case AMO_FAddTestType: {
|
||||
const T expected = (args.addr_mode == AddrMode::PerBlock)
|
||||
? static_cast<T>(args.wg_size * 2)
|
||||
: static_cast<T>(args.wg_size * args.num_wgs * 2);
|
||||
check_equal_all(expected);
|
||||
break;
|
||||
}
|
||||
case AMO_IncTestType:
|
||||
case AMO_FIncTestType: {
|
||||
const T expected = (args.addr_mode == AddrMode::PerBlock)
|
||||
? static_cast<T>(args.wg_size)
|
||||
: static_cast<T>(args.wg_size * args.num_wgs);
|
||||
check_equal_all(expected);
|
||||
break;
|
||||
}
|
||||
case AMO_FCswapTestType:
|
||||
check_nonzero_all();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AMOStandardTester<T>::verifyReturnValues() {
|
||||
// Only “fetch-*” types produce return values to validate.
|
||||
if (_type == AMO_AddTestType || _type == AMO_IncTestType) return;
|
||||
|
||||
const int loops = static_cast<int>(n_loops);
|
||||
const int n_elems = numElems();
|
||||
|
||||
auto check_sorted_sequence = [&](auto value_of_i) {
|
||||
for (int l = 0; l < loops; ++l) {
|
||||
for (int elem = 0; elem < n_elems; ++elem) {
|
||||
auto [p, cnt] = retChunk(l, elem);
|
||||
std::sort(p, p + cnt);
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
const T expected = static_cast<T>(value_of_i(i));
|
||||
if (p[i] != expected) fail_eq(p[i], expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto check_single_success_zero = [&]() {
|
||||
for (int l = 0; l < loops; ++l) {
|
||||
for (int elem = 0; elem < n_elems; ++elem) {
|
||||
auto [p, cnt] = retChunk(l, elem);
|
||||
unsigned success = 0;
|
||||
for (int i = 0; i < cnt; ++i) if (!p[i]) ++success;
|
||||
if (success != 1u) fail_eq(success, 1u);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
switch (_type) {
|
||||
case AMO_FAddTestType:
|
||||
check_sorted_sequence([](int i) { return i * 2; });
|
||||
break;
|
||||
case AMO_FIncTestType:
|
||||
check_sorted_sequence([](int i) { return i; });
|
||||
break;
|
||||
case AMO_FCswapTestType:
|
||||
check_single_success_zero();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AMOStandardTester<T>::verifyResults(size_t size) {
|
||||
// PE 0 checks returns; target PE checks dest.
|
||||
if (args.myid) {
|
||||
verifyDestValues();
|
||||
} else {
|
||||
verifyReturnValues();
|
||||
}
|
||||
}
|
||||
|
||||
#define AMO_STANDARD_DEF_GEN(T, TNAME) \
|
||||
template <> \
|
||||
__global__ void AMOStandardTest<T>( \
|
||||
int loop, int skip, long long int *start_time, \
|
||||
long long int *end_time, T *dest, T *ret_val, \
|
||||
AddrMode addr_mode, TestType type, ShmemContextType ctx_type) { \
|
||||
__shared__ rocshmem_ctx_t ctx; \
|
||||
int wg_id = get_flat_grid_id(); \
|
||||
int global_id = get_flat_id(); \
|
||||
int t_id = get_flat_block_id(); \
|
||||
int n_threads = get_flat_grid_size(); \
|
||||
int n_wgs = get_grid_num_blocks(); \
|
||||
rocshmem_wg_ctx_create(ctx_type, &ctx); \
|
||||
for (int i = 0; i < loop + skip; i++) { \
|
||||
T *ptr = compute_target_ptr<T>(dest, addr_mode, wg_id, i, n_wgs); \
|
||||
T ret = 0; \
|
||||
if (i == skip) { \
|
||||
start_time[wg_id] = wall_clock64(); \
|
||||
} \
|
||||
switch (type) { \
|
||||
case AMO_FAddTestType: \
|
||||
ret = rocshmem_ctx_##TNAME##_atomic_fetch_add(ctx, (T *)ptr, 2, 1); \
|
||||
break; \
|
||||
case AMO_FIncTestType: \
|
||||
ret = rocshmem_ctx_##TNAME##_atomic_fetch_inc(ctx, (T *)ptr, 1); \
|
||||
break; \
|
||||
case AMO_FCswapTestType: \
|
||||
ret = rocshmem_ctx_##TNAME##_atomic_compare_swap(ctx, (T *)ptr, 0, \
|
||||
(T)(t_id + 1), 1); \
|
||||
break; \
|
||||
case AMO_AddTestType: \
|
||||
rocshmem_ctx_##TNAME##_atomic_add(ctx, (T *)ptr, 2, 1); \
|
||||
break; \
|
||||
case AMO_IncTestType: \
|
||||
rocshmem_ctx_##TNAME##_atomic_inc(ctx, (T *)ptr, 1); \
|
||||
break; \
|
||||
default: \
|
||||
break; \
|
||||
} \
|
||||
ret_val[global_id + i * n_threads] = ret; \
|
||||
} \
|
||||
rocshmem_ctx_quiet(ctx); \
|
||||
end_time[wg_id] = wall_clock64(); \
|
||||
__syncthreads(); \
|
||||
rocshmem_wg_ctx_destroy(&ctx); \
|
||||
} \
|
||||
template class AMOStandardTester<T>;
|
||||
|
||||
AMO_STANDARD_DEF_GEN(int, int)
|
||||
AMO_STANDARD_DEF_GEN(long, long)
|
||||
AMO_STANDARD_DEF_GEN(long long, longlong)
|
||||
AMO_STANDARD_DEF_GEN(unsigned int, uint)
|
||||
AMO_STANDARD_DEF_GEN(unsigned long, ulong)
|
||||
AMO_STANDARD_DEF_GEN(unsigned long long, ulonglong)
|
||||
@@ -0,0 +1,62 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _AMO_STANDARD_TESTER_HPP_
|
||||
#define _AMO_STANDARD_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
template <typename T>
|
||||
class AMOStandardTester : public Tester {
|
||||
public:
|
||||
explicit AMOStandardTester(TesterArguments args);
|
||||
virtual ~AMOStandardTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
void verifyDestValues();
|
||||
void verifyReturnValues();
|
||||
|
||||
int destIndex(int l, int elem_idx) const;
|
||||
int numElems() const;
|
||||
std::pair<T*, int> retChunk(int l, int elem_idx) const;
|
||||
|
||||
T* dest{nullptr}; // symmetric target buffer [loop][elem]
|
||||
T* ret_val{nullptr}; // device returns [loop][thread]
|
||||
|
||||
size_t n_in{0}; // num_wgs * wg_size
|
||||
size_t n_out{0}; // elements per loop: PerBlock->num_wgs, PerGrid->1
|
||||
size_t n_loops{0}; // loop + skip
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,151 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "barrier_all_on_stream_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
BarrierAllOnStreamTester::BarrierAllOnStreamTester(TesterArguments args)
|
||||
: Tester(args) {
|
||||
my_pe = rocshmem_my_pe();
|
||||
n_pes = rocshmem_n_pes();
|
||||
|
||||
char *value{nullptr};
|
||||
if ((value = getenv("ROCSHMEM_TEST_NUM_STREAMS"))) {
|
||||
num_streams = atoi(value);
|
||||
} else {
|
||||
// Default to 1 stream
|
||||
num_streams = 1;
|
||||
}
|
||||
|
||||
// Check if we should test with nullptr (default stream)
|
||||
use_default_stream = false;
|
||||
if ((value = getenv("ROCSHMEM_TEST_USE_DEFAULT_STREAM"))) {
|
||||
use_default_stream = (atoi(value) != 0);
|
||||
if (use_default_stream) {
|
||||
num_streams = 1; // Only test with one nullptr stream
|
||||
}
|
||||
}
|
||||
|
||||
streams.resize(num_streams);
|
||||
start_events_timed.resize(num_streams);
|
||||
stop_events_timed.resize(num_streams);
|
||||
for (int i = 0; i < num_streams; i++) {
|
||||
if (use_default_stream) {
|
||||
streams[i] = nullptr; // Use default stream (0)
|
||||
} else {
|
||||
CHECK_HIP(hipStreamCreate(&streams[i]));
|
||||
}
|
||||
CHECK_HIP(hipEventCreate(&start_events_timed[i]));
|
||||
CHECK_HIP(hipEventCreate(&stop_events_timed[i]));
|
||||
}
|
||||
}
|
||||
|
||||
BarrierAllOnStreamTester::~BarrierAllOnStreamTester() {
|
||||
for (int i = 0; i < num_streams; i++) {
|
||||
CHECK_HIP(hipEventDestroy(stop_events_timed[i]));
|
||||
CHECK_HIP(hipEventDestroy(start_events_timed[i]));
|
||||
// Don't destroy default stream (nullptr)
|
||||
if (!use_default_stream) {
|
||||
CHECK_HIP(hipStreamDestroy(streams[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BarrierAllOnStreamTester::preLaunchKernel() {
|
||||
// No specific setup needed for barrier
|
||||
}
|
||||
|
||||
void BarrierAllOnStreamTester::postLaunchKernel() {
|
||||
// Synchronize all streams to ensure events are recorded
|
||||
for (int i = 0; i < num_streams; i++) {
|
||||
CHECK_HIP(hipStreamSynchronize(streams[i]));
|
||||
}
|
||||
|
||||
// Get elapsed time for each stream from HIP events
|
||||
for (int stream_id = 0; stream_id < num_streams && stream_id < num_timers;
|
||||
stream_id++) {
|
||||
float elapsed_time_ms = 0.0f;
|
||||
CHECK_HIP(hipEventElapsedTime(&elapsed_time_ms,
|
||||
start_events_timed[stream_id],
|
||||
stop_events_timed[stream_id]));
|
||||
|
||||
// Convert milliseconds to GPU cycles
|
||||
// wall_clk_rate is in kHz, so: cycles = ms * wall_clk_rate
|
||||
long long int elapsed_cycles =
|
||||
static_cast<long long int>(elapsed_time_ms *
|
||||
static_cast<float>(wall_clk_rate));
|
||||
|
||||
start_time[stream_id] = 0;
|
||||
end_time[stream_id] = elapsed_cycles;
|
||||
}
|
||||
|
||||
// Fill remaining timers with zero if num_timers > num_streams
|
||||
for (int i = num_streams; i < num_timers; i++) {
|
||||
start_time[i] = 0;
|
||||
end_time[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void BarrierAllOnStreamTester::resetBuffers(size_t size) {}
|
||||
|
||||
void BarrierAllOnStreamTester::launchKernel(dim3 gridSize, dim3 blockSize,
|
||||
int loop, size_t size) {
|
||||
// Execute warmup iterations (skip)
|
||||
for (int i = 0; i < args.skip; i++) {
|
||||
for (int stream_id = 0; stream_id < num_streams; stream_id++) {
|
||||
rocshmem_barrier_all_on_stream(streams[stream_id]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < loop; i++) {
|
||||
for (int stream_id = 0; stream_id < num_streams; stream_id++) {
|
||||
// Record start event for this stream on first iteration
|
||||
if (i == 0) {
|
||||
CHECK_HIP(hipEventRecord(start_events_timed[stream_id],
|
||||
streams[stream_id]));
|
||||
}
|
||||
|
||||
rocshmem_barrier_all_on_stream(streams[stream_id]);
|
||||
|
||||
// Record stop event for this stream on last iteration
|
||||
if (i == loop - 1) {
|
||||
CHECK_HIP(hipEventRecord(stop_events_timed[stream_id],
|
||||
streams[stream_id]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
num_msgs = (loop + args.skip) * num_streams;
|
||||
num_timed_msgs = loop * num_streams;
|
||||
}
|
||||
|
||||
void BarrierAllOnStreamTester::verifyResults(size_t size) {}
|
||||
@@ -0,0 +1,67 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _BARRIER_ALL_ON_STREAM_TESTER_HPP_
|
||||
#define _BARRIER_ALL_ON_STREAM_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
#include <vector>
|
||||
#include <hip/hip_runtime.h>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class BarrierAllOnStreamTester : public Tester {
|
||||
public:
|
||||
explicit BarrierAllOnStreamTester(TesterArguments args);
|
||||
virtual ~BarrierAllOnStreamTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void preLaunchKernel() override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void postLaunchKernel() override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
private:
|
||||
int my_pe;
|
||||
int n_pes;
|
||||
int num_streams = 1;
|
||||
bool use_default_stream = false;
|
||||
std::vector<hipStream_t> streams;
|
||||
std::vector<hipEvent_t> start_events_timed;
|
||||
std::vector<hipEvent_t> stop_events_timed;
|
||||
};
|
||||
|
||||
#include "barrier_all_on_stream_tester.cpp"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "barrier_all_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void BarrierAllTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, TestType type,
|
||||
int wf_size) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
int t_id = get_flat_block_id();
|
||||
int wg_id = get_flat_grid_id();
|
||||
int wf_id = t_id / wf_size;
|
||||
|
||||
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (hipThreadIdx_x == 0 && i == skip) {
|
||||
start_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
if (is_block_zero_in_grid()) {
|
||||
switch (type) {
|
||||
case BarrierAllTestType:
|
||||
if(t_id == 0) {
|
||||
/**
|
||||
* The function `rocshmem_barrier_all` should be called from only
|
||||
* one thread within the grid to avoid undefined behavior.
|
||||
*/
|
||||
rocshmem_barrier_all();
|
||||
}
|
||||
break;
|
||||
case WAVEBarrierAllTestType:
|
||||
if(wf_id == 0) {
|
||||
/**
|
||||
* The function `rocshmem_barrier_all_wave` should be called from only
|
||||
* one wavefront within the grid to avoid undefined behavior.
|
||||
*/
|
||||
rocshmem_barrier_all_wave();
|
||||
}
|
||||
break;
|
||||
case WGBarrierAllTestType:
|
||||
/**
|
||||
* The function `rocshmem_barrier_all_wg` should be called from only
|
||||
* one workgroup within the grid to avoid undefined behavior.
|
||||
*/
|
||||
rocshmem_barrier_all_wg();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
__syncthreads();
|
||||
}
|
||||
|
||||
if (hipThreadIdx_x == 0) {
|
||||
end_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
BarrierAllTester::BarrierAllTester(TesterArguments args) : Tester(args) {}
|
||||
|
||||
BarrierAllTester::~BarrierAllTester() {}
|
||||
|
||||
void BarrierAllTester::launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
hipLaunchKernelGGL(BarrierAllTest, gridSize, blockSize, shared_bytes, stream,
|
||||
loop, args.skip, start_time, end_time, _type, wf_size);
|
||||
|
||||
num_msgs = (loop + args.skip);
|
||||
num_timed_msgs = loop;
|
||||
}
|
||||
|
||||
void BarrierAllTester::resetBuffers(size_t size) {}
|
||||
|
||||
void BarrierAllTester::verifyResults(size_t size) {}
|
||||
@@ -0,0 +1,52 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _BARRIER_ALL_TESTER_HPP_
|
||||
#define _BARRIER_ALL_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void BarrierAllTest(TestType type);
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class BarrierAllTester : public Tester {
|
||||
public:
|
||||
explicit BarrierAllTester(TesterArguments args);
|
||||
virtual ~BarrierAllTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,194 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "default_ctx_primitive_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void DefaultCTXPrimitiveTest(int loop, int skip,
|
||||
long long int *start_time,
|
||||
long long int *end_time, char *source,
|
||||
char *dest, size_t size, TestType type,
|
||||
ShmemContextType ctx_type, int wf_size) {
|
||||
int wg_id = get_flat_grid_id();
|
||||
int t_id = get_flat_block_id();
|
||||
int wf_id = t_id / wf_size;
|
||||
|
||||
/**
|
||||
* Shared array to capture the start time for each wavefront
|
||||
* Max threads per block = 1024, wavefront size = 64 or 32 depending
|
||||
* on the GPUs. Using 32 since its safer for the dimensioning of the array,
|
||||
* the last 16 elements will not be used on GPUs with a wf size of 64.
|
||||
* Maximum array size required = 1024/32 = 32
|
||||
*/
|
||||
__shared__ long long int wf_start_time[32];
|
||||
|
||||
/**
|
||||
* Calculate start index for each thread within the grid
|
||||
*/
|
||||
size_t offset = size * get_flat_id();
|
||||
source += offset;
|
||||
dest += offset;
|
||||
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (i == skip) {
|
||||
__syncthreads();
|
||||
// Ensures all RMA calls from the skip loops are completed
|
||||
if(is_thread_zero_in_block()) {
|
||||
rocshmem_quiet();
|
||||
}
|
||||
__syncthreads();
|
||||
// Capture the start time of each wavefront to identify the earliest one
|
||||
wf_start_time[wf_id] = wall_clock64();
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case DefaultCTXGetTestType:
|
||||
rocshmem_getmem(dest, source, size, 1);
|
||||
break;
|
||||
case DefaultCTXGetNBITestType:
|
||||
rocshmem_getmem_nbi(dest, source, size, 1);
|
||||
break;
|
||||
case DefaultCTXPutTestType:
|
||||
rocshmem_putmem(dest, source, size, 1);
|
||||
break;
|
||||
case DefaultCTXPutNBITestType:
|
||||
rocshmem_putmem_nbi(dest, source, size, 1);
|
||||
break;
|
||||
case DefaultCTXPTestType:
|
||||
for (int s = 0; s < size; s++) {
|
||||
char val = source[s];
|
||||
rocshmem_char_p(&dest[s], val, 1);
|
||||
}
|
||||
break;
|
||||
case DefaultCTXGTestType:
|
||||
for (int s = 0; s < size; s++) {
|
||||
char ret = rocshmem_char_g(&source[s], 1);
|
||||
dest[s] = ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
if(is_thread_zero_in_block()) {
|
||||
rocshmem_quiet();
|
||||
}
|
||||
|
||||
/**
|
||||
* End time of the last wavefront is recorded by overwriting
|
||||
* the value previously set by earlier wavefronts.
|
||||
*/
|
||||
end_time[wg_id] = wall_clock64();
|
||||
|
||||
// Find the earliest start time
|
||||
int num_wfs = (get_flat_block_size() - 1 ) / wf_size + 1;
|
||||
for (int i = num_wfs / 2; i > 0; i >>= 1 ) {
|
||||
if(t_id < i) {
|
||||
wf_start_time[t_id] = min(wf_start_time[t_id], wf_start_time[t_id + i]);
|
||||
}
|
||||
}
|
||||
__syncthreads();
|
||||
|
||||
if (t_id == 0) {
|
||||
start_time[wg_id] = wf_start_time[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
DefaultCTXPrimitiveTester::DefaultCTXPrimitiveTester(TesterArguments args)
|
||||
: Tester(args) {
|
||||
size_t buff_size = args.max_msg_size * args.wg_size * args.num_wgs;
|
||||
source = (char *)rocshmem_malloc(buff_size);
|
||||
dest = (char *)rocshmem_malloc(buff_size);
|
||||
|
||||
if (source == nullptr || dest == nullptr) {
|
||||
std::cerr << "Error allocating memory from symmetric heap" << std::endl;
|
||||
std::cerr << "source: " << source << ", dest: " << dest << std::endl;
|
||||
if (source) {
|
||||
rocshmem_free(source);
|
||||
}
|
||||
if (dest) {
|
||||
rocshmem_free(dest);
|
||||
}
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < buff_size; i++) {
|
||||
source[i] = static_cast<char>('a' + i % 26);
|
||||
}
|
||||
}
|
||||
|
||||
DefaultCTXPrimitiveTester::~DefaultCTXPrimitiveTester() {
|
||||
rocshmem_free(source);
|
||||
rocshmem_free(dest);
|
||||
}
|
||||
|
||||
void DefaultCTXPrimitiveTester::resetBuffers(size_t size) {
|
||||
size_t buff_size = size * args.wg_size * args.num_wgs;
|
||||
memset(dest, '1', buff_size);
|
||||
}
|
||||
|
||||
void DefaultCTXPrimitiveTester::launchKernel(dim3 gridSize, dim3 blockSize,
|
||||
int loop, size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
hipLaunchKernelGGL(DefaultCTXPrimitiveTest, gridSize, blockSize,
|
||||
shared_bytes, stream, loop, args.skip, start_time,
|
||||
end_time, source, dest, size, _type, _shmem_context,
|
||||
wf_size);
|
||||
|
||||
num_msgs = (loop + args.skip) * gridSize.x * blockSize.x;
|
||||
num_timed_msgs = loop * gridSize.x * blockSize.x;
|
||||
}
|
||||
|
||||
void DefaultCTXPrimitiveTester::verifyResults(size_t size) {
|
||||
int check_id =
|
||||
(_type == DefaultCTXGetTestType ||
|
||||
_type == DefaultCTXGetNBITestType || _type == DefaultCTXGTestType)
|
||||
? 0
|
||||
: 1;
|
||||
|
||||
if (args.myid == check_id) {
|
||||
size_t buff_size = size * args.wg_size * args.num_wgs;
|
||||
for (size_t i = 0; i < buff_size; i++) {
|
||||
if (dest[i] != source[i]) {
|
||||
std::cerr << "Data validation error at idx " << i << std::endl;
|
||||
std::cerr << " Got " << dest[i] << ", Expected "
|
||||
<< source[i] << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _DEFAULT_CTX_PRIMITIVE_TESTER_HPP_
|
||||
#define _DEFAULT_CTX_PRIMITIVE_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class DefaultCTXPrimitiveTester : public Tester {
|
||||
public:
|
||||
explicit DefaultCTXPrimitiveTester(TesterArguments args);
|
||||
virtual ~DefaultCTXPrimitiveTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
char *source = nullptr;
|
||||
char *dest = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,61 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "empty_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void EmptyTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, int size, TestType type,
|
||||
ShmemContextType ctx_type) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
rocshmem_wg_ctx_create(ctx_type, &ctx);
|
||||
|
||||
rocshmem_wg_ctx_destroy(&ctx);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
EmptyTester::EmptyTester(TesterArguments args) : Tester(args) {}
|
||||
|
||||
EmptyTester::~EmptyTester() {}
|
||||
|
||||
void EmptyTester::resetBuffers(size_t size) {}
|
||||
|
||||
void EmptyTester::launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
hipLaunchKernelGGL(EmptyTest, gridSize, blockSize, shared_bytes, stream,
|
||||
loop, args.skip, start_time, end_time, size, _type,
|
||||
_shmem_context);
|
||||
}
|
||||
|
||||
void EmptyTester::verifyResults(size_t size) {}
|
||||
@@ -0,0 +1,47 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ROCSHMEM_CLIENTS_FUNCTIONAL_TESTS_EMPTY_TESTER_HPP
|
||||
#define ROCSHMEM_CLIENTS_FUNCTIONAL_TESTS_EMPTY_TESTER_HPP
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class EmptyTester : public Tester {
|
||||
public:
|
||||
explicit EmptyTester(TesterArguments args);
|
||||
virtual ~EmptyTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
};
|
||||
|
||||
#endif // ROCSHMEM_CLIENTS_FUNCTIONAL_TESTS_EMPTY_TESTER_HPP
|
||||
@@ -0,0 +1,217 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "flood_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void FloodTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, uint64_t *r_buf, uint64_t *s_buf,
|
||||
TestType type, ShmemContextType ctx_type, int wf_size) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
|
||||
/**
|
||||
* Shared array to capture the start time for each wavefront
|
||||
* Max threads per block = 1024, wavefront size = 64 or 32 depending
|
||||
* on the GPUs. Using 32 since its safer for the dimensioning of the array,
|
||||
* the last 16 elements will not be used on GPUs with a wf size of 64.
|
||||
* Maximum array size required = 1024/32 = 32
|
||||
*/
|
||||
__shared__ long long int wf_start_time[32];
|
||||
|
||||
rocshmem_wg_ctx_create(ctx_type, &ctx);
|
||||
|
||||
int num_pe {rocshmem_ctx_n_pes(ctx)};
|
||||
int num_wg {get_grid_num_blocks()};
|
||||
int num_th {get_flat_block_size()};
|
||||
int my_pe {rocshmem_ctx_my_pe(ctx)};
|
||||
int wg_id {get_flat_grid_id()};
|
||||
int t_id {get_flat_block_id()};
|
||||
int wf_id {t_id / wf_size};
|
||||
|
||||
auto t_offset {wg_id * num_th + t_id};
|
||||
auto tgt_offset {my_pe * num_wg * num_th + t_offset};
|
||||
auto dst_offset {0};
|
||||
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (i == skip) {
|
||||
// Capture the start time of each wavefront to identify the earliest one
|
||||
wf_start_time[wf_id] = wall_clock64();
|
||||
}
|
||||
|
||||
for (int j{0}; j < num_pe; j++) {
|
||||
// shuffle ordering so that threads in the wave put to a
|
||||
// different pe 'simultaneously'
|
||||
auto pe = (t_id + j) % num_pe;
|
||||
switch (type) {
|
||||
case FloodPutTestType:
|
||||
rocshmem_ctx_putmem(ctx, &r_buf[tgt_offset], &s_buf[t_offset], sizeof(uint64_t), pe);
|
||||
break;
|
||||
case FloodPutNBITestType:
|
||||
rocshmem_ctx_putmem_nbi(ctx, &r_buf[tgt_offset], &s_buf[t_offset], sizeof(uint64_t), pe);
|
||||
break;
|
||||
case FloodPTestType:
|
||||
rocshmem_ctx_ulong_p(ctx, &r_buf[tgt_offset], s_buf[t_offset], pe);
|
||||
break;
|
||||
case FloodGetTestType:
|
||||
dst_offset = pe * num_wg * num_th + t_offset;
|
||||
rocshmem_ctx_getmem(ctx, &r_buf[dst_offset], &s_buf[t_offset], sizeof(uint64_t), pe);
|
||||
break;
|
||||
case FloodGetNBITestType:
|
||||
dst_offset = pe * num_wg * num_th + t_offset;
|
||||
rocshmem_ctx_getmem_nbi(ctx, &r_buf[dst_offset], &s_buf[t_offset], sizeof(uint64_t), pe);
|
||||
break;
|
||||
case FloodGTestType:
|
||||
dst_offset = pe * num_wg * num_th + t_offset;
|
||||
r_buf[dst_offset] = rocshmem_ctx_ulong_g(ctx, &s_buf[t_offset], pe);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
__syncthreads();
|
||||
if (is_thread_zero_in_block()) {
|
||||
rocshmem_ctx_quiet(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
if (is_thread_zero_in_wave()) {
|
||||
end_time[wg_id] = wall_clock64();
|
||||
}
|
||||
// Find the earliest start time
|
||||
int num_wfs = (get_flat_block_size() - 1 ) / wf_size + 1;
|
||||
for (int i = num_wfs / 2; i > 0; i >>= 1 ) {
|
||||
if(t_id < i) {
|
||||
wf_start_time[t_id] = min(wf_start_time[t_id], wf_start_time[t_id + i]);
|
||||
}
|
||||
}
|
||||
__syncthreads();
|
||||
if (t_id == 0) {
|
||||
start_time[wg_id] = wf_start_time[0];
|
||||
}
|
||||
|
||||
rocshmem_wg_ctx_destroy(&ctx);
|
||||
}
|
||||
|
||||
static __global__ void verify_results_kernel(uint64_t *dest, size_t buf_size,
|
||||
bool *verification_error) {
|
||||
int num_pe {rocshmem_n_pes()};
|
||||
int num_wg {get_grid_num_blocks()};
|
||||
int num_th {get_flat_block_size()};
|
||||
int my_pe {rocshmem_my_pe()};
|
||||
int wg_id {get_flat_grid_id()};
|
||||
int t_id {get_flat_block_id()};
|
||||
|
||||
auto t_offset {wg_id * num_th + t_id};
|
||||
|
||||
for (int pe{0}; pe < num_pe; pe++) {
|
||||
auto dst_offset {pe * num_wg * num_th + t_offset};
|
||||
auto value = dest[dst_offset];
|
||||
auto v_th = value & 0x0fff;
|
||||
auto v_wg = (value>>12) & 0xffff'ffff;
|
||||
auto v_pe = (value>>44);
|
||||
|
||||
if (v_th != t_id || v_wg != wg_id || v_pe != pe) {
|
||||
*verification_error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
FloodTester::FloodTester(TesterArguments args) : Tester(args) {
|
||||
int num_pes {rocshmem_n_pes()};
|
||||
int my_pe {rocshmem_my_pe()};
|
||||
s_buf = (uint64_t*)rocshmem_malloc(sizeof(uint64_t) * args.num_wgs * args.wg_size);
|
||||
for(int wg = 0; wg < args.num_wgs; wg++) for(int th = 0; th < args.wg_size; th++) {
|
||||
s_buf[wg * args.wg_size + th] = (((uint64_t)my_pe)<<44) + (wg<<12) + th; // set value for verification
|
||||
}
|
||||
r_buf = (uint64_t*)rocshmem_malloc(sizeof(uint64_t) * args.num_wgs * args.wg_size * num_pes);
|
||||
}
|
||||
|
||||
FloodTester::~FloodTester() {
|
||||
rocshmem_free(s_buf);
|
||||
rocshmem_free(r_buf);
|
||||
}
|
||||
|
||||
void FloodTester::resetBuffers(size_t size) {
|
||||
int num_pes {rocshmem_n_pes()};
|
||||
memset(r_buf, 0, sizeof(uint64_t) * args.num_wgs * args.wg_size * num_pes);
|
||||
}
|
||||
|
||||
void FloodTester::launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
int num_pes {rocshmem_n_pes()};
|
||||
|
||||
hipLaunchKernelGGL(FloodTest, gridSize, blockSize, shared_bytes, stream,
|
||||
loop, args.skip, start_time, end_time, r_buf, s_buf,
|
||||
_type, _shmem_context, wf_size);
|
||||
|
||||
|
||||
num_msgs = (loop + args.skip) * gridSize.x * blockSize.x * num_pes;
|
||||
num_timed_msgs = loop * gridSize.x * blockSize.x * num_pes;
|
||||
}
|
||||
|
||||
void FloodTester::verifyResults(size_t size) {
|
||||
int num_pes {rocshmem_n_pes()};
|
||||
int my_pe {rocshmem_my_pe()};
|
||||
|
||||
if (num_pes > 1<<20 || args.num_wgs > 1<<31 || args.wg_size > 1<<12) {
|
||||
// can't check
|
||||
return;
|
||||
}
|
||||
assert(size == sizeof(uint64_t));
|
||||
|
||||
hipLaunchKernelGGL(verify_results_kernel, args.num_wgs, args.wg_size, 0, stream,
|
||||
r_buf, sizeof(uint64_t), verification_error);
|
||||
CHECK_HIP(hipStreamSynchronize(stream));
|
||||
|
||||
if (*verification_error) {
|
||||
for(auto pe = 0; pe < num_pes; pe++)
|
||||
for(auto wg = 0; wg < args.num_wgs; wg++)
|
||||
for(auto th = 0; th < args.wg_size; th++) {
|
||||
auto t_offset {wg * args.wg_size + th};
|
||||
auto dst_offset {pe * args.num_wgs * args.wg_size + t_offset};
|
||||
auto value = r_buf[dst_offset];
|
||||
auto v_th = value & 0x0fff;
|
||||
auto v_wg = (value>>12) & 0xffff'ffff;
|
||||
auto v_pe = (value>>44);
|
||||
if (v_th != th || v_wg != wg || v_pe != pe) {
|
||||
std::cerr << "Data validation error at idx " << dst_offset << std::endl;
|
||||
std::cerr << " Got " << v_pe << ":" << v_wg << ":" << v_th
|
||||
<< ", Expected " << pe << ":" << wg << ":" << th << std::endl;
|
||||
|
||||
*verification_error = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _FLOOD_TESTER_HPP_
|
||||
#define _FLOOD_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void FloodTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, uint64_t *r_buf);
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class FloodTester : public Tester {
|
||||
public:
|
||||
explicit FloodTester(TesterArguments args);
|
||||
virtual ~FloodTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
uint64_t *r_buf;
|
||||
uint64_t *s_buf;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,205 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "getmem_on_stream_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
GetmemOnStreamTester::GetmemOnStreamTester(TesterArguments args)
|
||||
: Tester(args) {
|
||||
my_pe = rocshmem_my_pe();
|
||||
n_pes = rocshmem_n_pes();
|
||||
|
||||
char *value{nullptr};
|
||||
if ((value = getenv("ROCSHMEM_TEST_NUM_STREAMS"))) {
|
||||
num_streams = atoi(value);
|
||||
} else {
|
||||
// Default to 1 stream
|
||||
num_streams = 1;
|
||||
}
|
||||
|
||||
// Set target PE to get from (default: next PE in ring)
|
||||
pe_target = (my_pe + 1) % n_pes;
|
||||
if ((value = getenv("ROCSHMEM_TEST_GETMEM_TARGET"))) {
|
||||
pe_target = atoi(value);
|
||||
if (pe_target < 0 || pe_target >= n_pes) {
|
||||
std::cerr << "Invalid ROCSHMEM_TEST_GETMEM_TARGET value. Using next PE."
|
||||
<< std::endl;
|
||||
pe_target = (my_pe + 1) % n_pes;
|
||||
}
|
||||
}
|
||||
|
||||
int num_bytes_stream = args.max_msg_size;
|
||||
int total_bytes = num_bytes_stream * num_streams;
|
||||
buf_size = total_bytes;
|
||||
|
||||
source_buf = static_cast<char *>(rocshmem_malloc(buf_size));
|
||||
dest_buf = static_cast<char *>(rocshmem_malloc(buf_size));
|
||||
|
||||
if (source_buf == nullptr || dest_buf == nullptr) {
|
||||
std::cerr << "Error allocating memory from symmetric heap" << std::endl;
|
||||
std::cerr << "source: " << source_buf << ", dest: " << dest_buf
|
||||
<< std::endl;
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
|
||||
streams.resize(num_streams);
|
||||
start_events_timed.resize(num_streams);
|
||||
stop_events_timed.resize(num_streams);
|
||||
for (int i = 0; i < num_streams; i++) {
|
||||
CHECK_HIP(hipStreamCreate(&streams[i]));
|
||||
CHECK_HIP(hipEventCreate(&start_events_timed[i]));
|
||||
CHECK_HIP(hipEventCreate(&stop_events_timed[i]));
|
||||
}
|
||||
}
|
||||
|
||||
GetmemOnStreamTester::~GetmemOnStreamTester() {
|
||||
for (int i = 0; i < num_streams; i++) {
|
||||
CHECK_HIP(hipEventDestroy(stop_events_timed[i]));
|
||||
CHECK_HIP(hipEventDestroy(start_events_timed[i]));
|
||||
CHECK_HIP(hipStreamDestroy(streams[i]));
|
||||
}
|
||||
rocshmem_free(source_buf);
|
||||
rocshmem_free(dest_buf);
|
||||
}
|
||||
|
||||
void GetmemOnStreamTester::preLaunchKernel() {
|
||||
bw_factor = 1; // Point-to-point operation
|
||||
}
|
||||
|
||||
void GetmemOnStreamTester::postLaunchKernel() {
|
||||
// Synchronize all streams to ensure events are recorded
|
||||
for (int i = 0; i < num_streams; i++) {
|
||||
CHECK_HIP(hipStreamSynchronize(streams[i]));
|
||||
}
|
||||
|
||||
// Get elapsed time for each stream from HIP events
|
||||
for (int stream_id = 0; stream_id < num_streams && stream_id < num_timers;
|
||||
stream_id++) {
|
||||
float elapsed_time_ms = 0.0f;
|
||||
CHECK_HIP(hipEventElapsedTime(&elapsed_time_ms,
|
||||
start_events_timed[stream_id],
|
||||
stop_events_timed[stream_id]));
|
||||
|
||||
// Convert milliseconds to GPU cycles
|
||||
// wall_clk_rate is in kHz, so: cycles = ms * wall_clk_rate
|
||||
long long int elapsed_cycles =
|
||||
static_cast<long long int>(elapsed_time_ms *
|
||||
static_cast<float>(wall_clk_rate));
|
||||
|
||||
start_time[stream_id] = 0;
|
||||
end_time[stream_id] = elapsed_cycles;
|
||||
}
|
||||
|
||||
// Fill remaining timers with zero if num_timers > num_streams
|
||||
for (int i = num_streams; i < num_timers; i++) {
|
||||
start_time[i] = 0;
|
||||
end_time[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GetmemOnStreamTester::resetBuffers(size_t size) {
|
||||
// Initialize source buffer on all PEs
|
||||
// Each stream has its own portion
|
||||
for (int stream_id = 0; stream_id < num_streams; stream_id++) {
|
||||
int idx = stream_id * size;
|
||||
// Each PE fills its source buffer with a unique value
|
||||
int value = (my_pe + 1) * 100 + stream_id;
|
||||
std::memset(source_buf + idx, value, size);
|
||||
}
|
||||
|
||||
// Clear destination buffer
|
||||
std::memset(dest_buf, 0, buf_size);
|
||||
}
|
||||
|
||||
void GetmemOnStreamTester::launchKernel(dim3 gridSize, dim3 blockSize,
|
||||
int loop, size_t size) {
|
||||
// Execute warmup iterations (skip)
|
||||
for (int i = 0; i < args.skip; i++) {
|
||||
for (int stream_id = 0; stream_id < num_streams; stream_id++) {
|
||||
char *stream_dest = dest_buf + stream_id * size;
|
||||
char *stream_source = source_buf + stream_id * size;
|
||||
rocshmem_getmem_on_stream(stream_dest, stream_source, size, pe_target,
|
||||
streams[stream_id]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_streams; i++) {
|
||||
CHECK_HIP(hipStreamSynchronize(streams[i]));
|
||||
}
|
||||
|
||||
for (int i = 0; i < loop; i++) {
|
||||
for (int stream_id = 0; stream_id < num_streams; stream_id++) {
|
||||
// Record start event for this stream on first iteration
|
||||
if (i == 0) {
|
||||
CHECK_HIP(hipEventRecord(start_events_timed[stream_id],
|
||||
streams[stream_id]));
|
||||
}
|
||||
|
||||
char *stream_dest = dest_buf + stream_id * size;
|
||||
char *stream_source = source_buf + stream_id * size;
|
||||
rocshmem_getmem_on_stream(stream_dest, stream_source, size, pe_target,
|
||||
streams[stream_id]);
|
||||
|
||||
// Record stop event for this stream on last iteration
|
||||
if (i == loop - 1) {
|
||||
CHECK_HIP(hipEventRecord(stop_events_timed[stream_id],
|
||||
streams[stream_id]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
num_msgs = (loop + args.skip) * num_streams;
|
||||
num_timed_msgs = loop * num_streams;
|
||||
}
|
||||
|
||||
void GetmemOnStreamTester::verifyResults(size_t size) {
|
||||
// Verify correctness: after getmem, local dest buffer should have
|
||||
// the data from target PE's source buffer
|
||||
for (int stream_id = 0; stream_id < num_streams; stream_id++) {
|
||||
int idx = stream_id * size;
|
||||
// Expected value is from pe_target
|
||||
int expected_value = (pe_target + 1) * 100 + stream_id;
|
||||
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
if (static_cast<unsigned char>(dest_buf[idx + k]) !=
|
||||
static_cast<unsigned char>(expected_value)) {
|
||||
std::cerr << "PE " << my_pe << ": Verification failed for stream "
|
||||
<< stream_id << " at byte " << k << std::endl;
|
||||
std::cerr << "Expected value: " << expected_value
|
||||
<< ", Got: " << static_cast<int>(dest_buf[idx + k])
|
||||
<< std::endl;
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _GETMEM_ON_STREAM_TESTER_HPP_
|
||||
#define _GETMEM_ON_STREAM_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
#include <vector>
|
||||
#include <hip/hip_runtime.h>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class GetmemOnStreamTester : public Tester {
|
||||
public:
|
||||
explicit GetmemOnStreamTester(TesterArguments args);
|
||||
virtual ~GetmemOnStreamTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void preLaunchKernel() override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void postLaunchKernel() override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
private:
|
||||
char *source_buf;
|
||||
char *dest_buf;
|
||||
int my_pe;
|
||||
int n_pes;
|
||||
size_t buf_size;
|
||||
int num_streams = 1;
|
||||
int pe_target; // Target PE to get from
|
||||
std::vector<hipStream_t> streams;
|
||||
std::vector<hipEvent_t> start_events_timed;
|
||||
std::vector<hipEvent_t> stop_events_timed;
|
||||
};
|
||||
|
||||
#include "getmem_on_stream_tester.cpp"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "ping_all_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void PingAllTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, int *r_buf,
|
||||
ShmemContextType ctx_type) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
int wg_id = get_flat_grid_id();
|
||||
|
||||
rocshmem_wg_ctx_create(ctx_type, &ctx);
|
||||
|
||||
int pe = rocshmem_ctx_my_pe(ctx);
|
||||
int num_pe = rocshmem_ctx_n_pes(ctx);
|
||||
int status[1024];
|
||||
for (int j{0}; j < num_pe; j++) {
|
||||
status[j] = 0;
|
||||
}
|
||||
|
||||
if (is_thread_zero_in_block()) {
|
||||
auto blk_pe_off {wg_id * num_pe};
|
||||
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (i == skip) {
|
||||
start_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
for (int j{0}; j < num_pe; j++) {
|
||||
rocshmem_ctx_int_p(ctx, &r_buf[blk_pe_off + pe], 1, j);
|
||||
}
|
||||
rocshmem_int_wait_until_all(&r_buf[blk_pe_off], num_pe, status, ROCSHMEM_CMP_EQ, 1);
|
||||
}
|
||||
end_time[wg_id] = wall_clock64();
|
||||
rocshmem_ctx_quiet(ctx);
|
||||
}
|
||||
rocshmem_wg_ctx_destroy(&ctx);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
PingAllTester::PingAllTester(TesterArguments args) : Tester(args) {
|
||||
int num_pes {rocshmem_n_pes()};
|
||||
r_buf = (int *)rocshmem_malloc(sizeof(int) * args.num_wgs * num_pes);
|
||||
}
|
||||
|
||||
PingAllTester::~PingAllTester() { rocshmem_free(r_buf); }
|
||||
|
||||
void PingAllTester::resetBuffers(size_t size) {
|
||||
int num_pes {rocshmem_n_pes()};
|
||||
memset(r_buf, 0, sizeof(int) * args.num_wgs * num_pes);
|
||||
}
|
||||
|
||||
void PingAllTester::launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
hipLaunchKernelGGL(PingAllTest, gridSize, blockSize, shared_bytes, stream,
|
||||
loop, args.skip, start_time, end_time, r_buf,
|
||||
_shmem_context);
|
||||
|
||||
num_msgs = (loop + args.skip) * gridSize.x;
|
||||
num_timed_msgs = loop;
|
||||
}
|
||||
|
||||
void PingAllTester::verifyResults(size_t size) {}
|
||||
@@ -0,0 +1,55 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _PING_ALL_TESTER_HPP_
|
||||
#define _PING_ALL_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void PingAllTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, int *r_buf);
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class PingAllTester : public Tester {
|
||||
public:
|
||||
explicit PingAllTester(TesterArguments args);
|
||||
virtual ~PingAllTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
int *r_buf;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,94 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "ping_pong_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void PingPongTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, int *r_buf,
|
||||
ShmemContextType ctx_type) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
int wg_id = get_flat_grid_id();
|
||||
|
||||
rocshmem_wg_ctx_create(ctx_type, &ctx);
|
||||
|
||||
int pe = rocshmem_ctx_my_pe(ctx);
|
||||
|
||||
if (is_thread_zero_in_block()) {
|
||||
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (i == skip) {
|
||||
start_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
if (pe == 0) {
|
||||
rocshmem_ctx_int_p(ctx, &r_buf[hipBlockIdx_x], i + 1, 1);
|
||||
rocshmem_int_wait_until(&r_buf[hipBlockIdx_x], ROCSHMEM_CMP_EQ,
|
||||
i + 1);
|
||||
} else {
|
||||
rocshmem_int_wait_until(&r_buf[hipBlockIdx_x], ROCSHMEM_CMP_EQ,
|
||||
i + 1);
|
||||
rocshmem_ctx_int_p(ctx, &r_buf[hipBlockIdx_x], i + 1, 0);
|
||||
}
|
||||
}
|
||||
end_time[wg_id] = wall_clock64();
|
||||
|
||||
rocshmem_ctx_quiet(ctx);
|
||||
}
|
||||
|
||||
rocshmem_wg_ctx_destroy(&ctx);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
PingPongTester::PingPongTester(TesterArguments args) : Tester(args) {
|
||||
r_buf = (int *)rocshmem_malloc(sizeof(int) * args.num_wgs);
|
||||
}
|
||||
|
||||
PingPongTester::~PingPongTester() { rocshmem_free(r_buf); }
|
||||
|
||||
void PingPongTester::resetBuffers(size_t size) {
|
||||
memset(r_buf, 0, sizeof(int) * args.num_wgs);
|
||||
}
|
||||
|
||||
void PingPongTester::launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
hipLaunchKernelGGL(PingPongTest, gridSize, blockSize, shared_bytes, stream,
|
||||
loop, args.skip, start_time, end_time, r_buf,
|
||||
_shmem_context);
|
||||
|
||||
num_msgs = (loop + args.skip) * gridSize.x;
|
||||
num_timed_msgs = loop;
|
||||
}
|
||||
|
||||
void PingPongTester::verifyResults(size_t size) {}
|
||||
@@ -0,0 +1,55 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _PING_PONG_TESTER_HPP_
|
||||
#define _PING_PONG_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void PingPongTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, int *r_buf);
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class PingPongTester : public Tester {
|
||||
public:
|
||||
explicit PingPongTester(TesterArguments args);
|
||||
virtual ~PingPongTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
int *r_buf;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,114 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "primitive_mr_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void PrimitiveMRTest(int loop, long long int *start_time,
|
||||
long long int *end_time, char *s_buf,
|
||||
char *r_buf, size_t size,
|
||||
ShmemContextType ctx_type) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
int wg_id = get_flat_grid_id();
|
||||
rocshmem_wg_ctx_create(ctx_type, &ctx);
|
||||
|
||||
if (hipThreadIdx_x == 0) {
|
||||
|
||||
start_time[wg_id] = wall_clock64();
|
||||
|
||||
for (int win_i = 0; win_i < 64 * loop; win_i++) {
|
||||
for (int i = 0; i < 64; i++) {
|
||||
rocshmem_ctx_putmem_nbi(ctx, r_buf, s_buf, size, 1);
|
||||
}
|
||||
rocshmem_ctx_quiet(ctx);
|
||||
}
|
||||
|
||||
end_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
rocshmem_wg_ctx_destroy(&ctx);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
PrimitiveMRTester::PrimitiveMRTester(TesterArguments args) : Tester(args) {
|
||||
s_buf = (char *)rocshmem_malloc(args.max_msg_size * args.wg_size);
|
||||
r_buf = (char *)rocshmem_malloc(args.max_msg_size * args.wg_size);
|
||||
}
|
||||
|
||||
PrimitiveMRTester::~PrimitiveMRTester() {
|
||||
rocshmem_free(s_buf);
|
||||
rocshmem_free(r_buf);
|
||||
}
|
||||
|
||||
void PrimitiveMRTester::resetBuffers(size_t size) {
|
||||
memset(s_buf, '0', args.max_msg_size * args.wg_size);
|
||||
memset(r_buf, '1', args.max_msg_size * args.wg_size);
|
||||
}
|
||||
|
||||
void PrimitiveMRTester::launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
/* Warmup */
|
||||
hipLaunchKernelGGL(PrimitiveMRTest, gridSize, blockSize, shared_bytes, stream,
|
||||
loop, start_time, end_time, s_buf, r_buf, size,
|
||||
_shmem_context);
|
||||
|
||||
/* Benchmark */
|
||||
hipLaunchKernelGGL(PrimitiveMRTest, gridSize, blockSize, shared_bytes, stream,
|
||||
loop, start_time, end_time, s_buf, r_buf, size,
|
||||
_shmem_context);
|
||||
|
||||
CHECK_HIP(hipDeviceSynchronize());
|
||||
|
||||
num_msgs = (loop + args.skip) * gridSize.x;
|
||||
num_timed_msgs = loop * 64;
|
||||
}
|
||||
|
||||
void PrimitiveMRTester::verifyResults(size_t size) {
|
||||
int check_id =
|
||||
(_type == GetTestType || _type == GetNBITestType || _type == GTestType)
|
||||
? 0
|
||||
: 1;
|
||||
|
||||
if (args.myid == check_id) {
|
||||
for (uint64_t i = 0; i < size; i++) {
|
||||
if (r_buf[i] != '0') {
|
||||
fprintf(stderr, "Data validation error at idx %lu\n", i);
|
||||
fprintf(stderr, "Got %c, Expected %c\n", r_buf[i], '0');
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _PRIMITIVE_MR_TESTER_HPP_
|
||||
#define _PRIMITIVE_MR_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class PrimitiveMRTester : public Tester {
|
||||
public:
|
||||
explicit PrimitiveMRTester(TesterArguments args);
|
||||
virtual ~PrimitiveMRTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
char *s_buf = nullptr;
|
||||
char *r_buf = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,201 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "primitive_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void PrimitiveTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, char *source,
|
||||
char *dest, size_t size, TestType type,
|
||||
ShmemContextType ctx_type, int wf_size) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
int wg_id = get_flat_grid_id();
|
||||
int t_id = get_flat_block_id();
|
||||
int wf_id = t_id / wf_size;
|
||||
rocshmem_wg_ctx_create(ctx_type, &ctx);
|
||||
|
||||
/**
|
||||
* Shared array to capture the start time for each wavefront
|
||||
* Max threads per block = 1024, wavefront size = 64 or 32 depending
|
||||
* on the GPUs. Using 32 since its safer for the dimensioning of the array,
|
||||
* the last 16 elements will not be used on GPUs with a wf size of 64.
|
||||
* Maximum array size required = 1024/32 = 32
|
||||
*/
|
||||
__shared__ long long int wf_start_time[32];
|
||||
|
||||
/**
|
||||
* Calculate start index for each thread within the grid
|
||||
*/
|
||||
size_t offset = size * get_flat_id();
|
||||
source += offset;
|
||||
dest += offset;
|
||||
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (i == skip) {
|
||||
__syncthreads();
|
||||
// Ensures all RMA calls from the skip loops are completed
|
||||
if(is_thread_zero_in_block()) {
|
||||
rocshmem_ctx_quiet(ctx);
|
||||
}
|
||||
__syncthreads();
|
||||
// Capture the start time of each wavefront to identify the earliest one
|
||||
wf_start_time[wf_id] = wall_clock64();
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case GetTestType:
|
||||
rocshmem_ctx_getmem(ctx, dest, source, size, 1);
|
||||
break;
|
||||
case GetNBITestType:
|
||||
rocshmem_ctx_getmem_nbi(ctx, dest, source, size, 1);
|
||||
break;
|
||||
case PutTestType:
|
||||
rocshmem_ctx_putmem(ctx, dest, source, size, 1);
|
||||
break;
|
||||
case PutNBITestType:
|
||||
rocshmem_ctx_putmem_nbi(ctx, dest, source, size, 1);
|
||||
break;
|
||||
case PTestType:
|
||||
{
|
||||
/* Assigment required to verify we can send non-symetric memory */
|
||||
char val = *source;
|
||||
rocshmem_ctx_char_p(ctx, dest, val, 1);
|
||||
}
|
||||
break;
|
||||
case GTestType:
|
||||
*dest = rocshmem_ctx_char_g(ctx, source, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
if(is_thread_zero_in_block()) {
|
||||
rocshmem_ctx_quiet(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* End time of the last wavefront is recorded by overwriting
|
||||
* the value previously set by earlier wavefronts.
|
||||
*/
|
||||
end_time[wg_id] = wall_clock64();
|
||||
|
||||
// Find the earliest start time
|
||||
int num_wfs = (get_flat_block_size() - 1 ) / wf_size + 1;
|
||||
for (int i = num_wfs / 2; i > 0; i >>= 1 ) {
|
||||
if(t_id < i) {
|
||||
wf_start_time[t_id] = min(wf_start_time[t_id], wf_start_time[t_id + i]);
|
||||
}
|
||||
}
|
||||
__syncthreads();
|
||||
|
||||
if (t_id == 0) {
|
||||
start_time[wg_id] = wf_start_time[0];
|
||||
}
|
||||
|
||||
rocshmem_wg_ctx_destroy(&ctx);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
PrimitiveTester::PrimitiveTester(TesterArguments args) : Tester(args) {
|
||||
size_t buff_size = args.max_msg_size * args.wg_size * args.num_wgs;
|
||||
source = (char *)rocshmem_malloc(buff_size);
|
||||
dest = (char *)rocshmem_malloc(buff_size);
|
||||
|
||||
if (source == nullptr || dest == nullptr) {
|
||||
std::cerr << "Error allocating memory from symmetric heap" << std::endl;
|
||||
std::cerr << "source: " << source << ", dest: " << dest << std::endl;
|
||||
if (source) {
|
||||
rocshmem_free(source);
|
||||
}
|
||||
if (dest) {
|
||||
rocshmem_free(dest);
|
||||
}
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < buff_size; i++) {
|
||||
source[i] = static_cast<char>('a' + i % 26);
|
||||
}
|
||||
}
|
||||
|
||||
PrimitiveTester::~PrimitiveTester() {
|
||||
rocshmem_free(source);
|
||||
rocshmem_free(dest);
|
||||
}
|
||||
|
||||
void PrimitiveTester::resetBuffers(size_t size) {
|
||||
size_t buff_size = size * args.wg_size * args.num_wgs;
|
||||
memset(dest, '1', buff_size);
|
||||
}
|
||||
|
||||
void PrimitiveTester::launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
hipLaunchKernelGGL(PrimitiveTest, gridSize, blockSize, shared_bytes, stream,
|
||||
loop, args.skip, start_time, end_time, source, dest,
|
||||
size, _type, _shmem_context, wf_size);
|
||||
|
||||
num_msgs = (loop + args.skip) * gridSize.x * blockSize.x;
|
||||
num_timed_msgs = loop * gridSize.x * blockSize.x;
|
||||
}
|
||||
|
||||
void PrimitiveTester::verifyResults(size_t size) {
|
||||
int check_id =
|
||||
(_type == GetTestType || _type == GetNBITestType || _type == GTestType)
|
||||
? 0
|
||||
: 1;
|
||||
|
||||
if (args.myid == check_id) {
|
||||
size_t buff_size = size * args.wg_size * args.num_wgs;
|
||||
size_t verify_wg_size = std::min((size_t) 1024, buff_size);
|
||||
size_t verify_num_wgs = buff_size / verify_wg_size;
|
||||
|
||||
hipLaunchKernelGGL(verify_results_kernel_char, verify_num_wgs, verify_wg_size, 0, stream,
|
||||
source, dest, buff_size, verification_error);
|
||||
CHECK_HIP(hipStreamSynchronize(stream));
|
||||
|
||||
if (*verification_error) {
|
||||
for (uint64_t i = 0; i < buff_size; i++) {
|
||||
if (dest[i] != source[i]) {
|
||||
std::cerr << "Data validation error at idx " << i << std::endl;
|
||||
std::cerr << " Got " << dest[i] << ", Expected "
|
||||
<< source[i] << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
*verification_error = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _PRIMITIVE_TESTER_HPP_
|
||||
#define _PRIMITIVE_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class PrimitiveTester : public Tester {
|
||||
public:
|
||||
explicit PrimitiveTester(TesterArguments args);
|
||||
virtual ~PrimitiveTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
char *source = nullptr;
|
||||
char *dest = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,225 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "putmem_on_stream_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
PutmemOnStreamTester::PutmemOnStreamTester(TesterArguments args)
|
||||
: Tester(args) {
|
||||
my_pe = rocshmem_my_pe();
|
||||
n_pes = rocshmem_n_pes();
|
||||
|
||||
char *value{nullptr};
|
||||
if ((value = getenv("ROCSHMEM_TEST_NUM_STREAMS"))) {
|
||||
num_streams = atoi(value);
|
||||
} else {
|
||||
// Default to 1 stream
|
||||
num_streams = 1;
|
||||
}
|
||||
|
||||
// Check if we should test with nullptr (default stream)
|
||||
use_default_stream = false;
|
||||
if ((value = getenv("ROCSHMEM_TEST_USE_DEFAULT_STREAM"))) {
|
||||
use_default_stream = (atoi(value) != 0);
|
||||
if (use_default_stream) {
|
||||
num_streams = 1; // Only test with one nullptr stream
|
||||
}
|
||||
}
|
||||
|
||||
// Set target PE to put to (default: next PE in ring)
|
||||
pe_target = (my_pe + 1) % n_pes;
|
||||
if ((value = getenv("ROCSHMEM_TEST_PUTMEM_TARGET"))) {
|
||||
pe_target = atoi(value);
|
||||
if (pe_target < 0 || pe_target >= n_pes) {
|
||||
std::cerr << "Invalid ROCSHMEM_TEST_PUTMEM_TARGET value. Using next PE."
|
||||
<< std::endl;
|
||||
pe_target = (my_pe + 1) % n_pes;
|
||||
}
|
||||
}
|
||||
|
||||
int num_bytes_stream = args.max_msg_size;
|
||||
int total_bytes = num_bytes_stream * num_streams;
|
||||
buf_size = total_bytes;
|
||||
|
||||
source_buf = static_cast<char *>(rocshmem_malloc(buf_size));
|
||||
dest_buf = static_cast<char *>(rocshmem_malloc(buf_size));
|
||||
|
||||
if (source_buf == nullptr || dest_buf == nullptr) {
|
||||
std::cerr << "Error allocating memory from symmetric heap" << std::endl;
|
||||
std::cerr << "source: " << source_buf << ", dest: " << dest_buf
|
||||
<< std::endl;
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
|
||||
streams.resize(num_streams);
|
||||
start_events_timed.resize(num_streams);
|
||||
stop_events_timed.resize(num_streams);
|
||||
for (int i = 0; i < num_streams; i++) {
|
||||
if (use_default_stream) {
|
||||
streams[i] = nullptr; // Use default stream (0)
|
||||
} else {
|
||||
CHECK_HIP(hipStreamCreate(&streams[i]));
|
||||
}
|
||||
CHECK_HIP(hipEventCreate(&start_events_timed[i]));
|
||||
CHECK_HIP(hipEventCreate(&stop_events_timed[i]));
|
||||
}
|
||||
}
|
||||
|
||||
PutmemOnStreamTester::~PutmemOnStreamTester() {
|
||||
for (int i = 0; i < num_streams; i++) {
|
||||
CHECK_HIP(hipEventDestroy(stop_events_timed[i]));
|
||||
CHECK_HIP(hipEventDestroy(start_events_timed[i]));
|
||||
// Don't destroy default stream (nullptr)
|
||||
if (!use_default_stream) {
|
||||
CHECK_HIP(hipStreamDestroy(streams[i]));
|
||||
}
|
||||
}
|
||||
rocshmem_free(source_buf);
|
||||
rocshmem_free(dest_buf);
|
||||
}
|
||||
|
||||
void PutmemOnStreamTester::preLaunchKernel() {
|
||||
bw_factor = 1; // Point-to-point operation
|
||||
}
|
||||
|
||||
void PutmemOnStreamTester::postLaunchKernel() {
|
||||
// Synchronize all streams to ensure events are recorded
|
||||
for (int i = 0; i < num_streams; i++) {
|
||||
CHECK_HIP(hipStreamSynchronize(streams[i]));
|
||||
}
|
||||
|
||||
// Get elapsed time for each stream from HIP events
|
||||
for (int stream_id = 0; stream_id < num_streams && stream_id < num_timers;
|
||||
stream_id++) {
|
||||
float elapsed_time_ms = 0.0f;
|
||||
CHECK_HIP(hipEventElapsedTime(&elapsed_time_ms,
|
||||
start_events_timed[stream_id],
|
||||
stop_events_timed[stream_id]));
|
||||
|
||||
// Convert milliseconds to GPU cycles
|
||||
// wall_clk_rate is in kHz, so: cycles = ms * wall_clk_rate
|
||||
long long int elapsed_cycles =
|
||||
static_cast<long long int>(elapsed_time_ms *
|
||||
static_cast<float>(wall_clk_rate));
|
||||
|
||||
start_time[stream_id] = 0;
|
||||
end_time[stream_id] = elapsed_cycles;
|
||||
}
|
||||
|
||||
// Fill remaining timers with zero if num_timers > num_streams
|
||||
for (int i = num_streams; i < num_timers; i++) {
|
||||
start_time[i] = 0;
|
||||
end_time[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void PutmemOnStreamTester::resetBuffers(size_t size) {
|
||||
// Initialize source buffer on all PEs
|
||||
// Each stream has its own portion
|
||||
for (int stream_id = 0; stream_id < num_streams; stream_id++) {
|
||||
int idx = stream_id * size;
|
||||
// Each PE fills its source buffer with a unique value
|
||||
int value = (my_pe + 1) * 100 + stream_id;
|
||||
std::memset(source_buf + idx, value, size);
|
||||
}
|
||||
|
||||
// Clear destination buffer (will receive data from other PEs)
|
||||
std::memset(dest_buf, 0, buf_size);
|
||||
}
|
||||
|
||||
void PutmemOnStreamTester::launchKernel(dim3 gridSize, dim3 blockSize,
|
||||
int loop, size_t size) {
|
||||
// Execute warmup iterations (skip)
|
||||
for (int i = 0; i < args.skip; i++) {
|
||||
for (int stream_id = 0; stream_id < num_streams; stream_id++) {
|
||||
char *stream_source = source_buf + stream_id * size;
|
||||
char *stream_dest = dest_buf + stream_id * size;
|
||||
rocshmem_putmem_on_stream(stream_dest, stream_source, size, pe_target,
|
||||
streams[stream_id]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_streams; i++) {
|
||||
CHECK_HIP(hipStreamSynchronize(streams[i]));
|
||||
}
|
||||
|
||||
for (int i = 0; i < loop; i++) {
|
||||
for (int stream_id = 0; stream_id < num_streams; stream_id++) {
|
||||
// Record start event for this stream on first iteration
|
||||
if (i == 0) {
|
||||
CHECK_HIP(hipEventRecord(start_events_timed[stream_id],
|
||||
streams[stream_id]));
|
||||
}
|
||||
|
||||
char *stream_source = source_buf + stream_id * size;
|
||||
char *stream_dest = dest_buf + stream_id * size;
|
||||
rocshmem_putmem_on_stream(stream_dest, stream_source, size, pe_target,
|
||||
streams[stream_id]);
|
||||
|
||||
// Record stop event for this stream on last iteration
|
||||
if (i == loop - 1) {
|
||||
CHECK_HIP(hipEventRecord(stop_events_timed[stream_id],
|
||||
streams[stream_id]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
num_msgs = (loop + args.skip) * num_streams;
|
||||
num_timed_msgs = loop * num_streams;
|
||||
}
|
||||
|
||||
void PutmemOnStreamTester::verifyResults(size_t size) {
|
||||
// Verify correctness: after putmem, my dest buffer should have
|
||||
// the data that was put from the PE that targets me
|
||||
// We need to find which PE writes to me: pe_source where (pe_source + 1) % n_pes == my_pe
|
||||
int pe_source = (my_pe - 1 + n_pes) % n_pes;
|
||||
|
||||
for (int stream_id = 0; stream_id < num_streams; stream_id++) {
|
||||
int idx = stream_id * size;
|
||||
// Expected value is from pe_source
|
||||
int expected_value = (pe_source + 1) * 100 + stream_id;
|
||||
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
if (static_cast<unsigned char>(dest_buf[idx + k]) !=
|
||||
static_cast<unsigned char>(expected_value)) {
|
||||
std::cerr << "PE " << my_pe << ": Verification failed for stream "
|
||||
<< stream_id << " at byte " << k << std::endl;
|
||||
std::cerr << "Expected value from PE " << pe_source << ": "
|
||||
<< expected_value
|
||||
<< ", Got: " << static_cast<int>(dest_buf[idx + k])
|
||||
<< std::endl;
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _PUTMEM_ON_STREAM_TESTER_HPP_
|
||||
#define _PUTMEM_ON_STREAM_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
#include <vector>
|
||||
#include <hip/hip_runtime.h>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class PutmemOnStreamTester : public Tester {
|
||||
public:
|
||||
explicit PutmemOnStreamTester(TesterArguments args);
|
||||
virtual ~PutmemOnStreamTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void preLaunchKernel() override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void postLaunchKernel() override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
private:
|
||||
char *source_buf;
|
||||
char *dest_buf;
|
||||
int my_pe;
|
||||
int n_pes;
|
||||
size_t buf_size;
|
||||
int num_streams = 1;
|
||||
bool use_default_stream = false;
|
||||
int pe_target; // Target PE to put to
|
||||
std::vector<hipStream_t> streams;
|
||||
std::vector<hipEvent_t> start_events_timed;
|
||||
std::vector<hipEvent_t> stop_events_timed;
|
||||
};
|
||||
|
||||
#include "putmem_on_stream_tester.cpp"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "putmem_signal_on_stream_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
PutmemSignalOnStreamTester::PutmemSignalOnStreamTester(TesterArguments args)
|
||||
: Tester(args) {
|
||||
my_pe = rocshmem_my_pe();
|
||||
n_pes = rocshmem_n_pes();
|
||||
|
||||
char *value{nullptr};
|
||||
if ((value = getenv("ROCSHMEM_TEST_NUM_STREAMS"))) {
|
||||
num_streams = atoi(value);
|
||||
} else {
|
||||
// Default to 1 stream
|
||||
num_streams = 1;
|
||||
}
|
||||
|
||||
// Set target PE to put to (default: next PE in ring)
|
||||
pe_target = (my_pe + 1) % n_pes;
|
||||
if ((value = getenv("ROCSHMEM_TEST_PUTMEM_TARGET"))) {
|
||||
pe_target = atoi(value);
|
||||
if (pe_target < 0 || pe_target >= n_pes) {
|
||||
std::cerr << "Invalid ROCSHMEM_TEST_PUTMEM_TARGET value. Using next PE."
|
||||
<< std::endl;
|
||||
pe_target = (my_pe + 1) % n_pes;
|
||||
}
|
||||
}
|
||||
|
||||
int num_bytes_stream = args.max_msg_size;
|
||||
int total_bytes = num_bytes_stream * num_streams;
|
||||
buf_size = total_bytes;
|
||||
|
||||
source_buf = static_cast<char *>(rocshmem_malloc(buf_size));
|
||||
dest_buf = static_cast<char *>(rocshmem_malloc(buf_size));
|
||||
sig_addr = static_cast<uint64_t *>(rocshmem_malloc(num_streams * sizeof(uint64_t)));
|
||||
|
||||
if (source_buf == nullptr || dest_buf == nullptr || sig_addr == nullptr) {
|
||||
std::cerr << "Error allocating memory from symmetric heap" << std::endl;
|
||||
std::cerr << "source: " << source_buf << ", dest: " << dest_buf
|
||||
<< ", sig_addr: " << sig_addr << std::endl;
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
|
||||
streams.resize(num_streams);
|
||||
start_events_timed.resize(num_streams);
|
||||
stop_events_timed.resize(num_streams);
|
||||
for (int i = 0; i < num_streams; i++) {
|
||||
CHECK_HIP(hipStreamCreate(&streams[i]));
|
||||
CHECK_HIP(hipEventCreate(&start_events_timed[i]));
|
||||
CHECK_HIP(hipEventCreate(&stop_events_timed[i]));
|
||||
}
|
||||
}
|
||||
|
||||
PutmemSignalOnStreamTester::~PutmemSignalOnStreamTester() {
|
||||
for (int i = 0; i < num_streams; i++) {
|
||||
CHECK_HIP(hipEventDestroy(stop_events_timed[i]));
|
||||
CHECK_HIP(hipEventDestroy(start_events_timed[i]));
|
||||
CHECK_HIP(hipStreamDestroy(streams[i]));
|
||||
}
|
||||
rocshmem_free(source_buf);
|
||||
rocshmem_free(dest_buf);
|
||||
rocshmem_free(sig_addr);
|
||||
}
|
||||
|
||||
void PutmemSignalOnStreamTester::preLaunchKernel() {
|
||||
bw_factor = 1; // Point-to-point operation
|
||||
}
|
||||
|
||||
void PutmemSignalOnStreamTester::postLaunchKernel() {
|
||||
// Synchronize all streams to ensure events are recorded
|
||||
for (int i = 0; i < num_streams; i++) {
|
||||
CHECK_HIP(hipStreamSynchronize(streams[i]));
|
||||
}
|
||||
|
||||
// Get elapsed time for each stream from HIP events
|
||||
for (int stream_id = 0; stream_id < num_streams && stream_id < num_timers;
|
||||
stream_id++) {
|
||||
float elapsed_time_ms = 0.0f;
|
||||
CHECK_HIP(hipEventElapsedTime(&elapsed_time_ms,
|
||||
start_events_timed[stream_id],
|
||||
stop_events_timed[stream_id]));
|
||||
|
||||
// Convert milliseconds to GPU cycles
|
||||
// wall_clk_rate is in kHz, so: cycles = ms * wall_clk_rate
|
||||
long long int elapsed_cycles =
|
||||
static_cast<long long int>(elapsed_time_ms *
|
||||
static_cast<float>(wall_clk_rate));
|
||||
|
||||
start_time[stream_id] = 0;
|
||||
end_time[stream_id] = elapsed_cycles;
|
||||
}
|
||||
|
||||
// Fill remaining timers with zero if num_timers > num_streams
|
||||
for (int i = num_streams; i < num_timers; i++) {
|
||||
start_time[i] = 0;
|
||||
end_time[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void PutmemSignalOnStreamTester::resetBuffers(size_t size) {
|
||||
// Initialize source buffer on all PEs
|
||||
// Each stream has its own portion
|
||||
for (int stream_id = 0; stream_id < num_streams; stream_id++) {
|
||||
int idx = stream_id * size;
|
||||
// Each PE fills its source buffer with a unique value
|
||||
int value = (my_pe + 1) * 100 + stream_id;
|
||||
std::memset(source_buf + idx, value, size);
|
||||
}
|
||||
|
||||
// Clear destination buffer (will receive data from other PEs)
|
||||
std::memset(dest_buf, 0, buf_size);
|
||||
|
||||
// Clear signal addresses
|
||||
std::memset(sig_addr, 0, num_streams * sizeof(uint64_t));
|
||||
}
|
||||
|
||||
void PutmemSignalOnStreamTester::launchKernel(dim3 gridSize, dim3 blockSize,
|
||||
int loop, size_t size) {
|
||||
uint64_t signal_value = 1;
|
||||
|
||||
// Execute warmup iterations (skip)
|
||||
for (int i = 0; i < args.skip; i++) {
|
||||
for (int stream_id = 0; stream_id < num_streams; stream_id++) {
|
||||
char *stream_source = source_buf + stream_id * size;
|
||||
char *stream_dest = dest_buf + stream_id * size;
|
||||
rocshmem_putmem_signal_on_stream(stream_dest, stream_source, size,
|
||||
&sig_addr[stream_id], signal_value,
|
||||
sig_op, pe_target, streams[stream_id]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_streams; i++) {
|
||||
CHECK_HIP(hipStreamSynchronize(streams[i]));
|
||||
}
|
||||
|
||||
// Reset signal addresses after warmup and synchronize across PEs
|
||||
std::memset(sig_addr, 0, num_streams * sizeof(uint64_t));
|
||||
rocshmem_barrier_all();
|
||||
|
||||
for (int i = 0; i < loop; i++) {
|
||||
for (int stream_id = 0; stream_id < num_streams; stream_id++) {
|
||||
// Record start event for this stream on first iteration
|
||||
if (i == 0) {
|
||||
CHECK_HIP(hipEventRecord(start_events_timed[stream_id],
|
||||
streams[stream_id]));
|
||||
}
|
||||
|
||||
char *stream_source = source_buf + stream_id * size;
|
||||
char *stream_dest = dest_buf + stream_id * size;
|
||||
rocshmem_putmem_signal_on_stream(stream_dest, stream_source, size,
|
||||
&sig_addr[stream_id], signal_value,
|
||||
sig_op, pe_target, streams[stream_id]);
|
||||
|
||||
// Record stop event for this stream on last iteration
|
||||
if (i == loop - 1) {
|
||||
CHECK_HIP(hipEventRecord(stop_events_timed[stream_id],
|
||||
streams[stream_id]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
num_msgs = (loop + args.skip) * num_streams;
|
||||
num_timed_msgs = loop * num_streams;
|
||||
}
|
||||
|
||||
void PutmemSignalOnStreamTester::verifyResults(size_t size) {
|
||||
// Synchronize to ensure all operations completed
|
||||
rocshmem_barrier_all();
|
||||
|
||||
// Verify correctness: after putmem_signal, my dest buffer should have
|
||||
// the data that was put from the PE that targets me
|
||||
// We need to find which PE writes to me: pe_source where (pe_source + 1) % n_pes == my_pe
|
||||
int pe_source = (my_pe - 1 + n_pes) % n_pes;
|
||||
|
||||
for (int stream_id = 0; stream_id < num_streams; stream_id++) {
|
||||
int idx = stream_id * size;
|
||||
// Expected value is from pe_source
|
||||
int expected_value = (pe_source + 1) * 100 + stream_id;
|
||||
|
||||
// Verify data
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
if (static_cast<unsigned char>(dest_buf[idx + k]) !=
|
||||
static_cast<unsigned char>(expected_value)) {
|
||||
std::cerr << "PE " << my_pe << ": Data verification failed for stream "
|
||||
<< stream_id << " at byte " << k << std::endl;
|
||||
std::cerr << "Expected value from PE " << pe_source << ": "
|
||||
<< expected_value
|
||||
<< ", Got: " << static_cast<int>(dest_buf[idx + k])
|
||||
<< std::endl;
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Verify signal
|
||||
uint64_t expected_signal = 1;
|
||||
if (sig_addr[stream_id] != expected_signal) {
|
||||
std::cerr << "PE " << my_pe << ": Signal verification failed for stream "
|
||||
<< stream_id << std::endl;
|
||||
std::cerr << "Expected signal: " << expected_signal
|
||||
<< ", Got: " << sig_addr[stream_id] << std::endl;
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _PUTMEM_SIGNAL_ON_STREAM_TESTER_HPP_
|
||||
#define _PUTMEM_SIGNAL_ON_STREAM_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
#include <vector>
|
||||
#include <hip/hip_runtime.h>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class PutmemSignalOnStreamTester : public Tester {
|
||||
public:
|
||||
explicit PutmemSignalOnStreamTester(TesterArguments args);
|
||||
virtual ~PutmemSignalOnStreamTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void preLaunchKernel() override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void postLaunchKernel() override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
private:
|
||||
char *source_buf;
|
||||
char *dest_buf;
|
||||
uint64_t *sig_addr;
|
||||
int my_pe;
|
||||
int n_pes;
|
||||
size_t buf_size;
|
||||
int num_streams = 1;
|
||||
int pe_target; // Target PE to put to
|
||||
int sig_op = ROCSHMEM_SIGNAL_SET; // Signal operation
|
||||
std::vector<hipStream_t> streams;
|
||||
std::vector<hipEvent_t> start_events_timed;
|
||||
std::vector<hipEvent_t> stop_events_timed;
|
||||
};
|
||||
|
||||
#include "putmem_signal_on_stream_tester.cpp"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "random_access_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
#include <cassert>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
|
||||
__device__ bool thread_passing(int num_bins, uint32_t *bin_threads,
|
||||
uint32_t *off_bins, uint32_t *PE_bins,
|
||||
size_t *offset, int *PE, int coal_coef,
|
||||
size_t size) {
|
||||
bool pass = false;
|
||||
int wave_id = ((hipThreadIdx_x + hipBlockIdx_x * hipBlockDim_x) /
|
||||
64); // get_global_wave_id();
|
||||
|
||||
int off = wave_id * num_bins;
|
||||
for (int i = 0; i < num_bins; i++) {
|
||||
if (((hipThreadIdx_x % 64) >= bin_threads[i + off]) &&
|
||||
((hipThreadIdx_x % 64) < bin_threads[i + off] + coal_coef)) {
|
||||
pass = true;
|
||||
*offset = off_bins[i + off] +
|
||||
(((hipThreadIdx_x % 64) - bin_threads[i + off]) * size);
|
||||
*PE = PE_bins[i + off];
|
||||
}
|
||||
}
|
||||
return pass;
|
||||
}
|
||||
|
||||
__global__ void RandomAccessTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, int *s_buf,
|
||||
int *r_buf, size_t size, OpType type,
|
||||
int coal_coef, int num_bins, int num_waves,
|
||||
uint32_t *threads_bins, uint32_t *off_bins,
|
||||
uint32_t *PE_bins, ShmemContextType ctx_type) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
int wg_id = get_flat_grid_id();
|
||||
rocshmem_wg_ctx_create(ctx_type, &ctx);
|
||||
|
||||
int pe = rocshmem_ctx_my_pe(ctx);
|
||||
size_t offset;
|
||||
int PE;
|
||||
|
||||
if (thread_passing(num_bins, threads_bins, off_bins, PE_bins, &offset, &PE,
|
||||
coal_coef, (size / sizeof(int))) == true) {
|
||||
s_buf = s_buf + offset;
|
||||
r_buf = r_buf + offset;
|
||||
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (i == skip) {
|
||||
start_time[wg_id] = wall_clock64();
|
||||
}
|
||||
switch (type) {
|
||||
case GetType:
|
||||
rocshmem_ctx_getmem(ctx, r_buf, s_buf, size, PE);
|
||||
break;
|
||||
case PutType:
|
||||
rocshmem_ctx_putmem(ctx, (char *)r_buf, (char *)s_buf, size, PE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rocshmem_ctx_quiet(ctx);
|
||||
|
||||
// atomicAdd((unsigned long long *)&timer[hipBlockIdx_x],
|
||||
// rocshmem_timer() - start);
|
||||
end_time[wg_id] = wall_clock64();
|
||||
}
|
||||
rocshmem_wg_ctx_destroy(&ctx);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST HELPER FUNCTIONS
|
||||
****************************************************************************/
|
||||
__host__ void init_bins(int num_bins, int num_waves, uint32_t *off_bins,
|
||||
uint32_t *threads_bins, uint32_t *PE_bins, int size,
|
||||
int coal_coef, int num_pes, int max_size) {
|
||||
srand(time(NULL));
|
||||
|
||||
for (int j = 0; j < num_waves; j++) {
|
||||
for (int i = 0; i < num_bins; i++) {
|
||||
int current_bin = j * num_bins + i;
|
||||
assert((64 % num_bins) == 0);
|
||||
int quad_size = 64 / num_bins;
|
||||
int allowed_index_range = quad_size - coal_coef - 1;
|
||||
assert(allowed_index_range >= 0);
|
||||
int rand_val = 0;
|
||||
|
||||
if (allowed_index_range) rand_val = rand() % allowed_index_range;
|
||||
|
||||
threads_bins[current_bin] = rand_val + i * quad_size;
|
||||
|
||||
quad_size = max_size / (num_bins + num_waves);
|
||||
rand_val = rand() % (quad_size - (size * coal_coef - 1));
|
||||
off_bins[current_bin] = rand_val + current_bin * quad_size;
|
||||
|
||||
PE_bins[current_bin] = rand() % num_pes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
RandomAccessTester::RandomAccessTester(TesterArguments args) : Tester(args) {
|
||||
int max_size = args.max_msg_size;
|
||||
int wg_size = args.wg_size;
|
||||
_num_waves = (args.wg_size / 64) * args.num_wgs;
|
||||
_num_bins = args.thread_access / args.coal_coef;
|
||||
if ((args.wg_size / 64) > 1 || (64 % _num_bins) != 0) {
|
||||
printf("Argument are incorrect\n");
|
||||
assert((args.wg_size / 64) <= 1);
|
||||
assert((64 % _num_bins) == 0);
|
||||
abort();
|
||||
}
|
||||
|
||||
s_buf = (int *)rocshmem_malloc(max_size * wg_size * space);
|
||||
r_buf = (int *)rocshmem_malloc(max_size * wg_size * space);
|
||||
h_buf = (int *)malloc(max_size * wg_size * space);
|
||||
h_dev_buf = (int *)malloc(max_size * wg_size * space);
|
||||
CHECK_HIP(hipMalloc((void **)&_threads_bins, sizeof(uint32_t) * _num_waves * _num_bins));
|
||||
CHECK_HIP(hipMalloc((void **)&_off_bins, sizeof(uint32_t) * _num_waves * _num_bins));
|
||||
CHECK_HIP(hipMalloc((void **)&_PE_bins, sizeof(uint32_t) * _num_waves * _num_bins));
|
||||
memset(_threads_bins, 0, sizeof(uint32_t) * _num_waves * _num_bins);
|
||||
memset(_off_bins, 0, sizeof(uint32_t) * _num_waves * _num_bins);
|
||||
memset(_PE_bins, 0, sizeof(uint32_t) * _num_waves * _num_bins);
|
||||
}
|
||||
|
||||
RandomAccessTester::~RandomAccessTester() {
|
||||
rocshmem_free(s_buf);
|
||||
rocshmem_free(r_buf);
|
||||
free(h_buf);
|
||||
free(h_dev_buf);
|
||||
CHECK_HIP(hipFree(_threads_bins));
|
||||
CHECK_HIP(hipFree(_off_bins));
|
||||
CHECK_HIP(hipFree(_PE_bins));
|
||||
}
|
||||
|
||||
void RandomAccessTester::resetBuffers(size_t size) {
|
||||
for (size_t i = 0; i < args.max_msg_size / sizeof(int) * args.wg_size * space;
|
||||
i++) {
|
||||
s_buf[i] = 1;
|
||||
r_buf[i] = 0;
|
||||
h_buf[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void RandomAccessTester::launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
int _thread_access = args.thread_access;
|
||||
int _coal_coef = args.coal_coef;
|
||||
|
||||
assert(_coal_coef >= 1);
|
||||
assert(gridSize.x == 1 && gridSize.y == 1 && gridSize.z == 1);
|
||||
|
||||
init_bins(_num_bins, _num_waves, _off_bins, _threads_bins, _PE_bins,
|
||||
size / sizeof(int), _coal_coef, args.numprocs,
|
||||
(space * size * args.wg_size) / sizeof(int));
|
||||
|
||||
if (args.myid == 0) {
|
||||
hipLaunchKernelGGL(RandomAccessTest, gridSize, blockSize, shared_bytes,
|
||||
stream, loop, args.skip, start_time, end_time, s_buf,
|
||||
r_buf, size, (OpType)args.op_type, _coal_coef,
|
||||
_num_bins, _num_waves, _threads_bins, _off_bins,
|
||||
_PE_bins, _shmem_context);
|
||||
}
|
||||
num_msgs = (loop + args.skip) * _num_waves * _thread_access;
|
||||
num_timed_msgs = loop * _num_waves * _thread_access;
|
||||
}
|
||||
|
||||
void RandomAccessTester::verifyResults(size_t size) {
|
||||
uint64_t offset;
|
||||
for (int k = 0; k < _num_waves; k++) {
|
||||
for (int i = 0; i < _num_bins; i++) {
|
||||
int index = i + _num_bins * k;
|
||||
if (args.op_type == PutType) {
|
||||
if (_PE_bins[index] == static_cast<uint32_t>(args.myid)) {
|
||||
offset = _off_bins[index];
|
||||
for (uint64_t j = 0; j < ((size / sizeof(int)) * args.coal_coef); j++) {
|
||||
h_buf[offset + j] = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (args.myid == 0) {
|
||||
offset = _off_bins[index];
|
||||
for (uint64_t j = 0; j < ((size / sizeof(int)) * args.coal_coef); j++) {
|
||||
h_buf[offset + j] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_HIP(hipMemcpy(h_dev_buf, r_buf, space * args.wg_size * size,
|
||||
hipMemcpyDeviceToHost));
|
||||
CHECK_HIP(hipDeviceSynchronize());
|
||||
for (uint64_t i = 0; i < (space * args.wg_size * size / sizeof(int)); i++) {
|
||||
if (h_dev_buf[i] != h_buf[i]) {
|
||||
printf("PE %d Got Data Validation: expecting %d got %d at %lu\n",
|
||||
args.myid, h_buf[i], h_dev_buf[i], i);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _RANDOM_ACCESS_TESTER_HPP_
|
||||
#define _RANDOM_ACCESS_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void RandomAccessTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, int *s_buf,
|
||||
int *r_buf, int size, OpType type,
|
||||
int coal_coef, int num_bins, int num_waves,
|
||||
uint32_t *threads_bins, uint32_t *off_bins,
|
||||
uint32_t *PE_bins);
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class RandomAccessTester : public Tester {
|
||||
public:
|
||||
explicit RandomAccessTester(TesterArguments args);
|
||||
virtual ~RandomAccessTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
int *r_buf;
|
||||
int *s_buf;
|
||||
int *h_buf;
|
||||
int *h_dev_buf;
|
||||
uint32_t *_threads_bins;
|
||||
uint32_t *_off_bins;
|
||||
uint32_t *_PE_bins;
|
||||
int _num_waves;
|
||||
int _num_bins;
|
||||
static constexpr int space = 16 * 2;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,176 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "shmem_ptr_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void ShmemPtrTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, char *dest, int wf_size,
|
||||
ShmemContextType ctx_type, int *available) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
int wg_id = get_flat_grid_id();
|
||||
int t_id = get_flat_block_id();
|
||||
int wf_id = t_id / wf_size;
|
||||
|
||||
rocshmem_wg_ctx_create(ctx_type, &ctx);
|
||||
|
||||
/**
|
||||
* Shared array to capture the start time for each wavefront
|
||||
* Max threads per block = 1024, wavefront size = 64 or 32 depending
|
||||
* on the GPUs. Using 32 since its safer for the dimensioning of the array,
|
||||
* the last 16 elements will not be used on GPUs with a wf size of 64.
|
||||
* Maximum array size required = 1024/32 = 32
|
||||
*/
|
||||
__shared__ long long int wf_start_time[32];
|
||||
|
||||
|
||||
/**
|
||||
* Calculate start index for each thread within the grid
|
||||
*/
|
||||
dest += get_flat_id();
|
||||
|
||||
char *local_addr = dest;
|
||||
void *remote_addr = rocshmem_ptr((void *)local_addr, 1);
|
||||
if (remote_addr != NULL) {
|
||||
*available = 1;
|
||||
}
|
||||
|
||||
if(*available) {
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (i == skip) {
|
||||
__syncthreads();
|
||||
// Ensures all RMA calls from the skip loops are completed
|
||||
if(is_thread_zero_in_block()) {
|
||||
rocshmem_ctx_quiet(ctx);
|
||||
}
|
||||
__syncthreads();
|
||||
// Capture the start time of each wavefront to identify the earliest one
|
||||
wf_start_time[wf_id] = wall_clock64();
|
||||
}
|
||||
|
||||
((char *)remote_addr)[0] = '1';
|
||||
}
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
if(is_thread_zero_in_block()) {
|
||||
rocshmem_ctx_quiet(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* End time of the last wavefront is recorded by overwriting
|
||||
* the value previously set by earlier wavefronts.
|
||||
*/
|
||||
end_time[wg_id] = wall_clock64();
|
||||
|
||||
// Find the earliest start time
|
||||
int num_wfs = (get_flat_block_size() - 1 ) / wf_size + 1;
|
||||
for (int i = num_wfs / 2; i > 0; i >>= 1 ) {
|
||||
if(t_id < i) {
|
||||
wf_start_time[t_id] = min(wf_start_time[t_id], wf_start_time[t_id + i]);
|
||||
}
|
||||
}
|
||||
|
||||
// For data validation in remote PE
|
||||
if( get_flat_id() == 0 ) {
|
||||
int *store_avail = (int*)(dest + get_flat_grid_size());
|
||||
*store_avail = *available;
|
||||
rocshmem_ctx_int_put(ctx, store_avail, store_avail, 1, 1);
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
if (t_id == 0) {
|
||||
start_time[wg_id] = wf_start_time[0];
|
||||
}
|
||||
|
||||
rocshmem_wg_ctx_destroy(&ctx);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
ShmemPtrTester::ShmemPtrTester(TesterArguments args) : Tester(args) {
|
||||
size_t buff_size = args.wg_size * args.num_wgs + sizeof(int);
|
||||
CHECK_HIP(hipMalloc((void **)&_available, sizeof(int)));
|
||||
dest = (char *)rocshmem_malloc(buff_size);
|
||||
|
||||
if (dest == nullptr) {
|
||||
std::cerr << "Error allocating memory from symmetric heap" << std::endl;
|
||||
std::cerr << "dest: " << dest << std::endl;
|
||||
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
ShmemPtrTester::~ShmemPtrTester() {
|
||||
CHECK_HIP(hipFree(_available));
|
||||
rocshmem_free(dest);
|
||||
}
|
||||
|
||||
void ShmemPtrTester::resetBuffers(size_t size) {
|
||||
size_t buff_size = args.wg_size * args.num_wgs + sizeof(int);
|
||||
memset(dest, '0', buff_size);
|
||||
memset(_available, 0, sizeof(int));
|
||||
}
|
||||
|
||||
void ShmemPtrTester::launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
hipLaunchKernelGGL(ShmemPtrTest, gridSize, blockSize, shared_bytes,
|
||||
stream, loop, args.skip, start_time, end_time,
|
||||
dest, wf_size, _type, _available);
|
||||
|
||||
num_msgs = (loop + args.skip) * gridSize.x * blockSize.x;
|
||||
num_timed_msgs = loop * gridSize.x * blockSize.x;
|
||||
}
|
||||
|
||||
void ShmemPtrTester::verifyResults(size_t size) {
|
||||
if (args.myid == 0) {
|
||||
if (*_available == 0) {
|
||||
_print_results = false;
|
||||
std::cout << "rocshmem ptr not available\n" << std::endl;
|
||||
}
|
||||
}
|
||||
else {
|
||||
size_t buff_size = args.wg_size * args.num_wgs;
|
||||
int *available = (int*)(dest + buff_size);
|
||||
if(*available == 1) {
|
||||
for (size_t i = 0; i < buff_size; i++) {
|
||||
if (dest[i] != '1') {
|
||||
std::cerr << "Data validation error at idx " << i << std::endl;
|
||||
std::cerr << " Got " << dest[i] << ", Expected 1 " << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _SHMEM_PTR_TESTER_HPP_
|
||||
#define _SHMEM_PTR_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class ShmemPtrTester : public Tester {
|
||||
public:
|
||||
explicit ShmemPtrTester(TesterArguments args);
|
||||
virtual ~ShmemPtrTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
char *dest = nullptr;
|
||||
int *_available = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,204 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 <rocshmem/rocshmem.hpp>
|
||||
#include <hip/hip_runtime.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
SignalWaitUntilOnStreamTester::SignalWaitUntilOnStreamTester(
|
||||
TesterArguments args)
|
||||
: Tester(args) {
|
||||
my_pe = rocshmem_my_pe();
|
||||
n_pes = rocshmem_n_pes();
|
||||
|
||||
char *value{nullptr};
|
||||
if ((value = getenv("ROCSHMEM_TEST_NUM_STREAMS"))) {
|
||||
num_streams = atoi(value);
|
||||
} else {
|
||||
// Default to 1 stream
|
||||
num_streams = 1;
|
||||
}
|
||||
|
||||
// Set target PE (next PE in ring)
|
||||
pe_target = (my_pe + 1) % n_pes;
|
||||
|
||||
// Allocate signal addresses on symmetric heap
|
||||
sig_addr =
|
||||
static_cast<uint64_t *>(rocshmem_malloc(num_streams * sizeof(uint64_t)));
|
||||
source_buf =
|
||||
static_cast<uint64_t *>(rocshmem_malloc(num_streams * sizeof(uint64_t)));
|
||||
|
||||
if (sig_addr == nullptr || source_buf == nullptr) {
|
||||
std::cerr << "Error allocating memory from symmetric heap" << std::endl;
|
||||
std::cerr << "sig_addr: " << sig_addr << ", source_buf: " << source_buf
|
||||
<< std::endl;
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
|
||||
streams.resize(num_streams);
|
||||
start_events_timed.resize(num_streams);
|
||||
stop_events_timed.resize(num_streams);
|
||||
for (int i = 0; i < num_streams; i++) {
|
||||
CHECK_HIP(hipStreamCreate(&streams[i]));
|
||||
CHECK_HIP(hipEventCreate(&start_events_timed[i]));
|
||||
CHECK_HIP(hipEventCreate(&stop_events_timed[i]));
|
||||
}
|
||||
}
|
||||
|
||||
SignalWaitUntilOnStreamTester::~SignalWaitUntilOnStreamTester() {
|
||||
for (int i = 0; i < num_streams; i++) {
|
||||
CHECK_HIP(hipEventDestroy(stop_events_timed[i]));
|
||||
CHECK_HIP(hipEventDestroy(start_events_timed[i]));
|
||||
CHECK_HIP(hipStreamDestroy(streams[i]));
|
||||
}
|
||||
rocshmem_free(sig_addr);
|
||||
rocshmem_free(source_buf);
|
||||
}
|
||||
|
||||
void SignalWaitUntilOnStreamTester::preLaunchKernel() {
|
||||
bw_factor = 1; // Point-to-point operation
|
||||
}
|
||||
|
||||
void SignalWaitUntilOnStreamTester::postLaunchKernel() {
|
||||
// Synchronize all streams to ensure events are recorded
|
||||
for (int i = 0; i < num_streams; i++) {
|
||||
CHECK_HIP(hipStreamSynchronize(streams[i]));
|
||||
}
|
||||
|
||||
// Get elapsed time for each stream from HIP events
|
||||
for (int stream_id = 0; stream_id < num_streams && stream_id < num_timers;
|
||||
stream_id++) {
|
||||
float elapsed_time_ms = 0.0f;
|
||||
CHECK_HIP(hipEventElapsedTime(&elapsed_time_ms,
|
||||
start_events_timed[stream_id],
|
||||
stop_events_timed[stream_id]));
|
||||
|
||||
// Convert milliseconds to GPU cycles
|
||||
long long int elapsed_cycles =
|
||||
static_cast<long long int>(elapsed_time_ms *
|
||||
static_cast<float>(wall_clk_rate));
|
||||
|
||||
start_time[stream_id] = 0;
|
||||
end_time[stream_id] = elapsed_cycles;
|
||||
}
|
||||
|
||||
// Fill remaining timers with zero if num_timers > num_streams
|
||||
for (int i = num_streams; i < num_timers; i++) {
|
||||
start_time[i] = 0;
|
||||
end_time[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SignalWaitUntilOnStreamTester::resetBuffers(size_t size) {
|
||||
// Clear signal addresses
|
||||
std::memset(sig_addr, 0, num_streams * sizeof(uint64_t));
|
||||
}
|
||||
|
||||
void SignalWaitUntilOnStreamTester::launchKernel(dim3 gridSize, dim3 blockSize,
|
||||
int loop, size_t size) {
|
||||
// Execute warmup + timed iterations
|
||||
for (int i = 0; i < args.skip + loop; i++) {
|
||||
// Increment signal value for each iteration
|
||||
uint64_t signal_value = i + 1;
|
||||
|
||||
for (int stream_id = 0; stream_id < num_streams; stream_id++) {
|
||||
// Record start event after warmup on first timed iteration for all streams
|
||||
if (i == args.skip) {
|
||||
CHECK_HIP(hipEventRecord(start_events_timed[stream_id],
|
||||
streams[stream_id]));
|
||||
}
|
||||
|
||||
// PE 0 starts the ring by signaling PE 1
|
||||
if (my_pe == 0) {
|
||||
rocshmem_putmem_signal_on_stream(&sig_addr[stream_id],
|
||||
&source_buf[stream_id],
|
||||
sizeof(uint64_t), &sig_addr[stream_id],
|
||||
signal_value, sig_op, pe_target,
|
||||
streams[stream_id]);
|
||||
} else {
|
||||
// All other PEs wait for signal from previous PE
|
||||
rocshmem_signal_wait_until_on_stream(&sig_addr[stream_id],
|
||||
ROCSHMEM_CMP_GE, signal_value,
|
||||
streams[stream_id]);
|
||||
|
||||
// Forward the signal to next PE (unless we're the last PE)
|
||||
if (my_pe != n_pes - 1) {
|
||||
rocshmem_putmem_signal_on_stream(&sig_addr[stream_id],
|
||||
&source_buf[stream_id],
|
||||
sizeof(uint64_t), &sig_addr[stream_id],
|
||||
signal_value, sig_op, pe_target,
|
||||
streams[stream_id]);
|
||||
}
|
||||
}
|
||||
|
||||
// Record stop event on last timed iteration for all streams
|
||||
if (i == args.skip + loop - 1) {
|
||||
CHECK_HIP(hipEventRecord(stop_events_timed[stream_id],
|
||||
streams[stream_id]));
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for all streams to complete
|
||||
for (int j = 0; j < num_streams; j++) {
|
||||
CHECK_HIP(hipStreamSynchronize(streams[j]));
|
||||
}
|
||||
|
||||
// Barrier to ensure all RMA operations completed across all PEs
|
||||
rocshmem_barrier_all();
|
||||
}
|
||||
|
||||
num_msgs = (loop + args.skip) * num_streams;
|
||||
num_timed_msgs = loop * num_streams;
|
||||
}
|
||||
|
||||
void SignalWaitUntilOnStreamTester::verifyResults(size_t size) {
|
||||
// Synchronize to ensure all operations completed
|
||||
rocshmem_barrier_all();
|
||||
|
||||
// Verify signal values
|
||||
// All PEs except PE 0 should have received the final signal value
|
||||
uint64_t expected_signal = args.skip + args.loop;
|
||||
|
||||
for (int stream_id = 0; stream_id < num_streams; stream_id++) {
|
||||
// PE 0 doesn't receive signals (it initiates), so skip verification
|
||||
if (my_pe == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Verify signal
|
||||
if (sig_addr[stream_id] != expected_signal) {
|
||||
std::cerr << "PE " << my_pe << ": Signal verification failed for stream "
|
||||
<< stream_id << std::endl;
|
||||
std::cerr << "Expected signal: " << expected_signal
|
||||
<< ", Got: " << sig_addr[stream_id] << std::endl;
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _SIGNAL_WAIT_UNTIL_ON_STREAM_TESTER_HPP_
|
||||
#define _SIGNAL_WAIT_UNTIL_ON_STREAM_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
#include <vector>
|
||||
#include <hip/hip_runtime.h>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class SignalWaitUntilOnStreamTester : public Tester {
|
||||
public:
|
||||
explicit SignalWaitUntilOnStreamTester(TesterArguments args);
|
||||
virtual ~SignalWaitUntilOnStreamTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void preLaunchKernel() override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void postLaunchKernel() override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
private:
|
||||
uint64_t *sig_addr;
|
||||
uint64_t *source_buf; // Source buffer in symmetric heap
|
||||
int my_pe;
|
||||
int n_pes;
|
||||
int num_streams = 1;
|
||||
int pe_target; // Target PE to signal next
|
||||
int sig_op = ROCSHMEM_SIGNAL_SET; // Signal operation
|
||||
std::vector<hipStream_t> streams;
|
||||
std::vector<hipEvent_t> start_events_timed;
|
||||
std::vector<hipEvent_t> stop_events_timed;
|
||||
};
|
||||
|
||||
#include "signal_wait_until_on_stream_tester.cpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,239 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "signaling_operations_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void PutmemSignalTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, char *s_buf,
|
||||
char *r_buf, size_t size, uint64_t *sig_addr,
|
||||
TestType type, ShmemContextType ctx_type,
|
||||
int sig_op) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
int wg_id = get_flat_grid_id();
|
||||
rocshmem_wg_ctx_create(ctx_type, &ctx);
|
||||
|
||||
uint64_t signal = 1;
|
||||
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (i == skip) {
|
||||
__syncthreads();
|
||||
start_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case PutSignalTestType:
|
||||
rocshmem_ctx_putmem_signal(ctx, r_buf, s_buf, size, sig_addr,
|
||||
signal, sig_op, 1);
|
||||
break;
|
||||
case WGPutSignalTestType:
|
||||
rocshmem_ctx_putmem_signal_wg(ctx, r_buf, s_buf, size, sig_addr,
|
||||
signal, sig_op, 1);
|
||||
break;
|
||||
case WAVEPutSignalTestType:
|
||||
rocshmem_ctx_putmem_signal_wave(ctx, r_buf, s_buf, size, sig_addr,
|
||||
signal, sig_op, 1);
|
||||
break;
|
||||
case PutSignalNBITestType:
|
||||
rocshmem_ctx_putmem_signal_nbi(ctx, r_buf, s_buf, size, sig_addr,
|
||||
signal, sig_op, 1);
|
||||
break;
|
||||
case WGPutSignalNBITestType:
|
||||
rocshmem_ctx_putmem_signal_nbi_wg(ctx, r_buf, s_buf, size, sig_addr,
|
||||
signal, sig_op, 1);
|
||||
break;
|
||||
case WAVEPutSignalNBITestType:
|
||||
rocshmem_ctx_putmem_signal_nbi_wave(ctx, r_buf, s_buf, size, sig_addr,
|
||||
signal, sig_op, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rocshmem_ctx_quiet(ctx);
|
||||
|
||||
__syncthreads();
|
||||
|
||||
if (hipThreadIdx_x == 0) {
|
||||
end_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
rocshmem_wg_ctx_destroy(&ctx);
|
||||
}
|
||||
|
||||
__global__ void SignalFetchTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, uint64_t *sig_addr,
|
||||
uint64_t *fetched_value, TestType type) {
|
||||
|
||||
int wg_id = get_flat_grid_id();
|
||||
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (i == skip) {
|
||||
__syncthreads();
|
||||
start_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case SignalFetchTestType:
|
||||
*fetched_value = rocshmem_signal_fetch(sig_addr);
|
||||
break;
|
||||
case WGSignalFetchTestType:
|
||||
*fetched_value = rocshmem_signal_fetch_wg(sig_addr);
|
||||
break;
|
||||
case WAVESignalFetchTestType:
|
||||
*fetched_value = rocshmem_signal_fetch_wave(sig_addr);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
if (hipThreadIdx_x == 0) {
|
||||
end_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
SignalingOperationsTester::SignalingOperationsTester(TesterArguments args)
|
||||
: Tester(args) {
|
||||
s_buf = (char *)rocshmem_malloc(args.max_msg_size * args.wg_size);
|
||||
r_buf = (char *)rocshmem_malloc(args.max_msg_size * args.wg_size);
|
||||
sig_addr = (uint64_t *)rocshmem_malloc(sizeof(uint64_t));
|
||||
CHECK_HIP(hipMallocManaged(&fetched_value, sizeof(uint64_t), hipMemAttachHost));
|
||||
}
|
||||
|
||||
SignalingOperationsTester::SignalingOperationsTester(TesterArguments args,
|
||||
int signal_op)
|
||||
: SignalingOperationsTester(args) {
|
||||
sig_op = signal_op;
|
||||
}
|
||||
|
||||
SignalingOperationsTester::~SignalingOperationsTester() {
|
||||
rocshmem_free(s_buf);
|
||||
rocshmem_free(r_buf);
|
||||
rocshmem_free(sig_addr);
|
||||
CHECK_HIP(hipFree(fetched_value));
|
||||
}
|
||||
|
||||
void SignalingOperationsTester::resetBuffers(size_t size) {
|
||||
memset(s_buf, '0', args.max_msg_size * args.wg_size);
|
||||
memset(r_buf, '1', args.max_msg_size * args.wg_size);
|
||||
*fetched_value = -1;
|
||||
*sig_addr = args.myid + 123;
|
||||
}
|
||||
|
||||
void SignalingOperationsTester::launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
|
||||
if ((_type == SignalFetchTestType) ||
|
||||
(_type == WAVESignalFetchTestType) ||
|
||||
(_type == WGSignalFetchTestType)) {
|
||||
hipLaunchKernelGGL(SignalFetchTest, gridSize, blockSize, shared_bytes, stream,
|
||||
loop, args.skip, start_time, end_time, sig_addr, fetched_value, _type);
|
||||
} else {
|
||||
hipLaunchKernelGGL(PutmemSignalTest, gridSize, blockSize, shared_bytes, stream,
|
||||
loop, args.skip, start_time, end_time, s_buf, r_buf, size, sig_addr,
|
||||
_type, _shmem_context, sig_op);
|
||||
}
|
||||
|
||||
num_msgs = (loop + args.skip) * gridSize.x;
|
||||
num_timed_msgs = loop;
|
||||
}
|
||||
|
||||
void SignalingOperationsTester::verifyResults(size_t size) {
|
||||
if (_type == SignalFetchTestType ||
|
||||
_type == WAVESignalFetchTestType ||
|
||||
_type == WGSignalFetchTestType) {
|
||||
if (0 == args.myid) {
|
||||
uint64_t value = *fetched_value;
|
||||
uint64_t expected_value = (args.myid + 123);
|
||||
if (value != expected_value) {
|
||||
fprintf(stderr, "Fetched Value %lu, Expected %lu\n", value, expected_value);
|
||||
exit(-1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (1 == args.myid) {
|
||||
// Validate Data
|
||||
for (uint64_t i = 0; i < size; i++) {
|
||||
if (r_buf[i] != '0') {
|
||||
fprintf(stderr, "Data validation error at idx %lu\n", i);
|
||||
fprintf(stderr, "Got %c, Expected %c\n", r_buf[i], '0');
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
// Validate Signal
|
||||
if (ROCSHMEM_SIGNAL_SET == sig_op) {
|
||||
uint64_t expected_value = 1;
|
||||
uint64_t value = *sig_addr;
|
||||
|
||||
if (value != expected_value) {
|
||||
fprintf(stderr, "ROCSHMEM_SIGNAL_SET Value %lu, Expected %lu\n", value, expected_value);
|
||||
exit(-1);
|
||||
}
|
||||
} else if (ROCSHMEM_SIGNAL_ADD == sig_op) {
|
||||
uint64_t value = *sig_addr;
|
||||
uint64_t expected_value = (args.myid + 123); // Initial Value
|
||||
|
||||
switch (_type) {
|
||||
case PutSignalTestType:
|
||||
case PutSignalNBITestType:
|
||||
expected_value += ((args.skip + args.loop) * args.wg_size * args.num_wgs);
|
||||
break;
|
||||
case WGPutSignalTestType:
|
||||
case WGPutSignalNBITestType:
|
||||
expected_value += ((args.skip + args.loop) * args.num_wgs);
|
||||
break;
|
||||
case WAVEPutSignalTestType:
|
||||
case WAVEPutSignalNBITestType:
|
||||
expected_value += ((args.skip + args.loop) * args.num_wgs * num_warps);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Invalid Test\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (value != expected_value) {
|
||||
fprintf(stderr, "ROCSHMEM_SIGNAL_ADD Value %lu, Expected %lu\n", value, expected_value);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _SIGNALING_OPERATIONS_
|
||||
#define _SIGNALING_OPERATIONS_
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class SignalingOperationsTester : public Tester {
|
||||
public:
|
||||
explicit SignalingOperationsTester(TesterArguments args);
|
||||
explicit SignalingOperationsTester(TesterArguments args, int signal_op);
|
||||
virtual ~SignalingOperationsTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
int sig_op;
|
||||
char *s_buf = nullptr;
|
||||
char *r_buf = nullptr;
|
||||
uint64_t *sig_addr;
|
||||
uint64_t *fetched_value;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,108 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "sync_all_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void SyncAllTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, TestType type,
|
||||
int wf_size) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
int t_id = get_flat_block_id();
|
||||
int wg_id = get_flat_grid_id();
|
||||
int wf_id = t_id / wf_size;
|
||||
|
||||
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (hipThreadIdx_x == 0 && i == skip) {
|
||||
start_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
if (is_block_zero_in_grid()) {
|
||||
switch (type) {
|
||||
case SyncAllTestType:
|
||||
if(t_id == 0) {
|
||||
/**
|
||||
* The function `rocshmem_sync_all` should be called from only
|
||||
* one thread within the grid to avoid undefined behavior.
|
||||
*/
|
||||
rocshmem_sync_all();
|
||||
}
|
||||
break;
|
||||
case WAVESyncAllTestType:
|
||||
if(wf_id == 0) {
|
||||
/**
|
||||
* The function `rocshmem_sync_all_wave` should be called from only
|
||||
* one thread within the grid to avoid undefined behavior.
|
||||
*/
|
||||
rocshmem_sync_all_wave();
|
||||
}
|
||||
break;
|
||||
case WGSyncAllTestType:
|
||||
/**
|
||||
* The function `rocshmem_sync_all_wg` should be called from only
|
||||
* one thread within the grid to avoid undefined behavior.
|
||||
*/
|
||||
rocshmem_sync_all_wg();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
__syncthreads();
|
||||
}
|
||||
}
|
||||
|
||||
if (hipThreadIdx_x == 0) {
|
||||
end_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
SyncAllTester::SyncAllTester(TesterArguments args) : Tester(args) {}
|
||||
|
||||
SyncAllTester::~SyncAllTester() {}
|
||||
|
||||
void SyncAllTester::launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
hipLaunchKernelGGL(SyncAllTest, gridSize, blockSize, shared_bytes, stream,
|
||||
loop, args.skip, start_time, end_time, _type, wf_size);
|
||||
|
||||
num_msgs = (loop + args.skip);
|
||||
num_timed_msgs = loop;
|
||||
}
|
||||
|
||||
void SyncAllTester::resetBuffers(size_t size) {}
|
||||
|
||||
void SyncAllTester::verifyResults(size_t size) {}
|
||||
@@ -0,0 +1,52 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _SYNC_ALL_TESTER_HPP_
|
||||
#define _SYNC_ALL_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void SyncAllTest(TestType type);
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class SyncAllTester : public Tester {
|
||||
public:
|
||||
explicit SyncAllTester(TesterArguments args);
|
||||
virtual ~SyncAllTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,222 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/* Declare the template with a generic implementation */
|
||||
template <typename T>
|
||||
__device__ void wg_team_alltoall(rocshmem_ctx_t ctx, rocshmem_team_t team,
|
||||
T *dest, const T *source, int nelem) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Define templates to call rocSHMEM */
|
||||
#define TEAM_ALLTOALL_DEF_GEN(T, TNAME) \
|
||||
template <> \
|
||||
__device__ void wg_team_alltoall<T>(rocshmem_ctx_t ctx, rocshmem_team_t team,\
|
||||
T * dest, const T *source, int nelem) { \
|
||||
rocshmem_ctx_##TNAME##_alltoall_wg(ctx, team, dest, source, nelem); \
|
||||
}
|
||||
|
||||
TEAM_ALLTOALL_DEF_GEN(float, float)
|
||||
TEAM_ALLTOALL_DEF_GEN(double, double)
|
||||
TEAM_ALLTOALL_DEF_GEN(char, char)
|
||||
// TEAM_ALLTOALL_DEF_GEN(long double, longdouble)
|
||||
TEAM_ALLTOALL_DEF_GEN(signed char, schar)
|
||||
TEAM_ALLTOALL_DEF_GEN(short, short)
|
||||
TEAM_ALLTOALL_DEF_GEN(int, int)
|
||||
TEAM_ALLTOALL_DEF_GEN(long, long)
|
||||
TEAM_ALLTOALL_DEF_GEN(long long, longlong)
|
||||
TEAM_ALLTOALL_DEF_GEN(unsigned char, uchar)
|
||||
TEAM_ALLTOALL_DEF_GEN(unsigned short, ushort)
|
||||
TEAM_ALLTOALL_DEF_GEN(unsigned int, uint)
|
||||
TEAM_ALLTOALL_DEF_GEN(unsigned long, ulong)
|
||||
TEAM_ALLTOALL_DEF_GEN(unsigned long long, ulonglong)
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
template <typename T1>
|
||||
__global__ void TeamAlltoallTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, T1 *source_buf,
|
||||
T1 *dest_buf, int num_elems,
|
||||
ShmemContextType ctx_type,
|
||||
rocshmem_team_t *teams) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
int wg_id = get_flat_grid_id();
|
||||
|
||||
rocshmem_wg_team_create_ctx(teams[wg_id], ctx_type, &ctx);
|
||||
|
||||
int n_pes = rocshmem_ctx_n_pes(ctx);
|
||||
|
||||
source_buf += wg_id * n_pes * num_elems;
|
||||
dest_buf += wg_id * n_pes * num_elems;
|
||||
|
||||
__syncthreads();
|
||||
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (i == skip && hipThreadIdx_x == 0) {
|
||||
start_time[wg_id] = wall_clock64();
|
||||
}
|
||||
wg_team_alltoall<T1>(ctx, teams[wg_id],
|
||||
dest_buf, // T* dest
|
||||
source_buf, // const T* source
|
||||
num_elems); // int nelement
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
if (hipThreadIdx_x == 0) {
|
||||
end_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
rocshmem_wg_ctx_destroy(&ctx);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
template <typename T1>
|
||||
TeamAlltoallTester<T1>::TeamAlltoallTester(TesterArguments args)
|
||||
: Tester(args){
|
||||
my_pe = rocshmem_team_my_pe(ROCSHMEM_TEAM_WORLD);
|
||||
n_pes = rocshmem_team_n_pes(ROCSHMEM_TEAM_WORLD);
|
||||
|
||||
// Number of elements per work group
|
||||
int num_elems_wg = (args.max_msg_size / sizeof(T1)) * n_pes;
|
||||
// Total number of elements in the GPU kernel
|
||||
int total_elems = num_elems_wg * args.num_wgs;
|
||||
int buff_size = total_elems * sizeof(T1);
|
||||
|
||||
source_buf = (T1 *)rocshmem_malloc(buff_size);
|
||||
dest_buf = (T1 *)rocshmem_malloc(buff_size);
|
||||
|
||||
if (source_buf == nullptr || dest_buf == nullptr) {
|
||||
std::cout << "Error allocating memory from symmetric heap" << std::endl;
|
||||
std::cout << "source: " << source_buf
|
||||
<< ", dest: " << dest_buf
|
||||
<< std::endl;
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
|
||||
char* value{nullptr};
|
||||
if ((value = getenv("ROCSHMEM_MAX_NUM_TEAMS"))) {
|
||||
num_teams = atoi(value);
|
||||
}
|
||||
|
||||
CHECK_HIP(hipMalloc(&team_alltoall_world_dup,
|
||||
sizeof(rocshmem_team_t) * num_teams));
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
TeamAlltoallTester<T1>::~TeamAlltoallTester() {
|
||||
rocshmem_free(source_buf);
|
||||
rocshmem_free(dest_buf);
|
||||
CHECK_HIP(hipFree(team_alltoall_world_dup));
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
void TeamAlltoallTester<T1>::preLaunchKernel() {
|
||||
bw_factor = n_pes;
|
||||
|
||||
for (int team_i = 0; team_i < num_teams; team_i++) {
|
||||
team_alltoall_world_dup[team_i] = ROCSHMEM_TEAM_INVALID;
|
||||
rocshmem_team_split_strided(ROCSHMEM_TEAM_WORLD, 0, 1, n_pes, nullptr, 0,
|
||||
&team_alltoall_world_dup[team_i]);
|
||||
if (team_alltoall_world_dup[team_i] == ROCSHMEM_TEAM_INVALID) {
|
||||
std::cout << "Team " << team_i << " is invalid!" << std::endl;
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
void TeamAlltoallTester<T1>::launchKernel(dim3 gridSize, dim3 blockSize,
|
||||
int loop, size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
int num_elems = size / sizeof(T1);
|
||||
|
||||
hipLaunchKernelGGL(TeamAlltoallTest<T1>, gridSize, blockSize, shared_bytes,
|
||||
stream, loop, args.skip, start_time, end_time,
|
||||
source_buf, dest_buf, num_elems, _shmem_context,
|
||||
team_alltoall_world_dup);
|
||||
|
||||
num_msgs = (loop + args.skip) * gridSize.x;
|
||||
num_timed_msgs = loop * gridSize.x;
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
void TeamAlltoallTester<T1>::postLaunchKernel() {
|
||||
for (int team_i = 0; team_i < num_teams; team_i++) {
|
||||
rocshmem_team_destroy(team_alltoall_world_dup[team_i]);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
void TeamAlltoallTester<T1>::resetBuffers(size_t size) {
|
||||
|
||||
int num_elems = size / sizeof(T1);
|
||||
int buff_size = num_elems * sizeof(T1) * args.num_wgs * n_pes;
|
||||
int idx = 0;
|
||||
|
||||
for(int wg_id = 0; wg_id < args.num_wgs; wg_id++) {
|
||||
for(int pe = 0; pe < n_pes; pe++) {
|
||||
for(int i = 0; i < num_elems; i++) {
|
||||
idx = (wg_id * n_pes + pe) * num_elems + i;
|
||||
if constexpr (std::is_same<T1, char>::value ||
|
||||
std::is_same<T1, signed char>::value ||
|
||||
std::is_same<T1, unsigned char>::value) {
|
||||
source_buf[idx] = static_cast<T1>('a' + my_pe + pe + wg_id);
|
||||
}
|
||||
else if constexpr (std::is_floating_point<T1>::value) {
|
||||
source_buf[idx] = static_cast<T1>(3.14 + my_pe + pe + wg_id);
|
||||
}
|
||||
else if constexpr (std::is_integral<T1>::value) {
|
||||
source_buf[idx] = static_cast<T1>(my_pe + pe + wg_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memset(dest_buf, -1, buff_size);
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
void TeamAlltoallTester<T1>::verifyResults(size_t size) {
|
||||
int num_elems = size / sizeof(T1);
|
||||
int idx = 0;
|
||||
|
||||
for(int wg_id = 0; wg_id < args.num_wgs; wg_id++) {
|
||||
for(int pe = 0; pe < n_pes; pe++) {
|
||||
for(int i = 0; i < num_elems; i++) {
|
||||
idx = (wg_id * n_pes + pe) * num_elems + i;
|
||||
if (dest_buf[idx] != source_buf[idx]) {
|
||||
std::cerr << "Data validation error at idx " << idx << std::endl;
|
||||
std::cerr << "PE " << my_pe << " Got " << dest_buf[idx]
|
||||
<< ", Expected " << source_buf[idx] << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _TEAM_ALLTOALL_TESTER_HPP_
|
||||
#define _TEAM_ALLTOALL_TESTER_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/************* *****************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
template <typename T1>
|
||||
class TeamAlltoallTester : public Tester {
|
||||
public:
|
||||
explicit TeamAlltoallTester(TesterArguments args);
|
||||
virtual ~TeamAlltoallTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void preLaunchKernel() override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void postLaunchKernel() override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
T1 *source_buf = nullptr;
|
||||
T1 *dest_buf = nullptr;
|
||||
|
||||
private:
|
||||
int my_pe = 0;
|
||||
int n_pes = 0;
|
||||
|
||||
/**
|
||||
* This constant should equal ROCSHMEM_MAX_NUM_TEAMS - 1.
|
||||
* The default value for the maximum number of teams is 40.
|
||||
*/
|
||||
int num_teams = 39;
|
||||
rocshmem_team_t *team_alltoall_world_dup;
|
||||
};
|
||||
|
||||
#include "team_alltoall_tester.cpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,219 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "team_alltoallmem_on_stream_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
TeamAlltoallmemOnStreamTester::TeamAlltoallmemOnStreamTester(TesterArguments args)
|
||||
: Tester(args) {
|
||||
my_pe = rocshmem_team_my_pe(ROCSHMEM_TEAM_WORLD);
|
||||
n_pes = rocshmem_team_n_pes(ROCSHMEM_TEAM_WORLD);
|
||||
|
||||
char* value{nullptr};
|
||||
if ((value = getenv("ROCSHMEM_TEST_MAX_NUM_TEAMS"))) {
|
||||
num_teams = atoi(value);
|
||||
} else {
|
||||
// Default to number of work groups
|
||||
num_teams = args.num_wgs;
|
||||
}
|
||||
|
||||
int num_bytes_wg = args.max_msg_size * n_pes;
|
||||
int total_bytes = num_bytes_wg * num_teams;
|
||||
buf_size = total_bytes;
|
||||
|
||||
source_buf = static_cast<char *>(rocshmem_malloc(buf_size));
|
||||
dest_buf = static_cast<char *>(rocshmem_malloc(buf_size));
|
||||
|
||||
if (source_buf == nullptr || dest_buf == nullptr) {
|
||||
std::cerr << "Error allocating memory from symmetric heap" << std::endl;
|
||||
std::cerr << "source: " << source_buf << ", dest: " << dest_buf
|
||||
<< std::endl;
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
|
||||
team_world_dup.resize(num_teams);
|
||||
|
||||
streams.resize(num_teams);
|
||||
start_events_timed.resize(num_teams);
|
||||
stop_events_timed.resize(num_teams);
|
||||
for (int i = 0; i < num_teams; i++) {
|
||||
CHECK_HIP(hipStreamCreate(&streams[i]));
|
||||
CHECK_HIP(hipEventCreate(&start_events_timed[i]));
|
||||
CHECK_HIP(hipEventCreate(&stop_events_timed[i]));
|
||||
}
|
||||
}
|
||||
|
||||
TeamAlltoallmemOnStreamTester::~TeamAlltoallmemOnStreamTester() {
|
||||
for (int i = 0; i < num_teams; i++) {
|
||||
CHECK_HIP(hipEventDestroy(stop_events_timed[i]));
|
||||
CHECK_HIP(hipEventDestroy(start_events_timed[i]));
|
||||
CHECK_HIP(hipStreamDestroy(streams[i]));
|
||||
}
|
||||
rocshmem_free(source_buf);
|
||||
rocshmem_free(dest_buf);
|
||||
}
|
||||
|
||||
void TeamAlltoallmemOnStreamTester::preLaunchKernel() {
|
||||
bw_factor = n_pes;
|
||||
|
||||
for (int team_i = 0; team_i < num_teams; team_i++) {
|
||||
team_world_dup[team_i] = ROCSHMEM_TEAM_INVALID;
|
||||
rocshmem_team_split_strided(ROCSHMEM_TEAM_WORLD, 0, 1, n_pes, nullptr, 0,
|
||||
&team_world_dup[team_i]);
|
||||
if (team_world_dup[team_i] == ROCSHMEM_TEAM_INVALID) {
|
||||
std::cerr << "Team " << team_i << " is invalid!" << std::endl;
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TeamAlltoallmemOnStreamTester::postLaunchKernel() {
|
||||
// Synchronize all streams to ensure events are recorded
|
||||
for (int i = 0; i < num_teams; i++) {
|
||||
CHECK_HIP(hipStreamSynchronize(streams[i]));
|
||||
}
|
||||
|
||||
// Get elapsed time for each work group from HIP events
|
||||
for (int wg_id = 0; wg_id < num_teams && wg_id < num_timers; wg_id++) {
|
||||
float elapsed_time_ms = 0.0f;
|
||||
CHECK_HIP(hipEventElapsedTime(&elapsed_time_ms, start_events_timed[wg_id],
|
||||
stop_events_timed[wg_id]));
|
||||
|
||||
// Convert milliseconds to GPU cycles
|
||||
// wall_clk_rate is in kHz, so: cycles = ms * wall_clk_rate
|
||||
long long int elapsed_cycles = static_cast<long long int>(
|
||||
elapsed_time_ms * static_cast<float>(wall_clk_rate));
|
||||
|
||||
start_time[wg_id] = 0;
|
||||
end_time[wg_id] = elapsed_cycles;
|
||||
}
|
||||
|
||||
// Fill remaining timers with zero if num_timers > num_teams
|
||||
for (int i = num_teams; i < num_timers; i++) {
|
||||
start_time[i] = 0;
|
||||
end_time[i] = 0;
|
||||
}
|
||||
|
||||
for (int team_i = 0; team_i < num_teams; team_i++) {
|
||||
rocshmem_team_destroy(team_world_dup[team_i]);
|
||||
}
|
||||
}
|
||||
|
||||
void TeamAlltoallmemOnStreamTester::resetBuffers(size_t size) {
|
||||
// Initialize source buffer: each PE fills its portion with its PE number
|
||||
// For alltoall, PE i sends block j to PE j
|
||||
// Support multiple work groups (teams)
|
||||
int idx = 0;
|
||||
|
||||
for (int wg_id = 0; wg_id < num_teams; wg_id++) {
|
||||
for (int pe = 0; pe < n_pes; pe++) {
|
||||
// Each block in source buffer is filled with (my_pe * n_pes + pe)
|
||||
// This makes it easy to verify correctness
|
||||
int value = my_pe * n_pes + pe;
|
||||
idx = (wg_id * n_pes + pe) * size;
|
||||
std::memset(source_buf + idx, value, size);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear destination buffer
|
||||
std::memset(dest_buf, 0, buf_size);
|
||||
}
|
||||
|
||||
void TeamAlltoallmemOnStreamTester::launchKernel(dim3 gridSize,
|
||||
dim3 blockSize,
|
||||
int loop,
|
||||
size_t size) {
|
||||
// Execute warmup iterations (skip)
|
||||
for (int i = 0; i < args.skip; i++) {
|
||||
for (int wg_id = 0; wg_id < num_teams; wg_id++) {
|
||||
char *wg_source = source_buf + wg_id * n_pes * size;
|
||||
char *wg_dest = dest_buf + wg_id * n_pes * size;
|
||||
rocshmem_alltoallmem_on_stream(team_world_dup[wg_id], wg_dest,
|
||||
wg_source, size, streams[wg_id]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_teams; i++) {
|
||||
CHECK_HIP(hipStreamSynchronize(streams[i]));
|
||||
}
|
||||
|
||||
for (int i = 0; i < loop; i++) {
|
||||
for (int wg_id = 0; wg_id < num_teams; wg_id++) {
|
||||
// Record start event for this work group on first iteration
|
||||
if (i == 0) {
|
||||
CHECK_HIP(hipEventRecord(start_events_timed[wg_id], streams[wg_id]));
|
||||
}
|
||||
|
||||
char *wg_source = source_buf + wg_id * n_pes * size;
|
||||
char *wg_dest = dest_buf + wg_id * n_pes * size;
|
||||
rocshmem_alltoallmem_on_stream(team_world_dup[wg_id], wg_dest,
|
||||
wg_source, size, streams[wg_id]);
|
||||
|
||||
// Record stop event for this work group on last iteration
|
||||
if (i == loop - 1) {
|
||||
CHECK_HIP(hipEventRecord(stop_events_timed[wg_id], streams[wg_id]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
num_msgs = (loop + args.skip) * num_teams;
|
||||
num_timed_msgs = loop * num_teams;
|
||||
}
|
||||
|
||||
void TeamAlltoallmemOnStreamTester::verifyResults(size_t size) {
|
||||
// Verify correctness: after alltoall, PE i should receive from PE j
|
||||
// the block that PE j sent to PE i
|
||||
// PE j sends block i (containing value j * n_pes + i) to PE i
|
||||
// Support multiple work groups (teams)
|
||||
int idx = 0;
|
||||
|
||||
for (int wg_id = 0; wg_id < num_teams; wg_id++) {
|
||||
for (int j = 0; j < n_pes; j++) {
|
||||
int expected_value = j * n_pes + my_pe;
|
||||
idx = (wg_id * n_pes + j) * size;
|
||||
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
if (static_cast<unsigned char>(dest_buf[idx + k]) !=
|
||||
static_cast<unsigned char>(expected_value)) {
|
||||
std::cerr << "PE " << my_pe << ": Verification failed for WG "
|
||||
<< wg_id << ", block from PE " << j << " at byte " << k
|
||||
<< std::endl;
|
||||
std::cerr << "Expected value: " << expected_value
|
||||
<< ", Got: " << static_cast<int>(dest_buf[idx + k])
|
||||
<< std::endl;
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _TEAM_ALLTOALLMEM_ON_STREAM_TESTER_HPP_
|
||||
#define _TEAM_ALLTOALLMEM_ON_STREAM_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
#include <vector>
|
||||
#include <hip/hip_runtime.h>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class TeamAlltoallmemOnStreamTester : public Tester {
|
||||
public:
|
||||
explicit TeamAlltoallmemOnStreamTester(TesterArguments args);
|
||||
virtual ~TeamAlltoallmemOnStreamTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void preLaunchKernel() override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void postLaunchKernel() override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
private:
|
||||
char *source_buf;
|
||||
char *dest_buf;
|
||||
int my_pe;
|
||||
int n_pes;
|
||||
size_t buf_size;
|
||||
int num_teams = 1;
|
||||
std::vector<rocshmem_team_t> team_world_dup;
|
||||
std::vector<hipStream_t> streams;
|
||||
std::vector<hipEvent_t> start_events_timed;
|
||||
std::vector<hipEvent_t> stop_events_timed;
|
||||
};
|
||||
|
||||
#include "team_alltoallmem_on_stream_tester.cpp"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
rocshmem_team_t team_barrier_world_dup;
|
||||
|
||||
/******************************************************************************
|
||||
* Device TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void TeamBarrierTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time,
|
||||
ShmemContextType ctx_type, TestType type,
|
||||
int wf_size, rocshmem_team_t *teams) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
int t_id = get_flat_block_id();
|
||||
int wg_id = get_flat_grid_id();
|
||||
int wf_id = t_id / wf_size;
|
||||
|
||||
rocshmem_wg_team_create_ctx(teams[wg_id], ctx_type, &ctx);
|
||||
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (i == skip && hipThreadIdx_x == 0) {
|
||||
start_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case TeamBarrierTestType:
|
||||
if(t_id == 0) {
|
||||
rocshmem_ctx_barrier(ctx, teams[wg_id]);
|
||||
}
|
||||
break;
|
||||
case TeamWAVEBarrierTestType:
|
||||
if(wf_id == 0) {
|
||||
rocshmem_ctx_barrier_wave(ctx, teams[wg_id]);
|
||||
}
|
||||
break;
|
||||
case TeamWGBarrierTestType:
|
||||
rocshmem_ctx_barrier_wg(ctx, teams[wg_id]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
__syncthreads();
|
||||
}
|
||||
|
||||
if (hipThreadIdx_x == 0) {
|
||||
end_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
rocshmem_wg_ctx_destroy(&ctx);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
TeamBarrierTester::TeamBarrierTester(TesterArguments args)
|
||||
: Tester(args){
|
||||
my_pe = rocshmem_team_my_pe(ROCSHMEM_TEAM_WORLD);
|
||||
n_pes = rocshmem_team_n_pes(ROCSHMEM_TEAM_WORLD);
|
||||
|
||||
char* value{nullptr};
|
||||
if ((value = getenv("ROCSHMEM_MAX_NUM_TEAMS"))) {
|
||||
num_teams = atoi(value);
|
||||
}
|
||||
|
||||
CHECK_HIP(hipMalloc(&team_barrier_world_dup,
|
||||
sizeof(rocshmem_team_t) * num_teams));
|
||||
}
|
||||
|
||||
TeamBarrierTester::~TeamBarrierTester() {
|
||||
CHECK_HIP(hipFree(team_barrier_world_dup));
|
||||
}
|
||||
|
||||
void TeamBarrierTester::preLaunchKernel() {
|
||||
for (int team_i = 0; team_i < num_teams; team_i++) {
|
||||
team_barrier_world_dup[team_i] = ROCSHMEM_TEAM_INVALID;
|
||||
rocshmem_team_split_strided(ROCSHMEM_TEAM_WORLD, 0, 1, n_pes, nullptr, 0,
|
||||
&team_barrier_world_dup[team_i]);
|
||||
if (team_barrier_world_dup[team_i] == ROCSHMEM_TEAM_INVALID) {
|
||||
printf("Team %d is invalid!\n", team_i);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TeamBarrierTester::launchKernel(dim3 gridSize, dim3 blockSize,
|
||||
int loop, size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
hipLaunchKernelGGL(TeamBarrierTest, gridSize, blockSize, shared_bytes,
|
||||
stream, loop, args.skip, start_time, end_time,
|
||||
_shmem_context, _type, wf_size,
|
||||
team_barrier_world_dup);
|
||||
|
||||
num_msgs = (loop + args.skip) * gridSize.x;
|
||||
num_timed_msgs = loop * gridSize.x;
|
||||
}
|
||||
|
||||
void TeamBarrierTester::postLaunchKernel() {
|
||||
for (int team_i = 0; team_i < num_teams; team_i++) {
|
||||
rocshmem_team_destroy(team_barrier_world_dup[team_i]);
|
||||
}
|
||||
}
|
||||
|
||||
void TeamBarrierTester::resetBuffers(size_t size) {}
|
||||
|
||||
void TeamBarrierTester::verifyResults(size_t size) {}
|
||||
@@ -0,0 +1,68 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _TEAM_BARRIER_TESTER_HPP_
|
||||
#define _TEAM_BARRIER_TESTER_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/************* *****************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class TeamBarrierTester : public Tester {
|
||||
public:
|
||||
explicit TeamBarrierTester(TesterArguments args);
|
||||
virtual ~TeamBarrierTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void preLaunchKernel() override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void postLaunchKernel() override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
private:
|
||||
int my_pe = 0;
|
||||
int n_pes = 0;
|
||||
/**
|
||||
* This constant should equal ROCSHMEM_MAX_NUM_TEAMS - 1.
|
||||
* The default value for the maximum number of teams is 40.
|
||||
*/
|
||||
int num_teams = 39;
|
||||
rocshmem_team_t *team_barrier_world_dup;
|
||||
};
|
||||
|
||||
#include "team_barrier_tester.cpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,243 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/* Declare the template with a generic implementation */
|
||||
template <typename T>
|
||||
__device__ void wg_team_broadcast(rocshmem_ctx_t ctx, rocshmem_team_t team,
|
||||
T *dest, const T *source, int nelem,
|
||||
int pe_root) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Define templates to call ROCSHMEM */
|
||||
#define TEAM_BROADCAST_DEF_GEN(T, TNAME) \
|
||||
template <> \
|
||||
__device__ void wg_team_broadcast<T>( \
|
||||
rocshmem_ctx_t ctx, rocshmem_team_t team, T * dest, const T *source, \
|
||||
int nelem, int pe_root) { \
|
||||
rocshmem_ctx_##TNAME##_broadcast_wg(ctx, team, dest, source, nelem, \
|
||||
pe_root); \
|
||||
}
|
||||
|
||||
TEAM_BROADCAST_DEF_GEN(float, float)
|
||||
TEAM_BROADCAST_DEF_GEN(double, double)
|
||||
TEAM_BROADCAST_DEF_GEN(char, char)
|
||||
// TEAM_BROADCAST_DEF_GEN(long double, longdouble)
|
||||
TEAM_BROADCAST_DEF_GEN(signed char, schar)
|
||||
TEAM_BROADCAST_DEF_GEN(short, short)
|
||||
TEAM_BROADCAST_DEF_GEN(int, int)
|
||||
TEAM_BROADCAST_DEF_GEN(long, long)
|
||||
TEAM_BROADCAST_DEF_GEN(long long, longlong)
|
||||
TEAM_BROADCAST_DEF_GEN(unsigned char, uchar)
|
||||
TEAM_BROADCAST_DEF_GEN(unsigned short, ushort)
|
||||
TEAM_BROADCAST_DEF_GEN(unsigned int, uint)
|
||||
TEAM_BROADCAST_DEF_GEN(unsigned long, ulong)
|
||||
TEAM_BROADCAST_DEF_GEN(unsigned long long, ulonglong)
|
||||
|
||||
rocshmem_team_t team_bcast_world_dup;
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
template <typename T1>
|
||||
__global__ void TeamBroadcastTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, T1 *source_buf,
|
||||
T1 *dest_buf, int size,
|
||||
ShmemContextType ctx_type,
|
||||
rocshmem_team_t *teams) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
int wg_id = get_flat_grid_id();
|
||||
|
||||
rocshmem_wg_team_create_ctx(teams[wg_id], ctx_type, &ctx);
|
||||
|
||||
int n_pes = rocshmem_ctx_n_pes(ctx);
|
||||
source_buf += wg_id * size;
|
||||
dest_buf += wg_id * size;
|
||||
|
||||
__syncthreads();
|
||||
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (i == skip && hipThreadIdx_x == 0) {
|
||||
start_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
wg_team_broadcast<T1>(ctx, teams[wg_id],
|
||||
dest_buf, // T* dest
|
||||
source_buf, // const T* source
|
||||
size, // int nelement
|
||||
0); // int PE_root
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
if (hipThreadIdx_x == 0) {
|
||||
end_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
rocshmem_wg_ctx_destroy(&ctx);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
template <typename T1>
|
||||
TeamBroadcastTester<T1>::TeamBroadcastTester(TesterArguments args)
|
||||
: Tester(args){
|
||||
my_pe = rocshmem_team_my_pe(ROCSHMEM_TEAM_WORLD);
|
||||
n_pes = rocshmem_team_n_pes(ROCSHMEM_TEAM_WORLD);
|
||||
|
||||
// Total number of elements in src buffer
|
||||
int total_elems = (args.max_msg_size / sizeof(T1)) * args.num_wgs ;
|
||||
int buff_size = total_elems * sizeof(T1);
|
||||
|
||||
source_buf = (T1 *)rocshmem_malloc(buff_size);
|
||||
dest_buf = (T1 *)rocshmem_malloc(buff_size);
|
||||
|
||||
if (source_buf == nullptr || dest_buf == nullptr) {
|
||||
std::cout << "Error allocating memory from symmetric heap" << std::endl;
|
||||
std::cout << "source: " << source_buf << ", dest: " << dest_buf << std::endl;
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
|
||||
char* value{nullptr};
|
||||
if ((value = getenv("ROCSHMEM_MAX_NUM_TEAMS"))) {
|
||||
num_teams = atoi(value);
|
||||
}
|
||||
|
||||
CHECK_HIP(hipMalloc(&team_bcast_world_dup,
|
||||
sizeof(rocshmem_team_t) * num_teams));
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
TeamBroadcastTester<T1>::~TeamBroadcastTester() {
|
||||
rocshmem_free(source_buf);
|
||||
rocshmem_free(dest_buf);
|
||||
CHECK_HIP(hipFree(team_bcast_world_dup));
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
void TeamBroadcastTester<T1>::preLaunchKernel() {
|
||||
for (int team_i = 0; team_i < num_teams; team_i++) {
|
||||
team_bcast_world_dup[team_i] = ROCSHMEM_TEAM_INVALID;
|
||||
rocshmem_team_split_strided(ROCSHMEM_TEAM_WORLD, 0, 1, n_pes, nullptr, 0,
|
||||
&team_bcast_world_dup[team_i]);
|
||||
if (team_bcast_world_dup[team_i] == ROCSHMEM_TEAM_INVALID) {
|
||||
printf("Team %d is invalid!\n", team_i);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
void TeamBroadcastTester<T1>::launchKernel(dim3 gridSize, dim3 blockSize,
|
||||
int loop, size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
int num_elems = size / sizeof(T1);
|
||||
|
||||
hipLaunchKernelGGL(TeamBroadcastTest<T1>, gridSize, blockSize,
|
||||
shared_bytes, stream, loop, args.skip,
|
||||
start_time, end_time, source_buf, dest_buf,
|
||||
num_elems, _shmem_context, team_bcast_world_dup);
|
||||
|
||||
num_msgs = (loop + args.skip) * gridSize.x;
|
||||
num_timed_msgs = loop * gridSize.x;
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
void TeamBroadcastTester<T1>::postLaunchKernel() {
|
||||
for (int team_i = 0; team_i < num_teams; team_i++) {
|
||||
rocshmem_team_destroy(team_bcast_world_dup[team_i]);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
void TeamBroadcastTester<T1>::resetBuffers(size_t size) {
|
||||
|
||||
int num_elems = size / sizeof(T1);
|
||||
int buff_size = num_elems * sizeof(T1) * args.num_wgs;
|
||||
int idx = 0;
|
||||
|
||||
for (int wg_id = 0; wg_id < args.num_wgs; wg_id++) {
|
||||
for (int i = 0; i < num_elems; i++) {
|
||||
idx = wg_id * num_elems + i;
|
||||
if constexpr (std::is_same<T1, char>::value ||
|
||||
std::is_same<T1, signed char>::value ||
|
||||
std::is_same<T1, unsigned char>::value) {
|
||||
source_buf[idx] = static_cast<T1>('a' + n_pes + wg_id);
|
||||
dest_buf[idx] = static_cast<T1>('a' + wg_id);
|
||||
}
|
||||
else if constexpr (std::is_floating_point<T1>::value) {
|
||||
source_buf[idx] = static_cast<T1>(3.14 + n_pes + wg_id);
|
||||
dest_buf[idx] = static_cast<T1>(3.14 + wg_id);
|
||||
}
|
||||
else if constexpr (std::is_integral<T1>::value) {
|
||||
source_buf[idx] = static_cast<T1>(n_pes + wg_id);
|
||||
dest_buf[idx] = static_cast<T1>(wg_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
void TeamBroadcastTester<T1>::verifyResults(size_t size) {
|
||||
|
||||
int num_elems = size / sizeof(T1);
|
||||
int idx = 0;
|
||||
T1 expected;
|
||||
|
||||
/**
|
||||
* The verification routine here requires that the
|
||||
* PE_root value is 0 which denotes that the
|
||||
* sending processing element is rank 0.
|
||||
*
|
||||
* The difference in expected values arises from
|
||||
* the specification for broadcast where the
|
||||
* PE_root processing element does not copy the
|
||||
* contents from its own source to dest during
|
||||
* the broadcast.
|
||||
*/
|
||||
for (int wg_id = 0; wg_id < args.num_wgs; wg_id++) {
|
||||
for (int i = 0; i < num_elems; i++) {
|
||||
idx = wg_id * num_elems + i;
|
||||
if constexpr (std::is_same<T1, char>::value ||
|
||||
std::is_same<T1, signed char>::value ||
|
||||
std::is_same<T1, unsigned char>::value) {
|
||||
expected = static_cast<T1>('a' + wg_id + (my_pe ? n_pes : 0));
|
||||
}
|
||||
else if constexpr (std::is_floating_point<T1>::value) {
|
||||
expected = static_cast<T1>(3.14 + wg_id + (my_pe ? n_pes : 0));
|
||||
}
|
||||
else if constexpr (std::is_integral<T1>::value) {
|
||||
expected = static_cast<T1>(wg_id + (my_pe ? n_pes : 0));
|
||||
}
|
||||
if (dest_buf[idx] != expected) {
|
||||
std::cerr << "Data validation error at idx " << idx << std::endl;
|
||||
std::cerr << "PE " << my_pe << " Got " << dest_buf[idx]
|
||||
<< ", Expected " << expected << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _TEAM_BROADCAST_TESTER_HPP_
|
||||
#define _TEAM_BROADCAST_TESTER_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/************* *****************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
template <typename T1>
|
||||
class TeamBroadcastTester : public Tester {
|
||||
public:
|
||||
explicit TeamBroadcastTester(TesterArguments args);
|
||||
virtual ~TeamBroadcastTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void preLaunchKernel() override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void postLaunchKernel() override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
T1 *source_buf;
|
||||
T1 *dest_buf;
|
||||
|
||||
private:
|
||||
int my_pe = 0;
|
||||
int n_pes = 0;
|
||||
/**
|
||||
* This constant should equal ROCSHMEM_MAX_NUM_TEAMS - 1.
|
||||
* The default value for the maximum number of teams is 40.
|
||||
*/
|
||||
int num_teams = 39;
|
||||
rocshmem_team_t *team_bcast_world_dup;
|
||||
};
|
||||
|
||||
#include "team_broadcast_tester.cpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,240 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "team_broadcastmem_on_stream_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
TeamBroadcastmemOnStreamTester::TeamBroadcastmemOnStreamTester(TesterArguments args)
|
||||
: Tester(args) {
|
||||
my_pe = rocshmem_team_my_pe(ROCSHMEM_TEAM_WORLD);
|
||||
n_pes = rocshmem_team_n_pes(ROCSHMEM_TEAM_WORLD);
|
||||
|
||||
char* value{nullptr};
|
||||
if ((value = getenv("ROCSHMEM_TEST_MAX_NUM_TEAMS"))) {
|
||||
num_teams = atoi(value);
|
||||
} else {
|
||||
// Default to number of work groups
|
||||
num_teams = args.num_wgs;
|
||||
}
|
||||
|
||||
// Set root PE to 0 by default, can be modified via environment variable
|
||||
if ((value = getenv("ROCSHMEM_TEST_BROADCAST_ROOT"))) {
|
||||
pe_root = atoi(value);
|
||||
if (pe_root < 0 || pe_root >= n_pes) {
|
||||
std::cerr << "Invalid ROCSHMEM_TEST_BROADCAST_ROOT value. Using PE 0."
|
||||
<< std::endl;
|
||||
pe_root = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int num_bytes_wg = args.max_msg_size;
|
||||
int total_bytes = num_bytes_wg * num_teams;
|
||||
buf_size = total_bytes;
|
||||
|
||||
source_buf = static_cast<char *>(rocshmem_malloc(buf_size));
|
||||
dest_buf = static_cast<char *>(rocshmem_malloc(buf_size));
|
||||
|
||||
if (source_buf == nullptr || dest_buf == nullptr) {
|
||||
std::cerr << "Error allocating memory from symmetric heap" << std::endl;
|
||||
std::cerr << "source: " << source_buf << ", dest: " << dest_buf
|
||||
<< std::endl;
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
|
||||
team_world_dup.resize(num_teams);
|
||||
|
||||
streams.resize(num_teams);
|
||||
start_events_timed.resize(num_teams);
|
||||
stop_events_timed.resize(num_teams);
|
||||
for (int i = 0; i < num_teams; i++) {
|
||||
CHECK_HIP(hipStreamCreate(&streams[i]));
|
||||
CHECK_HIP(hipEventCreate(&start_events_timed[i]));
|
||||
CHECK_HIP(hipEventCreate(&stop_events_timed[i]));
|
||||
}
|
||||
}
|
||||
|
||||
TeamBroadcastmemOnStreamTester::~TeamBroadcastmemOnStreamTester() {
|
||||
for (int i = 0; i < num_teams; i++) {
|
||||
CHECK_HIP(hipEventDestroy(stop_events_timed[i]));
|
||||
CHECK_HIP(hipEventDestroy(start_events_timed[i]));
|
||||
CHECK_HIP(hipStreamDestroy(streams[i]));
|
||||
}
|
||||
rocshmem_free(source_buf);
|
||||
rocshmem_free(dest_buf);
|
||||
}
|
||||
|
||||
void TeamBroadcastmemOnStreamTester::preLaunchKernel() {
|
||||
bw_factor = 1; // Broadcast is one-to-all
|
||||
|
||||
for (int team_i = 0; team_i < num_teams; team_i++) {
|
||||
team_world_dup[team_i] = ROCSHMEM_TEAM_INVALID;
|
||||
rocshmem_team_split_strided(ROCSHMEM_TEAM_WORLD, 0, 1, n_pes, nullptr, 0,
|
||||
&team_world_dup[team_i]);
|
||||
if (team_world_dup[team_i] == ROCSHMEM_TEAM_INVALID) {
|
||||
std::cerr << "Team " << team_i << " is invalid!" << std::endl;
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TeamBroadcastmemOnStreamTester::postLaunchKernel() {
|
||||
// Synchronize all streams to ensure events are recorded
|
||||
for (int i = 0; i < num_teams; i++) {
|
||||
CHECK_HIP(hipStreamSynchronize(streams[i]));
|
||||
}
|
||||
|
||||
// Get elapsed time for each work group from HIP events
|
||||
for (int wg_id = 0; wg_id < num_teams && wg_id < num_timers; wg_id++) {
|
||||
float elapsed_time_ms = 0.0f;
|
||||
CHECK_HIP(hipEventElapsedTime(&elapsed_time_ms, start_events_timed[wg_id],
|
||||
stop_events_timed[wg_id]));
|
||||
|
||||
// Convert milliseconds to GPU cycles
|
||||
// wall_clk_rate is in kHz, so: cycles = ms * wall_clk_rate
|
||||
long long int elapsed_cycles = static_cast<long long int>(
|
||||
elapsed_time_ms * static_cast<float>(wall_clk_rate));
|
||||
|
||||
start_time[wg_id] = 0;
|
||||
end_time[wg_id] = elapsed_cycles;
|
||||
}
|
||||
|
||||
// Fill remaining timers with zero if num_timers > num_teams
|
||||
for (int i = num_teams; i < num_timers; i++) {
|
||||
start_time[i] = 0;
|
||||
end_time[i] = 0;
|
||||
}
|
||||
|
||||
for (int team_i = 0; team_i < num_teams; team_i++) {
|
||||
rocshmem_team_destroy(team_world_dup[team_i]);
|
||||
}
|
||||
}
|
||||
|
||||
void TeamBroadcastmemOnStreamTester::resetBuffers(size_t size) {
|
||||
// Initialize source buffer on all PEs
|
||||
// Each work group has its own portion
|
||||
for (int wg_id = 0; wg_id < num_teams; wg_id++) {
|
||||
int idx = wg_id * size;
|
||||
if (my_pe == pe_root) {
|
||||
// Root PE fills its source buffer with broadcast value
|
||||
int value = (pe_root + 1) * 100 + wg_id;
|
||||
std::memset(source_buf + idx, value, size);
|
||||
} else {
|
||||
// Non-root PEs source buffer (not used in broadcast)
|
||||
std::memset(source_buf + idx, 0xFF, size);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize destination buffer on all PEs
|
||||
// Root PE keeps its initial dest value (broadcast doesn't copy to root's
|
||||
// dest) Non-root PEs set to 0 (will receive broadcast data)
|
||||
for (int wg_id = 0; wg_id < num_teams; wg_id++) {
|
||||
int idx = wg_id * size;
|
||||
if (my_pe == pe_root) {
|
||||
// Root PE's dest buffer stays with a different value
|
||||
int root_dest_value = 0xAA;
|
||||
std::memset(dest_buf + idx, root_dest_value, size);
|
||||
} else {
|
||||
std::memset(dest_buf + idx, 0, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TeamBroadcastmemOnStreamTester::launchKernel(dim3 gridSize,
|
||||
dim3 blockSize,
|
||||
int loop,
|
||||
size_t size) {
|
||||
// Execute warmup iterations (skip)
|
||||
for (int i = 0; i < args.skip; i++) {
|
||||
for (int wg_id = 0; wg_id < num_teams; wg_id++) {
|
||||
char *wg_source = source_buf + wg_id * size;
|
||||
char *wg_dest = dest_buf + wg_id * size;
|
||||
rocshmem_broadcastmem_on_stream(team_world_dup[wg_id], wg_dest,
|
||||
wg_source, size, pe_root, streams[wg_id]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_teams; i++) {
|
||||
CHECK_HIP(hipStreamSynchronize(streams[i]));
|
||||
}
|
||||
|
||||
for (int i = 0; i < loop; i++) {
|
||||
for (int wg_id = 0; wg_id < num_teams; wg_id++) {
|
||||
// Record start event for this work group on first iteration
|
||||
if (i == 0) {
|
||||
CHECK_HIP(hipEventRecord(start_events_timed[wg_id], streams[wg_id]));
|
||||
}
|
||||
|
||||
char *wg_source = source_buf + wg_id * size;
|
||||
char *wg_dest = dest_buf + wg_id * size;
|
||||
rocshmem_broadcastmem_on_stream(team_world_dup[wg_id], wg_dest,
|
||||
wg_source, size, pe_root, streams[wg_id]);
|
||||
|
||||
// Record stop event for this work group on last iteration
|
||||
if (i == loop - 1) {
|
||||
CHECK_HIP(hipEventRecord(stop_events_timed[wg_id], streams[wg_id]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
num_msgs = (loop + args.skip) * num_teams;
|
||||
num_timed_msgs = loop * num_teams;
|
||||
}
|
||||
|
||||
void TeamBroadcastmemOnStreamTester::verifyResults(size_t size) {
|
||||
// Verify correctness: after broadcast, non-root PEs receive the broadcast
|
||||
// data Root PE's dest buffer is NOT modified (per OpenSHMEM/rocSHMEM spec)
|
||||
for (int wg_id = 0; wg_id < num_teams; wg_id++) {
|
||||
int idx = wg_id * size;
|
||||
int expected_value;
|
||||
|
||||
if (my_pe == pe_root) {
|
||||
// Root PE's dest buffer should remain unchanged (0xAA)
|
||||
expected_value = 0xAA;
|
||||
} else {
|
||||
// Non-root PEs should have received the broadcast value
|
||||
expected_value = (pe_root + 1) * 100 + wg_id;
|
||||
}
|
||||
|
||||
for (size_t k = 0; k < size; k++) {
|
||||
if (static_cast<unsigned char>(dest_buf[idx + k]) !=
|
||||
static_cast<unsigned char>(expected_value)) {
|
||||
std::cerr << "PE " << my_pe << ": Verification failed for WG "
|
||||
<< wg_id << " at byte " << k << std::endl;
|
||||
std::cerr << "Expected value: " << expected_value
|
||||
<< ", Got: " << static_cast<int>(dest_buf[idx + k])
|
||||
<< std::endl;
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _TEAM_BROADCASTMEM_ON_STREAM_TESTER_HPP_
|
||||
#define _TEAM_BROADCASTMEM_ON_STREAM_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
#include <vector>
|
||||
#include <hip/hip_runtime.h>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class TeamBroadcastmemOnStreamTester : public Tester {
|
||||
public:
|
||||
explicit TeamBroadcastmemOnStreamTester(TesterArguments args);
|
||||
virtual ~TeamBroadcastmemOnStreamTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void preLaunchKernel() override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void postLaunchKernel() override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
private:
|
||||
char *source_buf;
|
||||
char *dest_buf;
|
||||
int my_pe;
|
||||
int n_pes;
|
||||
size_t buf_size;
|
||||
int num_teams = 1;
|
||||
int pe_root = 0; // Root PE for broadcast
|
||||
std::vector<rocshmem_team_t> team_world_dup;
|
||||
std::vector<hipStream_t> streams;
|
||||
std::vector<hipEvent_t> start_events_timed;
|
||||
std::vector<hipEvent_t> stop_events_timed;
|
||||
};
|
||||
|
||||
#include "team_broadcastmem_on_stream_tester.cpp"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,273 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "team_ctx_infra_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/* this constant should equal ROCSHMEM_MAX_NUM_TEAMS-1 */
|
||||
#define NUM_TEAMS 39
|
||||
|
||||
rocshmem_team_t team_world_dup[NUM_TEAMS];
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void TeamCtxInfraSimpleTest(ShmemContextType ctx_type,
|
||||
rocshmem_team_t team,
|
||||
int expected_pe, int expected_n_pes) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
|
||||
rocshmem_wg_team_create_ctx(team, ctx_type, &ctx);
|
||||
|
||||
int num_pes = rocshmem_ctx_n_pes(ctx);
|
||||
int my_pe = rocshmem_ctx_my_pe(ctx);
|
||||
|
||||
if (my_pe != expected_pe) {
|
||||
printf("PE doesn't match. Expected %d got %d\n", expected_pe, my_pe);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (num_pes != expected_n_pes) {
|
||||
printf("Team size doesn't match. Expected %d got %d\n", expected_n_pes, num_pes);
|
||||
abort();
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
rocshmem_ctx_quiet(ctx);
|
||||
rocshmem_wg_ctx_destroy(&ctx);
|
||||
}
|
||||
|
||||
__global__ void TeamCtxInfraTest(ShmemContextType ctx_type,
|
||||
rocshmem_team_t *team) {
|
||||
__shared__ rocshmem_ctx_t ctx1, ctx2, ctx3;
|
||||
__shared__ rocshmem_ctx_t ctx[NUM_TEAMS];
|
||||
|
||||
|
||||
/**
|
||||
* Test 1: Assert team infos of different ctxs
|
||||
* from the same team are the same.
|
||||
*/
|
||||
|
||||
rocshmem_wg_team_create_ctx(team[0], ctx_type, &ctx1);
|
||||
if (nullptr == ctx1.ctx_opaque) {
|
||||
printf("Create ctx1 on team[0] returned an invalid context!\n");
|
||||
abort();
|
||||
}
|
||||
rocshmem_wg_team_create_ctx(team[0], ctx_type, &ctx2);
|
||||
if (nullptr == ctx2.ctx_opaque) {
|
||||
printf("Create ctx2 on team[0] returned an invalid context!\n");
|
||||
abort();
|
||||
}
|
||||
rocshmem_wg_ctx_destroy(&ctx1);
|
||||
rocshmem_wg_team_create_ctx(team[0], ctx_type, &ctx3);
|
||||
if (nullptr == ctx3.ctx_opaque) {
|
||||
printf("Create ctx3 on team[0] returned an invalid context!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
if (ctx3.team_opaque != ctx2.team_opaque) {
|
||||
printf("Incorrect for teams of ctx2 and ctx3 to be different!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
rocshmem_wg_ctx_destroy(&ctx2);
|
||||
rocshmem_wg_ctx_destroy(&ctx3);
|
||||
|
||||
__syncthreads();
|
||||
|
||||
/**
|
||||
* Test 2: Assert team infos of different ctxs
|
||||
* from different teams are different.
|
||||
*/
|
||||
for (int team_i = 0; team_i < NUM_TEAMS; team_i++) {
|
||||
rocshmem_wg_team_create_ctx(team[team_i], ctx_type, &ctx[team_i]);
|
||||
if (nullptr == ctx[team_i].ctx_opaque) {
|
||||
printf("Create ctx on team[%d] returned an invalid context!\n", team_i);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx[0].team_opaque == ctx[NUM_TEAMS - 1].team_opaque) {
|
||||
printf("Incorrect for teams of ctx[0] and ctx[NUM_TEAMS-1] to be equal to each other\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
for (int team_i = 0; team_i < NUM_TEAMS; team_i++) {
|
||||
rocshmem_wg_ctx_destroy(&ctx[team_i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
TeamCtxInfraTester::TeamCtxInfraTester(TesterArguments args) : Tester(args) {
|
||||
_splitType = args.team_type;
|
||||
}
|
||||
|
||||
TeamCtxInfraTester::~TeamCtxInfraTester() {}
|
||||
|
||||
void TeamCtxInfraTester::resetBuffers(size_t size) {}
|
||||
|
||||
void TeamCtxInfraTester::preLaunchKernel() {
|
||||
int n_pes = rocshmem_team_n_pes(_parentTeam);
|
||||
int my_pe = rocshmem_team_my_pe(_parentTeam);
|
||||
|
||||
if (_splitType == ROCSHMEM_TEST_TEAM_DUP) {
|
||||
// validate we can run the test
|
||||
if (auto maximum_num_contexts_str = getenv("ROCSHMEM_MAX_NUM_CONTEXTS")) {
|
||||
int max_ctx = atoi(maximum_num_contexts_str);
|
||||
if (max_ctx <= NUM_TEAMS) {
|
||||
printf("ROCSHMEM_MAX_NUM_CONTEXTS=%d is smaller than NUM_TEAMS %d, invalid test setup!\n", max_ctx, NUM_TEAMS);
|
||||
assert(max_ctx > NUM_TEAMS);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
for (int team_i = 0; team_i < NUM_TEAMS; team_i++) {
|
||||
team_world_dup[team_i] = ROCSHMEM_TEAM_INVALID;
|
||||
rocshmem_team_split_strided(_parentTeam, 0, 1, n_pes, nullptr, 0,
|
||||
&team_world_dup[team_i]);
|
||||
if (team_world_dup[team_i] == ROCSHMEM_TEAM_INVALID) {
|
||||
printf("Created team %d is invalid!\n", team_i);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/* Assert the failure of a new team creation. */
|
||||
rocshmem_team_t new_team = ROCSHMEM_TEAM_INVALID;
|
||||
rocshmem_team_split_strided(_parentTeam, 0, 1, n_pes, nullptr, 0,
|
||||
&new_team);
|
||||
if (new_team != ROCSHMEM_TEAM_INVALID) {
|
||||
printf("Created new team should have been invalid!\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
else if (_splitType == ROCSHMEM_TEST_TEAM_SINGLE) {
|
||||
rocshmem_team_split_strided(_parentTeam, my_pe, 1, 1, nullptr, 0,
|
||||
&team_world_dup[0]);
|
||||
_expected_pe = rocshmem_team_my_pe(team_world_dup[0]);
|
||||
_expected_n_pes = rocshmem_team_n_pes(team_world_dup[0]);
|
||||
|
||||
if (_expected_n_pes != 1) {
|
||||
printf("ROCSHMEM_TEST_TEAM_SINGLE: n_pes %d expected: 1\n", _expected_n_pes);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (_expected_pe != 0) {
|
||||
printf("ROCSHMEM_TEST_TEAM_SINGLE: my_pe %d expected: 0\n", _expected_pe);
|
||||
abort();
|
||||
}
|
||||
} else if (_splitType == ROCSHMEM_TEST_TEAM_BLOCK) {
|
||||
int mid_pe = n_pes / 2; // integer division
|
||||
int start_pe = my_pe < mid_pe ? 0 : mid_pe;
|
||||
int end_pe = my_pe < mid_pe ? (mid_pe - 1) : (n_pes - 1);
|
||||
int num_pes = end_pe - start_pe + 1;
|
||||
int new_pe = my_pe < mid_pe ? my_pe : (my_pe - start_pe);
|
||||
|
||||
rocshmem_team_split_strided(_parentTeam, start_pe, 1, num_pes, nullptr, 0,
|
||||
&team_world_dup[0]);
|
||||
_expected_pe = rocshmem_team_my_pe(team_world_dup[0]);
|
||||
_expected_n_pes = rocshmem_team_n_pes(team_world_dup[0]);
|
||||
|
||||
if (_expected_n_pes != num_pes) {
|
||||
printf("ROCSHMEM_TEST_TEAM_BLOCK: n_pes %d expected: %d\n", _expected_n_pes, num_pes);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (_expected_pe != new_pe) {
|
||||
printf("ROCSHMEM_TEST_TEAM_BLOCK: my_pe %d expected: %d\n", _expected_pe, new_pe);
|
||||
abort();
|
||||
}
|
||||
} else if (_splitType == ROCSHMEM_TEST_TEAM_ODDEVEN) {
|
||||
int start_pe = (my_pe % 2) == 0 ? 0 : 1;
|
||||
int num_pes = n_pes / 2;
|
||||
if (((n_pes % 2) != 0) && ((my_pe % 2) == 0))
|
||||
num_pes++;
|
||||
int new_pe = (my_pe / 2);
|
||||
|
||||
rocshmem_team_split_strided(_parentTeam, start_pe, 2, num_pes, nullptr, 0,
|
||||
&team_world_dup[0]);
|
||||
_expected_pe = rocshmem_team_my_pe(team_world_dup[0]);
|
||||
_expected_n_pes = rocshmem_team_n_pes(team_world_dup[0]);
|
||||
|
||||
if (_expected_n_pes != num_pes) {
|
||||
printf("ROCSHMEM_TEST_TEAM_ODDEVEN: n_pes %d expected: %d\n", _expected_n_pes, num_pes);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (_expected_pe != new_pe) {
|
||||
printf("ROCSHMEM_TEST_TEAM_ODDEVEN: my_pe %d expected: %d\n", _expected_pe, new_pe);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TeamCtxInfraTester::launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
/* Copy array of teams to device */
|
||||
rocshmem_team_t *teams_on_device;
|
||||
|
||||
if (_splitType == ROCSHMEM_TEST_TEAM_DUP) {
|
||||
CHECK_HIP(hipMalloc(&teams_on_device, sizeof(rocshmem_team_t) * NUM_TEAMS));
|
||||
CHECK_HIP(hipMemcpy(teams_on_device, team_world_dup,
|
||||
sizeof(rocshmem_team_t) * NUM_TEAMS, hipMemcpyHostToDevice));
|
||||
|
||||
hipLaunchKernelGGL(TeamCtxInfraTest, gridSize, blockSize, shared_bytes,
|
||||
stream, _shmem_context, teams_on_device);
|
||||
} else if (_splitType == ROCSHMEM_TEST_TEAM_SINGLE ||
|
||||
_splitType == ROCSHMEM_TEST_TEAM_BLOCK ||
|
||||
_splitType == ROCSHMEM_TEST_TEAM_ODDEVEN ) {
|
||||
CHECK_HIP(hipMalloc(&teams_on_device, sizeof(rocshmem_team_t)));
|
||||
CHECK_HIP(hipMemcpy(teams_on_device, team_world_dup,
|
||||
sizeof(rocshmem_team_t), hipMemcpyHostToDevice));
|
||||
|
||||
hipLaunchKernelGGL(TeamCtxInfraSimpleTest, gridSize, blockSize, shared_bytes,
|
||||
stream, _shmem_context, teams_on_device[0], _expected_pe, _expected_n_pes);
|
||||
}
|
||||
|
||||
CHECK_HIP(hipFree(teams_on_device));
|
||||
}
|
||||
|
||||
void TeamCtxInfraTester::postLaunchKernel() {
|
||||
int num_teams = _splitType == ROCSHMEM_TEST_TEAM_DUP ? NUM_TEAMS : 1;
|
||||
for (int team_i = 0; team_i < num_teams; team_i++) {
|
||||
rocshmem_team_destroy(team_world_dup[team_i]);
|
||||
}
|
||||
}
|
||||
|
||||
void TeamCtxInfraTester::verifyResults(size_t size) {}
|
||||
@@ -0,0 +1,59 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _TEAM_CTX_INFRA_TESTER_HPP_
|
||||
#define _TEAM_CTX_INFRA_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class TeamCtxInfraTester : public Tester {
|
||||
public:
|
||||
explicit TeamCtxInfraTester(TesterArguments args);
|
||||
virtual ~TeamCtxInfraTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void preLaunchKernel() override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void postLaunchKernel() override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
char *s_buf = nullptr;
|
||||
char *r_buf = nullptr;
|
||||
|
||||
TeamSplitType _splitType;
|
||||
rocshmem::rocshmem_team_t _parentTeam = rocshmem::ROCSHMEM_TEAM_WORLD;
|
||||
int _expected_pe;
|
||||
int _expected_n_pes;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,196 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "team_ctx_primitive_tester.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
rocshmem_team_t team_primitive_world_dup;
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void TeamCtxPrimitiveTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, char *source,
|
||||
char *dest, size_t size, TestType type,
|
||||
ShmemContextType ctx_type, int wf_size,
|
||||
rocshmem_team_t team) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
int wg_id = get_flat_grid_id();
|
||||
int t_id = get_flat_block_id();
|
||||
int wf_id = t_id / wf_size;
|
||||
|
||||
rocshmem_wg_team_create_ctx(team, ctx_type, &ctx);
|
||||
|
||||
/**
|
||||
* Shared array to capture the start time for each wavefront
|
||||
* Max threads per block = 1024, wavefront size = 64 or 32 depending
|
||||
* on the GPUs. Using 32 since its safer for the dimensioning of the array,
|
||||
* the last 16 elements will not be used on GPUs with a wf size of 64.
|
||||
* Maximum array size required = 1024/32 = 32
|
||||
*/
|
||||
__shared__ long long int wf_start_time[32];
|
||||
|
||||
/**
|
||||
* Calculate start index for each thread within the grid
|
||||
*/
|
||||
size_t offset = size * get_flat_id();
|
||||
source += offset;
|
||||
dest += offset;
|
||||
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (i == skip) {
|
||||
__syncthreads();
|
||||
// Ensures all RMA calls from the skip loops are completed
|
||||
if(is_thread_zero_in_block()) {
|
||||
rocshmem_ctx_quiet(ctx);
|
||||
}
|
||||
__syncthreads();
|
||||
// Capture the start time of each wavefront to identify the earliest one
|
||||
wf_start_time[wf_id] = wall_clock64();
|
||||
}
|
||||
switch (type) {
|
||||
case TeamCtxGetTestType:
|
||||
rocshmem_ctx_getmem(ctx, dest, source, size, 1);
|
||||
break;
|
||||
case TeamCtxGetNBITestType:
|
||||
rocshmem_ctx_getmem_nbi(ctx, dest, source, size, 1);
|
||||
break;
|
||||
case TeamCtxPutTestType:
|
||||
rocshmem_ctx_putmem(ctx, dest, source, size, 1);
|
||||
break;
|
||||
case TeamCtxPutNBITestType:
|
||||
rocshmem_ctx_putmem_nbi(ctx, dest, source, size, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
if(is_thread_zero_in_block()) {
|
||||
rocshmem_ctx_quiet(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* End time of the last wavefront is recorded by overwriting
|
||||
* the value previously set by earlier wavefronts.
|
||||
*/
|
||||
end_time[wg_id] = wall_clock64();
|
||||
|
||||
// Find the earliest start time
|
||||
int num_wfs = (get_flat_block_size() - 1 ) / wf_size + 1;
|
||||
for (int i = num_wfs / 2; i > 0; i >>= 1 ) {
|
||||
if(t_id < i) {
|
||||
wf_start_time[t_id] = min(wf_start_time[t_id], wf_start_time[t_id + i]);
|
||||
}
|
||||
}
|
||||
__syncthreads();
|
||||
|
||||
if (t_id == 0) {
|
||||
start_time[wg_id] = wf_start_time[0];
|
||||
}
|
||||
|
||||
rocshmem_wg_ctx_destroy(&ctx);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
TeamCtxPrimitiveTester::TeamCtxPrimitiveTester(TesterArguments args)
|
||||
: Tester(args) {
|
||||
size_t buff_size = args.max_msg_size * args.wg_size * args.num_wgs;
|
||||
source = (char *)rocshmem_malloc(buff_size);
|
||||
dest = (char *)rocshmem_malloc(buff_size);
|
||||
|
||||
if (source == nullptr || dest == nullptr) {
|
||||
std::cerr << "Error allocating memory from symmetric heap" << std::endl;
|
||||
std::cerr << "source: " << source << ", dest: " << dest << std::endl;
|
||||
if (source) {
|
||||
rocshmem_free(source);
|
||||
}
|
||||
if (dest) {
|
||||
rocshmem_free(dest);
|
||||
}
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < buff_size; i++) {
|
||||
source[i] = static_cast<char>('a' + i % 26);
|
||||
}
|
||||
}
|
||||
|
||||
TeamCtxPrimitiveTester::~TeamCtxPrimitiveTester() {
|
||||
rocshmem_free(source);
|
||||
rocshmem_free(dest);
|
||||
}
|
||||
|
||||
void TeamCtxPrimitiveTester::resetBuffers(size_t size) {
|
||||
size_t buff_size = size * args.wg_size * args.num_wgs;
|
||||
memset(dest, '1', buff_size);
|
||||
}
|
||||
|
||||
void TeamCtxPrimitiveTester::preLaunchKernel() {
|
||||
int n_pes = rocshmem_team_n_pes(ROCSHMEM_TEAM_WORLD);
|
||||
|
||||
team_primitive_world_dup = ROCSHMEM_TEAM_INVALID;
|
||||
rocshmem_team_split_strided(ROCSHMEM_TEAM_WORLD, 0, 1, n_pes, nullptr, 0,
|
||||
&team_primitive_world_dup);
|
||||
}
|
||||
|
||||
void TeamCtxPrimitiveTester::launchKernel(dim3 gridSize, dim3 blockSize,
|
||||
int loop, size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
hipLaunchKernelGGL(TeamCtxPrimitiveTest, gridSize, blockSize, shared_bytes,
|
||||
stream, loop, args.skip, start_time, end_time, source,
|
||||
dest, size, _type, _shmem_context, wf_size,
|
||||
team_primitive_world_dup);
|
||||
|
||||
num_msgs = (loop + args.skip) * gridSize.x * blockSize.x;
|
||||
num_timed_msgs = loop * gridSize.x * blockSize.x;
|
||||
}
|
||||
|
||||
void TeamCtxPrimitiveTester::postLaunchKernel() {
|
||||
rocshmem_team_destroy(team_primitive_world_dup);
|
||||
}
|
||||
|
||||
void TeamCtxPrimitiveTester::verifyResults(size_t size) {
|
||||
int check_id =
|
||||
(_type == TeamCtxGetTestType || _type == TeamCtxGetNBITestType) ? 0 : 1;
|
||||
|
||||
if (args.myid == check_id) {
|
||||
size_t buff_size = size * args.wg_size * args.num_wgs;
|
||||
for (uint64_t i = 0; i < buff_size; i++) {
|
||||
if (dest[i] != source[i]) {
|
||||
std::cerr << "Data validation error at idx " << i << std::endl;
|
||||
std::cerr << " Got " << dest[i] << ", Expected "
|
||||
<< source[i] << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _TEAM_CTX_PRIMITIVE_TESTER_HPP_
|
||||
#define _TEAM_CTX_PRIMITIVE_TESTER_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class TeamCtxPrimitiveTester : public Tester {
|
||||
public:
|
||||
explicit TeamCtxPrimitiveTester(TesterArguments args);
|
||||
virtual ~TeamCtxPrimitiveTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void preLaunchKernel() override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void postLaunchKernel() override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
char *source = nullptr;
|
||||
char *dest = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,232 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/* Declare the template with a generic implementation */
|
||||
template <typename T>
|
||||
__device__ void wg_team_fcollect(rocshmem_ctx_t ctx, rocshmem_team_t team,
|
||||
T *dest, const T *source, int nelems) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Define templates to call rocSHMEM */
|
||||
#define TEAM_FCOLLECT_DEF_GEN(T, TNAME) \
|
||||
template <> \
|
||||
__device__ void wg_team_fcollect<T>(rocshmem_ctx_t ctx, rocshmem_team_t team,\
|
||||
T * dest, const T *source, int nelem) { \
|
||||
rocshmem_ctx_##TNAME##_fcollect_wg(ctx, team, dest, source, nelem); \
|
||||
}
|
||||
|
||||
TEAM_FCOLLECT_DEF_GEN(float, float)
|
||||
TEAM_FCOLLECT_DEF_GEN(double, double)
|
||||
TEAM_FCOLLECT_DEF_GEN(char, char)
|
||||
// TEAM_FCOLLECT_DEF_GEN(long double, longdouble)
|
||||
TEAM_FCOLLECT_DEF_GEN(signed char, schar)
|
||||
TEAM_FCOLLECT_DEF_GEN(short, short)
|
||||
TEAM_FCOLLECT_DEF_GEN(int, int)
|
||||
TEAM_FCOLLECT_DEF_GEN(long, long)
|
||||
TEAM_FCOLLECT_DEF_GEN(long long, longlong)
|
||||
TEAM_FCOLLECT_DEF_GEN(unsigned char, uchar)
|
||||
TEAM_FCOLLECT_DEF_GEN(unsigned short, ushort)
|
||||
TEAM_FCOLLECT_DEF_GEN(unsigned int, uint)
|
||||
TEAM_FCOLLECT_DEF_GEN(unsigned long, ulong)
|
||||
TEAM_FCOLLECT_DEF_GEN(unsigned long long, ulonglong)
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
template <typename T1>
|
||||
__global__ void TeamFcollectTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, T1 *source_buf,
|
||||
T1 *dest_buf, int num_elems,
|
||||
ShmemContextType ctx_type,
|
||||
rocshmem_team_t *teams) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
int wg_id = get_flat_grid_id();
|
||||
|
||||
rocshmem_wg_team_create_ctx(teams[wg_id], ctx_type, &ctx);
|
||||
|
||||
int n_pes = rocshmem_ctx_n_pes(ctx);
|
||||
source_buf += wg_id * num_elems;
|
||||
dest_buf += wg_id * num_elems * n_pes;
|
||||
|
||||
__syncthreads();
|
||||
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (i == skip && hipThreadIdx_x == 0) {
|
||||
start_time[wg_id] = wall_clock64();
|
||||
}
|
||||
wg_team_fcollect<T1>(ctx, teams[wg_id],
|
||||
dest_buf, // T* dest
|
||||
source_buf, // const T* source
|
||||
num_elems); // int nelement
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
if (hipThreadIdx_x == 0) {
|
||||
end_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
rocshmem_wg_ctx_destroy(&ctx);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
template <typename T1>
|
||||
TeamFcollectTester<T1>::TeamFcollectTester(TesterArguments args)
|
||||
: Tester(args) {
|
||||
my_pe = rocshmem_team_my_pe(ROCSHMEM_TEAM_WORLD);
|
||||
n_pes = rocshmem_team_n_pes(ROCSHMEM_TEAM_WORLD);
|
||||
|
||||
// Total number of elements in src buffer
|
||||
int total_elems = (args.max_msg_size / sizeof(T1)) * args.num_wgs ;
|
||||
int buff_size = total_elems * sizeof(T1);
|
||||
|
||||
source_buf = (T1 *)rocshmem_malloc(buff_size);
|
||||
dest_buf = (T1 *)rocshmem_malloc(buff_size * n_pes);
|
||||
|
||||
if (source_buf == nullptr || dest_buf == nullptr) {
|
||||
std::cout << "Error allocating memory from symmetric heap" << std::endl;
|
||||
std::cout << "source: " << source_buf
|
||||
<< ", dest: " << dest_buf
|
||||
<< std::endl;
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
|
||||
if constexpr (std::is_same<T1, char>::value ||
|
||||
std::is_same<T1, signed char>::value ||
|
||||
std::is_same<T1, unsigned char>::value) {
|
||||
for (int i = 0; i < total_elems; ++i) {
|
||||
source_buf[i] = static_cast<T1>('a' + my_pe);
|
||||
}
|
||||
}
|
||||
else if constexpr (std::is_floating_point<T1>::value) {
|
||||
for (int i = 0; i < total_elems; ++i) {
|
||||
source_buf[i] = static_cast<T1>(3.14 + my_pe);
|
||||
}
|
||||
}
|
||||
else if constexpr (std::is_integral<T1>::value) {
|
||||
for (int i = 0; i < total_elems; i++) {
|
||||
source_buf[i] = static_cast<T1>(my_pe);
|
||||
}
|
||||
}
|
||||
|
||||
char* value{nullptr};
|
||||
if ((value = getenv("ROCSHMEM_MAX_NUM_TEAMS"))) {
|
||||
num_teams = atoi(value);
|
||||
}
|
||||
|
||||
CHECK_HIP(hipMalloc(&team_fcollect_world_dup,
|
||||
sizeof(rocshmem_team_t) * num_teams));
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
TeamFcollectTester<T1>::~TeamFcollectTester() {
|
||||
rocshmem_free(source_buf);
|
||||
rocshmem_free(dest_buf);
|
||||
CHECK_HIP(hipFree(team_fcollect_world_dup));
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
void TeamFcollectTester<T1>::preLaunchKernel() {
|
||||
bw_factor = n_pes;
|
||||
|
||||
for (int team_i = 0; team_i < num_teams; team_i++) {
|
||||
team_fcollect_world_dup[team_i] = ROCSHMEM_TEAM_INVALID;
|
||||
rocshmem_team_split_strided(ROCSHMEM_TEAM_WORLD, 0, 1, n_pes, nullptr, 0,
|
||||
&team_fcollect_world_dup[team_i]);
|
||||
if (team_fcollect_world_dup[team_i] == ROCSHMEM_TEAM_INVALID) {
|
||||
std::cout << "Team " << team_i << " is invalid!" << std::endl;
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
void TeamFcollectTester<T1>::launchKernel(dim3 gridSize, dim3 blockSize,
|
||||
int loop, size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
int num_elems = size / sizeof(T1);
|
||||
|
||||
int my_pe = rocshmem_team_my_pe(ROCSHMEM_TEAM_WORLD);
|
||||
int n_pes = rocshmem_team_n_pes(ROCSHMEM_TEAM_WORLD);
|
||||
|
||||
hipLaunchKernelGGL(TeamFcollectTest<T1>, gridSize, blockSize, shared_bytes,
|
||||
stream, loop, args.skip, start_time, end_time,
|
||||
source_buf, dest_buf, num_elems, _shmem_context,
|
||||
team_fcollect_world_dup);
|
||||
|
||||
num_msgs = (loop + args.skip) * gridSize.x;
|
||||
num_timed_msgs = loop * gridSize.x;
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
void TeamFcollectTester<T1>::postLaunchKernel() {
|
||||
for (int team_i = 0; team_i < num_teams; team_i++) {
|
||||
rocshmem_team_destroy(team_fcollect_world_dup[team_i]);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
void TeamFcollectTester<T1>::resetBuffers(size_t size) {
|
||||
int num_elems = (size / sizeof(T1));
|
||||
int buff_size = num_elems * sizeof(T1) * args.num_wgs * n_pes;
|
||||
|
||||
memset(dest_buf, -1, buff_size);
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
void TeamFcollectTester<T1>::verifyResults(size_t size) {
|
||||
|
||||
int num_elems = size / sizeof(T1);
|
||||
int idx = 0;
|
||||
T1 expected;
|
||||
|
||||
for(int wg_id = 0; wg_id < args.num_wgs; wg_id++) {
|
||||
for(int pe = 0; pe < n_pes; pe++) {
|
||||
for(int i = 0; i < num_elems; i++) {
|
||||
idx = (wg_id * n_pes + pe) * num_elems + i;
|
||||
if constexpr (std::is_same<T1, char>::value ||
|
||||
std::is_same<T1, signed char>::value ||
|
||||
std::is_same<T1, unsigned char>::value) {
|
||||
expected = static_cast<T1>('a' + pe);
|
||||
}
|
||||
else if constexpr (std::is_floating_point<T1>::value) {
|
||||
expected = static_cast<T1>(3.14 + pe);
|
||||
}
|
||||
else if constexpr (std::is_integral<T1>::value) {
|
||||
expected = pe;
|
||||
}
|
||||
if (dest_buf[idx] != expected) {
|
||||
std::cerr << "Data validation error at idx " << idx << std::endl;
|
||||
std::cerr << "PE " << my_pe << " Got " << dest_buf[idx]
|
||||
<< ", Expected " << expected << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _TEAM_FCOLLECT_TESTER_HPP_
|
||||
#define _TEAM_FCOLLECT_TESTER_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/************* *****************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
template <typename T1>
|
||||
class TeamFcollectTester : public Tester {
|
||||
public:
|
||||
explicit TeamFcollectTester(TesterArguments args);
|
||||
virtual ~TeamFcollectTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void preLaunchKernel() override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void postLaunchKernel() override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
T1 *source_buf;
|
||||
T1 *dest_buf;
|
||||
|
||||
private:
|
||||
int my_pe = 0;
|
||||
int n_pes = 0;
|
||||
/**
|
||||
* This constant should equal ROCSHMEM_MAX_NUM_TEAMS - 1.
|
||||
* The default value for the maximum number of teams is 40.
|
||||
*/
|
||||
int num_teams = 39;
|
||||
rocshmem_team_t *team_fcollect_world_dup;
|
||||
};
|
||||
|
||||
#include "team_fcollect_tester.cpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,172 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/* Declare the template with a generic implementation */
|
||||
template <typename T, ROCSHMEM_OP Op>
|
||||
__device__ int wg_team_reduce(rocshmem_ctx_t ctx, rocshmem_team_t, T *dest,
|
||||
const T *source, int nreduce) {
|
||||
return ROCSHMEM_SUCCESS;
|
||||
}
|
||||
|
||||
/* Define templates to call rocSHMEM */
|
||||
#define TEAM_REDUCTION_DEF_GEN(T, TNAME, Op_API, Op) \
|
||||
template <> \
|
||||
__device__ int wg_team_reduce<T, Op>(rocshmem_ctx_t ctx, \
|
||||
rocshmem_team_t team, T * dest, \
|
||||
const T *source, int nreduce) { \
|
||||
return rocshmem_ctx_##TNAME##_##Op_API##_reduce_wg(ctx, team, dest, \
|
||||
source, nreduce); \
|
||||
}
|
||||
|
||||
#define TEAM_ARITH_REDUCTION_DEF_GEN(T, TNAME) \
|
||||
TEAM_REDUCTION_DEF_GEN(T, TNAME, sum, ROCSHMEM_SUM) \
|
||||
TEAM_REDUCTION_DEF_GEN(T, TNAME, min, ROCSHMEM_MIN) \
|
||||
TEAM_REDUCTION_DEF_GEN(T, TNAME, max, ROCSHMEM_MAX) \
|
||||
TEAM_REDUCTION_DEF_GEN(T, TNAME, prod, ROCSHMEM_PROD)
|
||||
|
||||
#define TEAM_BITWISE_REDUCTION_DEF_GEN(T, TNAME) \
|
||||
TEAM_REDUCTION_DEF_GEN(T, TNAME, or, ROCSHMEM_OR) \
|
||||
TEAM_REDUCTION_DEF_GEN(T, TNAME, and, ROCSHMEM_AND) \
|
||||
TEAM_REDUCTION_DEF_GEN(T, TNAME, xor, ROCSHMEM_XOR)
|
||||
|
||||
#define TEAM_INT_REDUCTION_DEF_GEN(T, TNAME) \
|
||||
TEAM_ARITH_REDUCTION_DEF_GEN(T, TNAME) \
|
||||
TEAM_BITWISE_REDUCTION_DEF_GEN(T, TNAME)
|
||||
|
||||
#define TEAM_FLOAT_REDUCTION_DEF_GEN(T, TNAME) \
|
||||
TEAM_ARITH_REDUCTION_DEF_GEN(T, TNAME)
|
||||
|
||||
TEAM_INT_REDUCTION_DEF_GEN(int, int)
|
||||
TEAM_INT_REDUCTION_DEF_GEN(short, short)
|
||||
TEAM_INT_REDUCTION_DEF_GEN(long, long)
|
||||
TEAM_INT_REDUCTION_DEF_GEN(long long, longlong)
|
||||
TEAM_FLOAT_REDUCTION_DEF_GEN(float, float)
|
||||
TEAM_FLOAT_REDUCTION_DEF_GEN(double, double)
|
||||
// long double reduction fails. hipcc/device may not support long double.
|
||||
// so disable it for now.
|
||||
// FLOAT_REDUCTION_DEF_GEN(long double, longdouble)
|
||||
|
||||
rocshmem_team_t team_reduce_world_dup;
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
template <typename T1, ROCSHMEM_OP T2>
|
||||
__global__ void TeamReductionTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time, T1 *s_buf, T1 *r_buf,
|
||||
size_t size, TestType type,
|
||||
ShmemContextType ctx_type,
|
||||
rocshmem_team_t team) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
int wg_id = get_flat_grid_id();
|
||||
|
||||
rocshmem_wg_team_create_ctx(team, ctx_type, &ctx);
|
||||
|
||||
int n_pes = rocshmem_ctx_n_pes(ctx);
|
||||
|
||||
__syncthreads();
|
||||
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (i == skip && hipThreadIdx_x == 0) {
|
||||
start_time[wg_id] = wall_clock64();
|
||||
}
|
||||
wg_team_reduce<T1, T2>(ctx, team, r_buf, s_buf, size);
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
if (hipThreadIdx_x == 0) {
|
||||
end_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
rocshmem_wg_ctx_destroy(&ctx);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
template <typename T1, ROCSHMEM_OP T2>
|
||||
TeamReductionTester<T1, T2>::TeamReductionTester(
|
||||
TesterArguments args, std::function<void(T1 &, T1 &)> f1,
|
||||
std::function<std::pair<bool, std::string>(const T1 &, const T1 &)> f2)
|
||||
: Tester(args), init_buf{f1}, verify_buf{f2} {
|
||||
s_buf = (T1 *)rocshmem_malloc(args.max_msg_size * sizeof(T1));
|
||||
r_buf = (T1 *)rocshmem_malloc(args.max_msg_size * sizeof(T1));
|
||||
}
|
||||
|
||||
template <typename T1, ROCSHMEM_OP T2>
|
||||
TeamReductionTester<T1, T2>::~TeamReductionTester() {
|
||||
rocshmem_free(s_buf);
|
||||
rocshmem_free(r_buf);
|
||||
}
|
||||
|
||||
template <typename T1, ROCSHMEM_OP T2>
|
||||
void TeamReductionTester<T1, T2>::preLaunchKernel() {
|
||||
int n_pes = rocshmem_team_n_pes(ROCSHMEM_TEAM_WORLD);
|
||||
|
||||
team_reduce_world_dup = ROCSHMEM_TEAM_INVALID;
|
||||
rocshmem_team_split_strided(ROCSHMEM_TEAM_WORLD, 0, 1, n_pes, nullptr, 0,
|
||||
&team_reduce_world_dup);
|
||||
}
|
||||
|
||||
template <typename T1, ROCSHMEM_OP T2>
|
||||
void TeamReductionTester<T1, T2>::launchKernel(dim3 gridSize, dim3 blockSize,
|
||||
int loop, size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
hipLaunchKernelGGL(HIP_KERNEL_NAME(TeamReductionTest<T1, T2>), gridSize,
|
||||
blockSize, shared_bytes, stream, loop, args.skip,
|
||||
start_time, end_time, s_buf, r_buf, size, _type,
|
||||
_shmem_context, team_reduce_world_dup);
|
||||
|
||||
num_msgs = loop + args.skip;
|
||||
num_timed_msgs = loop;
|
||||
}
|
||||
|
||||
template <typename T1, ROCSHMEM_OP T2>
|
||||
void TeamReductionTester<T1, T2>::postLaunchKernel() {
|
||||
rocshmem_team_destroy(team_reduce_world_dup);
|
||||
}
|
||||
|
||||
template <typename T1, ROCSHMEM_OP T2>
|
||||
void TeamReductionTester<T1, T2>::resetBuffers(size_t size) {
|
||||
for (uint64_t i = 0; i < args.max_msg_size; i++) {
|
||||
init_buf(s_buf[i], r_buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, ROCSHMEM_OP T2>
|
||||
void TeamReductionTester<T1, T2>::verifyResults(size_t size) {
|
||||
int n_pes = rocshmem_n_pes();
|
||||
for (uint64_t i = 0; i < size; i++) {
|
||||
auto r = verify_buf(r_buf[i], (T1)n_pes);
|
||||
if (r.first == false) {
|
||||
fprintf(stderr, "Data validation error at idx %lu\n", i);
|
||||
fprintf(stderr, "%s.\n", r.second.c_str());
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _TEAM_REDUCTION_TESTER_HPP_
|
||||
#define _TEAM_REDUCTION_TESTER_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
template <typename T1, ROCSHMEM_OP T2>
|
||||
class TeamReductionTester : public Tester {
|
||||
public:
|
||||
explicit TeamReductionTester(
|
||||
TesterArguments args, std::function<void(T1 &, T1 &)> f1,
|
||||
std::function<std::pair<bool, std::string>(const T1 &, const T1 &)> f2);
|
||||
virtual ~TeamReductionTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void preLaunchKernel() override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void postLaunchKernel() override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
T1 *s_buf;
|
||||
T1 *r_buf;
|
||||
T1 *pWrk;
|
||||
long *pSync;
|
||||
|
||||
private:
|
||||
std::function<void(T1 &, T1 &)> init_buf;
|
||||
std::function<std::pair<bool, std::string>(const T1 &, const T1 &)>
|
||||
verify_buf;
|
||||
};
|
||||
|
||||
#include "team_reduction_tester.cpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,124 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void TeamSyncTest(int loop, int skip, long long int *start_time,
|
||||
long long int *end_time,
|
||||
ShmemContextType ctx_type, TestType type,
|
||||
int wf_size, rocshmem_team_t *teams) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
int t_id = get_flat_block_id();
|
||||
int wg_id = get_flat_grid_id();
|
||||
int wf_id = t_id / wf_size;
|
||||
|
||||
rocshmem_wg_team_create_ctx(teams[wg_id], ctx_type, &ctx);
|
||||
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (i == skip && hipThreadIdx_x == 0) {
|
||||
start_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case TeamSyncTestType:
|
||||
if(t_id == 0) {
|
||||
rocshmem_ctx_sync(ctx, teams[wg_id]);
|
||||
}
|
||||
break;
|
||||
case TeamWAVESyncTestType:
|
||||
if(wf_id == 0) {
|
||||
rocshmem_ctx_sync_wave(ctx, teams[wg_id]);
|
||||
}
|
||||
break;
|
||||
case TeamWGSyncTestType:
|
||||
rocshmem_ctx_sync_wg(ctx, teams[wg_id]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
__syncthreads();
|
||||
}
|
||||
|
||||
if (hipThreadIdx_x == 0) {
|
||||
end_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
rocshmem_wg_ctx_destroy(&ctx);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
TeamSyncTester::TeamSyncTester(TesterArguments args) : Tester(args) {
|
||||
my_pe = rocshmem_team_my_pe(ROCSHMEM_TEAM_WORLD);
|
||||
n_pes = rocshmem_team_n_pes(ROCSHMEM_TEAM_WORLD);
|
||||
|
||||
char* value{nullptr};
|
||||
if ((value = getenv("ROCSHMEM_MAX_NUM_TEAMS"))) {
|
||||
num_teams = atoi(value);
|
||||
}
|
||||
|
||||
CHECK_HIP(hipMalloc(&team_sync_world_dup,
|
||||
sizeof(rocshmem_team_t) * num_teams));
|
||||
}
|
||||
|
||||
TeamSyncTester::~TeamSyncTester() {
|
||||
CHECK_HIP(hipFree(team_sync_world_dup));
|
||||
}
|
||||
|
||||
void TeamSyncTester::preLaunchKernel() {
|
||||
for (int team_i = 0; team_i < num_teams; team_i++) {
|
||||
team_sync_world_dup[team_i] = ROCSHMEM_TEAM_INVALID;
|
||||
rocshmem_team_split_strided(ROCSHMEM_TEAM_WORLD, 0, 1, n_pes, nullptr, 0,
|
||||
&team_sync_world_dup[team_i]);
|
||||
if (team_sync_world_dup[team_i] == ROCSHMEM_TEAM_INVALID) {
|
||||
printf("Team %d is invalid!\n", team_i);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TeamSyncTester::launchKernel(dim3 gridSize, dim3 blockSize,
|
||||
int loop, size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
hipLaunchKernelGGL(TeamSyncTest, gridSize, blockSize, shared_bytes,
|
||||
stream, loop, args.skip, start_time, end_time,
|
||||
_shmem_context, _type, wf_size,
|
||||
team_sync_world_dup);
|
||||
|
||||
num_msgs = (loop + args.skip) * gridSize.x;
|
||||
num_timed_msgs = loop * gridSize.x;
|
||||
}
|
||||
|
||||
void TeamSyncTester::postLaunchKernel() {
|
||||
for (int team_i = 0; team_i < num_teams; team_i++) {
|
||||
rocshmem_team_destroy(team_sync_world_dup[team_i]);
|
||||
}
|
||||
}
|
||||
|
||||
void TeamSyncTester::resetBuffers(size_t size) {}
|
||||
|
||||
void TeamSyncTester::verifyResults(size_t size) {}
|
||||
@@ -0,0 +1,68 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _TEAM_SYNC_TESTER_HPP_
|
||||
#define _TEAM_SYNC_TESTER_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class TeamSyncTester : public Tester {
|
||||
public:
|
||||
explicit TeamSyncTester(TesterArguments args);
|
||||
virtual ~TeamSyncTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void preLaunchKernel() override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void postLaunchKernel() override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
private:
|
||||
int my_pe = 0;
|
||||
int n_pes = 0;
|
||||
/**
|
||||
* This constant should equal ROCSHMEM_MAX_NUM_TEAMS - 1.
|
||||
* The default value for the maximum number of teams is 40.
|
||||
*/
|
||||
int num_teams = 39;
|
||||
rocshmem_team_t *team_sync_world_dup;
|
||||
};
|
||||
|
||||
#include "team_sync_tester.cpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,231 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 <rocshmem/rocshmem.hpp>
|
||||
#include <vector>
|
||||
|
||||
#include "tester.hpp"
|
||||
#include "tester_arguments.hpp"
|
||||
|
||||
#if defined(HAVE_PMIX)
|
||||
#include <pmix.h>
|
||||
|
||||
static pmix_proc_t pmix_myproc;
|
||||
static pmix_proc_t pmix_proc;
|
||||
|
||||
static void init_pmix(int *rank, int *nranks)
|
||||
{
|
||||
pmix_status_t rc;
|
||||
pmix_value_t *val;
|
||||
|
||||
if (PMIX_SUCCESS != (rc = PMIx_Init(&pmix_myproc, NULL, 0))) {
|
||||
std::cerr << "Rank " << pmix_myproc.rank << " PMIx_Init failed: " << rc << std::endl;
|
||||
abort();
|
||||
}
|
||||
#ifdef VERBOSE
|
||||
printf("Client ns %s rank %d: Running\n", pmix_myproc.nspace, pmix_myproc.rank);
|
||||
#endif
|
||||
PMIX_PROC_CONSTRUCT(&pmix_proc);
|
||||
PMIX_LOAD_PROCID(&pmix_proc, pmix_myproc.nspace, PMIX_RANK_WILDCARD);
|
||||
|
||||
/* get our job size */
|
||||
if (PMIX_SUCCESS != (rc = PMIx_Get(&pmix_proc, PMIX_JOB_SIZE, NULL, 0, &val))) {
|
||||
std::cerr << "Rank " << pmix_myproc.rank << " PMIx_Get universe size failed: "
|
||||
<< rc << std::endl;
|
||||
abort();
|
||||
}
|
||||
|
||||
*nranks = val->data.uint32;
|
||||
*rank = pmix_myproc.rank;
|
||||
|
||||
PMIX_VALUE_RELEASE(val);
|
||||
return;
|
||||
}
|
||||
|
||||
static void pmix_bcast(void *buf, size_t nbytes, char *key, int root)
|
||||
{
|
||||
pmix_status_t rc;
|
||||
pmix_value_t value;
|
||||
pmix_value_t *val;
|
||||
pmix_info_t *info;
|
||||
bool flag;
|
||||
|
||||
if (pmix_myproc.rank == root) {
|
||||
value.type = PMIX_BYTE_OBJECT;
|
||||
value.data.bo.bytes = (char *) (buf);
|
||||
value.data.bo.size = nbytes;
|
||||
|
||||
rc = PMIx_Put(PMIX_GLOBAL, key, &value);
|
||||
if (PMIX_SUCCESS != rc) {
|
||||
std::cerr << "Rank " << pmix_myproc.rank << " PMIx_Put failed: " << rc << std::endl;
|
||||
abort();
|
||||
}
|
||||
|
||||
/* push the data to our PMIx server */
|
||||
if (PMIX_SUCCESS != (rc = PMIx_Commit())) {
|
||||
std::cerr << "Rank " << pmix_myproc.rank << " PMIx_Commit failed: " << rc << std::endl;
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/* call fence to synchronize with our peers - instruct
|
||||
* the fence operation to collect and return all "put"
|
||||
* data from our peers */
|
||||
PMIX_INFO_CREATE(info, 1);
|
||||
flag = true;
|
||||
PMIX_INFO_LOAD(info, PMIX_COLLECT_DATA, &flag, PMIX_BOOL);
|
||||
if (PMIX_SUCCESS != (rc = PMIx_Fence(&pmix_proc, 1, info, 1))) {
|
||||
std::cerr << "Rank " << pmix_myproc.rank << " PMIx_Fence failed: " << rc << std::endl;
|
||||
abort();
|
||||
}
|
||||
PMIX_INFO_FREE(info, 1);
|
||||
|
||||
pmix_proc.rank = 0;
|
||||
if (PMIX_SUCCESS != (rc = PMIx_Get(&pmix_proc, key, NULL, 0, &val))) {
|
||||
std::cerr << "Rank " << pmix_myproc.rank << " PMIx_Get failed: " << rc << std::endl;
|
||||
abort();
|
||||
}
|
||||
if (PMIX_BYTE_OBJECT != val->type) {
|
||||
std::cerr << "Rank " << pmix_myproc.rank << " PMIx_Get returned wrong type: " << val->type << std::endl;
|
||||
PMIX_VALUE_RELEASE(val);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (pmix_myproc.rank != root) {
|
||||
if (NULL == val->data.bo.bytes) {
|
||||
std::cerr << "Rank " << pmix_myproc.rank << " PMIx_Get %d returned NULL pointer\n";
|
||||
PMIX_VALUE_RELEASE(val);
|
||||
abort();
|
||||
}
|
||||
memcpy (buf, val->data.bo.bytes, val->data.bo.size);
|
||||
}
|
||||
PMIX_VALUE_RELEASE(val);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
/**
|
||||
* Setup the tester arguments.
|
||||
*/
|
||||
TesterArguments args(argc, argv);
|
||||
|
||||
/***
|
||||
* Select a GPU
|
||||
*/
|
||||
char* ompi_local_rank = getenv("OMPI_COMM_WORLD_LOCAL_RANK");
|
||||
if (nullptr == ompi_local_rank) {
|
||||
printf("Could not determine local rank, use Open MPI `mpiexec`\n");
|
||||
abort();
|
||||
}
|
||||
CHECK_HIP(hipSetDevice(atoi(ompi_local_rank)));
|
||||
|
||||
/**
|
||||
* Must initialize rocshmem to access arguments needed by the tester.
|
||||
*/
|
||||
#ifdef HAVE_PMIX
|
||||
int test_uuid = 0;
|
||||
char *rocshmem_test_uuid = getenv("ROCSHMEM_TEST_UUID");
|
||||
if (rocshmem_test_uuid != nullptr) {
|
||||
test_uuid = atoi(rocshmem_test_uuid);
|
||||
}
|
||||
|
||||
if (test_uuid) {
|
||||
int ret;
|
||||
int rank, nranks;
|
||||
rocshmem_uniqueid_t uid;
|
||||
rocshmem_init_attr_t attr;
|
||||
|
||||
init_pmix(&rank, &nranks);
|
||||
if (rank == 0) {
|
||||
ret = rocshmem_get_uniqueid (&uid);
|
||||
if (ret != ROCSHMEM_SUCCESS) {
|
||||
std::cout << rank << ": Error in rocshmem_get_uniqueid. Aborting.\n";
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
char key[] = "rocshmem-uuid";
|
||||
pmix_bcast(&uid, sizeof(rocshmem_uniqueid_t), key, 0);
|
||||
|
||||
// Close PMIx before potentially doing MPI_Init inside rocshmem_init
|
||||
PMIx_Finalize(NULL, 0);
|
||||
|
||||
ret = rocshmem_set_attr_uniqueid_args(rank, nranks, &uid, &attr);
|
||||
if (ret != ROCSHMEM_SUCCESS) {
|
||||
std::cout << rank << ": Error in rocshmem_set_attr_uniqueid_args. Aborting.\n";
|
||||
abort();
|
||||
}
|
||||
|
||||
ret = rocshmem_init_attr(ROCSHMEM_INIT_WITH_UNIQUEID, &attr);
|
||||
if (ret != ROCSHMEM_SUCCESS) {
|
||||
std::cout << rank << ": Error in rocshmem_init_attr. Aborting.\n";
|
||||
abort();
|
||||
}
|
||||
|
||||
#ifdef VERBOSE
|
||||
std::cout << rank << ": rocshmem_init_attr SUCCESS\n";
|
||||
#endif
|
||||
} else {
|
||||
rocshmem_init();
|
||||
}
|
||||
#else
|
||||
rocshmem_init();
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Now grab the arguments from rocshmem.
|
||||
*/
|
||||
args.get_arguments();
|
||||
|
||||
/**
|
||||
* Using the arguments we just constructed, call the tester factory
|
||||
* method to get the tester (specified by the arguments).
|
||||
*/
|
||||
std::vector<Tester *> tests = Tester::create(args);
|
||||
|
||||
/**
|
||||
* Run the tests
|
||||
*/
|
||||
for (auto test : tests) {
|
||||
test->execute();
|
||||
|
||||
/**
|
||||
* The tester factory method news the tester to create it so we clean
|
||||
* up the memory here.
|
||||
*/
|
||||
delete test;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rocshmem library needs to be cleaned up with this call. It pairs
|
||||
* with the init function above.
|
||||
*/
|
||||
rocshmem_finalize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,771 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "tester.hpp"
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
#include <vector>
|
||||
|
||||
#include "amo_bitwise_tester.hpp"
|
||||
#include "amo_extended_tester.hpp"
|
||||
#include "amo_standard_tester.hpp"
|
||||
#include "default_ctx_primitive_tester.hpp"
|
||||
#include "barrier_all_tester.hpp"
|
||||
#include "barrier_all_on_stream_tester.hpp"
|
||||
#include "empty_tester.hpp"
|
||||
#include "getmem_on_stream_tester.hpp"
|
||||
#include "putmem_on_stream_tester.hpp"
|
||||
#include "putmem_signal_on_stream_tester.hpp"
|
||||
#include "signal_wait_until_on_stream_tester.hpp"
|
||||
#include "ping_all_tester.hpp"
|
||||
#include "ping_pong_tester.hpp"
|
||||
#include "primitive_mr_tester.hpp"
|
||||
#include "primitive_tester.hpp"
|
||||
#include "random_access_tester.hpp"
|
||||
#include "shmem_ptr_tester.hpp"
|
||||
#include "signaling_operations_tester.hpp"
|
||||
#include "sync_all_tester.hpp"
|
||||
#include "team_sync_tester.hpp"
|
||||
#include "team_alltoall_tester.hpp"
|
||||
#include "team_alltoallmem_on_stream_tester.hpp"
|
||||
#include "team_broadcastmem_on_stream_tester.hpp"
|
||||
#include "team_barrier_tester.hpp"
|
||||
#include "team_broadcast_tester.hpp"
|
||||
#include "team_ctx_infra_tester.hpp"
|
||||
#include "team_ctx_primitive_tester.hpp"
|
||||
#include "team_fcollect_tester.hpp"
|
||||
#include "team_reduction_tester.hpp"
|
||||
#include "wavefront_primitives.hpp"
|
||||
#include "workgroup_primitives.hpp"
|
||||
#include "flood_tester.hpp"
|
||||
|
||||
#include "backend_bc.hpp"
|
||||
extern Backend* backend;
|
||||
|
||||
Tester::Tester(TesterArguments args) : args(args) {
|
||||
_type = (TestType)args.algorithm;
|
||||
_shmem_context = args.shmem_context;
|
||||
CHECK_HIP(hipGetDevice(&device_id));
|
||||
CHECK_HIP(hipGetDeviceProperties(&deviceProps, device_id));
|
||||
wf_size = deviceProps.warpSize;
|
||||
num_warps = (args.wg_size - 1) / wf_size + 1;
|
||||
CHECK_HIP(hipStreamCreate(&stream));
|
||||
CHECK_HIP(hipEventCreate(&start_event));
|
||||
CHECK_HIP(hipEventCreate(&stop_event));
|
||||
CHECK_HIP(hipDeviceGetAttribute(&wall_clk_rate,
|
||||
hipDeviceAttributeWallClockRate, device_id));
|
||||
num_timers = args.num_wgs;
|
||||
switch (_type) {
|
||||
case WAVEGetTestType:
|
||||
case WAVEGetNBITestType:
|
||||
case WAVEPutTestType:
|
||||
case WAVEPutNBITestType:
|
||||
num_timers = args.num_wgs * num_warps;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
CHECK_HIP(hipMalloc((void**)&timer, sizeof(long long int) * num_timers));
|
||||
CHECK_HIP(hipMalloc((void**)&start_time, sizeof(long long int) * num_timers));
|
||||
CHECK_HIP(hipMalloc((void**)&end_time, sizeof(long long int) * num_timers));
|
||||
CHECK_HIP(hipHostMalloc((void**)&verification_error, sizeof(bool)));
|
||||
*verification_error = false;
|
||||
}
|
||||
|
||||
Tester::~Tester() {
|
||||
CHECK_HIP(hipFree(end_time));
|
||||
CHECK_HIP(hipFree(start_time));
|
||||
CHECK_HIP(hipFree(timer));
|
||||
CHECK_HIP(hipEventDestroy(stop_event));
|
||||
CHECK_HIP(hipEventDestroy(start_event));
|
||||
CHECK_HIP(hipStreamDestroy(stream));
|
||||
CHECK_HIP(hipFree(verification_error));
|
||||
}
|
||||
|
||||
std::vector<Tester*> Tester::create(TesterArguments args) {
|
||||
int rank = args.myid;
|
||||
std::vector<Tester*> testers;
|
||||
|
||||
if (rank == 0) std::cout << "### Creating Test: ";
|
||||
|
||||
BackendType backend_type = get_backend_type();
|
||||
TestType type = (TestType)args.algorithm;
|
||||
|
||||
switch (type) {
|
||||
case InitTestType:
|
||||
if (rank == 0) std::cout << "Init ###" << std::endl;
|
||||
testers.push_back(new EmptyTester(args));
|
||||
return testers;
|
||||
case GetTestType:
|
||||
if (rank == 0) std::cout << "Blocking Gets ###" << std::endl;
|
||||
testers.push_back(new PrimitiveTester(args));
|
||||
return testers;
|
||||
case GetNBITestType:
|
||||
if (rank == 0) std::cout << "Non-Blocking Gets ###" << std::endl;
|
||||
testers.push_back(new PrimitiveTester(args));
|
||||
return testers;
|
||||
case PutTestType:
|
||||
if (rank == 0) std::cout << "Blocking Puts ###" << std::endl;
|
||||
testers.push_back(new PrimitiveTester(args));
|
||||
return testers;
|
||||
case PutNBITestType:
|
||||
if (rank == 0) std::cout << "Non-Blocking Puts ###" << std::endl;
|
||||
testers.push_back(new PrimitiveTester(args));
|
||||
return testers;
|
||||
case DefaultCTXGetTestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Default context Blocking Gets ###" << std::endl;
|
||||
testers.push_back(new DefaultCTXPrimitiveTester(args));
|
||||
return testers;
|
||||
case DefaultCTXGetNBITestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Default context Non-Blocking Gets ###" << std::endl;
|
||||
testers.push_back(new DefaultCTXPrimitiveTester(args));
|
||||
return testers;
|
||||
case DefaultCTXPutTestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Default context Blocking Puts ###" << std::endl;
|
||||
testers.push_back(new DefaultCTXPrimitiveTester(args));
|
||||
return testers;
|
||||
case DefaultCTXPutNBITestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Default context Non-Blocking Puts ###" << std::endl;
|
||||
testers.push_back(new DefaultCTXPrimitiveTester(args));
|
||||
return testers;
|
||||
case TeamCtxInfraTestType:
|
||||
if (rank == 0) std::cout << "Team Ctx Infra test ###" << std::endl;
|
||||
testers.push_back(new TeamCtxInfraTester(args));
|
||||
return testers;
|
||||
case TeamCtxInfraTestSingleType:
|
||||
if (rank == 0) std::cout << "Team Ctx Infra Single test ###" << std::endl;
|
||||
args.team_type = ROCSHMEM_TEST_TEAM_SINGLE;
|
||||
testers.push_back(new TeamCtxInfraTester(args));
|
||||
return testers;
|
||||
case TeamCtxInfraTestBlockType:
|
||||
if (rank == 0) std::cout << "Team Ctx Infra Block test ###" << std::endl;
|
||||
args.team_type = ROCSHMEM_TEST_TEAM_BLOCK;
|
||||
testers.push_back(new TeamCtxInfraTester(args));
|
||||
return testers;
|
||||
case TeamCtxInfraTestOddEvenType:
|
||||
if (rank == 0) std::cout << "Team Ctx Infra Odd-Even test ###" << std::endl;
|
||||
args.team_type = ROCSHMEM_TEST_TEAM_ODDEVEN;
|
||||
testers.push_back(new TeamCtxInfraTester(args));
|
||||
return testers;
|
||||
case TeamCtxGetTestType:
|
||||
if (rank == 0) std::cout << "Blocking Team Ctx Gets ###" << std::endl;
|
||||
testers.push_back(new TeamCtxPrimitiveTester(args));
|
||||
return testers;
|
||||
case TeamCtxGetNBITestType:
|
||||
if (rank == 0) std::cout << "Non-Blocking Team Ctx Gets ###" << std::endl;
|
||||
testers.push_back(new TeamCtxPrimitiveTester(args));
|
||||
return testers;
|
||||
case TeamCtxPutTestType:
|
||||
if (rank == 0) std::cout << "Blocking Team Ctx Puts ###" << std::endl;
|
||||
testers.push_back(new TeamCtxPrimitiveTester(args));
|
||||
return testers;
|
||||
case TeamCtxPutNBITestType:
|
||||
if (rank == 0) std::cout << "Non-Blocking Team Ctx Puts ###" << std::endl;
|
||||
testers.push_back(new TeamCtxPrimitiveTester(args));
|
||||
return testers;
|
||||
case PTestType:
|
||||
if (rank == 0) std::cout << "P Test ###" << std::endl;
|
||||
testers.push_back(new PrimitiveTester(args));
|
||||
return testers;
|
||||
case GTestType:
|
||||
if (rank == 0) std::cout << "G Test ###" << std::endl;
|
||||
testers.push_back(new PrimitiveTester(args));
|
||||
return testers;
|
||||
case TeamReductionTestType:
|
||||
if (rank == 0)
|
||||
std::cout << "All-to-All Team-based Reduction ###" << std::endl;
|
||||
testers.push_back(new TeamReductionTester<float, ROCSHMEM_SUM>(
|
||||
args,
|
||||
[](float& f1, float& f2) {
|
||||
f1 = 1;
|
||||
f2 = 1;
|
||||
},
|
||||
[](float v, float n_pes) {
|
||||
return (v == n_pes)
|
||||
? std::make_pair(true, "")
|
||||
: std::make_pair(false, "Got " + std::to_string(v) +
|
||||
", Expect " +
|
||||
std::to_string(n_pes));
|
||||
}));
|
||||
return testers;
|
||||
case TeamBroadcastTestType:
|
||||
if (rank == 0) {
|
||||
std::cout << "Team Broadcast Test ###" << std::endl;
|
||||
}
|
||||
testers.push_back(new TeamBroadcastTester<int64_t>(args));
|
||||
testers.push_back(new TeamBroadcastTester<int>(args));
|
||||
testers.push_back(new TeamBroadcastTester<long long>(args));
|
||||
testers.push_back(new TeamBroadcastTester<float>(args));
|
||||
testers.push_back(new TeamBroadcastTester<double>(args));
|
||||
testers.push_back(new TeamBroadcastTester<char>(args));
|
||||
testers.push_back(new TeamBroadcastTester<unsigned char>(args));
|
||||
return testers;
|
||||
case TeamAllToAllTestType:
|
||||
if (rank == 0) {
|
||||
std::cout << "Alltoall Test ###" << std::endl;
|
||||
}
|
||||
testers.push_back(new TeamAlltoallTester<float>(args));
|
||||
return testers;
|
||||
case TeamAlltoallmemOnStreamTestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Alltoallmem_On_Stream ###" << std::endl;
|
||||
testers.push_back(new TeamAlltoallmemOnStreamTester(args));
|
||||
return testers;
|
||||
case BarrierAllOnStreamTestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Barrier_All_On_Stream ###" << std::endl;
|
||||
testers.push_back(new BarrierAllOnStreamTester(args));
|
||||
return testers;
|
||||
case TeamBroadcastmemOnStreamTestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Broadcastmem_On_Stream ###" << std::endl;
|
||||
testers.push_back(new TeamBroadcastmemOnStreamTester(args));
|
||||
return testers;
|
||||
case GetmemOnStreamTestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Getmem_On_Stream ###" << std::endl;
|
||||
testers.push_back(new GetmemOnStreamTester(args));
|
||||
return testers;
|
||||
case PutmemOnStreamTestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Putmem_On_Stream ###" << std::endl;
|
||||
testers.push_back(new PutmemOnStreamTester(args));
|
||||
return testers;
|
||||
case PutmemSignalOnStreamTestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Putmem_Signal_On_Stream ###" << std::endl;
|
||||
testers.push_back(new PutmemSignalOnStreamTester(args));
|
||||
return testers;
|
||||
case SignalWaitUntilOnStreamTestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Signal_Wait_Until_On_Stream ###" << std::endl;
|
||||
testers.push_back(new SignalWaitUntilOnStreamTester(args));
|
||||
return testers;
|
||||
case TeamFCollectTestType:
|
||||
if (rank == 0) {
|
||||
std::cout << "Fcollect Test ###" << std::endl;
|
||||
}
|
||||
testers.push_back(new TeamFcollectTester<int64_t>(args));
|
||||
testers.push_back(new TeamFcollectTester<int>(args));
|
||||
testers.push_back(new TeamFcollectTester<long long>(args));
|
||||
testers.push_back(new TeamFcollectTester<float>(args));
|
||||
testers.push_back(new TeamFcollectTester<double>(args));
|
||||
testers.push_back(new TeamFcollectTester<char>(args));
|
||||
testers.push_back(new TeamFcollectTester<unsigned char>(args));
|
||||
return testers;
|
||||
case AMO_FAddTestType:
|
||||
if (rank == 0) std::cout << "AMO Fetch_Add ###" << std::endl;
|
||||
testers.push_back(new AMOStandardTester<long long>(args));
|
||||
testers.push_back(new AMOStandardTester<long>(args));
|
||||
if (BackendType::GDA_BACKEND != backend_type) // not implemented for GDA
|
||||
testers.push_back(new AMOStandardTester<int>(args));
|
||||
return testers;
|
||||
case AMO_FIncTestType:
|
||||
if (rank == 0) std::cout << "AMO Fetch_Inc ###" << std::endl;
|
||||
testers.push_back(new AMOStandardTester<long long>(args));
|
||||
testers.push_back(new AMOStandardTester<long>(args));
|
||||
if (BackendType::GDA_BACKEND != backend_type) // not implemented for GDA
|
||||
testers.push_back(new AMOStandardTester<int>(args));
|
||||
return testers;
|
||||
case AMO_FetchTestType:
|
||||
if (rank == 0) std::cout << "AMO Fetch ###" << std::endl;
|
||||
testers.push_back(new AMOExtendedTester<long long>(args));
|
||||
testers.push_back(new AMOExtendedTester<long>(args));
|
||||
if (BackendType::GDA_BACKEND != backend_type) // not implemented for GDA
|
||||
testers.push_back(new AMOExtendedTester<int>(args));
|
||||
return testers;
|
||||
case AMO_FCswapTestType:
|
||||
if (rank == 0) std::cout << "AMO Fetch_CSWAP ###" << std::endl;
|
||||
testers.push_back(new AMOStandardTester<long long>(args));
|
||||
testers.push_back(new AMOStandardTester<long>(args));
|
||||
if (BackendType::GDA_BACKEND != backend_type) // not implemented for GDA
|
||||
testers.push_back(new AMOStandardTester<int>(args));
|
||||
return testers;
|
||||
case AMO_AddTestType:
|
||||
if (rank == 0) std::cout << "AMO Add ###" << std::endl;
|
||||
testers.push_back(new AMOStandardTester<long long>(args));
|
||||
testers.push_back(new AMOStandardTester<long>(args));
|
||||
if (BackendType::GDA_BACKEND != backend_type) // not implemented for GDA
|
||||
testers.push_back(new AMOStandardTester<int>(args));
|
||||
return testers;
|
||||
case AMO_SetTestType:
|
||||
if (rank == 0) std::cout << "AMO Set ###" << std::endl;
|
||||
testers.push_back(new AMOExtendedTester<long long>(args));
|
||||
testers.push_back(new AMOExtendedTester<long>(args));
|
||||
if (BackendType::GDA_BACKEND != backend_type) // not implemented for GDA
|
||||
testers.push_back(new AMOExtendedTester<int>(args));
|
||||
return testers;
|
||||
case AMO_SwapTestType:
|
||||
if (rank == 0) std::cout << "AMO Swap ###" << std::endl;
|
||||
testers.push_back(new AMOExtendedTester<long long>(args));
|
||||
testers.push_back(new AMOExtendedTester<long>(args));
|
||||
if (BackendType::GDA_BACKEND != backend_type) // not implemented for GDA
|
||||
testers.push_back(new AMOExtendedTester<int>(args));
|
||||
return testers;
|
||||
case AMO_FetchAndTestType:
|
||||
if (rank == 0) std::cout << "AMO Fetch And ###" << std::endl;
|
||||
testers.push_back(new AMOBitwiseTester<unsigned long long>(args));
|
||||
testers.push_back(new AMOBitwiseTester<unsigned long>(args));
|
||||
if (BackendType::GDA_BACKEND != backend_type) // not implemented for GDA
|
||||
testers.push_back(new AMOBitwiseTester<unsigned int>(args));
|
||||
return testers;
|
||||
case AMO_AndTestType:
|
||||
if (rank == 0) std::cout << "AMO And ###" << std::endl;
|
||||
testers.push_back(new AMOBitwiseTester<unsigned long long>(args));
|
||||
testers.push_back(new AMOBitwiseTester<unsigned long>(args));
|
||||
if (BackendType::GDA_BACKEND != backend_type) // not implemented for GDA
|
||||
testers.push_back(new AMOBitwiseTester<unsigned int>(args));
|
||||
return testers;
|
||||
case AMO_FetchOrTestType:
|
||||
if (rank == 0) std::cout << "AMO Fetch Or ###" << std::endl;
|
||||
testers.push_back(new AMOBitwiseTester<unsigned long long>(args));
|
||||
testers.push_back(new AMOBitwiseTester<unsigned long>(args));
|
||||
if (BackendType::GDA_BACKEND != backend_type) // not implemented for GDA
|
||||
testers.push_back(new AMOBitwiseTester<unsigned int>(args));
|
||||
return testers;
|
||||
case AMO_OrTestType:
|
||||
if (rank == 0) std::cout << "AMO Or ###" << std::endl;
|
||||
testers.push_back(new AMOBitwiseTester<unsigned long long>(args));
|
||||
testers.push_back(new AMOBitwiseTester<unsigned long>(args));
|
||||
if (BackendType::GDA_BACKEND != backend_type) // not implemented for GDA
|
||||
testers.push_back(new AMOBitwiseTester<unsigned int>(args));
|
||||
return testers;
|
||||
case AMO_FetchXorTestType:
|
||||
if (rank == 0) std::cout << "AMO Fetch Xor ###" << std::endl;
|
||||
testers.push_back(new AMOBitwiseTester<unsigned long long>(args));
|
||||
testers.push_back(new AMOBitwiseTester<unsigned long>(args));
|
||||
if (BackendType::GDA_BACKEND != backend_type) // not implemented for GDA
|
||||
testers.push_back(new AMOBitwiseTester<unsigned int>(args));
|
||||
return testers;
|
||||
case AMO_XorTestType:
|
||||
if (rank == 0) std::cout << "AMO Xor ###" << std::endl;
|
||||
testers.push_back(new AMOBitwiseTester<unsigned long long>(args));
|
||||
testers.push_back(new AMOBitwiseTester<unsigned long>(args));
|
||||
if (BackendType::GDA_BACKEND != backend_type) // not implemented for GDA
|
||||
testers.push_back(new AMOBitwiseTester<unsigned int>(args));
|
||||
return testers;
|
||||
case AMO_IncTestType:
|
||||
if (rank == 0) std::cout << "AMO Inc ###" << std::endl;
|
||||
testers.push_back(new AMOStandardTester<long long>(args));
|
||||
testers.push_back(new AMOStandardTester<long>(args));
|
||||
if (BackendType::GDA_BACKEND != backend_type) // not implemented for GDA
|
||||
testers.push_back(new AMOStandardTester<int>(args));
|
||||
return testers;
|
||||
case PingPongTestType:
|
||||
if (rank == 0) std::cout << "PingPong ###" << std::endl;
|
||||
testers.push_back(new PingPongTester(args));
|
||||
return testers;
|
||||
case PingAllTestType:
|
||||
if (rank == 0) std::cout << "PingAll ###" << std::endl;
|
||||
testers.push_back(new PingAllTester(args));
|
||||
return testers;
|
||||
case BarrierAllTestType:
|
||||
if (rank == 0) std::cout << "Barrier_All ###" << std::endl;
|
||||
testers.push_back(new BarrierAllTester(args));
|
||||
return testers;
|
||||
case WAVEBarrierAllTestType:
|
||||
if (rank == 0) std::cout << "WAVE Barrier_All ###" << std::endl;
|
||||
testers.push_back(new BarrierAllTester(args));
|
||||
return testers;
|
||||
case WGBarrierAllTestType:
|
||||
if (rank == 0) std::cout << "WG Barrier_All ###" << std::endl;
|
||||
testers.push_back(new BarrierAllTester(args));
|
||||
return testers;
|
||||
case TeamBarrierTestType:
|
||||
if (rank == 0) std::cout << "Team Barrier Test ###" << std::endl;
|
||||
testers.push_back(new TeamBarrierTester(args));
|
||||
return testers;
|
||||
case TeamWAVEBarrierTestType:
|
||||
if (rank == 0) std::cout << "Team WAVE Barrier Test ###" << std::endl;
|
||||
testers.push_back(new TeamBarrierTester(args));
|
||||
return testers;
|
||||
case TeamWGBarrierTestType:
|
||||
if (rank == 0) std::cout << "Team WG Barrier Test ###" << std::endl;
|
||||
testers.push_back(new TeamBarrierTester(args));
|
||||
return testers;
|
||||
case SyncAllTestType:
|
||||
if (rank == 0) std::cout << "SyncAll ###" << std::endl;
|
||||
testers.push_back(new SyncAllTester(args));
|
||||
return testers;
|
||||
case WAVESyncAllTestType:
|
||||
if (rank == 0) std::cout << "WAVE SyncAll ###" << std::endl;
|
||||
testers.push_back(new SyncAllTester(args));
|
||||
return testers;
|
||||
case WGSyncAllTestType:
|
||||
if (rank == 0) std::cout << "WG SyncAll ###" << std::endl;
|
||||
testers.push_back(new SyncAllTester(args));
|
||||
return testers;
|
||||
case TeamSyncTestType:
|
||||
if (rank == 0) std::cout << "Team Sync ###" << std::endl;
|
||||
testers.push_back(new TeamSyncTester(args));
|
||||
return testers;
|
||||
case TeamWAVESyncTestType:
|
||||
if (rank == 0) std::cout << "Team WAVE Sync ###" << std::endl;
|
||||
testers.push_back(new TeamSyncTester(args));
|
||||
return testers;
|
||||
case TeamWGSyncTestType:
|
||||
if (rank == 0) std::cout << "Team WG Sync ###" << std::endl;
|
||||
testers.push_back(new TeamSyncTester(args));
|
||||
return testers;
|
||||
case RandomAccessTestType:
|
||||
if (rank == 0) std::cout << "Random_Access ###" << std::endl;
|
||||
testers.push_back(new RandomAccessTester(args));
|
||||
return testers;
|
||||
case ShmemPtrTestType:
|
||||
if (rank == 0) std::cout << "Shmem_Ptr ###" << std::endl;
|
||||
testers.push_back(new ShmemPtrTester(args));
|
||||
return testers;
|
||||
case WGGetTestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Blocking WG level Gets ###" << std::endl;
|
||||
testers.push_back(new WorkGroupPrimitiveTester(args));
|
||||
return testers;
|
||||
case WGGetNBITestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Non-Blocking WG level Gets ###" << std::endl;
|
||||
testers.push_back(new WorkGroupPrimitiveTester(args));
|
||||
return testers;
|
||||
case WGPutTestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Blocking WG level Puts ###" << std::endl;
|
||||
testers.push_back(new WorkGroupPrimitiveTester(args));
|
||||
return testers;
|
||||
case WGPutNBITestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Non-Blocking WG level Puts ###" << std::endl;
|
||||
testers.push_back(new WorkGroupPrimitiveTester(args));
|
||||
return testers;
|
||||
case PutNBIMRTestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Non-Blocking Put message rate ###" << std::endl;
|
||||
testers.push_back(new PrimitiveMRTester(args));
|
||||
return testers;
|
||||
case WAVEGetTestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Blocking WAVE level Gets ###" << std::endl;
|
||||
testers.push_back(new WaveFrontPrimitiveTester(args));
|
||||
return testers;
|
||||
case WAVEGetNBITestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Non-Blocking WAVE level Gets ###" << std::endl;
|
||||
testers.push_back(new WaveFrontPrimitiveTester(args));
|
||||
return testers;
|
||||
case WAVEPutTestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Blocking WAVE level Puts ###" << std::endl;
|
||||
testers.push_back(new WaveFrontPrimitiveTester(args));
|
||||
return testers;
|
||||
case WAVEPutNBITestType:
|
||||
if (rank == 0)
|
||||
std::cout << "Non-Blocking WAVE level Puts ###" << std::endl;
|
||||
testers.push_back(new WaveFrontPrimitiveTester(args));
|
||||
return testers;
|
||||
case PutSignalTestType:
|
||||
if (rank == 0) std::cout << "Putmem Signal ###" << std::endl;
|
||||
testers.push_back(new SignalingOperationsTester(args, ROCSHMEM_SIGNAL_SET));
|
||||
testers.push_back(new SignalingOperationsTester(args, ROCSHMEM_SIGNAL_ADD));
|
||||
return testers;
|
||||
case WGPutSignalTestType:
|
||||
if (rank == 0) std::cout << "WG Putmem Signal ###" << std::endl;
|
||||
testers.push_back(new SignalingOperationsTester(args, ROCSHMEM_SIGNAL_SET));
|
||||
testers.push_back(new SignalingOperationsTester(args, ROCSHMEM_SIGNAL_ADD));
|
||||
return testers;
|
||||
case WAVEPutSignalTestType:
|
||||
if (rank == 0) std::cout << "Wave Putmem Signal ###" << std::endl;
|
||||
testers.push_back(new SignalingOperationsTester(args, ROCSHMEM_SIGNAL_SET));
|
||||
testers.push_back(new SignalingOperationsTester(args, ROCSHMEM_SIGNAL_ADD));
|
||||
return testers;
|
||||
case PutSignalNBITestType:
|
||||
if (rank == 0) std::cout << "Non-Blocking Putmem Signal ###" << std::endl;
|
||||
testers.push_back(new SignalingOperationsTester(args, ROCSHMEM_SIGNAL_SET));
|
||||
testers.push_back(new SignalingOperationsTester(args, ROCSHMEM_SIGNAL_ADD));
|
||||
return testers;
|
||||
case WGPutSignalNBITestType:
|
||||
if (rank == 0) std::cout << "Non-Blocking WG Putmem Signal ###" << std::endl;
|
||||
testers.push_back(new SignalingOperationsTester(args, ROCSHMEM_SIGNAL_SET));
|
||||
testers.push_back(new SignalingOperationsTester(args, ROCSHMEM_SIGNAL_ADD));
|
||||
return testers;
|
||||
case WAVEPutSignalNBITestType:
|
||||
if (rank == 0) std::cout << "Non-Blocking Wave Putmem Signal ###" << std::endl;
|
||||
testers.push_back(new SignalingOperationsTester(args, ROCSHMEM_SIGNAL_SET));
|
||||
testers.push_back(new SignalingOperationsTester(args, ROCSHMEM_SIGNAL_ADD));
|
||||
return testers;
|
||||
case SignalFetchTestType:
|
||||
if (rank == 0) std::cout << "Signal Fetch ###" << std::endl;
|
||||
testers.push_back(new SignalingOperationsTester(args));
|
||||
return testers;
|
||||
case WGSignalFetchTestType:
|
||||
if (rank == 0) std::cout << "WG Signal Fetch ###" << std::endl;
|
||||
testers.push_back(new SignalingOperationsTester(args));
|
||||
return testers;
|
||||
case WAVESignalFetchTestType:
|
||||
if (rank == 0) std::cout << "Wave Signal Fetch ###" << std::endl;
|
||||
testers.push_back(new SignalingOperationsTester(args));
|
||||
return testers;
|
||||
case FloodPutTestType:
|
||||
if (rank == 0) std::cout << "Flood Put (multidirectional) ###" << std::endl;
|
||||
testers.push_back(new FloodTester(args));
|
||||
return testers;
|
||||
case FloodPutNBITestType:
|
||||
if (rank == 0) std::cout << "Flood Non-Blocking Put (multidirectional) ###" << std::endl;
|
||||
testers.push_back(new FloodTester(args));
|
||||
return testers;
|
||||
case FloodPTestType:
|
||||
if (rank == 0) std::cout << "Flood P (multidirectional) ###" << std::endl;
|
||||
testers.push_back(new FloodTester(args));
|
||||
return testers;
|
||||
case FloodGetTestType:
|
||||
if (rank == 0) std::cout << "Flood Get (multidirectional) ###" << std::endl;
|
||||
testers.push_back(new FloodTester(args));
|
||||
return testers;
|
||||
case FloodGetNBITestType:
|
||||
if (rank == 0) std::cout << "Flood Non-Blocking Get (multidirectional) ###" << std::endl;
|
||||
testers.push_back(new FloodTester(args));
|
||||
return testers;
|
||||
case FloodGTestType:
|
||||
if (rank == 0) std::cout << "Flood G (multidirectional) ###" << std::endl;
|
||||
testers.push_back(new FloodTester(args));
|
||||
return testers;
|
||||
default:
|
||||
if (rank == 0) std::cout << "Empty Test ###" << std::endl;
|
||||
return testers;
|
||||
}
|
||||
return testers;
|
||||
}
|
||||
|
||||
void Tester::execute() {
|
||||
if (_type == InitTestType) return;
|
||||
|
||||
int num_loops = args.loop;
|
||||
|
||||
/**
|
||||
* Some tests loop through data sizes in powers of 2 and report the
|
||||
* results for those ranges.
|
||||
*/
|
||||
for (size_t size = args.min_msg_size; size <= args.max_msg_size;
|
||||
size <<= 1) {
|
||||
resetBuffers(size);
|
||||
|
||||
/**
|
||||
* Restricts the number of iterations of really large messages.
|
||||
*/
|
||||
if (size > args.large_message_size) num_loops = args.loop_large;
|
||||
|
||||
barrier();
|
||||
|
||||
preLaunchKernel();
|
||||
|
||||
/**
|
||||
* This conditional launches the HIP kernel.
|
||||
*
|
||||
* Some tests may only launch a single kernel. These kernels will
|
||||
* be kicked off by the initiator (denoted by the args.myid check).
|
||||
*
|
||||
* Other tests will initiate of both sides and launch from both
|
||||
* rocshmem pes.
|
||||
*/
|
||||
if (peLaunchesKernel()) {
|
||||
memset(timer, 0, sizeof(uint64_t) * args.num_wgs);
|
||||
|
||||
const dim3 blockSize(args.wg_size, 1, 1);
|
||||
const dim3 gridSize(args.num_wgs, 1, 1);
|
||||
|
||||
CHECK_HIP(hipEventRecord(start_event, stream));
|
||||
|
||||
launchKernel(gridSize, blockSize, num_loops, size);
|
||||
|
||||
CHECK_HIP(hipEventRecord(stop_event, stream));
|
||||
|
||||
hipError_t err = hipStreamSynchronize(stream);
|
||||
if (err != hipSuccess) {
|
||||
printf("error = %d \n", err);
|
||||
}
|
||||
}
|
||||
|
||||
barrier();
|
||||
|
||||
postLaunchKernel();
|
||||
|
||||
// data validation
|
||||
verifyResults(size);
|
||||
|
||||
barrier();
|
||||
|
||||
if (_type != TeamCtxInfraTestType &&
|
||||
_type != TeamCtxInfraTestSingleType &&
|
||||
_type != TeamCtxInfraTestBlockType &&
|
||||
_type != TeamCtxInfraTestOddEvenType ) {
|
||||
print(size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Tester::peLaunchesKernel() {
|
||||
/**
|
||||
* The PE assigned 0 is always active in these tests.
|
||||
*/
|
||||
bool is_launcher = (args.myid == 0);
|
||||
|
||||
/**
|
||||
* Some test types are active on both sides.
|
||||
*/
|
||||
switch (_type) {
|
||||
case TeamReductionTestType:
|
||||
case TeamBroadcastTestType:
|
||||
case TeamCtxInfraTestType:
|
||||
case TeamCtxInfraTestSingleType:
|
||||
case TeamCtxInfraTestBlockType:
|
||||
case TeamCtxInfraTestOddEvenType:
|
||||
case TeamAllToAllTestType:
|
||||
case TeamFCollectTestType:
|
||||
case PingPongTestType:
|
||||
case BarrierAllTestType:
|
||||
case WAVEBarrierAllTestType:
|
||||
case WGBarrierAllTestType:
|
||||
case TeamSyncTestType:
|
||||
case TeamWAVESyncTestType:
|
||||
case TeamWGSyncTestType:
|
||||
case SyncAllTestType:
|
||||
case WAVESyncAllTestType:
|
||||
case WGSyncAllTestType:
|
||||
case RandomAccessTestType:
|
||||
case PingAllTestType:
|
||||
case TeamBarrierTestType:
|
||||
case TeamWAVEBarrierTestType:
|
||||
case TeamWGBarrierTestType:
|
||||
case TeamAlltoallmemOnStreamTestType:
|
||||
case BarrierAllOnStreamTestType:
|
||||
case TeamBroadcastmemOnStreamTestType:
|
||||
case GetmemOnStreamTestType:
|
||||
case PutmemOnStreamTestType:
|
||||
case PutmemSignalOnStreamTestType:
|
||||
case SignalWaitUntilOnStreamTestType:
|
||||
case FloodPutTestType:
|
||||
case FloodPutNBITestType:
|
||||
case FloodPTestType:
|
||||
case FloodGetTestType:
|
||||
case FloodGetNBITestType:
|
||||
case FloodGTestType:
|
||||
is_launcher = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return is_launcher;
|
||||
}
|
||||
|
||||
void Tester::print(uint64_t size) {
|
||||
if (args.myid != 0 || !_print_results) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate total amount of data transfered
|
||||
*/
|
||||
uint64_t total_size = size * num_timed_msgs;
|
||||
double timer_avg = timerAvgInMicroseconds();
|
||||
|
||||
double time_us = gpuCyclesToMicroseconds(max_end_time - min_start_time);
|
||||
double time_s = time_us / 1e6;
|
||||
|
||||
double latency_avg = time_us / num_timed_msgs;
|
||||
|
||||
double avg_msg_rate = num_timed_msgs / time_s;
|
||||
|
||||
double bandwidth_avg_gbs =
|
||||
static_cast<double>(total_size * bw_factor) / time_s / pow(2, 30);
|
||||
|
||||
float total_kern_time_ms;
|
||||
CHECK_HIP(hipEventElapsedTime(&total_kern_time_ms, start_event, stop_event));
|
||||
float total_kern_time_s = total_kern_time_ms / 1000;
|
||||
|
||||
int field_width = 20;
|
||||
int float_precision = 2;
|
||||
|
||||
if (_print_header) {
|
||||
printf("%-*s%-*s%*s%*s%*s",
|
||||
15, "# Size (B)",
|
||||
15, "# of timed Msgs",
|
||||
field_width, "Latency (us)",
|
||||
field_width, "Bandwidth (GB/s)",
|
||||
field_width + 1, "Msg Rate (Msg/s)\n");
|
||||
_print_header = 0;
|
||||
}
|
||||
|
||||
printf("%-*lu%-*d%*.*f%*.*f%*.*f\n",
|
||||
15, size,
|
||||
15, num_timed_msgs,
|
||||
field_width, float_precision, latency_avg,
|
||||
field_width, float_precision, bandwidth_avg_gbs,
|
||||
field_width, float_precision, avg_msg_rate);
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void flush_hdp() {
|
||||
int hip_dev_id{};
|
||||
unsigned int* hdp_flush_ptr_{nullptr};
|
||||
CHECK_HIP(hipGetDevice(&hip_dev_id));
|
||||
CHECK_HIP(hipDeviceGetAttribute(reinterpret_cast<int*>(&hdp_flush_ptr_),
|
||||
hipDeviceAttributeHdpMemFlushCntl, hip_dev_id));
|
||||
__atomic_store_n(hdp_flush_ptr_, 0x1, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
void Tester::barrier() {
|
||||
rocshmem_barrier_all();
|
||||
flush_hdp();
|
||||
}
|
||||
|
||||
double Tester::gpuCyclesToMicroseconds(long long int cycles) {
|
||||
return static_cast<double>(cycles) /
|
||||
(static_cast<double>(wall_clk_rate) * 1e-3);
|
||||
}
|
||||
|
||||
double Tester::timerAvgInMicroseconds() {
|
||||
double sum = 0;
|
||||
min_start_time = LLONG_MAX;
|
||||
max_end_time = 0;
|
||||
|
||||
for (uint32_t i = 0; i < num_timers; i++) {
|
||||
timer[i] = end_time[i] - start_time[i];
|
||||
sum += gpuCyclesToMicroseconds(timer[i]);
|
||||
min_start_time = (start_time[i] < min_start_time)
|
||||
? start_time[i]
|
||||
: min_start_time;
|
||||
max_end_time = (end_time[i] > max_end_time)
|
||||
? end_time[i]
|
||||
: max_end_time;
|
||||
}
|
||||
|
||||
return sum / num_timers;
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _TESTER_HPP_
|
||||
#define _TESTER_HPP_
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
#include <vector>
|
||||
#include <climits>
|
||||
|
||||
#include "tester_arguments.hpp"
|
||||
#include "../src/util.hpp"
|
||||
#include "verify_results_kernels.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* TESTER CLASS TYPES
|
||||
*****************************************************************************/
|
||||
enum TestType {
|
||||
GetTestType = 0,
|
||||
GetNBITestType = 1,
|
||||
PutTestType = 2,
|
||||
PutNBITestType = 3,
|
||||
AMO_FAddTestType = 4,
|
||||
AMO_FIncTestType = 5,
|
||||
AMO_FetchTestType = 6,
|
||||
AMO_FCswapTestType = 7,
|
||||
AMO_AddTestType = 8,
|
||||
AMO_IncTestType = 9,
|
||||
AMO_CswapTestType = 10,
|
||||
InitTestType = 11,
|
||||
PingPongTestType = 12,
|
||||
RandomAccessTestType = 13,
|
||||
BarrierAllTestType = 14,
|
||||
SyncAllTestType = 15,
|
||||
TeamSyncTestType = 16,
|
||||
CollectTestType = 17,
|
||||
TeamFCollectTestType = 18,
|
||||
TeamAllToAllTestType = 19,
|
||||
AllToAllsTestType = 20,
|
||||
ShmemPtrTestType = 21,
|
||||
PTestType = 22,
|
||||
GTestType = 23,
|
||||
WGGetTestType = 24,
|
||||
WGGetNBITestType = 25,
|
||||
WGPutTestType = 26,
|
||||
WGPutNBITestType = 27,
|
||||
WAVEGetTestType = 28,
|
||||
WAVEGetNBITestType = 29,
|
||||
WAVEPutTestType = 30,
|
||||
WAVEPutNBITestType = 31,
|
||||
TeamBroadcastTestType = 32,
|
||||
TeamReductionTestType = 33,
|
||||
TeamCtxGetTestType = 34,
|
||||
TeamCtxGetNBITestType = 35,
|
||||
TeamCtxPutTestType = 36,
|
||||
TeamCtxPutNBITestType = 37,
|
||||
TeamCtxInfraTestType = 38,
|
||||
PutNBIMRTestType = 39,
|
||||
AMO_SetTestType = 40,
|
||||
AMO_SwapTestType = 41,
|
||||
AMO_FetchAndTestType = 42,
|
||||
AMO_FetchOrTestType = 43,
|
||||
AMO_FetchXorTestType = 44,
|
||||
AMO_AndTestType = 45,
|
||||
AMO_OrTestType = 46,
|
||||
AMO_XorTestType = 47,
|
||||
PingAllTestType = 48,
|
||||
PutSignalTestType = 49,
|
||||
WGPutSignalTestType = 50,
|
||||
WAVEPutSignalTestType = 51,
|
||||
PutSignalNBITestType = 52,
|
||||
WGPutSignalNBITestType = 53,
|
||||
WAVEPutSignalNBITestType = 54,
|
||||
SignalFetchTestType = 55,
|
||||
WGSignalFetchTestType = 56,
|
||||
WAVESignalFetchTestType = 57,
|
||||
TeamWGBarrierTestType = 58,
|
||||
DefaultCTXGetTestType = 59,
|
||||
DefaultCTXGetNBITestType = 60,
|
||||
DefaultCTXPutTestType = 61,
|
||||
DefaultCTXPutNBITestType = 62,
|
||||
DefaultCTXPTestType = 63,
|
||||
DefaultCTXGTestType = 64,
|
||||
WAVEBarrierAllTestType = 65,
|
||||
WGBarrierAllTestType = 66,
|
||||
WAVESyncAllTestType = 67,
|
||||
WGSyncAllTestType = 68,
|
||||
TeamBarrierTestType = 69,
|
||||
TeamWAVEBarrierTestType = 70,
|
||||
TeamWAVESyncTestType = 71,
|
||||
TeamWGSyncTestType = 72,
|
||||
TeamCtxInfraTestSingleType = 73,
|
||||
TeamCtxInfraTestBlockType = 74,
|
||||
TeamCtxInfraTestOddEvenType = 75,
|
||||
TeamAlltoallmemOnStreamTestType = 76,
|
||||
BarrierAllOnStreamTestType = 77,
|
||||
TeamBroadcastmemOnStreamTestType = 78,
|
||||
GetmemOnStreamTestType = 79,
|
||||
PutmemOnStreamTestType = 80,
|
||||
PutmemSignalOnStreamTestType = 81,
|
||||
SignalWaitUntilOnStreamTestType = 82,
|
||||
FloodPutTestType = 83,
|
||||
FloodPutNBITestType = 84,
|
||||
FloodPTestType = 85,
|
||||
FloodGetTestType = 86,
|
||||
FloodGetNBITestType = 87,
|
||||
FloodGTestType = 88,
|
||||
};
|
||||
|
||||
enum OpType { PutType = 0, GetType = 1 };
|
||||
|
||||
typedef int ShmemContextType;
|
||||
|
||||
/******************************************************************************
|
||||
* TESTER INTERFACE
|
||||
*****************************************************************************/
|
||||
class Tester {
|
||||
public:
|
||||
explicit Tester(TesterArguments args);
|
||||
virtual ~Tester();
|
||||
|
||||
void execute();
|
||||
|
||||
static std::vector<Tester *> create(TesterArguments args);
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(uint64_t size) = 0;
|
||||
|
||||
virtual void preLaunchKernel() {}
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
uint64_t size) = 0;
|
||||
|
||||
virtual void postLaunchKernel() {}
|
||||
|
||||
virtual void verifyResults(uint64_t size) = 0;
|
||||
|
||||
int num_msgs = 0;
|
||||
int num_timed_msgs = 0;
|
||||
int num_warps = 0;
|
||||
int bw_factor = 1;
|
||||
int device_id = 0;
|
||||
int wall_clk_rate = 0; //in kilohertz
|
||||
int wf_size = 0;
|
||||
|
||||
TesterArguments args;
|
||||
|
||||
TestType _type;
|
||||
ShmemContextType _shmem_context = 8; // SHMEM_CTX_WP_PRIVATE
|
||||
|
||||
hipStream_t stream;
|
||||
hipDeviceProp_t deviceProps;
|
||||
|
||||
long long int *timer = nullptr;
|
||||
long long int *start_time = nullptr;
|
||||
long long int *end_time = nullptr;
|
||||
long long int min_start_time = 0;
|
||||
long long int max_end_time = 0;
|
||||
uint32_t num_timers = 0;
|
||||
|
||||
bool *verification_error;
|
||||
|
||||
protected:
|
||||
bool _print_results = true;
|
||||
|
||||
private:
|
||||
bool _print_header = true;
|
||||
void print(uint64_t size);
|
||||
|
||||
void barrier();
|
||||
|
||||
double gpuCyclesToMicroseconds(long long int cycles);
|
||||
|
||||
double timerAvgInMicroseconds();
|
||||
|
||||
bool peLaunchesKernel();
|
||||
|
||||
hipEvent_t start_event;
|
||||
hipEvent_t stop_event;
|
||||
};
|
||||
|
||||
//TODO remove altogether? THere is a small difference in print format
|
||||
#undef CHECK_HIP
|
||||
#define CHECK_HIP(instr) do { \
|
||||
hipError_t error = (instr); \
|
||||
if (error != hipSuccess) { \
|
||||
fprintf(stderr, "error: " #instr ": %s (%d) at %s:%d\n", \
|
||||
hipGetErrorString(error), error, __FILE__, __LINE__); \
|
||||
abort(); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif /* _TESTER_HPP */
|
||||
@@ -0,0 +1,240 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "tester_arguments.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
TesterArguments::TesterArguments(int argc, char *argv[]) {
|
||||
for (int i = 1; i < argc; i++) {
|
||||
std::string arg = argv[i];
|
||||
if (arg == "-t") {
|
||||
i++;
|
||||
num_threads = atoi(argv[i]);
|
||||
} else if (arg == "-w") {
|
||||
i++;
|
||||
num_wgs = atoi(argv[i]);
|
||||
} else if (arg == "-s") {
|
||||
i++;
|
||||
max_msg_size = atoll(argv[i]);
|
||||
} else if (arg == "-a") {
|
||||
i++;
|
||||
algorithm = atoi(argv[i]);
|
||||
} else if (arg == "-z") {
|
||||
i++;
|
||||
wg_size = atoi(argv[i]);
|
||||
} else if (arg == "-c") {
|
||||
i++;
|
||||
coal_coef = atoi(argv[i]);
|
||||
} else if (arg == "-o") {
|
||||
i++;
|
||||
op_type = atoi(argv[i]);
|
||||
} else if (arg == "-ta") {
|
||||
i++;
|
||||
thread_access = atoi(argv[i]);
|
||||
} else if (arg == "-x") {
|
||||
i++;
|
||||
shmem_context = atoi(argv[i]);
|
||||
} else if (arg == "-m") {
|
||||
int atomics_addr_mode = atoi(argv[i]);
|
||||
if(atomics_addr_mode >= static_cast<int>(AddrMode::PerGrid) &&
|
||||
atomics_addr_mode <= static_cast<int>(AddrMode::PerBlock)) {
|
||||
addr_mode = static_cast<AddrMode>(atomics_addr_mode);
|
||||
}
|
||||
i++;
|
||||
} else if (arg == "-n") {
|
||||
i++;
|
||||
loop = atoi(argv[i]);
|
||||
loop_large = loop;
|
||||
} else if (arg == "-nloop") {
|
||||
i++;
|
||||
loop = atoi(argv[i]);
|
||||
} else if (arg == "-nlarge") {
|
||||
i++;
|
||||
loop_large = atoi(argv[i]);
|
||||
} else if (arg == "-nskip") {
|
||||
i++;
|
||||
skip = atoi(argv[i]);
|
||||
} else {
|
||||
show_usage(argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
TestType type = (TestType)algorithm;
|
||||
|
||||
switch (type) {
|
||||
case AMO_FAddTestType:
|
||||
case AMO_AddTestType:
|
||||
case AMO_SetTestType:
|
||||
case AMO_SwapTestType:
|
||||
case AMO_FetchAndTestType:
|
||||
case AMO_AndTestType:
|
||||
case AMO_FetchOrTestType:
|
||||
case AMO_OrTestType:
|
||||
case AMO_FetchXorTestType:
|
||||
case AMO_XorTestType:
|
||||
case AMO_FCswapTestType:
|
||||
case AMO_CswapTestType:
|
||||
case AMO_FIncTestType:
|
||||
case AMO_IncTestType:
|
||||
case AMO_FetchTestType:
|
||||
case BarrierAllTestType:
|
||||
case WAVEBarrierAllTestType:
|
||||
case WGBarrierAllTestType:
|
||||
case TeamBarrierTestType:
|
||||
case TeamWAVEBarrierTestType:
|
||||
case TeamWGBarrierTestType:
|
||||
case BarrierAllOnStreamTestType:
|
||||
case SyncAllTestType:
|
||||
case WAVESyncAllTestType:
|
||||
case WGSyncAllTestType:
|
||||
case TeamSyncTestType:
|
||||
case SignalWaitUntilOnStreamTestType:
|
||||
min_msg_size = 8;
|
||||
max_msg_size = 8;
|
||||
break;
|
||||
case PingPongTestType:
|
||||
case ShmemPtrTestType:
|
||||
min_msg_size = 4;
|
||||
max_msg_size = 4;
|
||||
break;
|
||||
case RandomAccessTestType:
|
||||
case TeamAlltoallmemOnStreamTestType:
|
||||
case TeamBroadcastmemOnStreamTestType:
|
||||
min_msg_size = 4;
|
||||
break;
|
||||
case TeamFCollectTestType:
|
||||
case TeamAllToAllTestType:
|
||||
case TeamBroadcastTestType:
|
||||
min_msg_size = 8;
|
||||
break;
|
||||
case TeamCtxInfraTestType:
|
||||
case TeamCtxInfraTestSingleType:
|
||||
case TeamCtxInfraTestBlockType:
|
||||
case TeamCtxInfraTestOddEvenType:
|
||||
max_msg_size = min_msg_size;
|
||||
break;
|
||||
case PutNBIMRTestType:
|
||||
min_msg_size = max_msg_size;
|
||||
break;
|
||||
case PTestType:
|
||||
case GTestType:
|
||||
min_msg_size = 1;
|
||||
max_msg_size = 1;
|
||||
break;
|
||||
case FloodPutTestType:
|
||||
case FloodPutNBITestType:
|
||||
case FloodPTestType:
|
||||
case FloodGetTestType:
|
||||
case FloodGetNBITestType:
|
||||
case FloodGTestType:
|
||||
min_msg_size = max_msg_size = 8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TesterArguments::show_usage(std::string executable_name) {
|
||||
std::cout << "Usage: " << executable_name << std::endl;
|
||||
std::cout << "\t-t <number of rocshmem service threads>\n";
|
||||
std::cout << "\t-w <number of workgroups>\n";
|
||||
std::cout << "\t-s <maximum message size (in bytes)>\n";
|
||||
std::cout << "\t-a <algorithm number to test>\n";
|
||||
std::cout << "\t-z <WorkGroup Size>\n";
|
||||
std::cout << "\t-c <Coalescing Coefficient>\n";
|
||||
std::cout << "\t-o <Operation type for the random_access test>\n";
|
||||
std::cout << "\t-ta <Number of Thread Accessing the communication>\n";
|
||||
std::cout << "\t-x <shmem context>\n";
|
||||
std::cout << "\t-m Atomics Address mode\n";
|
||||
std::cout << "\t-n Set both loop and loop_large count\n";
|
||||
std::cout << "\t-nloop Set loop count\n";
|
||||
std::cout << "\t-nlarge Set loop_large count\n";
|
||||
std::cout << "\t-nskip Set skip/warmup count\n";
|
||||
}
|
||||
|
||||
void TesterArguments::get_arguments() {
|
||||
numprocs = rocshmem_n_pes();
|
||||
myid = rocshmem_my_pe();
|
||||
|
||||
TestType type = (TestType)algorithm;
|
||||
// Check if test requires exactly 2 PEs
|
||||
// Tests that support arbitrary number of PEs are excluded
|
||||
bool requires_two_pes = true;
|
||||
switch (type) {
|
||||
// Collective/barrier tests - support any number of PEs
|
||||
case BarrierAllTestType:
|
||||
case WAVEBarrierAllTestType:
|
||||
case WGBarrierAllTestType:
|
||||
case SyncAllTestType:
|
||||
case WAVESyncAllTestType:
|
||||
case WGSyncAllTestType:
|
||||
case TeamSyncTestType:
|
||||
case TeamWAVESyncTestType:
|
||||
case TeamWGSyncTestType:
|
||||
case TeamAllToAllTestType:
|
||||
case TeamFCollectTestType:
|
||||
case TeamReductionTestType:
|
||||
case TeamBroadcastTestType:
|
||||
case PingAllTestType:
|
||||
case TeamBarrierTestType:
|
||||
case TeamWAVEBarrierTestType:
|
||||
case TeamWGBarrierTestType:
|
||||
case TeamCtxInfraTestBlockType:
|
||||
case TeamCtxInfraTestOddEvenType:
|
||||
// On-stream tests - support any number of PEs
|
||||
case TeamAlltoallmemOnStreamTestType:
|
||||
case BarrierAllOnStreamTestType:
|
||||
case TeamBroadcastmemOnStreamTestType:
|
||||
case GetmemOnStreamTestType:
|
||||
case PutmemOnStreamTestType:
|
||||
case PutmemSignalOnStreamTestType:
|
||||
case SignalWaitUntilOnStreamTestType:
|
||||
case FloodPutTestType:
|
||||
case FloodPutNBITestType:
|
||||
case FloodPTestType:
|
||||
case FloodGetTestType:
|
||||
case FloodGetNBITestType:
|
||||
case FloodGTestType:
|
||||
requires_two_pes = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (requires_two_pes && numprocs != 2) {
|
||||
if (myid == 0) {
|
||||
std::cerr << "This test requires exactly two processes, we have "
|
||||
<< numprocs << "\n";
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _TESTER_ARGUMENTS_HPP_
|
||||
#define _TESTER_ARGUMENTS_HPP_
|
||||
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
enum TeamSplitType {
|
||||
ROCSHMEM_TEST_TEAM_DUP = 0, // Dup parent team
|
||||
ROCSHMEM_TEST_TEAM_SINGLE, // each PE will be its own team
|
||||
ROCSHMEM_TEST_TEAM_BLOCK, // split parent into two halfs
|
||||
ROCSHMEM_TEST_TEAM_ODDEVEN, // odd-even splitting
|
||||
};
|
||||
|
||||
/*-----------------------------------------
|
||||
* Atomics Addressing modes (contention model)
|
||||
*-----------------------------------------*/
|
||||
enum class AddrMode : int {
|
||||
PerGrid, // all WGs -> same address
|
||||
PerBlock, // each WG -> its own address (default)
|
||||
};
|
||||
|
||||
class TesterArguments {
|
||||
public:
|
||||
TesterArguments(int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* Initialize rocshmem members
|
||||
* Valid after rocshmem_init function called.
|
||||
*/
|
||||
void get_arguments();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Output method which displays available command line options
|
||||
*/
|
||||
static void show_usage(std::string executable_name);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Arguments obtained from command line
|
||||
*/
|
||||
unsigned num_wgs = 1;
|
||||
unsigned num_threads = 1;
|
||||
unsigned algorithm = 0;
|
||||
size_t min_msg_size = 1;
|
||||
size_t max_msg_size = 1 << 20;
|
||||
unsigned wg_size = 64;
|
||||
unsigned thread_access = 64;
|
||||
unsigned coal_coef = 64;
|
||||
unsigned op_type = 0;
|
||||
unsigned shmem_context = rocshmem::ROCSHMEM_CTX_WG_PRIVATE;
|
||||
AddrMode addr_mode = AddrMode::PerBlock;
|
||||
|
||||
/**
|
||||
* Arguments obtained from rocshmem
|
||||
*/
|
||||
int numprocs = INT_MAX;
|
||||
int myid = INT_MAX;
|
||||
|
||||
/**
|
||||
* Defaults tester values
|
||||
*/
|
||||
int loop = 10;
|
||||
int skip = 10;
|
||||
int loop_large = 10;
|
||||
size_t large_message_size = 32768;
|
||||
|
||||
TeamSplitType team_type = ROCSHMEM_TEST_TEAM_DUP;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,46 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _VERIFY_RESULTS_KERNELS_HPP_
|
||||
#define _VERIFY_RESULTS_KERNELS_HPP_
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
static __global__ void verify_results_kernel_char(char *source, char *dest, size_t buf_size,
|
||||
bool *verification_error) {
|
||||
|
||||
int idx = get_flat_id();
|
||||
|
||||
if (idx >= buf_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dest[idx] != source[idx]) {
|
||||
*verification_error = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* _VERIFY_RESULTS_KERNELS_HPP_ */
|
||||
@@ -0,0 +1,165 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "wavefront_primitives.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
|
||||
#include <numeric>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void WaveFrontPrimitiveTest(int loop, int skip,
|
||||
long long int *start_time,
|
||||
long long int *end_time, char *source,
|
||||
char *dest, size_t size, TestType type,
|
||||
ShmemContextType ctx_type,
|
||||
int wf_size) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
int wg_id = get_flat_grid_id();
|
||||
|
||||
rocshmem_wg_ctx_create(ctx_type, &ctx);
|
||||
|
||||
// Calculate start index for each wavefront
|
||||
int wf_id = get_flat_block_id() / wf_size;
|
||||
int wg_offset = wg_id * ((get_flat_block_size() - 1 ) / wf_size + 1);
|
||||
int idx = wf_id + wg_offset;
|
||||
size_t offset = size * idx;
|
||||
source += offset;
|
||||
dest += offset;
|
||||
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (i == skip) {
|
||||
// Ensures all RMA calls from the skip loops are completed
|
||||
rocshmem_ctx_quiet(ctx);
|
||||
__syncthreads();
|
||||
if (is_thread_zero_in_wave()) {
|
||||
start_time[idx] = wall_clock64();
|
||||
}
|
||||
}
|
||||
switch (type) {
|
||||
case WAVEGetTestType:
|
||||
rocshmem_ctx_getmem_wave(ctx, dest, source, size, 1);
|
||||
break;
|
||||
case WAVEGetNBITestType:
|
||||
rocshmem_ctx_getmem_nbi_wave(ctx, dest, source, size, 1);
|
||||
break;
|
||||
case WAVEPutTestType:
|
||||
rocshmem_ctx_putmem_wave(ctx, dest, source, size, 1);
|
||||
break;
|
||||
case WAVEPutNBITestType:
|
||||
rocshmem_ctx_putmem_nbi_wave(ctx, dest, source, size, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rocshmem_ctx_quiet(ctx);
|
||||
if (is_thread_zero_in_wave()) {
|
||||
end_time[idx] = wall_clock64();
|
||||
}
|
||||
|
||||
rocshmem_wg_ctx_destroy(&ctx);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
WaveFrontPrimitiveTester::WaveFrontPrimitiveTester(TesterArguments args)
|
||||
: Tester(args) {
|
||||
size_t buff_size = args.max_msg_size * args.num_wgs * num_warps;
|
||||
source = (char *)rocshmem_malloc(buff_size);
|
||||
dest = (char *)rocshmem_malloc(buff_size);
|
||||
|
||||
if (source == nullptr || dest == nullptr) {
|
||||
std::cerr << "Error allocating memory from symmetric heap" << std::endl;
|
||||
std::cerr << "source: " << source << ", dest: " << dest << std::endl;
|
||||
if (source) {
|
||||
rocshmem_free(source);
|
||||
}
|
||||
if (dest) {
|
||||
rocshmem_free(dest);
|
||||
}
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < buff_size; i++) {
|
||||
source[i] = static_cast<char>('a' + i % 26);
|
||||
}
|
||||
}
|
||||
|
||||
WaveFrontPrimitiveTester::~WaveFrontPrimitiveTester() {
|
||||
rocshmem_free(source);
|
||||
rocshmem_free(dest);
|
||||
}
|
||||
|
||||
void WaveFrontPrimitiveTester::resetBuffers(size_t size) {
|
||||
size_t buff_size = size * args.num_wgs * num_warps;
|
||||
memset(dest, '1', buff_size);
|
||||
}
|
||||
|
||||
void WaveFrontPrimitiveTester::launchKernel(dim3 gridSize, dim3 blockSize,
|
||||
int loop, size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
hipLaunchKernelGGL(WaveFrontPrimitiveTest, gridSize, blockSize, shared_bytes,
|
||||
stream, loop, args.skip, start_time, end_time,
|
||||
source, dest, size, _type, _shmem_context,
|
||||
wf_size);
|
||||
|
||||
num_msgs = (loop + args.skip) * gridSize.x * num_warps;
|
||||
num_timed_msgs = loop * gridSize.x * num_warps;
|
||||
}
|
||||
|
||||
void WaveFrontPrimitiveTester::verifyResults(size_t size) {
|
||||
int check_id = (_type == WAVEGetTestType || _type == WAVEGetNBITestType)
|
||||
? 0
|
||||
: 1;
|
||||
|
||||
if (args.myid == check_id) {
|
||||
size_t buff_size = size * args.num_wgs * num_warps;
|
||||
size_t verify_wg_size = std::min((size_t) 1024, buff_size);
|
||||
size_t verify_num_wgs = buff_size / verify_wg_size;
|
||||
|
||||
hipLaunchKernelGGL(verify_results_kernel_char, verify_num_wgs, verify_wg_size, 0, stream,
|
||||
source, dest, buff_size, verification_error);
|
||||
CHECK_HIP(hipStreamSynchronize(stream));
|
||||
|
||||
if (*verification_error) {
|
||||
for (size_t i = 0; i < buff_size; i++) {
|
||||
if (dest[i] != source[i]) {
|
||||
std::cerr << "Data validation error at idx " << i << std::endl;
|
||||
std::cerr << " Got " << dest[i] << ", Expected "
|
||||
<< source[i] << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
*verification_error = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _WAVE_LEVEL_PRIMITIVE_TEST_HPP_
|
||||
#define _WAVE_LEVEL_PRIMITIVE_TEST_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class WaveFrontPrimitiveTester : public Tester {
|
||||
public:
|
||||
explicit WaveFrontPrimitiveTester(TesterArguments args);
|
||||
virtual ~WaveFrontPrimitiveTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
char *source = nullptr;
|
||||
char *dest = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,160 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "workgroup_primitives.hpp"
|
||||
|
||||
#include <rocshmem/rocshmem.hpp>
|
||||
|
||||
#include <numeric>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/******************************************************************************
|
||||
* DEVICE TEST KERNEL
|
||||
*****************************************************************************/
|
||||
__global__ void WorkGroupPrimitiveTest(int loop, int skip,
|
||||
long long int *start_time,
|
||||
long long int *end_time, char *source,
|
||||
char *dest, size_t size, TestType type,
|
||||
ShmemContextType ctx_type) {
|
||||
__shared__ rocshmem_ctx_t ctx;
|
||||
int wg_id = get_flat_grid_id();
|
||||
rocshmem_wg_ctx_create(ctx_type, &ctx);
|
||||
|
||||
// Calculate start index for each work group
|
||||
size_t offset = size * wg_id;
|
||||
source += offset;
|
||||
dest += offset;
|
||||
|
||||
for (int i = 0; i < loop + skip; i++) {
|
||||
if (i == skip) {
|
||||
// Ensures all RMA calls from the skip loops are completed
|
||||
if (is_thread_zero_in_block()) {
|
||||
rocshmem_ctx_quiet(ctx);
|
||||
}
|
||||
__syncthreads();
|
||||
start_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case WGGetTestType:
|
||||
rocshmem_ctx_getmem_wg(ctx, dest, source, size, 1);
|
||||
break;
|
||||
case WGGetNBITestType:
|
||||
rocshmem_ctx_getmem_nbi_wg(ctx, dest, source, size, 1);
|
||||
break;
|
||||
case WGPutTestType:
|
||||
rocshmem_ctx_putmem_wg(ctx, dest, source, size, 1);
|
||||
break;
|
||||
case WGPutNBITestType:
|
||||
rocshmem_ctx_putmem_nbi_wg(ctx, dest, source, size, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_thread_zero_in_block()) {
|
||||
rocshmem_ctx_quiet(ctx);
|
||||
end_time[wg_id] = wall_clock64();
|
||||
}
|
||||
|
||||
rocshmem_wg_ctx_destroy(&ctx);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS METHODS
|
||||
*****************************************************************************/
|
||||
WorkGroupPrimitiveTester::WorkGroupPrimitiveTester(TesterArguments args)
|
||||
: Tester(args) {
|
||||
size_t buff_size = args.max_msg_size * args.num_wgs;
|
||||
source = (char *)rocshmem_malloc(buff_size);
|
||||
dest = (char *)rocshmem_malloc(buff_size);
|
||||
|
||||
if (source == nullptr || dest == nullptr) {
|
||||
std::cerr << "Error allocating memory from symmetric heap" << std::endl;
|
||||
std::cerr << "source: " << source << ", dest: " << dest << std::endl;
|
||||
if (source) {
|
||||
rocshmem_free(source);
|
||||
}
|
||||
if (dest) {
|
||||
rocshmem_free(dest);
|
||||
}
|
||||
rocshmem_global_exit(1);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < buff_size; i++) {
|
||||
source[i] = static_cast<char>('a' + i % 26);
|
||||
}
|
||||
}
|
||||
|
||||
WorkGroupPrimitiveTester::~WorkGroupPrimitiveTester() {
|
||||
rocshmem_free(source);
|
||||
rocshmem_free(dest);
|
||||
}
|
||||
|
||||
void WorkGroupPrimitiveTester::resetBuffers(size_t size) {
|
||||
size_t buff_size = size * args.num_wgs;
|
||||
memset(dest, '1', buff_size);
|
||||
}
|
||||
|
||||
void WorkGroupPrimitiveTester::launchKernel(dim3 gridSize, dim3 blockSize,
|
||||
int loop, size_t size) {
|
||||
size_t shared_bytes = 0;
|
||||
|
||||
hipLaunchKernelGGL(WorkGroupPrimitiveTest, gridSize, blockSize, shared_bytes,
|
||||
stream, loop, args.skip, start_time, end_time,
|
||||
source, dest, size, _type, _shmem_context);
|
||||
|
||||
num_msgs = (loop + args.skip) * gridSize.x;
|
||||
num_timed_msgs = loop * gridSize.x;
|
||||
}
|
||||
|
||||
void WorkGroupPrimitiveTester::verifyResults(size_t size) {
|
||||
int check_id = (_type == WGGetTestType || _type == WGGetNBITestType)
|
||||
? 0
|
||||
: 1;
|
||||
|
||||
if (args.myid == check_id) {
|
||||
size_t buff_size = size * args.num_wgs;
|
||||
size_t verify_wg_size = std::min((size_t) 1024, buff_size);
|
||||
size_t verify_num_wgs = buff_size / verify_wg_size;
|
||||
|
||||
hipLaunchKernelGGL(verify_results_kernel_char, verify_num_wgs, verify_wg_size, 0, stream,
|
||||
source, dest, buff_size, verification_error);
|
||||
CHECK_HIP(hipStreamSynchronize(stream));
|
||||
|
||||
if (*verification_error) {
|
||||
for (size_t i = 0; i < buff_size; i++) {
|
||||
if (dest[i] != source[i]) {
|
||||
std::cerr << "Data validation error at idx " << i << std::endl;
|
||||
std::cerr << " Got " << dest[i] << ", Expected "
|
||||
<< source[i] << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
*verification_error = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _EXTENDED_PRIMITIVES_HPP_
|
||||
#define _EXTENDED_PRIMITIVES_HPP_
|
||||
|
||||
#include "tester.hpp"
|
||||
|
||||
/******************************************************************************
|
||||
* HOST TESTER CLASS
|
||||
*****************************************************************************/
|
||||
class WorkGroupPrimitiveTester : public Tester {
|
||||
public:
|
||||
explicit WorkGroupPrimitiveTester(TesterArguments args);
|
||||
virtual ~WorkGroupPrimitiveTester();
|
||||
|
||||
protected:
|
||||
virtual void resetBuffers(size_t size) override;
|
||||
|
||||
virtual void launchKernel(dim3 gridSize, dim3 blockSize, int loop,
|
||||
size_t size) override;
|
||||
|
||||
virtual void verifyResults(size_t size) override;
|
||||
|
||||
char *source = nullptr;
|
||||
char *dest = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,131 @@
|
||||
###############################################################################
|
||||
# Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# 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.
|
||||
###############################################################################
|
||||
|
||||
cmake_minimum_required(VERSION 3.16.3 FATAL_ERROR)
|
||||
|
||||
###############################################################################
|
||||
# PROJECT
|
||||
###############################################################################
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/setup_project.cmake)
|
||||
project(rocshmem_unit_tests VERSION 1.0.0 LANGUAGES CXX)
|
||||
|
||||
###############################################################################
|
||||
# SOURCES
|
||||
###############################################################################
|
||||
add_executable(${PROJECT_NAME} "")
|
||||
|
||||
target_include_directories(
|
||||
${PROJECT_NAME}
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
target_sources(
|
||||
${PROJECT_NAME}
|
||||
PRIVATE
|
||||
shmem_gtest.cpp
|
||||
heap_memory_gtest.cpp
|
||||
hipmalloc_gtest.cpp
|
||||
bin_gtest.cpp
|
||||
binner_gtest.cpp
|
||||
#bitwise_gtest.cpp # Test is disabled because of compilation errors
|
||||
address_record_gtest.cpp
|
||||
index_strategy_gtest.cpp
|
||||
single_heap_gtest.cpp
|
||||
symmetric_heap_gtest.cpp
|
||||
pow2_bins_gtest.cpp
|
||||
dlmalloc_gtest.cpp
|
||||
remote_heap_info_gtest.cpp
|
||||
mpi_instance_gtest.cpp
|
||||
abql_block_mutex_gtest.cpp
|
||||
notifier_gtest.cpp
|
||||
free_list_gtest.cpp
|
||||
wavefront_size_gtest.cpp
|
||||
atomic_wf_queue_gtest.cpp
|
||||
envvar_gtest.cpp
|
||||
)
|
||||
|
||||
if (USE_IPC)
|
||||
target_sources(
|
||||
${PROJECT_NAME}
|
||||
PRIVATE
|
||||
ipc_impl_simple_coarse_gtest.cpp
|
||||
ipc_impl_simple_fine_gtest.cpp
|
||||
ipc_impl_tiled_fine_gtest.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
###############################################################################
|
||||
# ROCSHMEM DEPENDENCY
|
||||
###############################################################################
|
||||
find_package(hip REQUIRED PATHS /opt/rocm)
|
||||
find_package(MPI REQUIRED)
|
||||
|
||||
if (BUILD_TESTS_ONLY)
|
||||
find_package(rocshmem REQUIRED PATHS /opt/rocm)
|
||||
|
||||
target_include_directories(
|
||||
${PROJECT_NAME}
|
||||
PRIVATE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
|
||||
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}>
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(
|
||||
${PROJECT_NAME}
|
||||
PRIVATE
|
||||
MPI::MPI_CXX
|
||||
roc::rocshmem
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
# GTEST DEPENDENCY
|
||||
###############################################################################
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
PREFIX extern/googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG release-1.12.0
|
||||
)
|
||||
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
set(BUILD_GMOCK OFF CACHE BOOL "" FORCE)
|
||||
set(BUILD_GTEST ON CACHE BOOL "" FORCE)
|
||||
set(INSTALL_GTEST OFF CACHE BOOL "" FORCE)
|
||||
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
configure_file(../../scripts/unit_tests/driver.sh rocshmem_unit_driver.sh COPYONLY)
|
||||
rocm_install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/rocshmem_unit_driver.sh COMPONENT tests DESTINATION ${CMAKE_INSTALL_DATADIR}/rocshmem)
|
||||
rocm_install(TARGETS rocshmem_unit_tests COMPONENT tests)
|
||||
|
||||
target_link_libraries(
|
||||
${PROJECT_NAME}
|
||||
PRIVATE
|
||||
gtest
|
||||
gtest_main
|
||||
)
|
||||
@@ -0,0 +1,75 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "abql_block_mutex_gtest.hpp"
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/*****************************************************************************
|
||||
******************************* Fixture Tests *******************************
|
||||
*****************************************************************************/
|
||||
|
||||
TEST_F(ABQLBlockMutexTestFixture, run_all_threads_once_1_1) {
|
||||
run_all_threads_once(1, 1);
|
||||
}
|
||||
|
||||
TEST_F(ABQLBlockMutexTestFixture, run_all_threads_once_1_2) {
|
||||
run_all_threads_once(1, 2);
|
||||
}
|
||||
|
||||
TEST_F(ABQLBlockMutexTestFixture, run_all_threads_once_1_8) {
|
||||
run_all_threads_once(1, 8);
|
||||
}
|
||||
|
||||
TEST_F(ABQLBlockMutexTestFixture, run_all_threads_once_1_64) {
|
||||
run_all_threads_once(1, 64);
|
||||
}
|
||||
|
||||
TEST_F(ABQLBlockMutexTestFixture, run_all_threads_once_1_128) {
|
||||
run_all_threads_once(1, 128);
|
||||
}
|
||||
|
||||
TEST_F(ABQLBlockMutexTestFixture, run_all_threads_once_1_256) {
|
||||
run_all_threads_once(1, 256);
|
||||
}
|
||||
|
||||
TEST_F(ABQLBlockMutexTestFixture, run_all_threads_once_1_1024) {
|
||||
run_all_threads_once(1, 1024);
|
||||
}
|
||||
|
||||
TEST_F(ABQLBlockMutexTestFixture, run_all_threads_once_1_2048) {
|
||||
run_all_threads_once(1, 2048);
|
||||
}
|
||||
|
||||
TEST_F(ABQLBlockMutexTestFixture, run_all_threads_once_1_4096) {
|
||||
run_all_threads_once(1, 4096);
|
||||
}
|
||||
|
||||
TEST_F(ABQLBlockMutexTestFixture, run_all_threads_once_1_8192) {
|
||||
run_all_threads_once(1, 8192);
|
||||
}
|
||||
|
||||
TEST_F(ABQLBlockMutexTestFixture, run_all_threads_once_1_65536) {
|
||||
run_all_threads_once(1, 65536);
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ROCSHMEM_ABQL_BLOCK_MUTEX_GTEST_HPP
|
||||
#define ROCSHMEM_ABQL_BLOCK_MUTEX_GTEST_HPP
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "../src/memory/hip_allocator.hpp"
|
||||
#include "../src/sync/abql_block_mutex.hpp"
|
||||
#include "../src/util.hpp"
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <cassert>
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
inline __device__
|
||||
void
|
||||
increment_counter(ABQLBlockMutex *mutex,
|
||||
size_t *counter) {
|
||||
auto ticket {mutex->lock()};
|
||||
(*counter)++;
|
||||
__threadfence();
|
||||
mutex->unlock(ticket);
|
||||
}
|
||||
|
||||
__global__
|
||||
void
|
||||
all_threads_once(ABQLBlockMutex *mutex,
|
||||
size_t *counter) {
|
||||
increment_counter(mutex, counter);
|
||||
}
|
||||
|
||||
__global__
|
||||
void
|
||||
block_leader_once(ABQLBlockMutex *mutex,
|
||||
size_t *counter) {
|
||||
if (is_thread_zero_in_block()) {
|
||||
increment_counter(mutex, counter);
|
||||
}
|
||||
}
|
||||
|
||||
__global__
|
||||
void
|
||||
warp_leader_once(ABQLBlockMutex *mutex,
|
||||
size_t *counter) {
|
||||
if (is_thread_zero_in_wave()) {
|
||||
increment_counter(mutex, counter);
|
||||
}
|
||||
}
|
||||
|
||||
class ABQLBlockMutexTestFixture : public ::testing::Test {
|
||||
public:
|
||||
ABQLBlockMutexTestFixture() {
|
||||
assert(mutex_ == nullptr);
|
||||
hip_allocator_.allocate((void**)&mutex_, sizeof(ABQLBlockMutex));
|
||||
|
||||
assert(mutex_);
|
||||
new (mutex_) ABQLBlockMutex();
|
||||
|
||||
assert(counter_ == nullptr);
|
||||
hip_allocator_.allocate((void**)&counter_, sizeof(int));
|
||||
|
||||
assert(counter_);
|
||||
*counter_ = 0;
|
||||
}
|
||||
|
||||
~ABQLBlockMutexTestFixture() {
|
||||
if (mutex_) {
|
||||
hip_allocator_.deallocate(mutex_);
|
||||
}
|
||||
|
||||
if (counter_) {
|
||||
hip_allocator_.deallocate(counter_);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run_all_threads_once(uint32_t x_block_dim,
|
||||
uint32_t x_grid_dim) {
|
||||
const dim3 hip_blocksize(x_block_dim, 1, 1);
|
||||
const dim3 hip_gridsize(x_grid_dim, 1, 1);
|
||||
|
||||
hipLaunchKernelGGL(all_threads_once,
|
||||
hip_gridsize,
|
||||
hip_blocksize,
|
||||
0,
|
||||
nullptr,
|
||||
mutex_,
|
||||
counter_);
|
||||
|
||||
CHECK_HIP(hipStreamSynchronize(nullptr));
|
||||
|
||||
size_t number_threads {x_block_dim * x_grid_dim};
|
||||
|
||||
ASSERT_EQ(*counter_, number_threads);
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief An allocator to create objects in device memory.
|
||||
*/
|
||||
HIPAllocator hip_allocator_ {};
|
||||
|
||||
/**
|
||||
* @brief A mutex to prevent data races.
|
||||
*/
|
||||
ABQLBlockMutex *mutex_ {nullptr};
|
||||
|
||||
/**
|
||||
* @brief A monotonically increasing counter to track accesses.
|
||||
*/
|
||||
size_t *counter_ {nullptr};
|
||||
};
|
||||
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // ROCSHMEM_ABQL_BLOCK_MUTEX_GTEST_HPP
|
||||
@@ -0,0 +1,90 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "address_record_gtest.hpp"
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
TEST_F(AddressRecordTestFixture, split_entry) {
|
||||
auto [ar1, ar2] = split_.split();
|
||||
|
||||
char* a1{reinterpret_cast<char*>(0x200)};
|
||||
size_t size1{0x40};
|
||||
ASSERT_EQ(ar1.get_address(), a1);
|
||||
ASSERT_EQ(ar1.get_size(), size1);
|
||||
|
||||
char* a2{reinterpret_cast<char*>(0x240)};
|
||||
size_t size2{0x40};
|
||||
ASSERT_EQ(ar2.get_address(), a2);
|
||||
ASSERT_EQ(ar2.get_size(), size2);
|
||||
}
|
||||
|
||||
#ifdef NDEBUG
|
||||
TEST_F(AddressRecordTestFixture, DISABLED_split_bad_address)
|
||||
#else
|
||||
TEST_F(AddressRecordTestFixture, split_bad_address)
|
||||
#endif
|
||||
{
|
||||
ASSERT_DEATH({ bad_addr_.split(); }, "");
|
||||
}
|
||||
|
||||
#ifdef NDEBUG
|
||||
TEST_F(AddressRecordTestFixture, DISABLED_split_bad_size)
|
||||
#else
|
||||
TEST_F(AddressRecordTestFixture, split_bad_size)
|
||||
#endif
|
||||
{
|
||||
ASSERT_DEATH({ bad_size_.split(); }, "");
|
||||
}
|
||||
|
||||
TEST_F(AddressRecordTestFixture, combine_1_into_combine_2) {
|
||||
AddressRecord ar{combine_1_.combine(combine_2_)};
|
||||
ASSERT_EQ(ar.get_address(), combine_1_.get_address());
|
||||
ASSERT_EQ(ar.get_size(), combine_1_.get_size() << 1);
|
||||
}
|
||||
|
||||
#ifdef NDEBUG
|
||||
TEST_F(AddressRecordTestFixture, DISABLED_combine_nullptr_record)
|
||||
#else
|
||||
TEST_F(AddressRecordTestFixture, combine_nullptr_record)
|
||||
#endif
|
||||
{
|
||||
ASSERT_DEATH({ AddressRecord ar = bad_addr_.combine(combine_2_); }, "");
|
||||
}
|
||||
|
||||
#ifdef NDEBUG
|
||||
TEST_F(AddressRecordTestFixture, DISABLED_combine_differerent_sizes)
|
||||
#else
|
||||
TEST_F(AddressRecordTestFixture, combine_different_sizes)
|
||||
#endif
|
||||
{
|
||||
char* a1{reinterpret_cast<char*>(0x120)};
|
||||
char* a2{reinterpret_cast<char*>(0x140)};
|
||||
size_t size1{0x20};
|
||||
size_t size2{0x40};
|
||||
|
||||
AddressRecord ar1{a1, size1};
|
||||
AddressRecord ar2{a2, size2};
|
||||
ASSERT_DEATH({ AddressRecord ar = ar1.combine(ar2); }, "");
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ROCSHMEM_ADDRESS_RECORD_GTEST_HPP
|
||||
#define ROCSHMEM_ADDRESS_RECORD_GTEST_HPP
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "../src/memory/address_record.hpp"
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
class AddressRecordTestFixture : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
AddressRecord split_ {reinterpret_cast<char*>(0x200), 0x80};
|
||||
AddressRecord combine_1_ {reinterpret_cast<char*>(0x120), 0x20};
|
||||
AddressRecord combine_2_ {reinterpret_cast<char*>(0x140), 0x20};
|
||||
AddressRecord bad_addr_ {nullptr, 0x20};
|
||||
AddressRecord bad_size_ {reinterpret_cast<char*>(0x800), 0x0};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // ROCSHMEM_ADDRESS_RECORD_GTEST_HPP
|
||||
@@ -0,0 +1,201 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "atomic_wf_queue_gtest.hpp"
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/*****************************************************************************
|
||||
******************************* Fixture Tests *******************************
|
||||
*****************************************************************************/
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, active_logical_lane_ids_4) {
|
||||
get_thread_lane_ids(4);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, active_logical_lane_ids_10) {
|
||||
get_thread_lane_ids(10);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, active_logical_lane_ids_16) {
|
||||
get_thread_lane_ids(16);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, active_logical_lane_ids_17) {
|
||||
get_thread_lane_ids(17);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, active_logical_lane_ids_64) {
|
||||
get_thread_lane_ids(64);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, active_logical_lane_ids_97) {
|
||||
get_thread_lane_ids(97);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, active_logical_lane_ids_256) {
|
||||
get_thread_lane_ids(256);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, active_logical_lane_ids_183) {
|
||||
get_thread_lane_ids(183);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, active_logical_lane_ids_1024) {
|
||||
get_thread_lane_ids(1024);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, init_2_64) {
|
||||
init_queue(2, 64);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, init_64_256) {
|
||||
init_queue(64, 256);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, init_1024_96) {
|
||||
init_queue(1024, 96);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, dequeue_enqueue_threads_eq_qsize_2_32) {
|
||||
int num_blocks {2};
|
||||
int block_size {32};
|
||||
int wf_size {this->wf_size};
|
||||
int queue_size {num_blocks * ((block_size - 1) / wf_size + 1)};
|
||||
dequeue_enqueue(num_blocks, block_size, queue_size);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, dequeue_enqueue_threads_eq_qsize_32_192) {
|
||||
int num_blocks {32};
|
||||
int block_size {192};
|
||||
int wf_size {this->wf_size};
|
||||
int queue_size {num_blocks * ((block_size - 1) / wf_size + 1)};
|
||||
dequeue_enqueue(num_blocks, block_size, queue_size);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, dequeue_enqueue_threads_eq_qsize_64_256) {
|
||||
int num_blocks {64};
|
||||
int block_size {256};
|
||||
int wf_size {this->wf_size};
|
||||
int queue_size {num_blocks * ((block_size - 1) / wf_size + 1)};
|
||||
dequeue_enqueue(num_blocks, block_size, queue_size);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, dequeue_enqueue_threads_ge_qsize_16_32_4) {
|
||||
int num_blocks {16};
|
||||
int block_size {32};
|
||||
int queue_size {4};
|
||||
dequeue_enqueue(num_blocks, block_size, queue_size);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, dequeue_enqueue_threads_ge_qsize_16_96_8) {
|
||||
int num_blocks {16};
|
||||
int block_size {96};
|
||||
int queue_size {8};
|
||||
dequeue_enqueue(num_blocks, block_size, queue_size);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, dequeue_enqueue_threads_ge_qsize_16_320_8) {
|
||||
int num_blocks {16};
|
||||
int block_size {320};
|
||||
int queue_size {8};
|
||||
dequeue_enqueue(num_blocks, block_size, queue_size);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, dequeue_enqueue_threads_ge_qsize_32_192_16) {
|
||||
int num_blocks {32};
|
||||
int block_size {192};
|
||||
int queue_size {16};
|
||||
dequeue_enqueue(num_blocks, block_size, queue_size);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, dequeue_enqueue_threads_ge_qsize_64_256_64) {
|
||||
int num_blocks {64};
|
||||
int block_size {256};
|
||||
int queue_size {64};
|
||||
dequeue_enqueue(num_blocks, block_size, queue_size);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, dequeue_enqueue_threads_ge_qsize_64_576_64) {
|
||||
int num_blocks {64};
|
||||
int block_size {576};
|
||||
int queue_size {64};
|
||||
dequeue_enqueue(num_blocks, block_size, queue_size);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, dequeue_enqueue_qsize_ge_threads_4_8_16) {
|
||||
int num_blocks {4};
|
||||
int block_size {8};
|
||||
int queue_size {16};
|
||||
dequeue_enqueue(num_blocks, block_size, queue_size);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, dequeue_enqueue_qsize_ge_threads_4_96_16) {
|
||||
int num_blocks {4};
|
||||
int block_size {96};
|
||||
int queue_size {16};
|
||||
dequeue_enqueue(num_blocks, block_size, queue_size);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, dequeue_enqueue_qsize_ge_threads_32_192_128) {
|
||||
int num_blocks {32};
|
||||
int block_size {192};
|
||||
int queue_size {128};
|
||||
dequeue_enqueue(num_blocks, block_size, queue_size);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, dequeue_enqueue_qsize_ge_threads_32_320_256) {
|
||||
int num_blocks {32};
|
||||
int block_size {320};
|
||||
int queue_size {256};
|
||||
dequeue_enqueue(num_blocks, block_size, queue_size);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, dequeue_enqueue_qsize_ge_threads_64_16_128) {
|
||||
int num_blocks {64};
|
||||
int block_size {16};
|
||||
int queue_size {128};
|
||||
dequeue_enqueue(num_blocks, block_size, queue_size);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, dequeue_enqueue_qsize_ge_threads_64_96_256) {
|
||||
int num_blocks {64};
|
||||
int block_size {96};
|
||||
int queue_size {256};
|
||||
dequeue_enqueue(num_blocks, block_size, queue_size);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, dequeue_enqueue_qsize_ge_threads_64_320_512) {
|
||||
int num_blocks {64};
|
||||
int block_size {320};
|
||||
int queue_size {512};
|
||||
dequeue_enqueue(num_blocks, block_size, queue_size);
|
||||
}
|
||||
|
||||
TEST_F(AtomicWFQueueTestFixture, dequeue_enqueue_qsize_ge_threads_64_576_1024) {
|
||||
int num_blocks {64};
|
||||
int block_size {576};
|
||||
int queue_size {1024};
|
||||
dequeue_enqueue(num_blocks, block_size, queue_size);
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ROCSHMEM_ATOMIC_WF_QUEUE_GTEST_HPP
|
||||
#define ROCSHMEM_ATOMIC_WF_QUEUE_GTEST_HPP
|
||||
|
||||
#include "../src/containers/atomic_wf_queue_impl.hpp"
|
||||
#include "gtest/gtest.h"
|
||||
#include "../src/memory/hip_allocator.hpp"
|
||||
#include "../src/util.hpp"
|
||||
#include <iostream>
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
template <typename AWFQueue>
|
||||
__global__ void wf_lane_ids(AWFQueue* awf_queue, unsigned int* device_array,
|
||||
int wf_size) {
|
||||
|
||||
int t_id {get_flat_id()};
|
||||
int lane_id {t_id % wf_size};
|
||||
device_array[t_id] = awf_queue->active_logical_lane_id();
|
||||
}
|
||||
|
||||
template <typename AWFQueue>
|
||||
__global__ void concurrent_enqueue_dequeue(
|
||||
AWFQueue* awf_queue,
|
||||
unsigned int* device_array) {
|
||||
|
||||
int t_id {get_flat_id()};
|
||||
int val {awf_queue->dequeue()};
|
||||
device_array[t_id] = val;
|
||||
awf_queue->enqueue(val);
|
||||
}
|
||||
|
||||
class AtomicWFQueueTestFixture : public ::testing::Test {
|
||||
public:
|
||||
AtomicWFQueueTestFixture() {
|
||||
awf_queue = awf_queue_proxy.get();
|
||||
|
||||
int device_id {};
|
||||
hipDeviceProp_t device_props;
|
||||
CHECK_HIP(hipGetDevice(&device_id));
|
||||
CHECK_HIP(hipGetDeviceProperties(&device_props, device_id));
|
||||
|
||||
wf_size = device_props.warpSize;
|
||||
}
|
||||
|
||||
~AtomicWFQueueTestFixture() {}
|
||||
|
||||
void get_thread_lane_ids(unsigned int num_threads = 4) {
|
||||
|
||||
unsigned int *device_array {nullptr};
|
||||
|
||||
hip_allocator_.allocate(reinterpret_cast<void**>(&device_array),
|
||||
sizeof(unsigned int) * num_threads);
|
||||
|
||||
|
||||
hipLaunchKernelGGL(wf_lane_ids, 1, num_threads, 0, nullptr,
|
||||
awf_queue, device_array, wf_size);
|
||||
|
||||
CHECK_HIP(hipDeviceSynchronize());
|
||||
|
||||
hip_allocator_.deallocate(device_array);
|
||||
|
||||
for (unsigned int i{0}; i < num_threads; i++) {
|
||||
EXPECT_EQ(device_array[i], i % wf_size);
|
||||
}
|
||||
}
|
||||
|
||||
void init_queue(int num_blocks, int block_size) {
|
||||
int num_elems = num_blocks * ((block_size - 1) / wf_size + 1);
|
||||
|
||||
awf_queue->allocate_queue(num_elems);
|
||||
|
||||
for (int i{0}; i < num_elems; i++) {
|
||||
awf_queue->push(i);
|
||||
}
|
||||
|
||||
EXPECT_EQ(awf_queue->get_curr_size(), num_elems);
|
||||
EXPECT_EQ(awf_queue->get_queue_size(), num_elems);
|
||||
EXPECT_EQ(awf_queue->get_tail(), awf_queue->get_head());
|
||||
|
||||
awf_queue->deallocate_queue();
|
||||
}
|
||||
|
||||
void verify(unsigned int *arr, int num_blocks, int block_size) {
|
||||
unsigned int expected_val {};
|
||||
unsigned int lane_id {};
|
||||
unsigned int idx {};
|
||||
for (unsigned int i{0}; i < num_blocks; i++) {
|
||||
for (unsigned int j{0}; j < block_size; j++) {
|
||||
idx = i * block_size + j;
|
||||
lane_id = j % wf_size;
|
||||
if (!lane_id) {
|
||||
expected_val = arr[idx];
|
||||
}
|
||||
EXPECT_EQ(arr[idx], expected_val + lane_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dequeue_enqueue(int num_blocks, int block_size, int queue_size) {
|
||||
|
||||
int num_threads {num_blocks * block_size};
|
||||
unsigned int *device_array {nullptr};
|
||||
|
||||
hip_allocator_.allocate(reinterpret_cast<void**>(&device_array),
|
||||
sizeof(unsigned int) * num_threads);
|
||||
|
||||
awf_queue->allocate_queue(queue_size);
|
||||
|
||||
for (int i{0}; i < queue_size; i++) {
|
||||
awf_queue->push(i);
|
||||
}
|
||||
|
||||
EXPECT_EQ(awf_queue->get_curr_size(), queue_size);
|
||||
EXPECT_EQ(awf_queue->get_queue_size(), queue_size);
|
||||
EXPECT_EQ(awf_queue->get_tail(), awf_queue->get_head());
|
||||
|
||||
hipLaunchKernelGGL(concurrent_enqueue_dequeue, num_blocks, block_size, 0,
|
||||
nullptr, awf_queue, device_array);
|
||||
CHECK_HIP(hipDeviceSynchronize());
|
||||
|
||||
EXPECT_EQ(awf_queue->get_curr_size(), queue_size);
|
||||
EXPECT_EQ(awf_queue->get_tail(), awf_queue->get_head());
|
||||
|
||||
verify(device_array, num_blocks, block_size);
|
||||
|
||||
hip_allocator_.deallocate(device_array);
|
||||
awf_queue->deallocate_queue();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
AtomicWFQueueProxy<HIPAllocator, int> awf_queue_proxy{};
|
||||
AtomicWFQueue<int, HIPAllocator>* awf_queue{};
|
||||
|
||||
/**
|
||||
* @brief An allocator to create objects in device memory.
|
||||
*/
|
||||
HIPAllocator hip_allocator_ {};
|
||||
|
||||
/**
|
||||
* @brief Wavefront size.
|
||||
*/
|
||||
int wf_size {};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // ROCSHMEM_ATOMIC_WF_QUEUE_GTEST_HPP
|
||||
@@ -0,0 +1,54 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "bin_gtest.hpp"
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
TEST_F(BinTestFixture, is_empty_check) { ASSERT_TRUE(bin_.empty()); }
|
||||
|
||||
TEST_F(BinTestFixture, is_not_empty_check) {
|
||||
bin_.put(nullptr);
|
||||
|
||||
ASSERT_FALSE(bin_.empty());
|
||||
}
|
||||
|
||||
TEST_F(BinTestFixture, size_check) {
|
||||
ASSERT_EQ(bin_.size(), 0);
|
||||
bin_.put(nullptr);
|
||||
ASSERT_EQ(bin_.size(), 1);
|
||||
bin_.put(nullptr);
|
||||
ASSERT_EQ(bin_.size(), 2);
|
||||
}
|
||||
|
||||
TEST_F(BinTestFixture, retrieval_check) {
|
||||
char* p_xa{reinterpret_cast<char*>(0xa)};
|
||||
char* p_xb{reinterpret_cast<char*>(0xb)};
|
||||
bin_.put(p_xa);
|
||||
bin_.put(p_xb);
|
||||
auto g_xb = bin_.get();
|
||||
auto g_xa = bin_.get();
|
||||
ASSERT_EQ(p_xa, g_xa);
|
||||
ASSERT_EQ(p_xb, g_xb);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ROCSHMEM_BIN_GTEST_HPP
|
||||
#define ROCSHMEM_BIN_GTEST_HPP
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "../src/memory/bin.hpp"
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
class BinTestFixture : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* @brief A bin object containing pointers
|
||||
*/
|
||||
Bin<char*> bin_ {};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // ROCSHMEM_BIN_GTEST_HPP
|
||||
@@ -0,0 +1,141 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "binner_gtest.hpp"
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
TEST(Binner, ffs_0) {
|
||||
size_t val{0x0};
|
||||
auto bit_pos{find_first_set_one(val)};
|
||||
ASSERT_EQ(bit_pos, UINT_MAX);
|
||||
}
|
||||
|
||||
TEST(Binner, ffs_1) {
|
||||
size_t val{0x1};
|
||||
auto bit_pos{find_first_set_one(val)};
|
||||
ASSERT_EQ(bit_pos, 0);
|
||||
}
|
||||
|
||||
TEST(Binner, ffs_2) {
|
||||
size_t val{0x2};
|
||||
auto bit_pos{find_first_set_one(val)};
|
||||
ASSERT_EQ(bit_pos, 1);
|
||||
}
|
||||
|
||||
TEST(Binner, ffs_4) {
|
||||
size_t val{0x4};
|
||||
auto bit_pos{find_first_set_one(val)};
|
||||
ASSERT_EQ(bit_pos, 2);
|
||||
}
|
||||
|
||||
TEST(Binner, ffs_8) {
|
||||
size_t val{0x8};
|
||||
auto bit_pos{find_first_set_one(val)};
|
||||
ASSERT_EQ(bit_pos, 3);
|
||||
}
|
||||
|
||||
TEST(Binner, ffs_100) {
|
||||
size_t val{0x100};
|
||||
auto bit_pos{find_first_set_one(val)};
|
||||
ASSERT_EQ(bit_pos, 8);
|
||||
}
|
||||
|
||||
TEST(Binner, ffs_8000) {
|
||||
size_t val{0x8000};
|
||||
auto bit_pos{find_first_set_one(val)};
|
||||
ASSERT_EQ(bit_pos, 15);
|
||||
}
|
||||
|
||||
TEST(Binner, ffs_ff80) {
|
||||
size_t val{0xFF80};
|
||||
auto bit_pos{find_first_set_one(val)};
|
||||
ASSERT_EQ(bit_pos, 15);
|
||||
}
|
||||
|
||||
TEST(Binner, ffs_4000_0000) {
|
||||
size_t val{0x40000000};
|
||||
auto bit_pos{find_first_set_one(val)};
|
||||
ASSERT_EQ(bit_pos, 30);
|
||||
}
|
||||
|
||||
TEST(Binner, ffs_0100_0000_0000_0000) {
|
||||
size_t val{0x0100000000000000};
|
||||
auto bit_pos{find_first_set_one(val)};
|
||||
ASSERT_EQ(bit_pos, 56);
|
||||
}
|
||||
|
||||
TEST(Binner, ffs_0200_0000_0000_0000) {
|
||||
size_t val{0x0200000000000000};
|
||||
auto bit_pos{find_first_set_one(val)};
|
||||
ASSERT_EQ(bit_pos, 57);
|
||||
}
|
||||
|
||||
TEST(Binner, ffs_4000_0000_0000_0000) {
|
||||
size_t val{0x4000000000000000};
|
||||
auto bit_pos{find_first_set_one(val)};
|
||||
ASSERT_EQ(bit_pos, 62);
|
||||
}
|
||||
|
||||
TEST(Binner, ffs_8000_0000_0000_0000) {
|
||||
size_t val{0x8000000000000000};
|
||||
auto bit_pos{find_first_set_one(val)};
|
||||
ASSERT_EQ(bit_pos, 63);
|
||||
}
|
||||
|
||||
TEST(Binner, ffs_max) {
|
||||
size_t val = -1;
|
||||
auto bit_pos{find_first_set_one(val)};
|
||||
ASSERT_EQ(bit_pos, 63);
|
||||
}
|
||||
|
||||
TEST_F(BinnerTestFixture, correct_bin_sizes_one_gig) {
|
||||
auto bins{binner_.get_bins()};
|
||||
ASSERT_EQ(bins->size(), 24);
|
||||
|
||||
std::array<unsigned, 24> a;
|
||||
for (unsigned i = 0; i < 24; i++) {
|
||||
a[i] = i + 7;
|
||||
}
|
||||
|
||||
for (auto e : a) {
|
||||
bool found = bins->count(std::pow(2, e));
|
||||
ASSERT_TRUE(found);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(BinnerTestFixture, bin_get_one_gig) {
|
||||
binner_.assign_heap_to_bins();
|
||||
|
||||
auto bins{binner_.get_bins()};
|
||||
ASSERT_EQ(bins->size(), 24);
|
||||
|
||||
size_t gibibyte = std::pow(2, 30);
|
||||
auto bin{(*bins)[gibibyte]};
|
||||
|
||||
ASSERT_EQ(bin.size(), 1);
|
||||
|
||||
auto address_record = bin.get();
|
||||
ASSERT_EQ(address_record.get_size(), gibibyte);
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ROCSHMEM_BINNER_GTEST_HPP
|
||||
#define ROCSHMEM_BINNER_GTEST_HPP
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "../src/../src/memory/address_record.hpp"
|
||||
#include "../src/memory/bin.hpp"
|
||||
#include "../src/memory/binner.hpp"
|
||||
#include "../src/memory/heap_memory.hpp"
|
||||
#include "../src/memory/hip_allocator.hpp"
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
class BinnerTestFixture : public ::testing::Test
|
||||
{
|
||||
/**
|
||||
* @brief Helper type for address records
|
||||
*/
|
||||
using AR_T = AddressRecord;
|
||||
|
||||
/**
|
||||
* @brief Helper type for size to bin maps
|
||||
*/
|
||||
using BINS_T = std::map<size_t, Bin<AR_T>>;
|
||||
|
||||
/**
|
||||
* @brief Helper type for binner
|
||||
*/
|
||||
using BINNER_T = Binner<AR_T, BINS_T>;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief a heap memory object
|
||||
*/
|
||||
HeapMemory<HIPAllocator> hm_ {};
|
||||
|
||||
/**
|
||||
* @brief a bins object
|
||||
*/
|
||||
BINS_T bins_ {};
|
||||
|
||||
/**
|
||||
* @brief a binner object
|
||||
*/
|
||||
BINNER_T binner_ {&bins_,
|
||||
hm_.get_ptr(),
|
||||
hm_.get_size()};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // ROCSHMEM_BINNER_GTEST_HPP
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -0,0 +1,351 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ROCSHMEM_BITWISE_GTEST_HPP
|
||||
#define ROCSHMEM_BITWISE_GTEST_HPP
|
||||
|
||||
#define HIP_ENABLE_PRINTF
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "wf_size.hpp"
|
||||
|
||||
#include "../src/memory/hip_allocator.hpp"
|
||||
#include "containers/matrix.hpp"
|
||||
#include "containers/share_strategy.hpp"
|
||||
#include "containers/strategies.hpp"
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <cassert>
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
/*****************************************************************************
|
||||
************************ WarpMatrix Type Helpers ****************************
|
||||
*****************************************************************************/
|
||||
typedef Matrix<uint64_t> WarpMatrix;
|
||||
|
||||
/*****************************************************************************
|
||||
***************************** Device Methods ********************************
|
||||
*****************************************************************************/
|
||||
class BitwiseDeviceMethods
|
||||
{
|
||||
public:
|
||||
/*************************************************************************
|
||||
************************* Block Strategy Methods ************************
|
||||
*************************************************************************/
|
||||
__device__
|
||||
void
|
||||
lowest_active_lane(WarpMatrix *warp_matrix,
|
||||
size_t lanes_bitfield)
|
||||
{
|
||||
Block block {};
|
||||
if (activate_lane_helper(lanes_bitfield)) {
|
||||
auto low_lane = block.lowest_active_lane();
|
||||
size_t warp_index = hipThreadIdx_x / WF_SIZE;
|
||||
size_t block_index = hipBlockIdx_x;
|
||||
auto *elem = warp_matrix->access(warp_index, block_index);
|
||||
*elem = low_lane;
|
||||
}
|
||||
}
|
||||
|
||||
__device__
|
||||
void
|
||||
is_lowest_active_lane(WarpMatrix *warp_matrix,
|
||||
size_t lanes_bitfield)
|
||||
{
|
||||
Block block {};
|
||||
if (activate_lane_helper(lanes_bitfield)) {
|
||||
if (block.is_lowest_active_lane()) {
|
||||
size_t warp_index = hipThreadIdx_x / WF_SIZE;
|
||||
size_t block_index = hipBlockIdx_x;
|
||||
auto *elem = warp_matrix->access(warp_index, block_index);
|
||||
*elem = block.lane_id();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__device__
|
||||
void
|
||||
active_logical_lane_id_2(WarpMatrix *warp_matrix,
|
||||
size_t lanes_bitfield)
|
||||
{
|
||||
Block block {};
|
||||
if (activate_lane_helper(lanes_bitfield)) {
|
||||
if (block.active_logical_lane_id() == 2) {
|
||||
size_t warp_index = hipThreadIdx_x / WF_SIZE;
|
||||
size_t block_index = hipBlockIdx_x;
|
||||
auto *elem = warp_matrix->access(warp_index, block_index);
|
||||
*elem = block.lane_id();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__device__
|
||||
void
|
||||
lane_id(WarpMatrix *warp_matrix,
|
||||
size_t lanes_bitfield)
|
||||
{
|
||||
Block block {};
|
||||
if (activate_lane_helper(lanes_bitfield)) {
|
||||
auto lane_id = block.lane_id();
|
||||
size_t warp_index = hipThreadIdx_x / WF_SIZE;
|
||||
size_t block_index = hipBlockIdx_x;
|
||||
auto *elem = warp_matrix->access(warp_index, block_index);
|
||||
*elem = lane_id;
|
||||
}
|
||||
}
|
||||
|
||||
__device__
|
||||
void
|
||||
number_active_lanes(WarpMatrix *warp_matrix,
|
||||
size_t lanes_bitfield)
|
||||
{
|
||||
Block block {};
|
||||
if (activate_lane_helper(lanes_bitfield)) {
|
||||
auto number_active_lanes = block.number_active_lanes();
|
||||
size_t warp_index = hipThreadIdx_x / WF_SIZE;
|
||||
size_t block_index = hipBlockIdx_x;
|
||||
auto *elem = warp_matrix->access(warp_index, block_index);
|
||||
*elem = number_active_lanes;
|
||||
}
|
||||
}
|
||||
|
||||
__device__
|
||||
void
|
||||
broadcast_up_value_42(WarpMatrix *warp_matrix,
|
||||
size_t lanes_bitfield)
|
||||
{
|
||||
Block block {};
|
||||
if (activate_lane_helper(lanes_bitfield)) {
|
||||
uint64_t value = 1;
|
||||
if (block.is_lowest_active_lane()) {
|
||||
value = 42;
|
||||
}
|
||||
value = block.broadcast_up(value);
|
||||
size_t warp_index = hipThreadIdx_x / WF_SIZE;
|
||||
size_t block_index = hipBlockIdx_x;
|
||||
auto *elem = warp_matrix->access(warp_index, block_index);
|
||||
*elem = value;
|
||||
}
|
||||
}
|
||||
|
||||
__device__
|
||||
void
|
||||
fetch_incr_lowest_active_lane(WarpMatrix *warp_matrix,
|
||||
size_t lanes_bitfield)
|
||||
{
|
||||
Block block {};
|
||||
if (activate_lane_helper(lanes_bitfield)) {
|
||||
auto orig = block.fetch_incr(_fetch_value);
|
||||
if (block.is_lowest_active_lane()) {
|
||||
size_t warp_index = hipThreadIdx_x / WF_SIZE;
|
||||
size_t block_index = hipBlockIdx_x;
|
||||
auto *elem = warp_matrix->access(warp_index, block_index);
|
||||
*elem = orig;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__device__
|
||||
void
|
||||
fetch_incr_active_logical_lane_1(WarpMatrix *warp_matrix,
|
||||
size_t lanes_bitfield)
|
||||
{
|
||||
Block block {};
|
||||
if (activate_lane_helper(lanes_bitfield)) {
|
||||
auto orig = block.fetch_incr(_fetch_value);
|
||||
if (block.active_logical_lane_id() == 1) {
|
||||
size_t warp_index = hipThreadIdx_x / WF_SIZE;
|
||||
size_t block_index = hipBlockIdx_x;
|
||||
auto *elem = warp_matrix->access(warp_index, block_index);
|
||||
*elem = orig;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
************************* Helper Methods ********************************
|
||||
*************************************************************************/
|
||||
__device__
|
||||
bool
|
||||
activate_lane_helper(uint64_t lanes_bitfield)
|
||||
{
|
||||
/*
|
||||
* In the following example, assume the following values:
|
||||
* hipThreadIdx_x := 66
|
||||
* _warp_size := 64.
|
||||
*
|
||||
* index (tens): 0 0 0 0 0 0 0 ... 6 6 . .
|
||||
* (ones): 0 1 2 3 4 5 6 ... 2 3 . .
|
||||
* lanes_bitfield: [1 0 1 0 1 0 1 ... 1 0 . .]
|
||||
*
|
||||
* Example:
|
||||
* warp_bit_id := hipThreadIdx_x % _warp_size;
|
||||
* warp_bit_id := 66 % 64
|
||||
* warp_bit_id := 2
|
||||
*/
|
||||
uint64_t warp_bit_id = hipThreadIdx_x % WF_SIZE;
|
||||
|
||||
/*
|
||||
* Example (continued):
|
||||
* warp_bitmask := 1 << 2
|
||||
* index (tens): 0 0 0 0 0 0 0 ... 6 6 . .
|
||||
* (ones): 0 1 2 3 4 5 6 ... 2 3 . .
|
||||
* warp_bitmask: [0 0 1 0 0 0 0 ... 0 0 . .]
|
||||
*/
|
||||
uint64_t my_warp_bitmask_id = 1UL << warp_bit_id;
|
||||
|
||||
/*
|
||||
* Example (continued):
|
||||
* index (tens): 0 0 0 0 0 0 0 ... 6 6 . .
|
||||
* (ones): 0 1 2 3 4 5 6 ... 2 3 . .
|
||||
* lanes_bitfield: [1 0 1 0 1 0 1 ... 1 0 . .]
|
||||
* warp_bitmask: [0 0 1 0 0 0 0 ... 0 0 . .]
|
||||
*/
|
||||
bool is_an_active_lane = lanes_bitfield & my_warp_bitmask_id;
|
||||
|
||||
return is_an_active_lane;
|
||||
}
|
||||
|
||||
long long unsigned *_fetch_value = nullptr;
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
***************************** Test Fixture **********************************
|
||||
*****************************************************************************/
|
||||
class BitwiseTestFixture : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
BitwiseTestFixture() = default;
|
||||
|
||||
~BitwiseTestFixture()
|
||||
{
|
||||
if (_device_methods) {
|
||||
if (_device_methods->_fetch_value) {
|
||||
_hip_allocator.deallocate(_device_methods->_fetch_value);
|
||||
}
|
||||
_hip_allocator.deallocate(_device_methods);
|
||||
}
|
||||
if (_warp_matrix) {
|
||||
_hip_allocator.deallocate(_warp_matrix);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
**************************** Setup Methods ******************************
|
||||
*************************************************************************/
|
||||
void
|
||||
setup_fixture(dim3 block_dim, dim3 grid_dim)
|
||||
{
|
||||
_hip_block_dim = block_dim;
|
||||
_hip_grid_dim = grid_dim;
|
||||
_wf_size = get_wf_size();
|
||||
|
||||
assert(_device_methods == nullptr);
|
||||
_hip_allocator.allocate(reinterpret_cast<void**>(&_device_methods),
|
||||
sizeof(BitwiseDeviceMethods));
|
||||
|
||||
assert(_device_methods);
|
||||
|
||||
_hip_allocator.allocate(reinterpret_cast<void**>(&_device_methods->_fetch_value),
|
||||
sizeof(long long unsigned));
|
||||
|
||||
assert(_device_methods->_fetch_value);
|
||||
|
||||
*_device_methods->_fetch_value = 0;
|
||||
|
||||
assert(_warp_matrix == nullptr);
|
||||
_hip_allocator.allocate(reinterpret_cast<void**>(&_warp_matrix),
|
||||
sizeof(WarpMatrix));
|
||||
|
||||
size_t warps_per_block = ceil(float(_hip_block_dim.x) / WF_SIZE);
|
||||
|
||||
const ObjectStrategy *default_object_strategy =
|
||||
DefaultObjectStrategy::instance()->get();
|
||||
|
||||
assert(_warp_matrix);
|
||||
new (_warp_matrix) WarpMatrix(warps_per_block,
|
||||
_hip_grid_dim.x,
|
||||
_hip_allocator,
|
||||
*default_object_strategy);
|
||||
}
|
||||
|
||||
void
|
||||
zero_warp_matrix()
|
||||
{
|
||||
for (size_t row = 0; row < _warp_matrix->rows(); row++) {
|
||||
for (size_t col = 0; col < _warp_matrix->columns(); col++) {
|
||||
auto *entry = _warp_matrix->access(row, col);
|
||||
*entry = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
verify_zeroed_warp_matrix()
|
||||
{
|
||||
for (size_t row = 0; row < _warp_matrix->rows(); row++) {
|
||||
for (size_t col = 0; col < _warp_matrix->columns(); col++) {
|
||||
auto *entry = _warp_matrix->access(row, col);
|
||||
ASSERT_EQ(*entry, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*********************** Kernel Launch Methods ***************************
|
||||
*************************************************************************/
|
||||
void
|
||||
host_run_device_kernel(void(*fn)(BitwiseDeviceMethods*,
|
||||
WarpMatrix*,
|
||||
size_t),
|
||||
size_t activate_lanes_bitfield)
|
||||
{
|
||||
hipLaunchKernelGGL(fn,
|
||||
_hip_grid_dim,
|
||||
_hip_block_dim,
|
||||
0,
|
||||
nullptr,
|
||||
_device_methods,
|
||||
_warp_matrix,
|
||||
activate_lanes_bitfield);
|
||||
|
||||
CHECK_HIP(hipStreamSynchronize(nullptr));
|
||||
}
|
||||
|
||||
protected:
|
||||
/*************************************************************************
|
||||
********************** Implementation Variables *************************
|
||||
*************************************************************************/
|
||||
dim3 _hip_block_dim {};
|
||||
dim3 _hip_grid_dim {};
|
||||
HIPAllocator _hip_allocator {};
|
||||
WarpMatrix *_warp_matrix = nullptr;
|
||||
BitwiseDeviceMethods *_device_methods = nullptr;
|
||||
int _wf_size;
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // ROCSHMEM_BITWISE_GTEST_HPP
|
||||
@@ -0,0 +1,130 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "dlmalloc_gtest.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
// a small portion of the heap is not available due to cost of dlmalloc bookkeeping
|
||||
#define DLMALLOC_BOOKKEEPING static_cast<size_t>(128 * ALIGNMENT)
|
||||
|
||||
TEST_F(DLMallocTestFixture, used_0_bytes) {
|
||||
size_t heap_size{1 << 30};
|
||||
ASSERT_LE(strat_.get_used(), DLMALLOC_BOOKKEEPING);
|
||||
ASSERT_EQ(strat_.get_used() + strat_.get_avail(), heap_size);
|
||||
}
|
||||
|
||||
TEST_F(DLMallocTestFixture, alloc_0_bytes) {
|
||||
size_t initial_used{strat_.get_used()};
|
||||
char* c_ptr{nullptr};
|
||||
size_t size{0};
|
||||
strat_.alloc(&c_ptr, size);
|
||||
ASSERT_EQ(c_ptr, nullptr);
|
||||
ASSERT_EQ(strat_.get_used(), initial_used);
|
||||
}
|
||||
|
||||
TEST_F(DLMallocTestFixture, alloc_1_byte) {
|
||||
char* c_ptr{nullptr};
|
||||
size_t size{1};
|
||||
strat_.alloc(&c_ptr, size);
|
||||
ASSERT_NE(c_ptr, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(DLMallocTestFixture, alloc_128_bytes) {
|
||||
char* c_ptr{nullptr};
|
||||
size_t size{128};
|
||||
strat_.alloc(&c_ptr, size);
|
||||
ASSERT_NE(c_ptr, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(DLMallocTestFixture, alloc_256_bytes) {
|
||||
char* c_ptr{nullptr};
|
||||
size_t size{256};
|
||||
strat_.alloc(&c_ptr, size);
|
||||
ASSERT_NE(c_ptr, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(DLMallocTestFixture, alloc_512_bytes) {
|
||||
char* c_ptr{nullptr};
|
||||
size_t size{512};
|
||||
strat_.alloc(&c_ptr, size);
|
||||
ASSERT_NE(c_ptr, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(DLMallocTestFixture, alloc_513_bytes) {
|
||||
char* c_ptr{nullptr};
|
||||
size_t size{513};
|
||||
strat_.alloc(&c_ptr, size);
|
||||
ASSERT_NE(c_ptr, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(DLMallocTestFixture, alloc_4KB) {
|
||||
char* c_ptr{nullptr};
|
||||
size_t size{4096};
|
||||
strat_.alloc(&c_ptr, size);
|
||||
ASSERT_NE(c_ptr, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(DLMallocTestFixture, alloc_128KB) {
|
||||
char* c_ptr{nullptr};
|
||||
size_t size{131072};
|
||||
strat_.alloc(&c_ptr, size);
|
||||
ASSERT_NE(c_ptr, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(DLMallocTestFixture, alloc_1GB) {
|
||||
char* c_ptr{nullptr};
|
||||
size_t heap_size{1 << 30};
|
||||
size_t size{heap_size - DLMALLOC_BOOKKEEPING};
|
||||
|
||||
strat_.alloc(&c_ptr, size);
|
||||
ASSERT_NE(c_ptr, nullptr);
|
||||
ASSERT_EQ(strat_.get_used() + strat_.get_avail(), heap_size);
|
||||
}
|
||||
|
||||
TEST_F(DLMallocTestFixture, alloc_256_bytes_X2_free_256_bytes_X2) {
|
||||
char* c_ptr_1{nullptr};
|
||||
char* c_ptr_2{nullptr};
|
||||
size_t size{256};
|
||||
strat_.alloc(&c_ptr_1, size);
|
||||
ASSERT_NE(c_ptr_1, nullptr);
|
||||
strat_.alloc(&c_ptr_2, size);
|
||||
ASSERT_NE(c_ptr_2, nullptr);
|
||||
|
||||
strat_.free(c_ptr_1);
|
||||
strat_.free(c_ptr_2);
|
||||
}
|
||||
|
||||
TEST_F(DLMallocTestFixture, alloc_1GB_free_1GB) {
|
||||
char* c_ptr{nullptr};
|
||||
size_t heap_size{1 << 30};
|
||||
size_t size{heap_size - DLMALLOC_BOOKKEEPING};
|
||||
strat_.alloc(&c_ptr, size);
|
||||
ASSERT_NE(c_ptr, nullptr);
|
||||
ASSERT_EQ(strat_.get_used() + strat_.get_avail(), heap_size);
|
||||
|
||||
strat_.free(c_ptr);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ROCSHMEM_DLMALLOC_GTEST_HPP
|
||||
#define ROCSHMEM_DLMALLOC_GTEST_HPP
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "../src/memory/heap_memory.hpp"
|
||||
#include "../src/memory/hip_allocator.hpp"
|
||||
#include "../src/memory/dlmalloc.hpp"
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
class DLMallocTestFixture : public ::testing::Test
|
||||
{
|
||||
/**
|
||||
* @brief Helper type for heap memory
|
||||
*/
|
||||
using HEAP_T = HeapMemory<HIPAllocator>;
|
||||
|
||||
/**
|
||||
* @brief Helper type for allocation strategy
|
||||
*/
|
||||
using STRAT_T = DLAllocatorStrategy<HEAP_T>;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Heap memory object
|
||||
*/
|
||||
HEAP_T heap_mem_ {};
|
||||
|
||||
/**
|
||||
* @brief Allocation strategy object
|
||||
*/
|
||||
STRAT_T strat_ {&heap_mem_};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // ROCSHMEM_DLMALLOC_GTEST_HPP
|
||||
@@ -0,0 +1,283 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 <limits>
|
||||
|
||||
#include "envvar_gtest.hpp"
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
using VarTypes = ::testing::Types<bool,
|
||||
uint32_t,
|
||||
size_t,
|
||||
int64_t,
|
||||
std::string,
|
||||
envvar::types::socket_family,
|
||||
envvar::types::debug_level>;
|
||||
|
||||
TYPED_TEST_SUITE(EnvVarUnsetTestFixture, VarTypes);
|
||||
TYPED_TEST_SUITE(EnvVarSetTestFixture, VarTypes);
|
||||
|
||||
TYPED_TEST(EnvVarUnsetTestFixture, name) {
|
||||
EXPECT_EQ(this->var_.get_name(), this->var_full_name_);
|
||||
}
|
||||
|
||||
TYPED_TEST(EnvVarUnsetTestFixture, doc) {
|
||||
EXPECT_EQ(this->var_.get_doc(), this->var_doc_);
|
||||
}
|
||||
|
||||
TYPED_TEST(EnvVarUnsetTestFixture, is_default) {
|
||||
EXPECT_TRUE(this->var_.is_default());
|
||||
EXPECT_EQ(this->var_.get_value(), this->var_.get_default());
|
||||
}
|
||||
|
||||
TYPED_TEST(EnvVarSetTestFixture, is_default) {
|
||||
EXPECT_FALSE(this->var_.is_default());
|
||||
EXPECT_EQ(this->var_.get_value(), this->var_.get_default());
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, string_custom_default) {
|
||||
const std::string default_value_{"This is the default value."};
|
||||
const envvar::var<std::string> var_{this->var_name_, this->var_doc_, default_value_};
|
||||
EXPECT_TRUE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), default_value_);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_integer) {
|
||||
this->setenv("1073741824");
|
||||
const envvar::var<int64_t> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_FALSE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), 0);
|
||||
EXPECT_EQ(var_.get_value(), 1L << 30);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_integer_notaninteger) {
|
||||
this->setenv("Ceci n'est pas un entier.");
|
||||
const envvar::var<int64_t> var_{this->var_name_, this->var_doc_, 1L << 30};
|
||||
EXPECT_TRUE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_value(), 1L << 30);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_integer_large) {
|
||||
this->setenv("9223372036854775807");
|
||||
const envvar::var<int64_t> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_FALSE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), 0);
|
||||
EXPECT_EQ(var_.get_value(), std::numeric_limits<int64_t>::max());
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_integer_too_large) {
|
||||
this->setenv("9223372036854775808");
|
||||
const envvar::var<int64_t> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_TRUE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), 0);
|
||||
EXPECT_EQ(var_.get_value(), var_.get_default());
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_integer_negative) {
|
||||
this->setenv("-1073741824");
|
||||
const envvar::var<int64_t> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_FALSE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), 0);
|
||||
EXPECT_EQ(var_.get_value(), -1L << 30);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_integer_negative_large) {
|
||||
this->setenv("-9223372036854775808");
|
||||
const envvar::var<int64_t> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_FALSE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), 0);
|
||||
EXPECT_EQ(var_.get_value(), std::numeric_limits<int64_t>::min());
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_integer_negative_too_large) {
|
||||
this->setenv("-9223372036854775809");
|
||||
const envvar::var<int64_t> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_TRUE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), 0);
|
||||
EXPECT_EQ(var_.get_value(), var_.get_default());
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_integer_hex) {
|
||||
this->setenv("0x40000000");
|
||||
const envvar::var<int64_t> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_FALSE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), 0);
|
||||
EXPECT_EQ(var_.get_value(), 1L << 30);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_integer_hex_only) {
|
||||
this->setenv("0x40000000");
|
||||
const envvar::var<int64_t> var_{this->var_name_, this->var_doc_,
|
||||
envvar::parser::parse_hex<int64_t>{}};
|
||||
EXPECT_FALSE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), 0);
|
||||
EXPECT_EQ(var_.get_value(), 1L << 30);
|
||||
}
|
||||
|
||||
// parse_hex<> interprets input digits as hexadecimal, even without 0x prefix
|
||||
TEST_F(EnvVarTestFixture, parse_integer_hex_only_noprefix) {
|
||||
this->setenv("40000000");
|
||||
const envvar::var<int64_t> var_{this->var_name_, this->var_doc_,
|
||||
envvar::parser::parse_hex<int64_t>{}};
|
||||
EXPECT_FALSE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), 0);
|
||||
EXPECT_EQ(var_.get_value(), 1L << 30);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_unsigned_integer) {
|
||||
this->setenv("1073741824");
|
||||
const envvar::var<uint32_t> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_FALSE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), 0);
|
||||
EXPECT_EQ(var_.get_value(), 1L << 30);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_unsigned_integer_negative) {
|
||||
this->setenv("-1");
|
||||
const envvar::var<uint32_t> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_TRUE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), 0);
|
||||
EXPECT_EQ(var_.get_value(), var_.get_default());
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_unsigned_large) {
|
||||
this->setenv("4294967296");
|
||||
const envvar::var<uint32_t> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_TRUE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), 0);
|
||||
EXPECT_EQ(var_.get_value(), var_.get_default());
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_bool_zero) {
|
||||
this->setenv("0");
|
||||
const envvar::var<bool> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_FALSE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), false);
|
||||
EXPECT_EQ(var_.get_value(), false);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_bool_one) {
|
||||
this->setenv("1");
|
||||
const envvar::var<bool> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_FALSE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), false);
|
||||
EXPECT_EQ(var_.get_value(), true);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_bool_negative) {
|
||||
this->setenv("-1");
|
||||
const envvar::var<bool> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_TRUE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), false);
|
||||
EXPECT_EQ(var_.get_value(), false);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_bool_two) {
|
||||
this->setenv("2");
|
||||
const envvar::var<bool> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_TRUE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), false);
|
||||
EXPECT_EQ(var_.get_value(), false);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_bool_false) {
|
||||
this->setenv("false");
|
||||
const envvar::var<bool> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_FALSE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), false);
|
||||
EXPECT_EQ(var_.get_value(), false);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_bool_true) {
|
||||
this->setenv("true");
|
||||
const envvar::var<bool> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_FALSE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), false);
|
||||
EXPECT_EQ(var_.get_value(), true);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_bool_other) {
|
||||
this->setenv("other");
|
||||
const envvar::var<bool> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_TRUE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), false);
|
||||
EXPECT_EQ(var_.get_value(), false);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_socket_family_unspec) {
|
||||
this->setenv("UNSPEC");
|
||||
const envvar::var<envvar::types::socket_family> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_FALSE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), envvar::types::socket_family::UNSPEC);
|
||||
EXPECT_EQ(var_.get_value(), envvar::types::socket_family::UNSPEC);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_socket_family_af_unspec) {
|
||||
this->setenv("AF_UNSPEC");
|
||||
const envvar::var<envvar::types::socket_family> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_FALSE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), envvar::types::socket_family::UNSPEC);
|
||||
EXPECT_EQ(var_.get_value(), envvar::types::socket_family::UNSPEC);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_socket_family_inet) {
|
||||
this->setenv("INET");
|
||||
const envvar::var<envvar::types::socket_family> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_FALSE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), envvar::types::socket_family::UNSPEC);
|
||||
EXPECT_EQ(var_.get_value(), envvar::types::socket_family::INET);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_socket_family_af_inet) {
|
||||
this->setenv("AF_INET");
|
||||
const envvar::var<envvar::types::socket_family> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_FALSE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), envvar::types::socket_family::UNSPEC);
|
||||
EXPECT_EQ(var_.get_value(), envvar::types::socket_family::INET);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_socket_family_inet6) {
|
||||
this->setenv("INET6");
|
||||
const envvar::var<envvar::types::socket_family> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_FALSE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), envvar::types::socket_family::UNSPEC);
|
||||
EXPECT_EQ(var_.get_value(), envvar::types::socket_family::INET6);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_socket_family_af_inet6) {
|
||||
this->setenv("AF_INET6");
|
||||
const envvar::var<envvar::types::socket_family> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_FALSE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), envvar::types::socket_family::UNSPEC);
|
||||
EXPECT_EQ(var_.get_value(), envvar::types::socket_family::INET6);
|
||||
}
|
||||
|
||||
TEST_F(EnvVarTestFixture, parse_socket_family_nonesense) {
|
||||
this->setenv("'Twas brillig, and the slithy toves, did gyre and gimble in the wabe.");
|
||||
const envvar::var<envvar::types::socket_family> var_{this->var_name_, this->var_doc_};
|
||||
EXPECT_TRUE(var_.is_default());
|
||||
EXPECT_EQ(var_.get_default(), envvar::types::socket_family::UNSPEC);
|
||||
EXPECT_EQ(var_.get_value(), var_.get_default());
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ROCSHMEM_ENVVAR_GTEST_HPP
|
||||
#define ROCSHMEM_ENVVAR_GTEST_HPP
|
||||
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "../src/envvar.hpp"
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
class EnvVarTestFixture : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
static constexpr envvar::category::tag category_ = envvar::category::tag::ROCSHMEM;
|
||||
static constexpr const char* var_name_ = "GTEST";
|
||||
static constexpr const char* var_prefix_ = envvar::category::prefix<category_>;
|
||||
static inline const std::string var_full_name_{std::string(var_prefix_).append("_").append(var_name_)};
|
||||
static constexpr const char* var_doc_ = "Test envvar documentation: documents the test envvar.";
|
||||
|
||||
static int setenv(const char* value) {
|
||||
return ::setenv(var_full_name_.c_str(), value, true);
|
||||
}
|
||||
|
||||
static int setenv(const std::string& value) {
|
||||
return setenv(value.c_str());
|
||||
}
|
||||
|
||||
static int unsetenv() {
|
||||
return ::unsetenv(var_full_name_.c_str());
|
||||
}
|
||||
|
||||
protected:
|
||||
static void SetUpTestSuite() {
|
||||
unsetenv();
|
||||
}
|
||||
|
||||
static void TearDownTestSuite() {
|
||||
unsetenv();
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
unsetenv();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
unsetenv();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class EnvVarUnsetTestFixture : public EnvVarTestFixture
|
||||
{
|
||||
protected:
|
||||
const envvar::var<T> var_{var_name_, var_doc_};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class EnvVarSetTestFixture : public EnvVarTestFixture
|
||||
{
|
||||
protected:
|
||||
const envvar::var<T> var_{var_name_, var_doc_};
|
||||
|
||||
static void SetUpTestSuite() {
|
||||
std::ostringstream oss{};
|
||||
oss << T{};
|
||||
setenv(oss.str());
|
||||
}
|
||||
};
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // ROCSHMEM_ENVVAR_GTEST_HPP
|
||||
@@ -0,0 +1,309 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "free_list_gtest.hpp"
|
||||
|
||||
#include "../src/util.hpp"
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
/*****************************************************************************
|
||||
******************************* Fixture Tests *******************************
|
||||
*****************************************************************************/
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
template <typename List, typename Value>
|
||||
__global__ void pop_all(List* list, Value* values, const std::size_t count) {
|
||||
const auto stride = blockDim.x * gridDim.x;
|
||||
const auto thread_index = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
// One push per block. block size is always WF_SIZE
|
||||
for (std::size_t i = thread_index; i < count * WF_SIZE; i += stride) {
|
||||
if (is_thread_zero_in_wave()) {
|
||||
auto last = list->pop_front();
|
||||
if (values != nullptr) {
|
||||
values[i / WF_SIZE] = last.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename List, typename Value>
|
||||
__global__ void push_all(List* list, const Value* values,
|
||||
const std::size_t count) {
|
||||
const auto stride = blockDim.x * gridDim.x;
|
||||
const auto thread_index = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
// One push per block. block size is always WF_SIZE
|
||||
for (std::size_t i = thread_index; i < count * WF_SIZE; i += stride) {
|
||||
if (is_thread_zero_in_wave()) {
|
||||
list->push_back(values[i / WF_SIZE]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename List>
|
||||
__global__ void pop_empty(List* list, bool* empty) {
|
||||
auto pop_result = list->pop_front();
|
||||
*empty = !pop_result.success;
|
||||
}
|
||||
} // namespace rocshmem
|
||||
|
||||
TYPED_TEST(FreeListTestFixture, pop_empty_device) {
|
||||
using Allocator = typename TestFixture::Allocator;
|
||||
using T = typename TestFixture::T;
|
||||
|
||||
auto& h_input = this->h_input;
|
||||
auto& free_list = this->free_list;
|
||||
auto& hip_allocator_ = this->hip_allocator_;
|
||||
|
||||
bool *is_empty {nullptr};
|
||||
hip_allocator_.allocate(reinterpret_cast<void**>(&is_empty),
|
||||
sizeof(bool));
|
||||
|
||||
CHECK_HIP(hipMemset(is_empty, 0, sizeof(bool)));
|
||||
FreeListProxy<Allocator, T> empty_list_proxy{};
|
||||
FreeList<T, Allocator>* empty_free_list{empty_list_proxy.get()};
|
||||
|
||||
rocshmem::pop_empty<<<1, 1>>>(empty_free_list, is_empty);
|
||||
CHECK_HIP(hipDeviceSynchronize());
|
||||
EXPECT_TRUE(is_empty[0]);
|
||||
|
||||
hip_allocator_.deallocate(is_empty);
|
||||
}
|
||||
|
||||
TYPED_TEST(FreeListTestFixture, push_host_pop_device) {
|
||||
using Allocator = typename TestFixture::Allocator;
|
||||
using T = typename TestFixture::T;
|
||||
|
||||
auto& h_input = this->h_input;
|
||||
auto& free_list = this->free_list;
|
||||
auto& hip_allocator_ = this->hip_allocator_;
|
||||
|
||||
T *results {nullptr};
|
||||
bool *is_empty {nullptr};
|
||||
size_t size_bytes = sizeof(T) * h_input.size() + sizeof(bool);
|
||||
hip_allocator_.allocate(reinterpret_cast<void**>(&results),
|
||||
size_bytes);
|
||||
|
||||
CHECK_HIP(hipMemset(results, 0, size_bytes));
|
||||
is_empty = reinterpret_cast<bool*>(results + h_input.size());
|
||||
const auto block_size = this->wf_size;
|
||||
rocshmem::pop_all<<<1, block_size>>>(free_list, results, h_input.size());
|
||||
CHECK_HIP(hipDeviceSynchronize());
|
||||
|
||||
for (std::size_t i = 0; i < h_input.size(); i++) {
|
||||
EXPECT_EQ(results[i], h_input[i]);
|
||||
}
|
||||
|
||||
rocshmem::pop_empty<<<1, 1>>>(free_list, is_empty);
|
||||
CHECK_HIP(hipDeviceSynchronize());
|
||||
|
||||
EXPECT_TRUE(is_empty[0]);
|
||||
hip_allocator_.deallocate(results);
|
||||
}
|
||||
|
||||
TYPED_TEST(FreeListTestFixture, push_host_concurrent_pop_device) {
|
||||
using Allocator = typename TestFixture::Allocator;
|
||||
using T = typename TestFixture::T;
|
||||
|
||||
auto& h_input = this->h_input;
|
||||
auto& free_list = this->free_list;
|
||||
auto& hip_allocator_ = this->hip_allocator_;
|
||||
|
||||
T *results {nullptr};
|
||||
bool *is_empty {nullptr};
|
||||
size_t size_bytes = sizeof(T) * h_input.size() + sizeof(bool);
|
||||
hip_allocator_.allocate(reinterpret_cast<void**>(&results),
|
||||
size_bytes);
|
||||
|
||||
CHECK_HIP(hipMemset(results, 0, size_bytes));
|
||||
is_empty = reinterpret_cast<bool*>(results + h_input.size());
|
||||
const auto num_blocks = h_input.size();
|
||||
const auto block_size = this->wf_size;
|
||||
rocshmem::pop_all<<<num_blocks, block_size>>>(
|
||||
free_list, results, h_input.size());
|
||||
CHECK_HIP(hipDeviceSynchronize());
|
||||
|
||||
std::vector<T> h_results(h_input.size());
|
||||
CHECK_HIP(hipMemcpy(h_results.data(), results, sizeof(T) * h_input.size(),
|
||||
hipMemcpyDeviceToHost));
|
||||
|
||||
// sort to guarantee that the ordering is correct
|
||||
std::sort(h_input.begin(), h_input.end());
|
||||
std::sort(h_results.begin(), h_results.end());
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < h_results.size(); i++) {
|
||||
EXPECT_EQ(h_results[i], h_input[i]);
|
||||
}
|
||||
|
||||
rocshmem::pop_empty<<<1, 1>>>(free_list, is_empty);
|
||||
CHECK_HIP(hipDeviceSynchronize());
|
||||
|
||||
EXPECT_TRUE(is_empty[0]);
|
||||
hip_allocator_.deallocate(results);
|
||||
}
|
||||
|
||||
TYPED_TEST(FreeListTestFixture, push_host_pop_push_device) {
|
||||
using Allocator = typename TestFixture::Allocator;
|
||||
using T = typename TestFixture::T;
|
||||
using FreeListType = FreeList<T, Allocator>;
|
||||
|
||||
auto& h_input = this->h_input;
|
||||
auto& free_list = this->free_list;
|
||||
auto& hip_allocator_ = this->hip_allocator_;
|
||||
|
||||
T *results {nullptr};
|
||||
T *d_input {nullptr};
|
||||
bool *is_empty {nullptr};
|
||||
size_t size_bytes = 2 * sizeof(T) * h_input.size() + sizeof(bool);
|
||||
hip_allocator_.allocate(reinterpret_cast<void**>(&results),
|
||||
size_bytes);
|
||||
|
||||
CHECK_HIP(hipMemset(results, 0, size_bytes));
|
||||
d_input = reinterpret_cast<T*>(results + h_input.size());
|
||||
is_empty = reinterpret_cast<bool*>(d_input + h_input.size());
|
||||
const auto block_size = this->wf_size;
|
||||
|
||||
CHECK_HIP(hipMemcpy(d_input, h_input.data(), sizeof(T) * h_input.size(),
|
||||
hipMemcpyHostToDevice));
|
||||
|
||||
rocshmem::pop_all<FreeListType, T><<<1, block_size>>>(
|
||||
free_list, nullptr, h_input.size());
|
||||
CHECK_HIP(hipDeviceSynchronize());
|
||||
|
||||
rocshmem::push_all<<<1, block_size>>>(free_list, d_input, h_input.size());
|
||||
CHECK_HIP(hipDeviceSynchronize());
|
||||
|
||||
rocshmem::pop_all<<<1, block_size>>>(free_list, results, h_input.size());
|
||||
CHECK_HIP(hipDeviceSynchronize());
|
||||
|
||||
for (std::size_t i = 0; i < h_input.size(); i++) {
|
||||
EXPECT_EQ(results[i], h_input[i]);
|
||||
}
|
||||
|
||||
hip_allocator_.deallocate(results);
|
||||
}
|
||||
|
||||
TYPED_TEST(FreeListTestFixture, push_host_pop_concurrent_push_device) {
|
||||
using Allocator = typename TestFixture::Allocator;
|
||||
using T = typename TestFixture::T;
|
||||
using FreeListType = FreeList<T, Allocator>;
|
||||
|
||||
auto& h_input = this->h_input;
|
||||
auto& free_list = this->free_list;
|
||||
auto& hip_allocator_ = this->hip_allocator_;
|
||||
|
||||
T *results {nullptr};
|
||||
T *d_input {nullptr};
|
||||
size_t size_bytes = 2 * sizeof(T) * h_input.size();
|
||||
hip_allocator_.allocate(reinterpret_cast<void**>(&results),
|
||||
size_bytes);
|
||||
|
||||
CHECK_HIP(hipMemset(results, 0, size_bytes));
|
||||
d_input = reinterpret_cast<T*>(results + h_input.size());
|
||||
const auto block_size = this->wf_size;
|
||||
|
||||
CHECK_HIP(hipMemcpy(d_input, h_input.data(), sizeof(T) * h_input.size(),
|
||||
hipMemcpyHostToDevice));
|
||||
|
||||
rocshmem::pop_all<FreeListType, T><<<1, block_size>>>(
|
||||
free_list, nullptr,h_input.size());
|
||||
CHECK_HIP(hipDeviceSynchronize());
|
||||
|
||||
// Concurrently push all values
|
||||
const auto num_blocks = h_input.size();
|
||||
rocshmem::push_all<<<num_blocks, block_size>>>(
|
||||
free_list, d_input, h_input.size());
|
||||
CHECK_HIP(hipDeviceSynchronize());
|
||||
|
||||
rocshmem::pop_all<<<1, block_size>>>(free_list, results, h_input.size());
|
||||
CHECK_HIP(hipDeviceSynchronize());
|
||||
|
||||
std::vector<T> h_results(h_input.size());
|
||||
CHECK_HIP(hipMemcpy(h_results.data(), results, sizeof(T) * h_input.size(),
|
||||
hipMemcpyDeviceToHost));
|
||||
|
||||
// sort to guarantee that the ordering is correct
|
||||
std::sort(h_input.begin(), h_input.end());
|
||||
std::sort(h_results.begin(), h_results.end());
|
||||
|
||||
for (std::size_t i = 0; i < h_results.size(); i++) {
|
||||
EXPECT_EQ(h_results[i], h_input[i]);
|
||||
}
|
||||
|
||||
hip_allocator_.deallocate(results);
|
||||
}
|
||||
|
||||
TYPED_TEST(FreeListTestFixture, push_host_concurrent_pop_push_device) {
|
||||
using Allocator = typename TestFixture::Allocator;
|
||||
using T = typename TestFixture::T;
|
||||
using FreeListType = FreeList<T, Allocator>;
|
||||
|
||||
auto& h_input = this->h_input;
|
||||
auto& free_list = this->free_list;
|
||||
auto& hip_allocator_ = this->hip_allocator_;
|
||||
|
||||
T *results {nullptr};
|
||||
T *d_input {nullptr};
|
||||
size_t size_bytes = 2 * sizeof(T) * h_input.size();
|
||||
hip_allocator_.allocate(reinterpret_cast<void**>(&results),
|
||||
size_bytes);
|
||||
|
||||
CHECK_HIP(hipMemset(results, 0, size_bytes));
|
||||
d_input = reinterpret_cast<T*>(results + h_input.size());
|
||||
|
||||
CHECK_HIP(hipMemcpy(d_input, h_input.data(), sizeof(T) * h_input.size(),
|
||||
hipMemcpyHostToDevice));
|
||||
|
||||
const auto block_size = this->wf_size;
|
||||
rocshmem::pop_all<FreeListType, T><<<1, block_size>>>(
|
||||
free_list, nullptr, h_input.size());
|
||||
CHECK_HIP(hipDeviceSynchronize());
|
||||
|
||||
// Concurrently push all values
|
||||
const auto num_blocks = h_input.size();
|
||||
rocshmem::push_all<<<num_blocks, block_size>>>(
|
||||
free_list, d_input, h_input.size());
|
||||
CHECK_HIP(hipDeviceSynchronize());
|
||||
|
||||
// Concurrently pop all values
|
||||
rocshmem::pop_all<<<num_blocks, block_size>>>(
|
||||
free_list, results, h_input.size());
|
||||
CHECK_HIP(hipDeviceSynchronize());
|
||||
|
||||
std::vector<T> h_results(h_input.size());
|
||||
CHECK_HIP(hipMemcpy(h_results.data(), results, sizeof(T) * h_input.size(),
|
||||
hipMemcpyDeviceToHost));
|
||||
|
||||
// sort to guarantee that the ordering is correct
|
||||
std::sort(h_input.begin(), h_input.end());
|
||||
std::sort(h_results.begin(), h_results.end());
|
||||
|
||||
for (std::size_t i = 0; i < h_results.size(); i++) {
|
||||
EXPECT_EQ(h_results[i], h_input[i]);
|
||||
}
|
||||
|
||||
hip_allocator_.deallocate(results);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ROCSHMEM_FREE_LIST_GTEST_HPP
|
||||
#define ROCSHMEM_FREE_LIST_GTEST_HPP
|
||||
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
|
||||
#include "../src/containers/free_list_impl.hpp"
|
||||
#include "gtest/gtest.h"
|
||||
#include "../src/memory/hip_allocator.hpp"
|
||||
#include "wf_size.hpp"
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
template <typename ValueType>
|
||||
class FreeListTestFixture : public ::testing::Test {
|
||||
public:
|
||||
FreeListTestFixture() : h_input(num_elements) {
|
||||
std::iota(h_input.begin(), h_input.end(), T{1});
|
||||
free_list = list_proxy.get();
|
||||
}
|
||||
|
||||
protected:
|
||||
void SetUp() override {
|
||||
free_list->push_back_range(h_input.begin(), h_input.end());
|
||||
wf_size = get_wf_size();
|
||||
}
|
||||
|
||||
using T = ValueType;
|
||||
using Allocator = HIPAllocator;
|
||||
Allocator hip_allocator_ {};
|
||||
const std::size_t num_elements{32};
|
||||
std::vector<T> h_input{};
|
||||
int wf_size;
|
||||
|
||||
FreeListProxy<Allocator, T> list_proxy{};
|
||||
FreeList<T, Allocator>* free_list{};
|
||||
};
|
||||
|
||||
using TestTypes = ::testing::Types<std::uint32_t, std::uint64_t>;
|
||||
TYPED_TEST_SUITE(FreeListTestFixture, TestTypes);
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // ROCSHMEM_FREE_LIST_GTEST_HPP
|
||||
@@ -0,0 +1,41 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "heap_memory_gtest.hpp"
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
TEST(HeapMemoryTest, size_constructor) {
|
||||
HeapMemory<HIPAllocator> heap_mem{2048};
|
||||
ASSERT_EQ(heap_mem.get_size(), 2048);
|
||||
ASSERT_NE(heap_mem.get_ptr(), nullptr);
|
||||
}
|
||||
|
||||
TEST_F(HeapMemoryTestFixture, size_check) {
|
||||
ASSERT_EQ(heap_mem_.get_size(), 1 << 30);
|
||||
}
|
||||
|
||||
TEST_F(HeapMemoryTestFixture, ptr_check) {
|
||||
ASSERT_NE(heap_mem_.get_ptr(), nullptr);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ROCSHMEM_HEAP_MEMORY_GTEST_HPP
|
||||
#define ROCSHMEM_HEAP_MEMORY_GTEST_HPP
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <hip/hip_runtime_api.h>
|
||||
|
||||
#include "../src/memory/hip_allocator.hpp"
|
||||
#include "../src/memory/heap_memory.hpp"
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
class HeapMemoryTestFixture : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* @brief a heap memory object
|
||||
*/
|
||||
HeapMemory<HIPAllocator> heap_mem_ {};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // ROCSHMEM_HEAP_MEMORY_GTEST_HPP
|
||||
@@ -0,0 +1,45 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "hipmalloc_gtest.hpp"
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
TEST_F(HipMallocTestFixture, normal_1GBx256) {
|
||||
void* ptr{nullptr};
|
||||
size_t gb {1073741824};
|
||||
for (int i{0}; i < 256; i++) {
|
||||
hip_allocator_.allocate(&ptr, gb);
|
||||
hip_allocator_.deallocate(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(HipMallocTestFixture, fine_1GBx256) {
|
||||
void* ptr{nullptr};
|
||||
size_t gb {1073741824};
|
||||
for (int i{0}; i < 256; i++) {
|
||||
hip_allocator_fg_.allocate(&ptr, gb);
|
||||
hip_allocator_fg_.deallocate(ptr);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ROCSHMEM_HIPMALLOC_GTEST_HPP
|
||||
#define ROCSHMEM_HIPMALLOC_GTEST_HPP
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "../src/memory/symmetric_heap.hpp"
|
||||
#include "../src/util.hpp"
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
class HipMallocTestFixture : public ::testing::Test {
|
||||
public:
|
||||
HIPAllocator hip_allocator_ {};
|
||||
HIPAllocatorFinegrained hip_allocator_fg_ {};
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // ROCSHMEM_HIPMALLOC_GTEST_HPP
|
||||
@@ -0,0 +1,157 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "index_strategy_gtest.hpp"
|
||||
|
||||
#define HIP_ENABLE_PRINTF
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TCBA_memory_set_test_grid_1_1_1_block_1_1_1) {
|
||||
using IndexStrategy = Thread_Contiguous_Block_Agnostic;
|
||||
run_memory_set_test<IndexStrategy>({1, 1, 1}, {1, 1, 1});
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBD_memory_set_test_grid_1_1_1_block_64_1_1) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Discontiguous;
|
||||
run_memory_set_test<IndexStrategy>({1, 1, 1}, {64, 1, 1});
|
||||
}
|
||||
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBD_memory_set_test_grid_1_1_1_block_64_2_1) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Discontiguous;
|
||||
run_memory_set_test<IndexStrategy>({1, 1, 1}, {64, 2, 1});
|
||||
}
|
||||
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBD_memory_set_test_grid_1_1_1_block_64_4_1) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Discontiguous;
|
||||
run_memory_set_test<IndexStrategy>({1, 1, 1}, {64, 4, 1});
|
||||
}
|
||||
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBD_memory_set_test_grid_1_1_1_block_64_16_1) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Discontiguous;
|
||||
run_memory_set_test<IndexStrategy>({1, 1, 1}, {64, 16, 1});
|
||||
}
|
||||
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBD_memory_set_test_grid_1_1_1_block_16_16_4) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Discontiguous;
|
||||
run_memory_set_test<IndexStrategy>({1, 1, 1}, {16, 16, 4});
|
||||
}
|
||||
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBD_memory_set_test_grid_4_1_1_block_16_16_4) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Discontiguous;
|
||||
run_memory_set_test<IndexStrategy>({4, 1, 1}, {16, 16, 4});
|
||||
}
|
||||
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBD_memory_set_test_grid_4_4_4_block_16_16_4) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Discontiguous;
|
||||
run_memory_set_test<IndexStrategy>({4, 4, 4}, {16, 16, 4});
|
||||
}
|
||||
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBD_memory_set_test_grid_1024_8_8_block_1024_1_1) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Discontiguous;
|
||||
run_memory_set_test<IndexStrategy>({1024, 8, 8}, {1024, 1, 1});
|
||||
}
|
||||
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBD_memory_set_test_grid_1024_8_8_block_1_1024_1) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Discontiguous;
|
||||
run_memory_set_test<IndexStrategy>({1024, 8, 8}, {1, 1024, 1});
|
||||
}
|
||||
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBD_memory_set_test_grid_1024_8_8_block_1_1_1024) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Discontiguous;
|
||||
run_memory_set_test<IndexStrategy>({1024, 8, 8}, {1, 1, 1024});
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBC_memory_set_test_grid_1_1_1_block_64_1_1) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Contiguous;
|
||||
run_memory_set_test<IndexStrategy>({1, 1, 1}, {64, 1, 1});
|
||||
}
|
||||
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBC_memory_set_test_grid_1_1_1_block_64_2_1) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Contiguous;
|
||||
run_memory_set_test<IndexStrategy>({1, 1, 1}, {64, 2, 1});
|
||||
}
|
||||
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBC_memory_set_test_grid_1_1_1_block_64_4_1) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Contiguous;
|
||||
run_memory_set_test<IndexStrategy>({1, 1, 1}, {64, 4, 1});
|
||||
}
|
||||
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBC_memory_set_test_grid_1_1_1_block_64_16_1) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Contiguous;
|
||||
run_memory_set_test<IndexStrategy>({1, 1, 1}, {64, 16, 1});
|
||||
}
|
||||
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBC_memory_set_test_grid_1_1_1_block_16_16_4) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Contiguous;
|
||||
run_memory_set_test<IndexStrategy>({1, 1, 1}, {16, 16, 4});
|
||||
}
|
||||
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBC_memory_set_test_grid_4_1_1_block_16_16_4) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Contiguous;
|
||||
run_memory_set_test<IndexStrategy>({4, 1, 1}, {16, 16, 4});
|
||||
}
|
||||
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBC_memory_set_test_grid_4_4_4_block_16_16_4) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Contiguous;
|
||||
run_memory_set_test<IndexStrategy>({4, 4, 4}, {16, 16, 4});
|
||||
}
|
||||
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBC_memory_set_test_grid_1024_8_8_block_1024_1_1) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Contiguous;
|
||||
run_memory_set_test<IndexStrategy>({1024, 8, 8}, {1024, 1, 1});
|
||||
}
|
||||
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBC_memory_set_test_grid_1024_8_8_block_1_1024_1) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Contiguous;
|
||||
run_memory_set_test<IndexStrategy>({1024, 8, 8}, {1, 1024, 1});
|
||||
}
|
||||
|
||||
TEST_F(IndexStrategyTestFixture,
|
||||
run_TDBC_memory_set_test_grid_1024_8_8_block_1_1_1024) {
|
||||
using IndexStrategy = Thread_Discontiguous_Block_Contiguous;
|
||||
run_memory_set_test<IndexStrategy>({1024, 8, 8}, {1, 1, 1024});
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ROCSHMEM_INDEX_STRATEGY_GTEST_HPP
|
||||
#define ROCSHMEM_INDEX_STRATEGY_GTEST_HPP
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "../src/containers/index_strategy.hpp"
|
||||
#include "../src/memory/hip_allocator.hpp"
|
||||
#include "../src/util.hpp"
|
||||
|
||||
#include <hip/hip_runtime_api.h>
|
||||
#include <cassert>
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
template <typename INDEX_STRAT>
|
||||
__global__
|
||||
void
|
||||
memory_set(int *raw_mem, size_t num_elems)
|
||||
{
|
||||
assert(raw_mem);
|
||||
|
||||
INDEX_STRAT idx_strat(num_elems);
|
||||
|
||||
for (size_t i = idx_strat.start();
|
||||
i < idx_strat.end();
|
||||
i = idx_strat.next(i)) {
|
||||
raw_mem[i]++;
|
||||
}
|
||||
}
|
||||
|
||||
class IndexStrategyTestFixture : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
IndexStrategyTestFixture()
|
||||
{
|
||||
assert(_raw_mem == nullptr);
|
||||
size_t raw_mem_size_bytes = sizeof(int) * _mem_elements;
|
||||
_hip_allocator.allocate(reinterpret_cast<void**>(&_raw_mem),
|
||||
raw_mem_size_bytes);
|
||||
|
||||
assert(_raw_mem);
|
||||
for (size_t i = 0; i < _mem_elements; i++) {
|
||||
_raw_mem[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
~IndexStrategyTestFixture()
|
||||
{
|
||||
if (_raw_mem) {
|
||||
_hip_allocator.deallocate(_raw_mem);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename INDEX_STRAT>
|
||||
void
|
||||
run_memory_set_test(const dim3 grid_dim, const dim3 block_dim)
|
||||
{
|
||||
hipLaunchKernelGGL(memory_set<INDEX_STRAT>,
|
||||
grid_dim,
|
||||
block_dim,
|
||||
0,
|
||||
nullptr,
|
||||
_raw_mem,
|
||||
_mem_elements);
|
||||
|
||||
CHECK_HIP(hipStreamSynchronize(nullptr));
|
||||
|
||||
for(size_t i = 0; i < _mem_elements; i++) {
|
||||
EXPECT_EQ(_raw_mem[i], 1);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
int *_raw_mem = nullptr;
|
||||
HIPAllocator _hip_allocator {};
|
||||
static constexpr size_t _mem_elements = 262144;
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // ROCSHMEM_INDEX_STRATEGY_GTEST_HPP
|
||||
@@ -0,0 +1,203 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "ipc_impl_simple_coarse_gtest.hpp"
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
|
||||
TEST_P(DegenerateSimpleCoarse, ptr_check) {
|
||||
ASSERT_NE(heap_mem_.get_ptr(), nullptr);
|
||||
}
|
||||
|
||||
TEST_P(DegenerateSimpleCoarse, MPI_num_pes) {
|
||||
ASSERT_EQ(mpi_->num_pes(), 2);
|
||||
}
|
||||
|
||||
TEST_P(DegenerateSimpleCoarse, IPC_bases) {
|
||||
ASSERT_EQ(mpi_->num_pes(), 2);
|
||||
ASSERT_NE(ipc_impl_.ipc_bases, nullptr);
|
||||
for(int i{0}; i < mpi_->num_pes(); i++) {
|
||||
ASSERT_NE(ipc_impl_.ipc_bases[i], nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(DegenerateSimpleCoarse, golden_1048576_int) {
|
||||
iota_golden(1048576);
|
||||
validate_golden(1048576);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
IPCImplSimpleCoarseTestFixture,
|
||||
DegenerateSimpleCoarse,
|
||||
::testing::Values(
|
||||
std::make_tuple(1, 1, 1))
|
||||
);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
TEST_P(ParameterizedBlockSimpleCoarse, write) {
|
||||
dim3 grid = dim3(std::get<0>(GetParam()), 1, 1);
|
||||
dim3 block = dim3(std::get<1>(GetParam()), 1, 1);
|
||||
size_t size = std::get<2>(GetParam());
|
||||
write(grid, block, size);
|
||||
}
|
||||
|
||||
TEST_P(ParameterizedBlockSimpleCoarse, read) {
|
||||
dim3 grid = dim3(std::get<0>(GetParam()), 1, 1);
|
||||
dim3 block = dim3(std::get<1>(GetParam()), 1, 1);
|
||||
size_t size = std::get<2>(GetParam());
|
||||
read(grid, block, size);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
IPCImplSimpleCoarseTestFixture,
|
||||
ParameterizedBlockSimpleCoarse,
|
||||
::testing::Values(
|
||||
std::make_tuple(1, 1024, 32), // 0
|
||||
std::make_tuple(1, 1, 1048576), // 1
|
||||
std::make_tuple(1, 2, 1048576), // 2
|
||||
std::make_tuple(1, 4, 1048576), // 3
|
||||
std::make_tuple(1, 8, 1048576), // 4
|
||||
std::make_tuple(1, 16, 1048576), // 5
|
||||
std::make_tuple(1, 32, 1048576), // 6
|
||||
std::make_tuple(1, 64, 1048576), // 7
|
||||
std::make_tuple(1, 128, 1048576), // 8
|
||||
std::make_tuple(1, 256, 1048576), // 9
|
||||
std::make_tuple(1, 512, 1048576), // 10
|
||||
std::make_tuple(1, 768, 1048576), // 11
|
||||
std::make_tuple(1, 1024, 1048576)) // 12
|
||||
);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
TEST_P(ParameterizedWarpSimpleCoarse, write) {
|
||||
dim3 grid = dim3(std::get<0>(GetParam()), 1, 1);
|
||||
dim3 block = dim3(std::get<1>(GetParam()), 1, 1);
|
||||
size_t size = std::get<2>(GetParam());
|
||||
write(grid, block, size);
|
||||
}
|
||||
|
||||
TEST_P(ParameterizedWarpSimpleCoarse, read) {
|
||||
dim3 grid = dim3(std::get<0>(GetParam()), 1, 1);
|
||||
dim3 block = dim3(std::get<1>(GetParam()), 1, 1);
|
||||
size_t size = std::get<2>(GetParam());
|
||||
read(grid, block, size);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
IPCImplSimpleCoarseTestFixture,
|
||||
ParameterizedWarpSimpleCoarse,
|
||||
::testing::Values(
|
||||
std::make_tuple(1, 64, 1), // 0
|
||||
std::make_tuple(1, 64, 32), // 1
|
||||
std::make_tuple(1, 1, 1048576), // 2
|
||||
std::make_tuple(1, 2, 1048576), // 3
|
||||
std::make_tuple(1, 3, 1048576), // 4
|
||||
std::make_tuple(1, 4, 1048576), // 5
|
||||
std::make_tuple(1, 5, 1048576), // 6
|
||||
std::make_tuple(1, 6, 1048576), // 7
|
||||
std::make_tuple(1, 7, 1048576), // 8
|
||||
std::make_tuple(1, 8, 1048576), // 9
|
||||
std::make_tuple(1, 9, 1048576), // 10
|
||||
std::make_tuple(1, 10, 1048576), // 11
|
||||
std::make_tuple(1, 11, 1048576), // 12
|
||||
std::make_tuple(1, 12, 1048576), // 13
|
||||
std::make_tuple(1, 13, 1048576), // 14
|
||||
std::make_tuple(1, 14, 1048576), // 15
|
||||
std::make_tuple(1, 15, 1048576), // 16
|
||||
std::make_tuple(1, 16, 1048576), // 17
|
||||
std::make_tuple(1, 17, 1048576), // 18
|
||||
std::make_tuple(1, 18, 1048576), // 19
|
||||
std::make_tuple(1, 19, 1048576), // 20
|
||||
std::make_tuple(1, 20, 1048576), // 21
|
||||
std::make_tuple(1, 21, 1048576), // 22
|
||||
std::make_tuple(1, 22, 1048576), // 23
|
||||
std::make_tuple(1, 23, 1048576), // 24
|
||||
std::make_tuple(1, 24, 1048576), // 25
|
||||
std::make_tuple(1, 25, 1048576), // 26
|
||||
std::make_tuple(1, 26, 1048576), // 27
|
||||
std::make_tuple(1, 27, 1048576), // 28
|
||||
std::make_tuple(1, 28, 1048576), // 29
|
||||
std::make_tuple(1, 28, 1048576), // 30
|
||||
std::make_tuple(1, 29, 1048576), // 31
|
||||
std::make_tuple(1, 30, 1048576), // 32
|
||||
std::make_tuple(1, 31, 1048576), // 33
|
||||
std::make_tuple(1, 32, 1048576), // 34
|
||||
std::make_tuple(1, 33, 1048576), // 35
|
||||
std::make_tuple(1, 34, 1048576), // 36
|
||||
std::make_tuple(1, 35, 1048576), // 37
|
||||
std::make_tuple(1, 36, 1048576), // 38
|
||||
std::make_tuple(1, 37, 1048576), // 39
|
||||
std::make_tuple(1, 38, 1048576), // 40
|
||||
std::make_tuple(1, 39, 1048576), // 41
|
||||
std::make_tuple(1, 40, 1048576), // 42
|
||||
std::make_tuple(1, 41, 1048576), // 43
|
||||
std::make_tuple(1, 42, 1048576), // 44
|
||||
std::make_tuple(1, 43, 1048576), // 45
|
||||
std::make_tuple(1, 44, 1048576), // 46
|
||||
std::make_tuple(1, 45, 1048576), // 47
|
||||
std::make_tuple(1, 46, 1048576), // 48
|
||||
std::make_tuple(1, 47, 1048576), // 49
|
||||
std::make_tuple(1, 48, 1048576), // 50
|
||||
std::make_tuple(1, 49, 1048576), // 51
|
||||
std::make_tuple(1, 50, 1048576), // 52
|
||||
std::make_tuple(1, 51, 1048576), // 53
|
||||
std::make_tuple(1, 52, 1048576), // 54
|
||||
std::make_tuple(1, 53, 1048576), // 55
|
||||
std::make_tuple(1, 54, 1048576), // 56
|
||||
std::make_tuple(1, 55, 1048576), // 57
|
||||
std::make_tuple(1, 56, 1048576), // 58
|
||||
std::make_tuple(1, 57, 1048576), // 59
|
||||
std::make_tuple(1, 58, 1048576), // 60
|
||||
std::make_tuple(1, 59, 1048576), // 61
|
||||
std::make_tuple(1, 60, 1048576), // 62
|
||||
std::make_tuple(1, 61, 1048576), // 63
|
||||
std::make_tuple(1, 62, 1048576), // 64
|
||||
std::make_tuple(1, 63, 1048576), // 65
|
||||
std::make_tuple(1, 64, 1048576)) // 66
|
||||
);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
TEST_P(ParameterizedThreadSimpleCoarse, write) {
|
||||
dim3 grid = dim3(std::get<0>(GetParam()), 1, 1);
|
||||
dim3 block = dim3(std::get<1>(GetParam()), 1, 1);
|
||||
size_t size = std::get<2>(GetParam());
|
||||
write(grid, block, size);
|
||||
}
|
||||
|
||||
TEST_P(ParameterizedThreadSimpleCoarse, read) {
|
||||
dim3 grid = dim3(std::get<0>(GetParam()), 1, 1);
|
||||
dim3 block = dim3(std::get<1>(GetParam()), 1, 1);
|
||||
size_t size = std::get<2>(GetParam());
|
||||
read(grid, block, size);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
IPCImplSimpleCoarseTestFixture,
|
||||
ParameterizedThreadSimpleCoarse,
|
||||
::testing::Values(
|
||||
std::make_tuple(1, 1, 1048576))
|
||||
);
|
||||
@@ -0,0 +1,233 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ROCSHMEM_IPC_IMPL_SIMPLE_COARSE_GTEST_HPP
|
||||
#define ROCSHMEM_IPC_IMPL_SIMPLE_COARSE_GTEST_HPP
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <numeric>
|
||||
#include <tuple>
|
||||
|
||||
#include <mpi.h>
|
||||
#include "../src/memory/symmetric_heap.hpp"
|
||||
#include "../src/ipc_policy.hpp"
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
namespace rocshmem {
|
||||
|
||||
__global__
|
||||
void
|
||||
kernel_simple_coarse_copy(IpcImpl *ipc_impl, int *src, int *dest, size_t bytes) {
|
||||
if (!threadIdx.x) {
|
||||
ipc_impl->ipcCopy(dest, src, bytes);
|
||||
ipc_impl->ipcFence();
|
||||
}
|
||||
__syncthreads();
|
||||
}
|
||||
|
||||
__global__
|
||||
void
|
||||
kernel_simple_coarse_copy_block(IpcImpl *ipc_impl, int *src, int *dest, size_t bytes) {
|
||||
ipc_impl->ipcCopy_wg(dest, src, bytes);
|
||||
ipc_impl->ipcFence();
|
||||
__syncthreads();
|
||||
}
|
||||
|
||||
__global__
|
||||
void
|
||||
kernel_simple_coarse_copy_warp(IpcImpl *ipc_impl, int *src, int *dest, size_t bytes) {
|
||||
ipc_impl->ipcCopy_wave(dest, src, bytes);
|
||||
ipc_impl->ipcFence();
|
||||
__syncthreads();
|
||||
}
|
||||
|
||||
class IPCImplSimpleCoarse : public ::testing::TestWithParam<std::tuple<int, int, int>> {
|
||||
using HEAP_T = HeapMemory<HIPAllocator>;
|
||||
using MPI_T = RemoteHeapInfo<CommunicatorMPI>;
|
||||
using FN_T = void (*)(IpcImpl*, int*, int*, size_t);
|
||||
|
||||
public:
|
||||
IPCImplSimpleCoarse() {
|
||||
MPIInstance::mpilib_dl_init();
|
||||
mpi_ = new MPI_T (heap_mem_.get_ptr(), heap_mem_.get_size(), MPI_COMM_WORLD);
|
||||
|
||||
ipc_impl_.ipcHostInit(mpi_->my_pe(), mpi_->get_heap_bases(), MPI_COMM_WORLD);
|
||||
assert(ipc_impl_dptr_ == nullptr);
|
||||
hip_allocator_.allocate((void**)&ipc_impl_dptr_, sizeof(IpcImpl));
|
||||
CHECK_HIP(hipMemcpy(ipc_impl_dptr_, &ipc_impl_,
|
||||
sizeof(IpcImpl), hipMemcpyHostToDevice));
|
||||
}
|
||||
|
||||
virtual ~IPCImplSimpleCoarse() {
|
||||
if (ipc_impl_dptr_) {
|
||||
hip_allocator_.deallocate(ipc_impl_dptr_);
|
||||
}
|
||||
ipc_impl_.ipcHostStop();
|
||||
MPIInstance::mpilib_dl_close();
|
||||
}
|
||||
|
||||
void launch(FN_T f, const dim3 grid, const dim3 block, int* src, int* dest, size_t bytes) {
|
||||
f<<<grid, block>>>(ipc_impl_dptr_, src, dest, bytes);
|
||||
CHECK_HIP(hipStreamSynchronize(nullptr));
|
||||
}
|
||||
|
||||
enum TestType {
|
||||
READ = 0,
|
||||
WRITE = 1
|
||||
};
|
||||
|
||||
virtual void copy(TestType test, dim3 grid, dim3 block) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
void write(const dim3 grid, const dim3 block, size_t elems) {
|
||||
iota_golden(elems);
|
||||
initialize_src_buffer(WRITE);
|
||||
copy(WRITE, grid, block);
|
||||
validate_dest_buffer(WRITE);
|
||||
}
|
||||
|
||||
void read(const dim3 grid, const dim3 block, size_t elems) {
|
||||
iota_golden(elems);
|
||||
initialize_src_buffer(READ);
|
||||
copy(READ, grid, block);
|
||||
validate_dest_buffer(READ);
|
||||
}
|
||||
|
||||
void iota_golden(size_t elems) {
|
||||
golden_.resize(elems);
|
||||
std::iota(golden_.begin(), golden_.end(), 0);
|
||||
}
|
||||
|
||||
void validate_golden(size_t elems) {
|
||||
ASSERT_EQ(golden_.size(), elems);
|
||||
for (int i = 0; i < static_cast<int>(golden_.size()); i++) {
|
||||
ASSERT_EQ(golden_[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
void initialize_src_buffer(TestType test) {
|
||||
if (!pe_initializes_src_buffer(test)) {
|
||||
return;
|
||||
}
|
||||
size_t bytes = golden_.size() * sizeof(int);
|
||||
auto dev_src = reinterpret_cast<int*>(ipc_impl_.ipc_bases[mpi_->my_pe()]);
|
||||
CHECK_HIP(hipMemcpy(dev_src, golden_.data(), bytes, hipMemcpyHostToDevice));
|
||||
CHECK_HIP(hipStreamSynchronize(nullptr));
|
||||
}
|
||||
|
||||
bool pe_initializes_src_buffer(TestType test) {
|
||||
bool is_write_test = test;
|
||||
bool is_read_test = !test;
|
||||
return (is_write_test && mpi_->my_pe() == 0) ||
|
||||
(is_read_test && mpi_->my_pe() == 1);
|
||||
}
|
||||
|
||||
void execute(TestType test, FN_T fn, const dim3 grid, const dim3 block) {
|
||||
if (mpi_->my_pe()) {
|
||||
mpi_->barrier();
|
||||
mpi_->barrier();
|
||||
return;
|
||||
}
|
||||
int *src{nullptr};
|
||||
int *dest{nullptr};
|
||||
if (test == WRITE) {
|
||||
src = reinterpret_cast<int*>(ipc_impl_.ipc_bases[0]);
|
||||
dest = reinterpret_cast<int*>(ipc_impl_.ipc_bases[1]);
|
||||
} else {
|
||||
src = reinterpret_cast<int*>(ipc_impl_.ipc_bases[1]);
|
||||
dest = reinterpret_cast<int*>(ipc_impl_.ipc_bases[0]);
|
||||
}
|
||||
size_t bytes = golden_.size() * sizeof(int);
|
||||
mpi_->barrier();
|
||||
launch(fn, grid, block, src, dest, bytes);
|
||||
mpi_->barrier();
|
||||
}
|
||||
|
||||
void validate_dest_buffer(TestType test) {
|
||||
if (!pe_validates_dest_buffer(test)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto dev_dest = reinterpret_cast<int*>(ipc_impl_.ipc_bases[mpi_->my_pe()]);
|
||||
for (int i = 0; i < static_cast<int>(golden_.size()); i++) {
|
||||
ASSERT_EQ(golden_[i], dev_dest[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool pe_validates_dest_buffer(TestType test) {
|
||||
return !pe_initializes_src_buffer(test);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::vector<int> golden_;
|
||||
|
||||
HEAP_T heap_mem_ {};
|
||||
MPI_T *mpi_{nullptr};
|
||||
|
||||
IpcImpl ipc_impl_ {};
|
||||
IpcImpl *ipc_impl_dptr_ {nullptr};
|
||||
|
||||
HIPAllocator hip_allocator_ {};
|
||||
};
|
||||
|
||||
class DegenerateSimpleCoarse : public IPCImplSimpleCoarse {
|
||||
public:
|
||||
~DegenerateSimpleCoarse() override {};
|
||||
};
|
||||
|
||||
class ParameterizedBlockSimpleCoarse : public IPCImplSimpleCoarse {
|
||||
public:
|
||||
~ParameterizedBlockSimpleCoarse() override {};
|
||||
|
||||
void copy(IPCImplSimpleCoarse::TestType test, dim3 grid, dim3 block) override {
|
||||
execute(test, kernel_simple_coarse_copy_block, grid, block);
|
||||
}
|
||||
};
|
||||
|
||||
class ParameterizedWarpSimpleCoarse : public IPCImplSimpleCoarse {
|
||||
public:
|
||||
~ParameterizedWarpSimpleCoarse() override {};
|
||||
|
||||
void copy(IPCImplSimpleCoarse::TestType test, dim3 grid, dim3 block) override {
|
||||
execute(test, kernel_simple_coarse_copy_warp, grid, block);
|
||||
}
|
||||
};
|
||||
|
||||
class ParameterizedThreadSimpleCoarse : public IPCImplSimpleCoarse {
|
||||
public:
|
||||
~ParameterizedThreadSimpleCoarse() override {};
|
||||
|
||||
void copy(IPCImplSimpleCoarse::TestType test, dim3 grid, dim3 block) override {
|
||||
execute(test, kernel_simple_coarse_copy, grid, block);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace rocshmem
|
||||
|
||||
#endif // ROCSHMEM_IPC_IMPL_SIMPLE_COARSE_GTEST_HPP
|
||||
@@ -0,0 +1,202 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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 "ipc_impl_simple_fine_gtest.hpp"
|
||||
|
||||
using namespace rocshmem;
|
||||
|
||||
TEST_P(DegenerateSimpleFine, ptr_check) {
|
||||
ASSERT_NE(heap_mem_.get_ptr(), nullptr);
|
||||
}
|
||||
|
||||
TEST_P(DegenerateSimpleFine, MPI_num_pes) {
|
||||
ASSERT_EQ(mpi_->num_pes(), 2);
|
||||
}
|
||||
|
||||
TEST_P(DegenerateSimpleFine, IPC_bases) {
|
||||
ASSERT_EQ(mpi_->num_pes(), 2);
|
||||
ASSERT_NE(ipc_impl_.ipc_bases, nullptr);
|
||||
for(int i{0}; i < mpi_->num_pes(); i++) {
|
||||
ASSERT_NE(ipc_impl_.ipc_bases[i], nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(DegenerateSimpleFine, golden_1048576_int) {
|
||||
iota_golden(1048576);
|
||||
validate_golden(1048576);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
IPCImplSimpleFineTestFixture,
|
||||
DegenerateSimpleFine,
|
||||
::testing::Values(
|
||||
std::make_tuple(1, 1, 1))
|
||||
);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
TEST_P(ParameterizedBlockSimpleFine, write) {
|
||||
dim3 grid = dim3(std::get<0>(GetParam()), 1, 1);
|
||||
dim3 block = dim3(std::get<1>(GetParam()), 1, 1);
|
||||
size_t size = std::get<2>(GetParam());
|
||||
write(grid, block, size);
|
||||
}
|
||||
|
||||
TEST_P(ParameterizedBlockSimpleFine, read) {
|
||||
dim3 grid = dim3(std::get<0>(GetParam()), 1, 1);
|
||||
dim3 block = dim3(std::get<1>(GetParam()), 1, 1);
|
||||
size_t size = std::get<2>(GetParam());
|
||||
read(grid, block, size);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
IPCImplSimpleFineTestFixture,
|
||||
ParameterizedBlockSimpleFine,
|
||||
::testing::Values(
|
||||
std::make_tuple(1, 1024, 32), // 0
|
||||
std::make_tuple(1, 1, 1048576), // 1
|
||||
std::make_tuple(1, 2, 1048576), // 2
|
||||
std::make_tuple(1, 4, 1048576), // 3
|
||||
std::make_tuple(1, 8, 1048576), // 4
|
||||
std::make_tuple(1, 16, 1048576), // 5
|
||||
std::make_tuple(1, 32, 1048576), // 6
|
||||
std::make_tuple(1, 64, 1048576), // 7
|
||||
std::make_tuple(1, 128, 1048576), // 8
|
||||
std::make_tuple(1, 256, 1048576), // 9
|
||||
std::make_tuple(1, 512, 1048576), // 10
|
||||
std::make_tuple(1, 768, 1048576), // 11
|
||||
std::make_tuple(1, 1024, 1048576)) // 12
|
||||
);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
TEST_P(ParameterizedWarpSimpleFine, write) {
|
||||
dim3 grid = dim3(std::get<0>(GetParam()), 1, 1);
|
||||
dim3 block = dim3(std::get<1>(GetParam()), 1, 1);
|
||||
size_t size = std::get<2>(GetParam());
|
||||
write(grid, block, size);
|
||||
}
|
||||
|
||||
TEST_P(ParameterizedWarpSimpleFine, read) {
|
||||
dim3 grid = dim3(std::get<0>(GetParam()), 1, 1);
|
||||
dim3 block = dim3(std::get<1>(GetParam()), 1, 1);
|
||||
size_t size = std::get<2>(GetParam());
|
||||
read(grid, block, size);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
IPCImplSimpleFineTestFixture,
|
||||
ParameterizedWarpSimpleFine,
|
||||
::testing::Values(
|
||||
std::make_tuple(1, 64, 1), // 0
|
||||
std::make_tuple(1, 64, 32), // 1
|
||||
std::make_tuple(1, 1, 1048576), // 2
|
||||
std::make_tuple(1, 2, 1048576), // 3
|
||||
std::make_tuple(1, 3, 1048576), // 4
|
||||
std::make_tuple(1, 4, 1048576), // 5
|
||||
std::make_tuple(1, 5, 1048576), // 6
|
||||
std::make_tuple(1, 6, 1048576), // 7
|
||||
std::make_tuple(1, 7, 1048576), // 8
|
||||
std::make_tuple(1, 8, 1048576), // 9
|
||||
std::make_tuple(1, 9, 1048576), // 10
|
||||
std::make_tuple(1, 10, 1048576), // 11
|
||||
std::make_tuple(1, 11, 1048576), // 12
|
||||
std::make_tuple(1, 12, 1048576), // 13
|
||||
std::make_tuple(1, 13, 1048576), // 14
|
||||
std::make_tuple(1, 14, 1048576), // 15
|
||||
std::make_tuple(1, 15, 1048576), // 16
|
||||
std::make_tuple(1, 16, 1048576), // 17
|
||||
std::make_tuple(1, 17, 1048576), // 18
|
||||
std::make_tuple(1, 18, 1048576), // 19
|
||||
std::make_tuple(1, 19, 1048576), // 20
|
||||
std::make_tuple(1, 20, 1048576), // 21
|
||||
std::make_tuple(1, 21, 1048576), // 22
|
||||
std::make_tuple(1, 22, 1048576), // 23
|
||||
std::make_tuple(1, 23, 1048576), // 24
|
||||
std::make_tuple(1, 24, 1048576), // 25
|
||||
std::make_tuple(1, 25, 1048576), // 26
|
||||
std::make_tuple(1, 26, 1048576), // 27
|
||||
std::make_tuple(1, 27, 1048576), // 28
|
||||
std::make_tuple(1, 28, 1048576), // 29
|
||||
std::make_tuple(1, 28, 1048576), // 30
|
||||
std::make_tuple(1, 29, 1048576), // 31
|
||||
std::make_tuple(1, 30, 1048576), // 32
|
||||
std::make_tuple(1, 31, 1048576), // 33
|
||||
std::make_tuple(1, 32, 1048576), // 34
|
||||
std::make_tuple(1, 33, 1048576), // 35
|
||||
std::make_tuple(1, 34, 1048576), // 36
|
||||
std::make_tuple(1, 35, 1048576), // 37
|
||||
std::make_tuple(1, 36, 1048576), // 38
|
||||
std::make_tuple(1, 37, 1048576), // 39
|
||||
std::make_tuple(1, 38, 1048576), // 40
|
||||
std::make_tuple(1, 39, 1048576), // 41
|
||||
std::make_tuple(1, 40, 1048576), // 42
|
||||
std::make_tuple(1, 41, 1048576), // 43
|
||||
std::make_tuple(1, 42, 1048576), // 44
|
||||
std::make_tuple(1, 43, 1048576), // 45
|
||||
std::make_tuple(1, 44, 1048576), // 46
|
||||
std::make_tuple(1, 45, 1048576), // 47
|
||||
std::make_tuple(1, 46, 1048576), // 48
|
||||
std::make_tuple(1, 47, 1048576), // 49
|
||||
std::make_tuple(1, 48, 1048576), // 50
|
||||
std::make_tuple(1, 49, 1048576), // 51
|
||||
std::make_tuple(1, 50, 1048576), // 52
|
||||
std::make_tuple(1, 51, 1048576), // 53
|
||||
std::make_tuple(1, 52, 1048576), // 54
|
||||
std::make_tuple(1, 53, 1048576), // 55
|
||||
std::make_tuple(1, 54, 1048576), // 56
|
||||
std::make_tuple(1, 55, 1048576), // 57
|
||||
std::make_tuple(1, 56, 1048576), // 58
|
||||
std::make_tuple(1, 57, 1048576), // 59
|
||||
std::make_tuple(1, 58, 1048576), // 60
|
||||
std::make_tuple(1, 59, 1048576), // 61
|
||||
std::make_tuple(1, 60, 1048576), // 62
|
||||
std::make_tuple(1, 61, 1048576), // 63
|
||||
std::make_tuple(1, 62, 1048576), // 64
|
||||
std::make_tuple(1, 63, 1048576), // 65
|
||||
std::make_tuple(1, 64, 1048576)) // 66
|
||||
);
|
||||
|
||||
//=============================================================================
|
||||
|
||||
TEST_P(ParameterizedThreadSimpleFine, write) {
|
||||
dim3 grid = dim3(std::get<0>(GetParam()), 1, 1);
|
||||
dim3 block = dim3(std::get<1>(GetParam()), 1, 1);
|
||||
size_t size = std::get<2>(GetParam());
|
||||
write(grid, block, size);
|
||||
}
|
||||
|
||||
TEST_P(ParameterizedThreadSimpleFine, read) {
|
||||
dim3 grid = dim3(std::get<0>(GetParam()), 1, 1);
|
||||
dim3 block = dim3(std::get<1>(GetParam()), 1, 1);
|
||||
size_t size = std::get<2>(GetParam());
|
||||
read(grid, block, size);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
IPCImplSimpleFineTestFixture,
|
||||
ParameterizedThreadSimpleFine,
|
||||
::testing::Values(
|
||||
std::make_tuple(1, 1, 1048576))
|
||||
);
|
||||
برخی از فایل ها نشان داده نشدند زیرا تعداد زیادی فایل در این تفاوت تغییر کرده اند نمایش بیشتر
مرجع در شماره جدید
Block a user