Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/laravel/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Concurrency GPU&;CPU并发:生产者-消费者边界缓冲区_Concurrency_Cuda - Fatal编程技术网

Concurrency GPU&;CPU并发:生产者-消费者边界缓冲区

Concurrency GPU&;CPU并发:生产者-消费者边界缓冲区,concurrency,cuda,Concurrency,Cuda,考虑以下问题: 您的计算环境只有一个gpu和一个cpu。 在gpu上,您可以运行一个程序,在1e6浮点数组上执行计算。此计算步骤重复n次(过程1)。在每个计算步骤之后,我将数组从设备内存转移到主机内存。传输完成后,在CPU上调用串行算法分析数据(进程2) 这个程序连续工作。我想知道如何并行化进程1和进程2,以减少整个程序的运行时间。流程1必须等待流程2完成,反之亦然 我知道CUDA内核是异步调用的,并且我知道有固定主机内存的异步复制操作。但是,在这种情况下,我需要等待GPU完成,然后CPU才能开

考虑以下问题:

您的计算环境只有一个gpu和一个cpu。 在gpu上,您可以运行一个程序,在1e6浮点数组上执行计算。此计算步骤重复n次(过程1)。在每个计算步骤之后,我将数组从设备内存转移到主机内存。传输完成后,在CPU上调用串行算法分析数据(进程2)

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

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

我试图修改多线程cpu生产者/消费者代码,但没有成功。我最终序列化了两个cpu线程,它们管理gpu和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();

}
#包括
#包括
#包括“ProducerConsumerBuffer.hpp”
ProducerConsumerBuffer::ProducerConsumerBuffer(int capacity_in,int n):容量(capacity_in),计数(0){
c_桥=新浮子[n];
c_CPU=新浮点[n];
}
ProducerConsumerBuffer::~ProducerConsumerBuffer(){
删除[]c_桥;
删除[]c_CPU;
}
void ProducerConsumerBuffer::upload(设备指针*d、参数&p、流*s){
std::唯一锁l(锁);
未满。等待(l,[this](){返回计数!=1;});
将GPU复制到CPU(d,c_桥,p,s);
计数++;
不是空的。通知一个();
}
void ProducerConsumerBuffer::fetch(){
std::唯一锁l(锁);
不为空。等待(l,[this](){返回计数!=0;});
交换(c_桥,c_CPU);
计数--;
未满。通知一个();
}
我希望cudastreams能有办法做到这一点。但我认为它们只适用于设备函数调用。我是否需要使用MPI,或者是否有其他选项可以在异构计算平台上同步进程?我读到OpenCL支持这个操作,因为所有的计算设备都组织在一个“上下文”中。难道CUDA就不可能做到这一点吗

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

如有任何见解,将不胜感激


编辑:CPU函数包含不可并行的串行代码。

如果不使用多个线程或进程,或者不显著地使CPU算法复杂化,以达到可容忍的调度延迟,就无法完成您想要的任务。这是因为您必须能够以正确的频率和低延迟命令GPU来处理GPU工作负载的数据,但CPU工作负载听起来并不无关紧要,必须考虑到循环的运行时


因此,为了确保CPU和GPU都能连续处理并实现最高吞吐量和最低延迟,您必须将GPU命令部分和昂贵的CPU计算部分分成不同的线程—在这两个线程之间是某种IPC—最好是共享内存。如果专用CPU处理线程的工作方式与CUDA类似,并且跨线程使用它的cudaEvent,并且使GPU命令线程也命令CPU线程,即1个命令线程和2个处理从线程(GPU,CPU),那么您可能能够简化一些任务。

只是一个旁注:为什么需要这样做“数据分析“在主机上?如果您可以在设备上执行此操作,根据此分析步骤的输出,您可以节省内存带宽…为了获得CPU和GPU之间的设备并发性,通常的习惯用法是双缓冲区:让CPU和GPU在两个不同的缓冲区上运行,然后在两个设备都完成时切换缓冲区的意义。您描述的工作负载听起来需要4个缓冲区和4个CPU线程来执行CPU处理。我们的目标是让这两个设备(CPU和GPU)中的每一个都花费相同的处理时间,否则其中一个会浪费等待的时间。这里的可分页memcpy示例应该会有所帮助@oscillon请确保标记一个答案和投票,这样我们就可以结束这场比赛。听起来,有cuda支持的MPI将是一种方式。对吗?我没有广泛使用MPI,所以我不能对特定的策略发表评论,除了传递数据块的消息不能扩展到大数据块,而且大多数MPI都是基于套接字的,这是我对它们的无知。我只想设计我自己的线程/服务器,但如果它适合您&您已经习惯了,那么就直接使用MPI/cuda——如果它是一个新的瓶颈,那么这只是一个问题。