Add 'projects/rocshmem/' from commit '0496586829058af5cfd7f23acda2a6d0040da584'
git-subtree-dir: projects/rocshmem git-subtree-mainline:5fd976da70git-subtree-split:0496586829
Этот коммит содержится в:
@@ -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
|
||||
+204
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+69
@@ -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
|
||||
+219
@@ -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
|
||||
+240
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+71
@@ -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
|
||||
Ссылка в новой задаче
Block a user