【发布时间】:2015-07-03 06:06:09
【问题描述】:
考虑以下问题:
您有一个具有单个 gpu 和单个 cpu 的计算环境。 在 gpu 上,您运行一个程序,该程序对 1e6 个浮点数的数组执行计算。该计算步骤重复 n 次(过程 1)。在每个计算步骤之后,我将数组从设备内存传输到主机内存。传输完成后,将在 CPU 上调用串行算法分析数据(过程 2)。
此程序连续运行。我想知道如何并行化进程 1 和 2,以减少整个程序的运行时间。进程 1 必须等待进程 2 完成,反之亦然。
我知道 CUDA 内核是异步调用的,并且我知道存在带有固定主机内存的异步复制操作。但是,在这种情况下,我需要等待 GPU 完成,然后 CPU 才能开始处理该输出。 我怎样才能传递这些信息?
我尝试修改多线程 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,因为所有计算设备都组织在一个“上下文”中。 CUDA不能做同样的事情吗?
如果我的序列化 CPU 操作的运行时间是 GPU 操作的 4 倍,我计划创建 4 个 CPU 使用者。
任何见解将不胜感激!
编辑:CPU 函数包含不可并行化的串行代码。
【问题讨论】:
-
只是附注:为什么需要在主机上进行“数据分析”?如果您可以在设备上执行它,根据此分析步骤的输出,您可以节省内存带宽...
-
为了在 CPU 和 GPU 之间获得设备并发,通常的习惯用法是双缓冲区:让 CPU 和 GPU 在 2 个不同的缓冲区上运行,然后在两个设备都完成后切换缓冲区的意义。您描述的工作负载听起来需要 4 个缓冲区和 4 个 CPU 线程来进行 CPU 处理。目标是让 2 台设备(CPU 和 GPU)中的每台都花费相等的时间处理,否则其中一个或另一个会浪费时间等待。此处的可分页 memcpy 示例应该会有所帮助。 github.com/ArchaeaSoftware/cudahandbook/tree/master/concurrency
-
@oscillon 请确保标记答案并投票,以便我们关闭它
标签: concurrency cuda