c++ - 异步CPU读取和GPU+CPU计算

标签 c++ asynchronous cuda

我的程序首先从 HDD 读取 2 个图像(使用 c++ file.read 函数),然后在 GPU 和 CPU 上执行计算(一堆 CUDA 内核与简单的 CPU 计算混合在一起)有了这些图像。我有大约 2000 对图像要处理。阅读和计算时间几乎相等。读取和处理并行化有没有比较简单的实现?

我知道,使用 CUDA 流,我可以相对于主机 (CPU) 异步评估内核,但在这里我的计算是复杂的。那么,是否可以使用某种 CPU 多线程?

我想要的是:

readfromHDD(im-1);
readfromHDD(im-2);

for(int i=3;i<1998;i=i+2){
     readfromHDD(im-i);                  |  functions inside the
     readfromHDD(im-(i+1));              |  for loop are evaluated
     ProcessGPU&CPU(im-(i-2),im-(i-1));  |  concurrently
     Synchronize_Reading_and_processing;
end

我认为,没有必要发布我的实际代码。我以前从未做过多线程,所以我不知道它如何与 CUDA 内核一起工作。 任何提示表示赞赏。

谢谢

最佳答案

我非常偏爱 pthreads 并在读取器上实现异步包装器,当您请求下一组数据时它会同步。

这是我能想到的最容易实现的方法。我已经包含了一些应该易于编译和完整演示实现的东西。 祝你好运。

main.cpp 演示使用。

#include "Reader.h"
#include "Reader_Async_Wrapper.h"

using namespace std;

int main() {
    Reader *reader = new Reader("test");
    Reader_Async_Wrapper async_reader(reader);
    int img_index=0;
    char* data;
    data = async_reader.get_data();
    while(((int*)data)[0]!=-1){

        cout<<"processing image "<<img_index<<endl;
        sleep(2);
        cout<<"processed image "<<img_index++<<endl;
        delete[] data;
        data = async_reader.get_data();
    }
    return 0;
}

Reader.h 是一个简单的串行实现的文件 i/o 类

#include <iostream>
#include <fstream>
#include <unistd.h>

using namespace std;
class Reader{
public:

    bool isFinished(){return finished;}

    Reader(string file_name){
        open_file(file_name);
        finished=false;
        img_index=0;
    }

    char* read_data(){
        cout<<"Reading img: "<<img_index<<endl;
        sleep(1);
        cout<<"Read img: "<<img_index++<<endl;
        if(img_index==10)finished=true;
        return new char[1000];
    }

private:
    bool finished;
    int img_index;
    void open_file(string name){
        // TODO
    }
};

Reader_Async_Wrapper.h 是 Reader.h 的简单包装器,可使其异步运行

#include "Reader.h"
#include <pthread.h>

using namespace std;

class Reader_Async_Wrapper{
public:

    pthread_t thread;
    pthread_attr_t attr;
    Reader* reader;
    pthread_barrier_t barrier;
    Reader_Async_Wrapper(Reader* reader):reader(reader){

        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
        pthread_barrier_init (&barrier, NULL, 2);
        pthread_create(&thread, &attr, &Reader_Async_Wrapper::threadHelper, this);
        finished=false;
        image_data=NULL;
    }

    void finish(){
        pthread_attr_destroy(&attr);
        void *status;
        pthread_join(thread, &status);
    }

    char* get_data(){
        pthread_barrier_wait (&barrier);
        return image_data;
    }
    void clear_buffer(char* old_image){
        delete[] old_image;
    }

private:
    char* image_data;

    static void *threadHelper(void * contx){
        return ((Reader_Async_Wrapper *)contx)->async_loop();
    }

    bool finished;
    void *async_loop(){
        while(!finished){
            if(reader->isFinished()){
                finished=true;
                image_data=new char[sizeof(int)];
                ((int*)image_data)[0]=-1;
            }else
                image_data=reader->read_data();
            pthread_barrier_wait(&barrier);
        }
        pthread_exit(NULL);
        return NULL;
    }

};

我建议改进与检测文件结尾相关的处理(假设您正在从一个长文件中读取)。否则我认为您可以轻松地将其扩展到您的应用程序。

只要您不打算同时处理许多情况,并且您主要将此方法用作隐藏与读取文件相关的延迟的方法,此方法就足够了。

如果你想同时处理很多情况,你可以使用包装器来包装文件的读取和处理。关于 CUDA,我认为它们都应该共享一个 CUDA 上下文。

如果您希望能够在 GPU 上并行处理,我会推荐以下几点: 创建包装类的多个拷贝,每个拷贝对应一个您想要的并行实例。 为类构造函数中的每个异步实例分配一次足够的内存。 为每个线程指定一个 GPU 线程,以便内核可以并行运行。 在 GPU 线程上执行所有内存复制和内核执行。

关于c++ - 异步CPU读取和GPU+CPU计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28509858/

相关文章:

C++ 层次结构打印练习

c# - 使用 NetworkStream.BeginRead 和 NetworkStream.EndRead 实现超时

swift - 异步线程的返回值

linux - 如何在 Linux 中包含 cutil.h

c# - BadImageFormatException 处理

c++ - 子类中具有不同值的静态基类属性

c++ - Pthread 将函数传递给池

python - Benefits of twisted-suds - 使用 python suds SOAP 库的异步方式

c - 使用CUDA内核进行数组操作

c++ - 是否可以将批处理的 FFT 与 CUDA 的 cuFFT 库和 cufftPlanMany 重叠?