当我启动 2 个内核实例以便在共享 GPU 资源的同时同时运行时,我遇到了一种奇怪的行为。
我开发了一个 CUDA 内核,旨在在单个 SM(多处理器)中运行,其中线程执行多次操作(带有循环)。
内核准备只创建一个块,因此只使用一个 SM。
简单的.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 中同时运行吗?
已编辑
为了让我更清楚,我将附上从 nvprof 获得的并发执行的配置文件:
现在,我想向您展示同一场景的行为,但同时执行 matrixMul 示例的两个实例:
如您所见,在第一种情况下,一个内核等待另一个内核完成。而在第二种情况(matrixMul)中,来自两个上下文的内核同时运行。
谢谢你。