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
462 lines
13 KiB
C++
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);
|
|
|
|
//============================================================================//
|