CUDA;使用设备内存共享

时间:2014-04-01 06:17:11

标签: c memory-management cuda

块中的每个线程可以具有不同的结果集(和大小)。目前我正在分配固定大小的设备内存;想想每个线程。

含义,对于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,将数据写入共享内存块,解锁互斥锁。

[问题解决了,谢谢,伙计们!]

2 个答案:

答案 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;
}