Files
TheRock/rocm-systems/projects/rocprofiler-sdk/external/ptl/examples/gpu/sum.cu
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

262 lines
8.2 KiB
Plaintext

//
// MIT License
// Copyright (c) 2018 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 CUDA implementation
//
//
//============================================================================//
#include "sum.hh"
#define PRINT_HERE(extra) \
printf("> %s@'%s':%i %s\n", __FUNCTION__, __FILE__, __LINE__, extra)
//============================================================================//
// gridDim: This variable contains the dimensions of the grid.
// blockIdx: This variable contains the block index within the grid.
// blockDim: This variable and contains the dimensions of the block.
// threadIdx: This variable contains the thread index within the block.
//============================================================================//
//
// efficient reduction
// https://developer.download.nvidia.com/assets/cuda/files/reduction.pdf
//
//============================================================================//
template <unsigned int blockSize, typename _Tp>
__device__ void
warpReduce(volatile _Tp* _data, unsigned int tid)
{
if(blockSize >= 64)
_data[tid] += _data[tid + 32];
if(blockSize >= 32)
_data[tid] += _data[tid + 16];
if(blockSize >= 16)
_data[tid] += _data[tid + 8];
if(blockSize >= 8)
_data[tid] += _data[tid + 4];
if(blockSize >= 4)
_data[tid] += _data[tid + 2];
if(blockSize >= 2)
_data[tid] += _data[tid + 1];
}
//----------------------------------------------------------------------------//
template <unsigned int blockSize, typename _Tp>
__global__ void
reduce(_Tp* _idata, _Tp* _odata, unsigned int n)
{
extern __shared__ _Tp _data[];
unsigned int tid = threadIdx.x;
unsigned int i = (2 * blockSize) * blockIdx.x + tid;
unsigned int gridSize = 2 * blockSize * gridDim.x;
_data[tid] = 0;
while(i < n)
{
_data[tid] += _idata[i] + _idata[i + blockSize];
i += gridSize;
}
__syncthreads();
if(blockSize >= 512)
{
if(tid < 256)
{
_data[tid] += _data[tid + 256];
}
__syncthreads();
}
if(blockSize >= 256)
{
if(tid < 128)
{
_data[tid] += _data[tid + 128];
}
__syncthreads();
}
if(blockSize >= 128)
{
if(tid < 64)
{
_data[tid] += _data[tid + 64];
}
__syncthreads();
}
if(tid < 32)
warpReduce<blockSize, _Tp>(_data, tid);
if(tid == 0)
_odata[blockIdx.x] = _data[0];
}
//----------------------------------------------------------------------------//
template <typename _Tp>
void
compute_reduction(int threads, _Tp* _idata, _Tp* _odata, int dimGrid, int dimBlock,
int smemSize, cudaStream_t stream)
{
cudaStreamSynchronize(stream);
CUDA_CHECK_LAST_ERROR();
switch(threads)
{
case 512:
reduce<512, _Tp>
<<<dimGrid, dimBlock, smemSize, stream>>>(_idata, _odata, threads);
break;
case 256:
reduce<256, _Tp>
<<<dimGrid, dimBlock, smemSize, stream>>>(_idata, _odata, threads);
break;
case 128:
reduce<128, _Tp>
<<<dimGrid, dimBlock, smemSize, stream>>>(_idata, _odata, threads);
break;
case 64:
reduce<64, _Tp>
<<<dimGrid, dimBlock, smemSize, stream>>>(_idata, _odata, threads);
break;
case 32:
reduce<32, _Tp>
<<<dimGrid, dimBlock, smemSize, stream>>>(_idata, _odata, threads);
break;
case 16:
reduce<16, _Tp>
<<<dimGrid, dimBlock, smemSize, stream>>>(_idata, _odata, threads);
break;
case 8:
reduce<8, _Tp>
<<<dimGrid, dimBlock, smemSize, stream>>>(_idata, _odata, threads);
break;
case 4:
reduce<4, _Tp>
<<<dimGrid, dimBlock, smemSize, stream>>>(_idata, _odata, threads);
break;
case 2:
reduce<2, _Tp>
<<<dimGrid, dimBlock, smemSize, stream>>>(_idata, _odata, threads);
break;
case 1:
reduce<1, _Tp>
<<<dimGrid, dimBlock, smemSize, stream>>>(_idata, _odata, threads);
break;
}
CUDA_CHECK_LAST_ERROR();
cudaStreamSynchronize(stream);
CUDA_CHECK_LAST_ERROR();
}
//============================================================================//
template <typename _Tp>
void
call_compute_reduction(int64_t& _i, uint64_t& _offset, int nthreads, _Tp* _idata,
_Tp* _odata, int dimGrid, int dimBlock, int smemSize,
cudaStream_t stream)
{
// assumes nthreads < cuda_max_threads_per_block()
compute_reduction(nthreads, _idata + _offset, _odata + _offset, dimGrid, dimBlock,
smemSize, stream);
_i -= nthreads;
_offset += nthreads;
}
//============================================================================//
float
compute_sum_host(aligned_ptr<float>& data, cudaStream_t stream, bool with_thrust,
float* buffer)
{
float _sum;
if(with_thrust)
{
cudaStreamSynchronize(stream);
CUDA_CHECK_LAST_ERROR();
_sum = thrust::reduce(thrust::system::cuda::par.on(stream), data.ptr,
data.ptr + data.size, 0.0f, thrust::plus<float>());
CUDA_CHECK_LAST_ERROR();
cudaStreamSynchronize(stream);
CUDA_CHECK_LAST_ERROR();
}
else
{
// PRINT_HERE("");
// PRINT_HERE(std::string(std::string("size : ") +
// std::to_string(data.size)).c_str());
// PRINT_HERE(std::string(std::string("padding : ") +
// std::to_string(data.padding)).c_str());
// PRINT_HERE(std::string(std::string("storage : ") +
// std::to_string(data.storage_size)).c_str());
if(data.size < 1 || data.storage_size < 1)
return 0.0f;
int64_t remain = data.size;
uint64_t offset = 0;
int smemSize = cuda_shared_memory_per_block();
int dimGrid = cuda_multi_processor_count();
int dimBlock = cuda_max_threads_per_block();
float* _idata = data.ptr;
float* _odata = buffer;
async_gpu_memset<float>(_odata, data.storage_size, stream);
CUDA_CHECK_LAST_ERROR();
while(remain > 0)
{
for(const auto& itr : { 512, 256, 128, 64, 32, 16, 8, 4, 2, 1 })
{
if(remain >= itr)
{
call_compute_reduction(remain, offset, itr, _idata, _odata, dimGrid,
dimBlock, smemSize, stream);
break;
}
}
}
cudaMemcpyAsync(&_sum, _odata, 1 * sizeof(float), cudaMemcpyDeviceToHost, stream);
CUDA_CHECK_LAST_ERROR();
cudaDeviceSynchronize();
CUDA_CHECK_LAST_ERROR();
}
return _sum;
}
//============================================================================//