[英]CUDA multiple dynamically allocated shared arrays in single kernel
我有以下問題。 我試圖將共享數組分成較小的數組,然后在其他設備功能中使用這些數組。 在我的內核函數中,
for (int block_x = 0; block_x < blockDim.x; block_x++) {
for (int block_y = 0; block_y < blockDim.y; block_y++) {
//set up shared memory block
extern __shared__ vec3f share[];
vec3f *sh_pos = share;
vec3f *sh_velocity = &sh_pos[blockDim.x*blockDim.y];
vec3f *sh_density = &sh_velocity[blockDim.x*blockDim.y];
vec3f *sh_pressure = &sh_density[blockDim.x*blockDim.y];
//index by 2d threadidx's
unsigned int index = (block_x * blockDim.x + threadIdx.x) + blockDim.x * gridDim.x * (block_y * blockDim.y + threadIdx.y);
sh_pos[blockDim.x * threadIdx.x + threadIdx.y] = oldParticles[index].position();
sh_velocity[blockDim.x * threadIdx.x + threadIdx.y] = oldParticles[index].velocity();
sh_pressure[blockDim.x * threadIdx.x + threadIdx.y].x = oldParticles[index].pressure();
sh_density[blockDim.x * threadIdx.x + threadIdx.y].x = oldParticles[index].density();
__syncthreads();
d_force_pressure(oldParticles[arr_pos],c_kernel_support);
__syncthreads();
}
}
據我所知,所有“ sh_”數組都填充有零而不是我想要的值。 我不知道我在做什么錯。 注意vec3f是float的向量,就像float3數據類型一樣。 另外,我不認為我可以混合使用浮子來獲得密度和壓力,因此我只是將它們作為矢量並使用了單個組件。 然后,例如我的d_force_pressure函數是
__device__ void d_force_pressure(particle& d_particle, float h) {
extern __shared__ vec3f share[];
vec3f *sh_pos = share;
vec3f *sh_velocity = &sh_pos[blockDim.x*blockDim.y];
vec3f *sh_density = &sh_velocity[blockDim.x*blockDim.y];
vec3f *sh_pressure = &sh_density[blockDim.x*blockDim.y];
for (int i = 0; i < blockDim.x * blockDim.y; i++) {
vec3f diffPos = d_particle.position() - sh_pos[i];
d_particle.force() += GradFuncion(diffPos,h) * -1.0 * c_particle_mass * (d_particle.pressure()+sh_pressure[i].x)/(2.0*sh_density[i].x);
}
}
調用此函數后,由於我被零除( sh_density[i].x
據我所知為0),因此得到NaN。 同樣,這也是加載共享內存的正確方法嗎?
內核由
dim3 block(BLOCK_SIZE,BLOCK_SIZE,1);
dim3 grid((int)ceil(sqrt(float(max_particles)) / (float(block.x*block.y))), (int)ceil(sqrt(float(max_particles)) / (float(block.x*block.y))), 1);
int sharedMemSize = block.x*block.y*4*sizeof(vec3f);
force_kernel<<< grid,block,sharedMemSize >>>(particle_ptrs[1],particle_ptrs[0],time_step);
這是一種后續答案。
根據@RobertCrovella的評論,我繼續運行cuda-memcheck。 信不信由你,這實際上沒有顯示任何錯誤。 但是,當我在代碼中更改一個常量(控制某些數組的大小)時,cuda-memcheck顯示與此處發布的問題相關的錯誤write error 。 這使我重新檢查了填充共享陣列的方式。 基本上需要改變的是
for (int block_x = 0; block_x < blockDim.x; block_x++) {
for (int block_y = 0; block_y < blockDim.y; block_y++) {
至
for (int block_x = 0; block_x < gridDim.x; block_x++) {
for (int block_y = 0; block_y < gridDim.y; block_y++) {
我相信這樣可以為index
變量提供正確的位置。 我基本上了解到,每當您使用共享內存並注意到運行緩慢時,使用cuda-memcheck是一個好主意。
我在您先前的問題中指出您不想這樣做:
dim3 grid((int)ceil(sqrt(float(max_particles)) / (float(block.x*block.y))), (int)ceil(sqrt(float(max_particles)) / (float(block.x*block.y))), 1);
您想這樣做:
dim3 grid((int)ceil(sqrt(float(max_particles)) / (float(block.x))), (int)ceil(sqrt(float(max_particles)) / (float(block.y))), 1);
x網格方向應按線程塊x尺寸而不是線程塊x尺寸*線程塊y尺寸縮放。 但是,即使我在注釋中指出了該錯誤,但我在上一個答案中發布的代碼也存在此錯誤,但我忘記進行修復。
此外,這種索引在我看來並不正確:
sh_velocity[blockDim.x * threadIdx.x + threadIdx.y]
我認為應該是:
sh_velocity[blockDim.x * threadIdx.y + threadIdx.x]
您有幾個例子。
您尚未發布完整的可執行文件。 當然,可能有比我上面指出的更多的問題。 如果我必須完成我在上一個問題中所做的所有vec3f-> float3轉換工作,那么其他人可以為您提供幫助。 如果您編寫的簡單復制器不依賴我沒有的一堆代碼,那么我可以嘗試進一步提供幫助。 如果您這樣做,很有可能自己發現問題。
您是否像我在上一個答案中所建議的那樣將cuda錯誤檢查放入代碼中?
您可能還想通過cuda-memcheck運行代碼:
cuda-memcheck ./mycode
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.