Multithreading 从每个主机线程启动CUDA流,每个流是否会并发运行?

Multithreading 从每个主机线程启动CUDA流,每个流是否会并发运行?,multithreading,cuda,gpu,Multithreading,Cuda,Gpu,通过搜索,我知道cuda支持从每个主机线程启动cuda流。我的问题是,当我只使用一个线程时,测试需要180秒才能完成。然后我使用了三个线程,测试耗时430秒。为什么他们不同时运行 我的gpu是特斯拉K20c 下面是我的简化代码,它切断了一些变量的定义和输出数据的保存等 int main() { cudaSetDevice(0); cudaSetDeviceFlags(cudaDeviceBlockingSync); cudaStream_t stream1; cu

通过搜索,我知道cuda支持从每个主机线程启动cuda流。我的问题是,当我只使用一个线程时,测试需要180秒才能完成。然后我使用了三个线程,测试耗时430秒。为什么他们不同时运行

我的gpu是特斯拉K20c

下面是我的简化代码,它切断了一些变量的定义和输出数据的保存等

int main()
{
    cudaSetDevice(0);
    cudaSetDeviceFlags(cudaDeviceBlockingSync);
    cudaStream_t stream1;
    cudaStream_t stream2;
    cudaStreamCreate(&stream1);
    cudaStreamCreate(&stream2);
    int ret;
    pthread_t id_1,id_2;
    ret = pthread_create(&id_1,NULL,thread_1,&stream1);
    ret = pthread_create(&id_2,NULL,thread_1,&stream2);
    pthread_join(id_1,NULL);
    pthread_join(id_2,NULL);
    cudaStreamDestroy(stream1);
    cudaStreamDestroy(stream2);
    return 0;
}

void* thread_1(void *streamno)
{ 
    char speechInFileName[1024] = "data/ori_in.bin";
    char bitOutFileName[1024] = "data/enc_out.bin";
    //make sure the bitOutFileName is exclusive
    char buf[1024];
    int nchar = snprintf(buf,1024,"%p",(char*)streamno);
    strcat(bitOutFileName,buf);

    //change the stack size limit
    size_t pvalue = 60 * 1024;
    if (cudaDeviceSetLimit(cudaLimitStackSize, pvalue) == cudaErrorInvalidValue)
        cout << "cudaErrorInvalidValue " << endl;

    Encoder_main(3, speechInFileName, bitOutFileName,(cudaStream_t*)streamno);

    pthread_exit(0);
}

int Encoder_main(int argc, char speechInFileName[], char bitOutFileName[], cudaStream_t *stream)
{
    void      *d_psEnc;
    cudaMalloc(&d_psEnc, encSizeBytes);
    cudaMemcpyAsync(d_psEnc, psEnc, encSizeBytes, cudaMemcpyHostToDevice, *stream);
    SKP_SILK_SDK_EncControlStruct *d_encControl; // Struct for input to encoder
    cudaMalloc(&d_encControl, sizeof(SKP_SILK_SDK_EncControlStruct));
    cudaMemcpyAsync(d_encControl, &encControl, sizeof(SKP_SILK_SDK_EncControlStruct), cudaMemcpyHostToDevice, *stream);
    SKP_int16 *d_in;
    cudaMalloc(&d_in, FRAME_LENGTH_MS * MAX_API_FS_KHZ * MAX_INPUT_FRAMES * sizeof(SKP_int16));
    SKP_int16 *d_nBytes;
    cudaMalloc(&d_nBytes, sizeof(SKP_int16));
    SKP_int32 *d_ret;
    cudaMalloc(&d_ret, sizeof(SKP_int32));
    SKP_uint8 *d_payload;
    cudaMalloc(&d_payload, MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES);


    while (1) {
        /* Read input from file */
        counter = fread(in, sizeof(SKP_int16), (frameSizeReadFromFile_ms * API_fs_Hz) / 1000, speechInFile);

        if ((SKP_int)counter < ((frameSizeReadFromFile_ms * API_fs_Hz) / 1000)) {
            break;
        }
        /* max payload size */
        nBytes = MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES;

        cudaMemcpyAsync(d_nBytes, &nBytes, sizeof(SKP_int16), cudaMemcpyHostToDevice, *stream);
        cudaMemcpyAsync(d_in, in, FRAME_LENGTH_MS * MAX_API_FS_KHZ * MAX_INPUT_FRAMES, cudaMemcpyHostToDevice * sizeof(SKP_int16), *stream);
        encoder_kernel <<<1, 1, 0, *stream>>>(d_psEnc, d_encControl, d_in, (SKP_int16)counter, d_payload, d_nBytes, d_ret);
        cudaMemcpyAsync(&nBytes, d_nBytes, sizeof(SKP_int16), cudaMemcpyDeviceToHost,*stream);
        cudaMemcpyAsync(&ret, d_ret, sizeof(ret), cudaMemcpyDeviceToHost,*stream);
        cudaMemcpyAsync(payload, d_payload, MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES, cudaMemcpyDeviceToHost,*stream);

        cudaStreamSynchronize(*stream);
    }

    cudaFree(d_psEnc);
    cudaFree(d_encControl);
    cudaFree(d_in);
    cudaFree(d_nBytes);
    cudaFree(d_ret);
    cudaFree(d_payload);

    return 0;
}
intmain()
{
cudaSetDevice(0);
cudaSetDeviceFlags(cudaDeviceBlockingSync);
cudaStream_t stream1;
cudaStream_t stream2;
cudaStreamCreate(&stream1);
cudaStreamCreate(&stream2);
int ret;
pthread_t id_1,id_2;
ret=pthread_create(&id_1,NULL,thread_1,&stream1);
ret=pthread_create(&id_2,NULL,thread_1,&stream2);
pthread_join(id_1,NULL);
pthread_join(id_2,NULL);
cudaStreamDestroy(stream1);
cudaStreamDestroy(stream2);
返回0;
}
空*螺纹1(空*流号)
{ 
char speechInFileName[1024]=“data/ori_in.bin”;
char bitOutFileName[1024]=“数据/enc_out.bin”;
//确保bitOutFileName是独占的
char-buf[1024];
int nchar=snprintf(buf,1024,“%p”,(char*)streamno);
strcat(比特输出文件名,buf);
//更改堆栈大小限制
尺寸p值=60*1024;
if(cudaDeviceSetLimit(cudaLimitStackSize,pvalue)==cudaErrorInvalidValue)

cout一个线程需要180秒,三个线程需要430秒。430/180=~2.4。这不是三倍长,表明您有一些并发性。是否可以做得更好取决于每个线程所做工作的细节


经常是通过英伟达可视化分析器运行应用程序的最佳方法。您可以从Visual Prror界面运行它,或者从命令行NVPROFF剖析器输出。这将显示每个CUDA API调用以及副本和内核。清楚地看到发生了什么。

您需要提供一个。请注意,我并不是要求您提供完整的代码,只是一个简化的示例。是的,这需要努力。请注意,
cudamaloc
是一个同步调用。在多线程环境中,它可能会导致意外行为。您希望将其排除在代码段(流)之外您希望重叠或同时运行的。可能会帮助您了解正在发生的情况。谢谢您的建议!我将代码更改为只打开两个流,并使用可视化探查器显示时间线。从图像中,我有时看到两个流同时运行,但大多数情况下没有!您能告诉我原因吗?谢谢!不,如果您你不想提供MCVE。由于缺少MCVE,我投票结束了这个问题。谢谢你的回答!我更改了我提供的代码,它适合MCVE吗?我是新来的。谢谢你的耐心。不,它不是MCVE。哪里定义了
encoder\u内核
?你读过MCVE链接了吗?MCVE应该是我可以使用的东西复制、粘贴、编译和运行,然后查看问题,而不必添加任何内容或更改任何内容。在您再次询问某个内容是否为MCVE之前,请尝试以下简单测试:1.从一个干净、空的项目开始。2.除了您在问题中发布的内容之外,您可以将其编译吗?如果不是,我不能使用它来尝试和工作使用您的代码。是的,它需要(通常)额外的努力来创建,并且您将希望简化不必要的元素。是的,您是对的,我已经更新了nvprof分析的映像,您能给我更多关于为什么测试只具有一些并发性的信息吗?