当我启动2个内核实例以便在共享GPU资源的同时运行时,我遇到了一种奇怪的行为。
我开发了一个CUDA内核,旨在在单个SM(多处理器)中运行,其中线程执行多次操作(使用循环)。
内核准备只创建一个块,因此只使用一个SM。
simple.cu
#include <cuda_runtime.h>
#include <stdlib.h>
#include <stdio.h>
#include <helper_cuda.h>
using namespace std;
__global__ void increment(float *in, float *out)
{
int it=0, i = blockIdx.x * blockDim.x + threadIdx.x;
float a=0.8525852f;
for(it=0; it<99999999; it++)
out[i] += (in[i]+a)*a-(in[i]+a);
}
int main( int argc, char* argv[])
{
int i;
int nBlocks = 1;
int threadsPerBlock = 1024;
float *A, *d_A, *d_B, *B;
size_t size=1024*13;
A = (float *) malloc(size * sizeof(float));
B = (float *) malloc(size * sizeof(float));
for(i=0;i<size;i++){
A[i]=0.74;
B[i]=0.36;
}
cudaMalloc((void **) &d_A, size * sizeof(float));
cudaMalloc((void **) &d_B, size * sizeof(float));
cudaMemcpy(d_A, A, size, cudaMemcpyHostToDevice);
cudaMemcpy(d_B, B, size, cudaMemcpyHostToDevice);
increment<<<nBlocks,threadsPerBlock>>>(d_A, d_B);
cudaDeviceSynchronize();
cudaMemcpy(B, d_B, size, cudaMemcpyDeviceToHost);
free(A);
free(B);
cudaFree(d_A);
cudaFree(d_B);
cudaDeviceReset();
return (0);
}
所以如果我执行内核:
time ./simple
我得到了
real 0m36.659s
user 0m4.033s
sys 0m1.124s
否则,如果我执行两个实例:
time ./simple & time ./simple
我得到了每个流程:
real 1m12.417s
user 0m29.494s
sys 0m42.721s
real 1m12.440s
user 0m36.387s
sys 0m8.820s
据我所知,执行应同时持续一个(约36秒)。但是,它们的基准时间是两倍。我们知道GPU有13个SM,每个SM应该执行一个块,因此内核只创建1个块。
它们是否在同一个SM中执行?
它们不应该在不同的SM中同时运行吗?
EDITED
为了让我更清楚,我将附上从nvprof获得的并发执行的配置文件:
现在,我想向您展示同一场景的行为,但同时执行matrixMul示例的两个实例:
正如您所看到的,在第一个场景中,内核等待另一个内核完成。而在第二种情况(matrixMul)中,来自两个上下文的内核同时运行。
谢谢。
答案 0 :(得分:3)
当您使用相同的GPU运行两个单独的进程时,它们每个都有自己的上下文。 CUDA不支持同时在同一设备上拥有多个上下文。相反,每个上下文以未定义的方式竞争设备,具有驱动程序级上下文切换。这就是为什么执行的行为就像进程被序列化一样 - 实际上它们是,但是在驱动程序而不是GPU级别。
有可用的技术(MPS,Hyper-Q)可以做你想要的,但你尝试这样做的方式是行不通的。
编辑以回复您问题中的更新:
使用MatrixMul示例添加的示例未显示您的想法。该应用程序运行300个短内核,并计算这300个运行的平均值的性能数。您的性能分析显示已设置为非常粗略的时间分辨率,因此看起来只有一个长时间运行的内核启动,而实际上它是一系列非常短的运行时内核。
为了说明这一点,请考虑以下事项:
这是在Kepler设备上运行的单个MatrixMul进程的常规性能分析运行。请注意,有许多单独的内核直接相互运行。
这些是在同一个Kepler设备上运行的两个同步MatrixMul进程的分析跟踪:
请注意,每个进程的配置文件跟踪中都存在间隙,这是两个进程之间发生上下文切换的位置。行为与原始示例相同,只是在更精细的时间粒度。正如本讨论过程中由几个不同的人重复多次--CUDA不支持使用标准运行时API同时在示例设备上使用多个上下文。 MPS服务器 允许这样做,方法是添加一个守护程序,该守护程序使用大型共享内部Hyper-Q管道重新实现API,但您没有使用它,它与您在此中显示的结果无关问题