执行C+时出现黑屏+;CUDA内核,输出正确的结果 我在CUDA C++的数组上做了一些简单的并行计算。一切正常,内核输出正确的结果(用串行CPU代码检查),但是当内核执行时,我的整个屏幕在整个内核执行期间变黑。我是CUDA的新手,所以我可能做错了什么,我只是不知道是什么 #define KERNEL_FOR_ITERS 1e6 __global__ void addKernel(float *c, const float *a, const float *b) { int i = blockIdx.x * blockDim.x + threadIdx.x; if (i % 2 == 0) for (int j = 0; j < KERNEL_FOR_ITERS; j++) c[i] += sqrt(abs(sin(a[i] * b[i]))); else for (int j = 0; j < KERNEL_FOR_ITERS; j++) c[i] += sqrt(abs(cos(a[i] * b[i]))); } #为ITERS 1e6定义内核 __全局无效添加内核(浮点*c,常量浮点*a,常量浮点*b) { int i=blockIdx.x*blockDim.x+threadIdx.x; 如果(i%2==0) for(int j=0;j

执行C+时出现黑屏+;CUDA内核,输出正确的结果 我在CUDA C++的数组上做了一些简单的并行计算。一切正常,内核输出正确的结果(用串行CPU代码检查),但是当内核执行时,我的整个屏幕在整个内核执行期间变黑。我是CUDA的新手,所以我可能做错了什么,我只是不知道是什么 #define KERNEL_FOR_ITERS 1e6 __global__ void addKernel(float *c, const float *a, const float *b) { int i = blockIdx.x * blockDim.x + threadIdx.x; if (i % 2 == 0) for (int j = 0; j < KERNEL_FOR_ITERS; j++) c[i] += sqrt(abs(sin(a[i] * b[i]))); else for (int j = 0; j < KERNEL_FOR_ITERS; j++) c[i] += sqrt(abs(cos(a[i] * b[i]))); } #为ITERS 1e6定义内核 __全局无效添加内核(浮点*c,常量浮点*a,常量浮点*b) { int i=blockIdx.x*blockDim.x+threadIdx.x; 如果(i%2==0) for(int j=0;j,c++,cuda,gpu,C++,Cuda,Gpu,我的问题是,我能在整个内核执行期间防止屏幕变黑而不影响太多的速度吗?如果您描述您的设置,包括您正在运行的操作系统和GPU,GPU是否驱动显示器,如果在windows操作系统上,GPU处于WDDM或TCC模式,这会有些有用 然而,我们可以在没有这一点的情况下作一些一般性发言 正如评论中指出的,目前,运行CUDA内核的GPU如果也支持显示,则不会为显示请求提供服务。这意味着当GPU内核运行时,显示器将显示为“冻结”或可能变为黑色。这当然有可能在未来发生变化,但这是当前和预期的行为 在这种情况下,通常

我的问题是,我能在整个内核执行期间防止屏幕变黑而不影响太多的速度吗?

如果您描述您的设置,包括您正在运行的操作系统和GPU,GPU是否驱动显示器,如果在windows操作系统上,GPU处于WDDM或TCC模式,这会有些有用

然而,我们可以在没有这一点的情况下作一些一般性发言

正如评论中指出的,目前,运行CUDA内核的GPU如果也支持显示,则不会为显示请求提供服务。这意味着当GPU内核运行时,显示器将显示为“冻结”或可能变为黑色。这当然有可能在未来发生变化,但这是当前和预期的行为

在这种情况下,通常的建议是使用第二个GPU运行CUDA,如果您根本不想干扰显示器,如果您在windows上,最好是该GPU能够运行,并置于TCC模式

为了在仅使用单个GPU的情况下减轻影响,并在单个GPU显示环境中为生产目的提供CUDA支持,应用程序的CUDA端的设计应确保内核持续时间受到限制。为了获得良好的交互性,一个合理的起点是将内核持续时间限制在0.1秒或更少,因为交互性损失的程度可能不是特别明显。如果你或某人不同意人为因素的说法,那没关系;我们不必为此争论。将内核持续时间减少到您决定的任何级别都将产生良好的显示交互性

在windows情况下(据我所知,在linux情况下),WDDM命令批处理使情况更加复杂。为了提高性能,可以对命令进行批处理,并且对背靠背内核调用进行批处理可能会导致比单个内核调用所显示的更长时间的交互性丢失。我不知道有什么方法可以正式解决这个问题。在每次内核调用之后,您可以通过发出虚假的(即不需要的)CUDA操作(如
cudaStreamQuery()
)来“刷新”WDDM命令队列。同样,我不知道有正式的文档化方法来实现这一点,在某种程度上,这可能取决于您的应用程序设计

就性能而言,CUDA内核启动通常需要大约100微秒或更少的启动开销(我们可以称之为浪费时间)。因此,如果我们将一个长时间运行的内核分解为100毫秒的“块”,并且每个块增加约100微秒的开销,那么对性能的净影响可能是CUDA计算吞吐量减少0.1%(假设显示任务微不足道)

以您提供的代码为例,您希望将该内核分解为一系列内核,在您选择的GPU上对其进行基准测试/计时,以便内核运行时间不超过100毫秒(或您选择的数量)

#为ITERS 1e6定义内核
__全局无效添加内核(浮点*c、常量浮点*a、常量浮点*b、常量整数)
{
int i=blockIdx.x*blockDim.x+threadIdx.x;
如果(i%2==0)
对于(int j=0;j
我不认为这是您实际使用的内核,但顺便说一句,它的性能特征可以通过将线程之间的实际差异限制在一小段代码中来改进。例如:

__global__ void addKernel(float *c, const float *a, const float *b,const int iters)
{
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    float val = a[i] * b[i];
    if (i % 2 == 0)
       val = sin(val);
    else 
       val = cos(val);
    for (int j = 0; j < iters; j++)
            c[i] += sqrt(abs(val));
}
\uuuu全局\uuuuu无效添加内核(浮点*c、常量浮点*a、常量浮点*b、常量整数)
{
int i=blockIdx.x*blockDim.x+threadIdx.x;
浮点数val=a[i]*b[i];
如果(i%2==0)
val=sin(val);
其他的
val=cos(val);
对于(int j=0;j

不管怎样,编译器可能会找出这种收缩,但我通常会尽量给它一个最好的“开头”。

如果您描述您的设置,包括您正在运行的操作系统和GPU,GPU是否驱动显示器,如果在windows操作系统上,GPU处于WDDM或TCC模式,这会有些有用

然而,我们可以在没有这一点的情况下作一些一般性发言

正如评论中指出的,目前,运行CUDA内核的GPU如果也支持显示,则不会为显示请求提供服务。这意味着当GPU内核运行时,显示器将显示为“冻结”或可能变为黑色。这当然有可能在未来发生变化,但这是当前和预期的行为

在这种情况下,通常的建议是
__global__ void addKernel(float *c, const float *a, const float *b,const int iters)
{
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    float val = a[i] * b[i];
    if (i % 2 == 0)
       val = sin(val);
    else 
       val = cos(val);
    for (int j = 0; j < iters; j++)
            c[i] += sqrt(abs(val));
}