Concurrency 共享特斯拉K20的两个进程的并发执行

Concurrency 共享特斯拉K20的两个进程的并发执行,concurrency,cuda,tesla,Concurrency,Cuda,Tesla,当我启动一个内核的两个实例以便在共享GPU资源的同时运行时,我遇到了一个奇怪的行为 我开发了一个CUDA内核,目标是在单个SM(多处理器)中运行,其中线程执行一个操作数次(使用循环) 内核准备只创建一个块,因此只使用一个SM simple.cu #包括 #包括 #包括 #包括 使用名称空间std; __全局无效增量(浮动*入,浮动*出) { int it=0,i=blockIdx.x*blockDim.x+threadIdx.x; 浮子a=0.8525852f; 对于(it=0;it当您使用同一

当我启动一个内核的两个实例以便在共享GPU资源的同时运行时,我遇到了一个奇怪的行为

我开发了一个CUDA内核,目标是在单个SM(多处理器)中运行,其中线程执行一个操作数次(使用循环)

内核准备只创建一个块,因此只使用一个SM

simple.cu

#包括
#包括
#包括
#包括
使用名称空间std;
__全局无效增量(浮动*入,浮动*出)
{
int it=0,i=blockIdx.x*blockDim.x+threadIdx.x;
浮子a=0.8525852f;

对于(it=0;it当您使用同一GPU运行两个单独的进程时,它们都有自己的上下文。CUDA不支持在同一设备上同时具有多个上下文。相反,每个上下文以未定义的方式竞争设备,并进行驱动程序级别的上下文切换。这就是为什么执行过程的行为与进程的行为类似erialised——实际上它们是,但在驱动程序而不是GPU级别

有一些可用的技术(MPS、Hyper-Q)可以做你想做的事情,但你尝试的方式是行不通的


编辑以响应问题中的更新内容

您使用MatrixMul示例添加的示例没有显示您的想法。该应用程序运行300个短内核,并计算平均300次运行的性能数。您的分析显示已设置为非常粗略的时间刻度分辨率,因此看起来好像只有一次长时间运行的内核启动,而实际上,它是一系列非常短的运行时间内核

为了说明这一点,请考虑以下内容:

这是在开普勒设备上运行的单个MatrixMul进程的正常分析运行。请注意,有许多单独的内核直接在彼此之后运行。

以下是在同一开普勒设备上同时运行的两个MatrixMul进程的分析跟踪:


请注意,每个进程的配置文件跟踪中都存在缺口,这是两个进程之间发生上下文切换的地方。该行为与您的原始示例相同,只是在更精细的时间粒度上。在讨论过程中,几个不同的人多次重复了这一点——CUDA不支持使用标准运行时API在示例设备上同时支持多个上下文。MPS服务器通过添加一个守护进程来允许此操作,该守护进程使用大型共享内部Hyper-Q管道重新实现API,但您没有使用此操作,并且它与您在本问题中显示的结果无关。

当您运行两个单独的进程时使用相同GPU的ESS,每个都有自己的上下文。CUDA不支持在同一设备上同时具有多个上下文。相反,每个上下文以未定义的方式竞争设备,并进行驱动程序级别的上下文切换。这就是为什么执行过程的行为就像是串行化的——实际上是串行化的,但实际上是串行化的驱动程序而不是GPU级别

有一些可用的技术(MPS、Hyper-Q)可以做你想做的事情,但你尝试的方式是行不通的


编辑以响应问题中的更新内容

您使用MatrixMul示例添加的示例没有显示您的想法。该应用程序运行300个短内核,并计算平均300次运行的性能数。您的分析显示已设置为非常粗略的时间刻度分辨率,因此看起来好像只有一次长时间运行的内核启动,而实际上,它是一系列非常短的运行时间内核

为了说明这一点,请考虑以下内容:

这是在开普勒设备上运行的单个MatrixMul进程的正常分析运行。请注意,有许多单独的内核直接在彼此之后运行。

以下是在同一开普勒设备上同时运行的两个MatrixMul进程的分析跟踪:


请注意,每个进程的配置文件跟踪中都存在缺口,这是两个进程之间发生上下文切换的地方。该行为与您的原始示例相同,只是在更精细的时间粒度上。在讨论过程中,几个不同的人多次重复了这一点——CUDA不支持使用标准运行时API在示例设备上同时支持多个上下文。MPS服务器通过添加一个守护进程来允许此操作,该守护进程使用大型共享内部Hyper-Q管道重新实现API,但您没有使用此操作,并且它与您在本问题中显示的结果无关。

当您运行两个单独的进程时使用相同GPU的ESS,每个都有自己的上下文。CUDA不支持在同一设备上同时具有多个上下文。相反,每个上下文以未定义的方式竞争设备,并进行驱动程序级别的上下文切换。这就是为什么执行过程的行为就像是串行化的——实际上是串行化的,但实际上是串行化的驱动程序而不是GPU级别

有一些可用的技术(MPS、Hyper-Q)可以做你想做的事情,但你尝试的方式是行不通的


编辑以响应问题中的更新内容

您使用MatrixMul示例添加的示例没有显示您的想法。该应用程序运行300个短内核,并计算平均300次运行的性能数。您的分析显示已设置为非常粗略的时间刻度分辨率,因此看起来好像只有一次长时间运行的内核启动,而实际上,它是一系列非常短的运行时间内核

为了说明这一点,请考虑以下内容:

这是在开普勒设备上运行的单个MatrixMul进程的正常分析运行
#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);
}