Cuda 在GTX Titan卡中重叠内核执行和数据传输的最佳策略是什么?

Cuda 在GTX Titan卡中重叠内核执行和数据传输的最佳策略是什么?,cuda,Cuda,当我尝试重叠数据传输和内核执行时,无论我使用什么流,卡似乎都在按顺序执行所有内存传输 因此,如果我发布以下内容: 流1:MemcpyA_HtoD_1;内核_1;MemcpyA_DtoH_1 流2:MemcpyA_HtoD_2;内核2;MemcpyA_DtoH_2 MemcpyA_HtoD_2将等待MemcpyA_DtoH_1完成。因此,没有实现重叠。无论我使用什么配置的流,Memcpy操作总是按顺序发出的。因此,实现重叠的唯一方法是缓冲输出或将输出传输延迟到下一次迭代 我使用CUDA5.5、

当我尝试重叠数据传输和内核执行时,无论我使用什么流,卡似乎都在按顺序执行所有内存传输

因此,如果我发布以下内容:

  • 流1:MemcpyA_HtoD_1;内核_1;MemcpyA_DtoH_1
  • 流2:MemcpyA_HtoD_2;内核2;MemcpyA_DtoH_2
MemcpyA_HtoD_2将等待MemcpyA_DtoH_1完成。因此,没有实现重叠。无论我使用什么配置的流,Memcpy操作总是按顺序发出的。因此,实现重叠的唯一方法是缓冲输出或将输出传输延迟到下一次迭代

我使用CUDA5.5、Windows7x64和GTXTitan。所有cpu内存均固定,数据传输使用异步版本完成

查看以下屏幕,了解其行为:

发布时,主机\u到\u设备->内核->设备\u到\u主机(正常行为)不能重叠

将主机\u发送到\u设备->内核(避免在内核之后将设备\u发送到\u主机)会重叠。。。因为所有内存拷贝都是按顺序执行的,无论我尝试什么流配置

更新

如果有人对复制这个问题感兴趣,我已经编写了一个合成程序来显示这种不受欢迎的行为。这是一个使用CUDA 5.5的完整VS2010解决方案

是否有人可以在linux上执行此操作以进行测试

#include "cuda_runtime.h"
#include "device_launch_parameters.h"


#include <stdio.h>
#define N 1024*1024

__global__ void someKernel(int *d_in, int *d_out) {
    for (int i = threadIdx.x; i < threadIdx.x + 1024; i++) {
        d_out[i] = d_in[i];
    }
}

int main () {
    int *h_bufferIn[100];
    int *h_bufferOut[100];
    int *d_bufferIn[100];
    int *d_bufferOut[100];

    //allocate some memory
    for (int i = 0; i < 100; i++) {
        cudaMallocHost(&h_bufferIn[i],N*sizeof(int));
        cudaMallocHost(&h_bufferOut[i],N*sizeof(int));
        cudaMalloc(&d_bufferIn[i], N*sizeof(int));
        cudaMalloc(&d_bufferOut[i], N*sizeof(int));
    }

    //create cuda streams
    cudaStream_t st[2];
    cudaStreamCreate(&st[0]);
    cudaStreamCreate(&st[1]);

    //trying to overlap computation and memcpys
    for (int i = 0; i < 100; i+=2) {
        cudaMemcpyAsync(d_bufferIn[i], h_bufferIn[i], N*sizeof(int), cudaMemcpyHostToDevice, st[i%2]);
        someKernel<<<1,256, 0, st[i%2]>>>(d_bufferIn[i], d_bufferOut[i]);
        cudaMemcpyAsync(h_bufferOut[i], d_bufferOut[i], N*sizeof(int), cudaMemcpyDeviceToHost, st[i%2]);
        cudaStreamQuery(0);

        cudaMemcpyAsync(d_bufferIn[i+1], h_bufferIn[i+1], N*sizeof(int), cudaMemcpyHostToDevice, st[(i+1)%2]);
        someKernel<<<1,256, 0, st[(i+1)%2]>>>(d_bufferIn[i+1], d_bufferOut[i+1]);
        cudaMemcpyAsync(h_bufferOut[i+1], d_bufferOut[i+1], N*sizeof(int), cudaMemcpyDeviceToHost, st[(i+1)%2]);
        cudaStreamQuery(0);
    }
    cudaDeviceSynchronize();
}
#包括“cuda_runtime.h”
#包括“设备启动参数.h”
#包括
#定义n1024*1024
__全局\uuuuuvoid someKernel(int*d\u in,int*d\u out){
对于(int i=threadIdx.x;i
TL;DR:问题是由Nsight Monitor中的WDDM TDR延迟选项引起的!如果设置为false,则会出现问题。相反,如果您设置 TDR延迟值设置为非常高的数字,“启用”选项设置为 没错,这个问题消失了

阅读下面的其他(旧的)步骤,直到我找到上面的解决方案,以及一些其他可能的原因

我最近才部分解决了这个问题!我认为这是针对windows和aero的。请尝试这些步骤,并发布您的结果以帮助他人!我在GTX 650和GT 640上试过

<强>在你做任何事情之前,考虑一下,因为英伟达驱动程序已经为Windows验证了问题!当你使用板载gpu时,据说驱动程序并没有完全加载,所以很多错误都被避免了。此外,系统响应性在工作时得到保持

  • 确保您的并发问题与旧驱动程序(包括bios)等其他问题无关
  • 转到计算机>属性
  • 选择左侧的高级系统设置
  • 转到“高级”选项卡
  • 在性能上单击“设置”
  • 在“视觉效果”选项卡中,选择“调整以获得最佳性能”项目符号
  • 这将禁用aero和几乎所有的视觉效果。如果此配置有效,您可以尝试逐个启用视觉效果框,直到找到导致问题的精确框

    或者,您可以:

  • 右键单击桌面,选择个性化设置
  • 从基本主题中选择一个没有aero的主题
  • 这也将如上所述,但启用了更多的视觉选项。对于我的两台设备,这个设置也可以使用,所以我保留了它

    请,当您尝试这些解决方案时,回到这里并发布您的发现

    对我来说,它解决了大多数情况下的问题(我制作的平铺dgemm),但请注意我仍然无法正确运行“simpleStreams”并实现并发性…

    更新:通过新的windows安装,问题得到了完全解决!!前面的步骤改善了某些情况下的行为,但只有重新安装才能解决所有问题


    我将尝试找到一种不太激进的方法来解决这个问题,也许只恢复注册表就足够了。

    看起来Titan没有实现“Hyper-Q”?这种行为类似于以前的费米卡片。根据这篇白皮书,我必须测试将memcpyA_DtoH放在memcpyA_HtoD之前(因此将上一次迭代的结果上传到cpu)。它“应该”适用于我的具体算法,但我仍然对GTX中复制队列的实际实现方式感到困惑,因为它也不起作用。我真的很失望不能有效地重叠计算和执行:/这只是一个建议。研究关于堆栈溢出的类似问题并得出自己的结论。那是