首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >异步CPU读取和GPU+CPU计算

异步CPU读取和GPU+CPU计算
EN

Stack Overflow用户
提问于 2015-02-13 22:31:37
回答 2查看 561关注 0票数 3

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

我知道,使用CUDA流,我可以异步地评估主机(CPU)的内核,但是这里的计算是混合的和复杂的。那么,有可能使用某种CPU多线程吗?

我想要的是:

代码语言:javascript
运行
复制
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内核一起工作。如有任何提示,将不胜感激。

谢谢

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-02-15 15:58:22

我非常倾向于在读取器顶部实现线程和异步包装器,当您请求下一组数据时同步。

这是我能想到实现的最简单的方法。我已经包含了一些应该容易编译和充分演示实现的内容。祝好运。

main.cpp演示了它的用法。

代码语言:javascript
运行
复制
#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;
}

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

代码语言:javascript
运行
复制
#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的一个简单包装器,可以使它异步运行

代码语言:javascript
运行
复制
#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;
    }

};

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

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

如果希望同时处理许多情况,可以使用包装器包装、读取和处理文件。关于数据自动化系统,我认为他们都应该有一个数据自动化系统的背景。

如果您希望能够在GPU上并行处理,那么我建议您创建包装类的多个副本,每个并行实例一个。为类构造函数中异步的每个实例分配一次足够的内存。为每个线程指定一个GPU线程,以便内核的线程可以并行运行。在GPU线程上执行所有内存副本和内核执行。

票数 2
EN

Stack Overflow用户

发布于 2015-02-13 22:59:07

可能有成千上万种不同的解决方案。下面是我要从以下几个方面入手,看看它是如何运作的:

配料

  • 一条读线,
  • 某种消息队列
  • 处理线程

方法:

  1. 启动读取线程和处理线程。
  2. 读取线程一次读取两个图像,并将它们作为包发送到消息队列中。重复,直到所有图像被读取。
  3. 处理线程读取消息队列并处理这两个图像。重复,直到所有图像都被处理完毕。
  4. 停止线程并报告结果(视情况而定)

这可能有助于为消息队列提供一些“背压”,这样当您已经加载了4、6或10个图像时,读取器线程就会停止读取图像,直到队列中再次有空间为止。

以这种方式使用消息队列的优点是,您在线程之间有合理的自由,消息队列安排线程之间的所有同步。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28509858

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档