GPU& CPU并发:生产者消费者有界缓冲区

时间:2015-04-24 14:58:01

标签: concurrency cuda

考虑以下问题:

您拥有一个具有单个gpu和一个cpu的计算环境。 在gpu上,运行一个程序,对1e6浮点数组执行计算。该计算步骤重复n次(过程1)。在每个计算步骤之后,我将阵列从设备存储器传输到主机存储器。传输完成后,将在CPU上调用串行算法分析数据(过程2)。

这个程序是连续工作的。我想知道如何并行化进程1和2,以减少整个程序运行时间。过程1必须等待过程2完成,反之亦然。

我知道CUDA内核是异步调用的,我知道有固定主机内存的异步复制操作。但是,在这种情况下,我需要等待GPU完成才能开始处理该输出。 我怎样才能传递这些信息?

我尝试修改多线程cpu生产者/消费者代码,但它没有用。我最终序列化了两个管理gpu和cpu工作负载的cpu线程。 但是,在这里我的GPU等待CPU继续完成...

#include <mutex>
#include <condition_variable>

#include "ProducerConsumerBuffer.hpp"

ProducerConsumerBuffer::ProducerConsumerBuffer(int capacity_in, int n): capacity(capacity_in), count(0) {
    c_bridge = new float[n];
    c_CPU = new float[n];
}

ProducerConsumerBuffer::~ProducerConsumerBuffer(){
    delete[] c_bridge;
    delete[] c_CPU;
}

void ProducerConsumerBuffer::upload(device_pointers *d, params &p, streams *s){
    std::unique_lock<std::mutex> l(lock);

    not_full.wait(l, [this](){return count != 1; });

    copy_GPU_to_CPU(d,c_bridge,p,s);
    count++;

    not_empty.notify_one();
}



void ProducerConsumerBuffer::fetch(){
    std::unique_lock<std::mutex> l(lock);

    not_empty.wait(l, [this](){return count != 0; });

    std::swap(c_bridge,c_CPU);
    count--;

    not_full.notify_one();

}

我希望有一种方法可以用cudastreams来做到这一点。但我认为它们只适用于设备函数调用。我是否需要使用MPI或是否有其他选项来同步异构计算平台上的进程?我读到OpenCL支持此操作,因为所有计算设备都组织在一个&#34; context&#34;中。是不是可以用CUDA做同样的事情?

如果我的序列化CPU操作运行时间比GPU操作长4倍,我计划创建4个CPU消费者。

非常感谢任何见解!

编辑:CPU功能包含不可并行化的串行代码。

1 个答案:

答案 0 :(得分:0)

如果不使用多个线程或进程,或者有创地使CPU算法复杂化以实现可容忍的调度延迟,则无法执行您想要的操作。这是因为您必须能够以低延迟以正确的频率命令GPU来处理GPU工作负载的数据,但CPU工作负载听起来并不重要,必须考虑到循环的运行时间。

正因为如此,要确保CPU和GPU都在不断处理并实现最高的吞吐量。最低的延迟,你必须将GPU命令部分和昂贵的CPU计算部分分成不同的线程 - 而2之间是某种IPC - 最好是共享内存。如果专用CPU处理线程以类似于CUDA的方式使用并且使用它跨越线程的cudaEvent_t并使GPU命令线程也命令CPU线程,那么您可能能够简化某些任务。是1个命令线程和2个处理从属(GPU,CPU)。

相关问题