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

CUDA共享内存库冲突报告更高,cuda,gpu,shared-memory,bank-conflict,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; }

我一直在优化一些代码,但在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>>>();
}
intmain(){
冲突();
}
请注意,我正在使用一个单一的扭曲,以真正减少到最低限度。当我运行代码时,Nsight说有1个银行冲突,但根据我读到的所有内容,不应该有任何冲突。对于对共享内存阵列的每次访问,每个线程都在访问连续的值,每个值都属于不同的存储组

是否有其他人在Nsight的报告方面遇到过问题,或者我只是在银行冲突的运作方面遗漏了什么?如果有任何反馈,我将不胜感激

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

  • 视窗8
  • GTX 770
  • Visual Studio社区2013
  • CUDA 7
  • Nsight Visual studio版本4.5

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

如果目的是按原样运行发布的代码,使用
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
$
$cat t750.cu
#包括
typedef双mytype;
模板
__全局无效冲突(){
__共享的_u; T值[33];
值[threadIdx.x]=threadIdx.x;
值[threadIdx.x+1]=threadIdx.x;
}
int main(){
#ifdef EBM
cudaDeviceSetSharedMemConfig(cudaSharedMemBankSizeEightByte);
#恩迪夫
冲突();
cudaDeviceSynchronize();
}
$nvcc-arch=sm_35-o t750 t750.cu
t750.cu(8):警告:设置了变量“值”,但从未使用过
在实例化“void conflict()[with T=mytype]时检测到”
(19) :这里
$nvprof——指标共享\u重播\u开销。/t750
==46560==NVPROF正在分析进程46560,命令:./t750
==46560==分析应用程序:./t750
==46560==分析结果:
==46560==度量结果:
调用度量名称度量描述最小最大平均值
装置“特斯拉K40c(0)”
内核:无效冲突(void)
1共享内存重放开销共享内存重放开销0.142857 0.142857 0.142857
$nvcc-arch=sm_35-DEBM-o t750 t750.cu
t750.cu(8):警告:设置了变量“值”,但从未使用过
在实例化“void conflict()[with T=mytype]时检测到”
(19) :这里
$nvprof——指标共享\u重播\u开销。/t750
==46609==NVPROF正在分析进程46609,命令:./t750
==46609==分析应用程序:./t750
==46609==分析结果:
==46609==度量结果:
调用度量名称度量描述最小最大平均值
装置“特斯拉K40c(0)”
内核:无效冲突(void)
1共享内存重放开销共享内存重放开销0.0000000.0000000.000000
$

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

内核包含越界内存访问。我更担心的是银行冲突。对不起,我犯了越界的错误。数组应该是33个元素,固定的。