CUDA共享内存库冲突报告较高

时间:2015-04-29 03:47:36

标签: cuda gpu shared-memory bank-conflict

我一直致力于优化某些代码,并遇到了与CUDA Nsight性能分析共享内存库冲突报告的问题。我能够将它简化为Nsight报告为存在银行冲突的非常简单的代码,当它看起来不应该存在冲突时。以下是内核:

__global__ void conflict() {
    __shared__ double values[33];
    values[threadIdx.x] = threadIdx.x;
    values[threadIdx.x+1] = threadIdx.x;
}

调用它的主要功能:

int main() {
    conflict<<<1,32>>>();
}

请注意,我使用单个warp来将此值降至最低。当我运行代码时,Nsight说有1个银行冲突,但根据我读过的所有内容,应该没有。对于共享内存阵列的每次访问,每个线程都访问连续的值,每个值都属于不同的存储区。

是否有其他人遇到过有关Nsight报道的问题,或者我是否因为银行冲突的运作而遗漏了一些问题?我将不胜感激任何反馈!

顺便说一下,我正在运行以下设置:

  • Windows 8
  • GTX 770
  • Visual Studio Community 2013
  • CUDA 7
  • Nsight Visual studio edition Version 4.5

2 个答案:

答案 0 :(得分:3)

如果目的是按原样运行已发布的代码,使用double数据类型,并且没有银行冲突,我相信可以适当使用cudaDeviceSetSharedMemConfig(在cc3.x设备上) 。这是一个测试用例:

$ cat t750.cu
#include <stdio.h>

typedef double mytype;


template <typename T>
__global__ void conflict() {
    __shared__ T values[33];
    values[threadIdx.x] = threadIdx.x;
    values[threadIdx.x+1] = threadIdx.x;
}

int main(){

#ifdef EBM
  cudaDeviceSetSharedMemConfig(cudaSharedMemBankSizeEightByte);
#endif

  conflict<mytype><<<1,32>>>();
  cudaDeviceSynchronize();
}

$ nvcc -arch=sm_35 -o t750 t750.cu
t750.cu(8): warning: variable "values" was set but never used
          detected during instantiation of "void conflict<T>() [with T=mytype]"
(19): here

$ nvprof --metrics shared_replay_overhead ./t750
==46560== NVPROF is profiling process 46560, command: ./t750
==46560== Profiling application: ./t750
==46560== Profiling result:
==46560== Metric result:
Invocations                               Metric Name                        Metric Description         Min         Max         Avg
Device "Tesla K40c (0)"
 Kernel: void conflict<double>(void)
          1                    shared_replay_overhead             Shared Memory Replay Overhead    0.142857    0.142857    0.142857
$ nvcc -arch=sm_35 -DEBM -o t750 t750.cu
t750.cu(8): warning: variable "values" was set but never used
          detected during instantiation of "void conflict<T>() [with T=mytype]"
(19): here

$ nvprof --metrics shared_replay_overhead ./t750
==46609== NVPROF is profiling process 46609, command: ./t750
==46609== Profiling application: ./t750
==46609== Profiling result:
==46609== Metric result:
Invocations                               Metric Name                        Metric Description         Min         Max         Avg
Device "Tesla K40c (0)"
 Kernel: void conflict<double>(void)
          1                    shared_replay_overhead             Shared Memory Replay Overhead    0.000000    0.000000    0.000000
$

规范为EightByteMode时,共享内存重放开销为零。

答案 1 :(得分:0)

事实证明我的错误在于我使用的数据类型。我错误地认为每个元素都放在一个银行中是理所当然的。但是,double数据类型是8个字节,因此它跨越2个共享内存库。将数据类型更改为float可解决此问题,并且正确显示0个库冲突。感谢您的反馈和帮助。

相关问题