块中的每个线程可以具有不同的结果集(和大小)。目前我正在分配固定大小的设备内存;想想每个线程。
含义,对于XX线程我必须分配XX * max_result_count * data_structure * sizeof(int),我的数据包含整数。每个线程通过计算int i = blockDim.x * blockIdx.x + threadIdx.x来访问其内存块(偏移量);并将其与max_result_count * data_structure相乘,用于整数数组;
在现实世界中,这意味着对设备内存的巨大浪费,因为有些设备接近0,有些则不然。例如,我必须分配低于2GB的设备内存才能存储相当于300MB的结果。
关于如何重做的任何想法?
例如,每个线程锁定互斥锁,增加实际res_count,将数据写入共享内存块,解锁互斥锁。
[问题解决了,谢谢,伙计们!]
答案 0 :(得分:1)
重写内核并调用函数来计算所需点的一部分(显然,你必须改变每次启动的块数等)。
int offset = 0;
for(int i = 0; i < numKernelLaunches; i++) {
yourKernel<<<numBlocks,threadsPerBlock>>>(offset, /* your other parameters */);
offset += numBlocks*threadsPerBlock;
cudaDeviceSynchronize();
}
并在yourKernel
中保留int i = blockDim.x * blockIdx.x + threadIdx.x;
作为全局内存访问的索引,i + offset
作为数据位置的ID。
答案 1 :(得分:1)
您已经在一个可能的方法中暗示了您的问题:
#define DSIZE (100*1048576)
__device__ unsigned int buffer_index = 0;
__device__ int *buffer_data;
在您的主机代码中:
int *buffer_data_temp;
cudaMalloc(&buffer_data_temp, sizeof(int)*DSIZE);
cudaMemcpyToSymbol(buffer_data, &buffer_data_temp, sizeof(int *));
在你的线程代码中:
unsigned int my_buffer_offset = atomicAdd(&buffer_index, size_of_my_thread_data);
assert((my_buffer_offset+size_of_my_thread_data) < DSIZE);
memcpy(buffer_data+my_buffer_offset, my_thread_data, size_of_my_thread_data*sizeof(int));
(免责声明:在浏览器中编码,未经测试)
没有必要使用互斥锁,例如在memcpy
操作周围。一旦我们使用atomicAdd
保留了我们的分配的起点和终点,线程就不会相互踩,即使所有线程都在写数据,因为它们写入buffer_data
内的不同区域。
编辑: 这是一个完整的例子:
#include <stdio.h>
#include <assert.h>
#define DSIZE (100*1048576)
#define nTPB 32
#define BLKS 2
__device__ unsigned int buffer_index = 0;
__global__ void update_buffer(int *buffer_data){
const unsigned int size_of_my_thread_data = 1;
unsigned int my_buffer_offset = atomicAdd(&buffer_index, size_of_my_thread_data);
assert((my_buffer_offset+size_of_my_thread_data) < DSIZE);
int my_thread_data[size_of_my_thread_data];
my_thread_data[0] = (blockIdx.x*10000) + threadIdx.x;
memcpy(buffer_data+my_buffer_offset, my_thread_data, size_of_my_thread_data*sizeof(int));
}
int main(){
int *h_buffer_data, *d_buffer_data;
cudaMalloc(&d_buffer_data, sizeof(int)*DSIZE);
update_buffer<<<BLKS, nTPB>>>(d_buffer_data);
unsigned int result_size;
cudaMemcpyFromSymbol(&result_size, buffer_index, sizeof(unsigned int));
h_buffer_data = (int *)malloc(sizeof(int)*result_size);
cudaMemcpy(h_buffer_data, d_buffer_data, result_size*sizeof(int),cudaMemcpyDeviceToHost);
for (int i = 0; i < result_size; i++)
printf("%d\n", h_buffer_data[i]);
return 0;
}