2015-02-13 3 views
3

Моя программа сначала считывает 2 изображения с жесткого диска (с функцией C++ file.read), после чего выполняет вычисления на GPU и CPU (куча ядер CUDA, смешанных с простыми вычислениями ЦП) эти изображения. У меня есть около 2000 пар изображений для обработки. Время чтения и вычисления почти равны. Существует ли относительно простая реализация распараллеливания чтения и обработки?Асинхронное чтение CPU и вычисления графического процессора + CPU

Я знаю, что с потоками CUDA я могу асинхронно оценивать ядра относительно хоста (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. Любые советы приветствуются.

Thanks

+0

Спасибо, что принял, было ли что-нибудь еще, что вы искали? Я заметил, что вы не голосовали. –

ответ

2

Я очень неравнодушен к pthreads и реализую асинхронную оболочку ontop считывателя, которая синхронизируется при запросе следующего набора данных.

Это самый простой способ, который я могу реализовать. Я включил то, что должно быть легко компилировать и полностью продемонстрировать реализацию. Удачи.

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 простой последовательно реализован файл ввода/вывода класса

#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.

Если вы хотите, чтобы иметь возможность обрабатывать параллельно на графическом процессоре, есть несколько вещей, которые я бы рекомендовал: Создайте несколько экземпляров класса-обертки, по одному для каждого параллельного экземпляра, который вам нужен. Выделите достаточно памяти один раз для каждого экземпляра async в конструкторе класса. Назначьте поток GPU для каждой нити, чтобы ядро ​​могло работать параллельно. Выполняйте все копии памяти и выполнение ядра в потоке GPU.

2

Возможно, существуют тысячи различных возможных решений. Вот что я хотел бы начать с того, чтобы увидеть, как это работает:

Ингредиенты

  • прочитанной нитью,
  • какой-то очереди сообщений
  • обработка резьбы

Method :

  1. Начать читать поток и обрабатывать поток.

  2. Чтение темы считывает два изображения одновременно и отправляет их в виде пакета в очередь сообщений. Повторяйте пока все изображения не будут прочитаны.

  3. Обработка потока считывает очередь сообщений и обрабатывает два изображения. Повторяйте до тех пор, пока все изображения не будут обработаны.

  4. Стоп нити и отчета о результатах (если применимо)

Это может помочь дать некоторые «противодавление» для очереди сообщений, так что, когда у вас есть 4, 6 или 10 изображений уже загружен, поток чтения перестает считывать изображения до тех пор, пока в очереди не будет места.

Преимущество использования очереди сообщений таким образом заключается в том, что у вас есть разумная свобода между потоками, а очередь сообщений упорядочивает всю синхронизацию между потоками.

+0

Все, что я нашел к настоящему времени, это '' library, где я могу управлять некоторым количеством потоков, чтобы работать одновременно, но я не нашел, как отправлять сообщения из потока в поток. Может быть, вы можете дать мне ссылку на любые материалы об этом материале. –

+0

Что-то вроде 'boost :: message_queue', возможно, http://www.boost.org/doc/libs/1_35_0/doc/html/boost/interprocess/message_queue.html - есть много других возможных сценариев, канал [доступен как в Windows, так и в Linux/Unix в качестве родной конструкции], например, будет работать просто отлично [просто писать и читать блоки двоичных данных] (обратите внимание, что вы не хотите передавать изображение самостоятельно, просто какую-то ссылку на то, где это был загружен в память) –

+0

Спасибо. Может быть просто '' библиотеки достаточно для моей проблемы. Общее время вычисления будет одинаковым, будет ли я синхронизироваться после каждого вычисления (например, в моем «эскизе кода») или будет читать изображения, как вы говорите, - остановить после того, как в буфере отобразится 4,6,10 изображений. Во всяком случае, если расчет немного дольше, есть (кажется мне) отсутствие разницы в общем времени вычисления. –

Смежные вопросы