min cuda and min cuda axis
This commit is contained in:
parent
e2a0262c4e
commit
223229fcd3
1 changed files with 127 additions and 4 deletions
|
|
@ -227,26 +227,26 @@ __host__ void sum_tensor_cuda(Tensor* tensor, float* result_data, int axis) {
|
|||
}
|
||||
|
||||
__global__ void max_tensor_cuda_kernel(float* data, float* result_data, int size) {
|
||||
__shared__ float partial_sum[THREADS_PER_BLOCK * sizeof(float)];
|
||||
__shared__ float partial_max[THREADS_PER_BLOCK * sizeof(float)];
|
||||
|
||||
int tid = threadIdx.x;
|
||||
int i = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
|
||||
partial_sum[tid] = (i < size) ? data[i] : 0;
|
||||
partial_max[tid] = (i < size) ? data[i] : -FLT_MAX;
|
||||
|
||||
__syncthreads();
|
||||
|
||||
// Perform block-wise reduction
|
||||
for (int s = blockDim.x / 2; s > 0; s >>= 1) {
|
||||
if (tid < s) {
|
||||
partial_sum[tid] = fmax(partial_sum[tid], partial_sum[tid + s]);
|
||||
partial_max[tid] = fmax(partial_max[tid], partial_max[tid + s]);
|
||||
}
|
||||
__syncthreads();
|
||||
}
|
||||
|
||||
// Write block sum to global memory
|
||||
if (tid == 0) {
|
||||
result_data[blockIdx.x] = partial_sum[0];
|
||||
result_data[blockIdx.x] = partial_max[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -347,6 +347,129 @@ __host__ void max_tensor_cuda(Tensor* tensor, float* result_data, int axis) {
|
|||
}
|
||||
}
|
||||
|
||||
__global__ void min_tensor_cuda_kernel(float* data, float* result_data, int size) {
|
||||
__shared__ float partial_min[THREADS_PER_BLOCK * sizeof(float)];
|
||||
|
||||
int tid = threadIdx.x;
|
||||
int i = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
|
||||
partial_min[tid] = (i < size) ? data[i] : FLT_MAX;
|
||||
|
||||
__syncthreads();
|
||||
|
||||
// Perform block-wise reduction
|
||||
for (int s = blockDim.x / 2; s > 0; s >>= 1) {
|
||||
if (tid < s) {
|
||||
partial_min[tid] = fmin(partial_min[tid], partial_min[tid + s]);
|
||||
}
|
||||
__syncthreads();
|
||||
}
|
||||
|
||||
// Write block sum to global memory
|
||||
if (tid == 0) {
|
||||
result_data[blockIdx.x] = partial_min[0];
|
||||
}
|
||||
}
|
||||
|
||||
__device__ float atomicMinFloat(float* address, float val) {
|
||||
int* address_as_int = (int*)address;
|
||||
int old = *address_as_int, assumed;
|
||||
|
||||
do {
|
||||
assumed = old;
|
||||
old = atomicCAS(address_as_int, assumed,
|
||||
__float_as_int(fminf(val, __int_as_float(assumed))));
|
||||
} while (assumed != old);
|
||||
|
||||
return __int_as_float(old);
|
||||
}
|
||||
|
||||
__global__ void min_tensor_cuda_kernel_axis(float* data, float* result_data, int* strides, int* shape, int axis, int ndim, int axis_stride, int size, int result_size) {
|
||||
int tid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
|
||||
if (tid < result_size) {
|
||||
for (int i = 0; i < shape[axis]; i++) {
|
||||
int index = 0;
|
||||
int remainder = tid;
|
||||
for (int k = ndim - 2; k >= 0; k--) {
|
||||
index += (remainder % shape[k < axis ? k : k + 1]) * strides[k < axis ? k : k + 1];
|
||||
remainder /= shape[k < axis ? k : k + 1];
|
||||
}
|
||||
index += i * axis_stride;
|
||||
|
||||
atomicMinFloat(&result_data[tid], data[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__host__ void min_tensor_cuda(Tensor* tensor, float* result_data, int axis) {
|
||||
|
||||
if (axis == -1) {
|
||||
cudaMemcpy(result_data, tensor->data, tensor->size * sizeof(float), cudaMemcpyHostToDevice);
|
||||
|
||||
int num_blocks = (tensor->size + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK;
|
||||
|
||||
// First-level reduction
|
||||
min_tensor_cuda_kernel<<<num_blocks, THREADS_PER_BLOCK>>>(tensor->data, result_data, tensor->size);
|
||||
|
||||
// If necessary, perform multiple levels of reduction
|
||||
while (num_blocks > 1) {
|
||||
int num_blocks_next = (num_blocks + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK;
|
||||
min_tensor_cuda_kernel<<<num_blocks_next, THREADS_PER_BLOCK>>>(result_data, result_data, num_blocks);
|
||||
num_blocks = num_blocks_next;
|
||||
}
|
||||
|
||||
cudaError_t error = cudaGetLastError();
|
||||
if (error != cudaSuccess) {
|
||||
printf("CUDA error: %s\n", cudaGetErrorString(error));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
cudaDeviceSynchronize();
|
||||
|
||||
} else {
|
||||
int axis_stride = tensor->strides[axis];
|
||||
|
||||
// Calculate the size of the resulting tensor
|
||||
int result_size = 1;
|
||||
for (int i = 0; i < tensor->ndim; i++) {
|
||||
if (i != axis) {
|
||||
result_size *= tensor->shape[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate memory for strides and shape on the device
|
||||
int* d_strides;
|
||||
int* d_shape;
|
||||
cudaMalloc(&d_strides, tensor->ndim * sizeof(int));
|
||||
cudaMalloc(&d_shape, tensor->ndim * sizeof(int));
|
||||
cudaMemcpy(d_strides, tensor->strides, tensor->ndim * sizeof(int), cudaMemcpyHostToDevice);
|
||||
cudaMemcpy(d_shape, tensor->shape, tensor->ndim * sizeof(int), cudaMemcpyHostToDevice);
|
||||
|
||||
// Initialize result_data to 0
|
||||
float inf = FLT_MAX;
|
||||
cudaMemset(result_data, *reinterpret_cast<int*>(&inf), result_size * sizeof(float));
|
||||
|
||||
int num_threads = result_size;
|
||||
int num_blocks = (num_threads + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK;
|
||||
min_tensor_cuda_kernel_axis<<<num_blocks, THREADS_PER_BLOCK>>>(tensor->data, result_data, d_strides, d_shape, axis, tensor->ndim, axis_stride, tensor->size, result_size);
|
||||
|
||||
cudaError_t error = cudaGetLastError();
|
||||
if (error != cudaSuccess) {
|
||||
printf("CUDA error: %s\n", cudaGetErrorString(error));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
cudaDeviceSynchronize();
|
||||
|
||||
// Free allocated memory
|
||||
cudaFree(d_strides);
|
||||
cudaFree(d_shape);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
__global__ void sub_tensor_cuda_kernel(float* data1, float* data2, float* result_data, int size) {
|
||||
|
||||
int i = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue