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

462 lines
13 KiB
C++

//
// MIT License
// Copyright (c) 2019 Jonathan R. Madsen
// 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
// 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.
//
// ---------------------------------------------------------------
// PTL header
//
//
#pragma once
#ifdef __cplusplus
# ifndef BEGIN_EXTERN_C
# define BEGIN_EXTERN_C \
extern "C" \
{
# endif
# ifndef END_EXTERN_C
# define END_EXTERN_C }
# endif
#else
# ifndef BEGIN_EXTERN_C
# define BEGIN_EXTERN_C
# endif
# ifndef END_EXTERN_C
# define END_EXTERN_C
# endif
#endif
//============================================================================//
// C headers
BEGIN_EXTERN_C
#include "sum.h"
END_EXTERN_C
#include <cinttypes>
#include <cmath>
#include <cstdlib>
#include <ctime>
//============================================================================//
// C++ headers
#include <atomic>
#include <chrono>
#include <complex>
#include <iomanip>
#include <iostream>
#include <memory>
#include <unordered_map>
#include "PTL/ThreadData.hh"
#include "PTL/ThreadPool.hh"
#include "PTL/Threading.hh"
#if defined(PTL_USE_CUDA)
# include <cuda.h>
# include <cuda_runtime_api.h>
# include <thrust/device_vector.h>
# include <thrust/execution_policy.h>
# include <thrust/functional.h>
# include <thrust/host_vector.h>
# include <thrust/reduce.h>
# include <thrust/system/cpp/execution_policy.h>
# include <thrust/system/cuda/execution_policy.h>
# include <thrust/system/omp/execution_policy.h>
# include <thrust/system/tbb/execution_policy.h>
# include <thrust/transform.h>
# include <vector_types.h>
#endif
//============================================================================//
template <typename _Tp>
using cuda_device_info = std::unordered_map<int, _Tp>;
//============================================================================//
inline int&
this_thread_device()
{
#if defined(PTL_USE_CUDA)
static std::atomic<int> _ntid(0);
static thread_local int _instance =
(cuda_device_count() > 0) ? ((_ntid++) % cuda_device_count()) : 0;
return _instance;
#else
static thread_local int _instance = 0;
return _instance;
#endif
}
//============================================================================//
inline void
set_this_thread_device()
{
#if defined(PTL_USE_CUDA)
cuda_set_device(this_thread_device());
#endif
}
//============================================================================//
// CUDA only
#if defined(PTL_USE_CUDA)
//============================================================================//
// CUDA headers
# include <cuda.h>
# include <cuda_runtime_api.h>
# include <vector_types.h>
//============================================================================//
//
// CUDA streams
//
//============================================================================//
inline cudaStream_t*
create_streams(const uint64_t nstreams)
{
cudaStream_t* streams = new cudaStream_t[nstreams];
for(uint64_t i = 0; i < nstreams; ++i)
cudaStreamCreate(&streams[i]);
return streams;
}
//============================================================================//
inline void
destroy_streams(cudaStream_t* streams, const uint64_t nstreams)
{
for(uint64_t i = 0; i < nstreams; ++i)
cudaStreamDestroy(streams[i]);
delete[] streams;
}
//============================================================================//
//
// struct for aligned pointers
//
//============================================================================//
template <typename _Tp, uintmax_t _AlignWidth = 512>
struct aligned_pointer
{
typedef aligned_pointer<_Tp, _AlignWidth> this_type;
typedef _Tp value_type;
typedef _Tp* pointer_type;
_Tp* ptr;
uintmax_t size;
uintmax_t padding;
uintmax_t storage_size;
aligned_pointer(const uintmax_t _size)
: ptr(nullptr) // pointer to data
, size(_size) // size of data
, padding(
(_size % _AlignWidth == 0)
? 0
: (_AlignWidth -
(size %
_AlignWidth))) // extra padding aligning to "_AlignWidth" byte width
, storage_size(size + padding) // size of allocation
{}
this_type& allocate()
{
// allocate array aligned to "_AlignWidth"
cudaMalloc((void**) &ptr, storage_size * sizeof(_Tp));
return *this;
}
void free() { cudaFree((void*) ptr); }
};
template <typename _Tp>
using aligned_ptr = aligned_pointer<_Tp, 512>;
//============================================================================//
//
// Non-Asynchronous Routines
//
//============================================================================//
template <typename _Tp>
_Tp*
gpu_malloc(uintmax_t _size)
{
_Tp* _gpu;
cudaMalloc((void**) &_gpu, _size * sizeof(_Tp));
return _gpu;
}
//----------------------------------------------------------------------------//
template <typename _Tp, uintmax_t _Align = 512>
aligned_pointer<_Tp, _Align>
aligned_gpu_malloc(uintmax_t _size)
{
return aligned_pointer<_Tp, _Align>(_size).allocate();
}
//----------------------------------------------------------------------------//
template <typename _Tp>
void
gpu_memcpy(_Tp* _gpu, const _Tp* _cpu, uintmax_t _size)
{
cudaMemcpy(_gpu, _cpu, _size * sizeof(_Tp), cudaMemcpyHostToDevice);
}
//----------------------------------------------------------------------------//
template <typename _Tp>
void
cpu_memcpy(const _Tp* _gpu, _Tp* _cpu, uintmax_t _size)
{
cudaMemcpy(_cpu, _gpu, _size * sizeof(_Tp), cudaMemcpyDeviceToHost);
}
//----------------------------------------------------------------------------//
template <typename _Tp>
_Tp*
malloc_and_memcpy(const _Tp* _cpu, uintmax_t _size)
{
_Tp* _gpu;
cudaMalloc((void**) &_gpu, _size * sizeof(_Tp));
cudaMemcpy(_gpu, _cpu, _size * sizeof(_Tp), cudaMemcpyHostToDevice);
return _gpu;
}
//----------------------------------------------------------------------------//
template <typename _Tp>
void
memcpy_and_free(_Tp* _cpu, _Tp* _gpu, uintmax_t _size)
{
cudaMemcpy(_cpu, _gpu, _size * sizeof(_Tp), cudaMemcpyDeviceToHost);
cudaFree(_gpu);
}
//============================================================================//
//
// Asynchronous Routines
//
//============================================================================//
template <typename _Tp>
void
async_gpu_memcpy(_Tp* _gpu, const _Tp* _cpu, uintmax_t _size, cudaStream_t _stream)
{
cudaMemcpyAsync(_gpu, _cpu, _size * sizeof(_Tp), cudaMemcpyHostToDevice, _stream);
}
//----------------------------------------------------------------------------//
template <typename _Tp>
void
async_cpu_memcpy(const _Tp* _gpu, _Tp* _cpu, uintmax_t _size, cudaStream_t _stream)
{
cudaMemcpyAsync(_cpu, _gpu, _size * sizeof(_Tp), cudaMemcpyDeviceToHost, _stream);
}
//----------------------------------------------------------------------------//
template <typename _Tp>
void
async_gpu_memset(_Tp* _gpu, uintmax_t _size, cudaStream_t _stream)
{
cudaMemsetAsync(_gpu, 0, _size * sizeof(_Tp), _stream);
}
//----------------------------------------------------------------------------//
template <typename _Tp>
_Tp*
async_malloc_and_memset(uintmax_t _size, cudaStream_t _stream)
{
_Tp* _gpu = gpu_malloc<_Tp>(_size);
async_gpu_memset(_gpu, _size, _stream);
return _gpu;
}
//----------------------------------------------------------------------------//
template <typename _Tp>
_Tp*
async_malloc_and_memcpy(const _Tp* _cpu, uintmax_t _size, cudaStream_t _stream)
{
_Tp* _gpu;
cudaMalloc((void**) &_gpu, _size * sizeof(_Tp));
cudaMemcpyAsync(_gpu, _cpu, _size * sizeof(_Tp), cudaMemcpyHostToDevice, _stream);
return _gpu;
}
//----------------------------------------------------------------------------//
template <typename _Tp, uintmax_t _Align = 512>
aligned_pointer<_Tp, _Align>
aligned_async_malloc_and_memcpy(const _Tp* _cpu, uintmax_t _size, cudaStream_t _stream)
{
aligned_pointer<_Tp, _Align> _gpu(_size);
// run cudaMalloc
_gpu.allocate();
// copy "_size" values from CPU to GPU
cudaMemcpyAsync(_gpu.ptr, _cpu, _size * sizeof(_Tp), cudaMemcpyHostToDevice, _stream);
// zero initialize extra padding
cudaMemsetAsync(_gpu.ptr + _size, 0, _gpu.padding * sizeof(_Tp), _stream);
// return pointer
return _gpu;
}
//----------------------------------------------------------------------------//
template <typename _Tp>
void
async_memcpy_and_free(_Tp* _cpu, _Tp* _gpu, uintmax_t size, cudaStream_t stream)
{
cudaMemcpyAsync(_cpu, _gpu, size * sizeof(_Tp), cudaMemcpyDeviceToHost, stream);
cudaFree(_gpu);
}
//============================================================================//
#else // not defined(PTL_USE_CUDA)
# if !defined(cudaStream_t)
# define cudaStream_t int
# endif
//============================================================================//
template <typename _Tp>
_Tp*
gpu_malloc(uintmax_t size)
{
return nullptr;
}
//----------------------------------------------------------------------------//
template <typename _Tp>
void
gpu_memcpy(_Tp*, const _Tp*, uintmax_t, cudaStream_t)
{}
//----------------------------------------------------------------------------//
template <typename _Tp>
void
cpu_memcpy(const _Tp*, _Tp*, uintmax_t, cudaStream_t)
{}
//----------------------------------------------------------------------------//
template <typename _Tp>
_Tp*
malloc_and_memcpy(const _Tp*, uintmax_t)
{
return nullptr;
}
//----------------------------------------------------------------------------//
template <typename _Tp>
void
memcpy_and_free(_Tp*, _Tp*, uintmax_t)
{}
//----------------------------------------------------------------------------//
template <typename _Tp>
_Tp*
malloc_and_async_memcpy(const _Tp*, uintmax_t, cudaStream_t)
{
return nullptr;
}
//----------------------------------------------------------------------------//
template <typename _Tp>
void
async_memcpy_and_free(_Tp*, _Tp*, uintmax_t, cudaStream_t)
{}
//----------------------------------------------------------------------------//
inline cudaStream_t*
create_streams(const int)
{
return nullptr;
}
//----------------------------------------------------------------------------//
inline void
destroy_streams(cudaStream_t*, const int)
{}
//============================================================================//
#endif // if defined(PTL_USE_CUDA)
//============================================================================//
class cuda_streams
{
public:
cuda_streams(uint64_t nstreams = 64)
: m_nstreams(nstreams)
, m_streams(create_streams(nstreams))
{}
~cuda_streams() { destroy_streams(m_streams, m_nstreams); }
static cuda_streams*& instance()
{
static cuda_streams* _instance = new cuda_streams();
return _instance;
}
// operator cudaStream_t*() { return m_streams; }
cudaStream_t& get(uint64_t i) { return m_streams[i]; }
uint64_t size() const { return m_nstreams; }
uint64_t num_streams() const { return m_nstreams; }
private:
uint64_t m_nstreams;
cudaStream_t* m_streams;
};
//============================================================================//
template <typename _Tp>
using aligned_ptr = aligned_pointer<_Tp, 512>;
typedef std::vector<float> farray_t;
//----------------------------------------------------------------------------//
float
compute_sum(farray_t& data);
//----------------------------------------------------------------------------//
float
compute_sum_host(aligned_ptr<float>& data, cudaStream_t stream, bool with_thrust,
float* buffer);
//----------------------------------------------------------------------------//
uint64_t
run_gpu(uint64_t n);
//============================================================================//