Запуск потока CUDA из каждого потока хоста - PullRequest
0 голосов
/ 19 июля 2011

Мое намерение состоит в том, чтобы использовать n потоков хоста для одновременного создания n потоков на NVidia Tesla C2050. Ядро является простым векторным умножением ... Я делю данные поровну между n потоками, и каждый поток будет иметь параллельное выполнение / передачу данных.

Данные с плавающей запятой, иногда я получаю равные суммы CPU / GPU, а иногда они сильно расходятся ... Я думаю, это может быть связано с потерей конструкций синхронизации в моем коде, но также Я не думаю, что какие-либо конструкции синхронизации между потоками необходимы, потому что я хочу, чтобы каждый ЦП имел уникальный поток для управления, и меня не волнует асинхронное копирование данных и выполнение ядра в потоке.

Ниже приведен код, выполняемый каждым потоком:

//every thread would run this method in conjunction

static CUT_THREADPROC solverThread(TGPUplan *plan)
{

    //Allocate memory
    cutilSafeCall( cudaMalloc((void**)&plan->d_Data, plan->dataN * sizeof(float)) );

    //Copy input data from CPU
    cutilSafeCall( cudaMemcpyAsync((void *)plan->d_Data, (void *)plan->h_Data, plan->dataN * sizeof(float), cudaMemcpyHostToDevice, plan->stream) );
    //to make cudaMemcpyAsync blocking
    cudaStreamSynchronize( plan->stream );

    //launch
    launch_simpleKernel( plan->d_Data, BLOCK_N, THREAD_N, plan->stream);
    cutilCheckMsg("simpleKernel() execution failed.\n");

    cudaStreamSynchronize(plan->stream);

    //Read back GPU results
    cutilSafeCall( cudaMemcpyAsync(plan->h_Data, plan->d_Data, plan->dataN * sizeof(float), cudaMemcpyDeviceToHost, plan->stream) );
    //to make the cudaMemcpyAsync blocking...               
    cudaStreamSynchronize(plan->stream);

    cutilSafeCall( cudaFree(plan->d_Data) );

    CUT_THREADEND;
}

И создание нескольких потоков и вызов вышеупомянутой функции:

    for(i = 0; i < nkernels; i++)
            threadID[i] = cutStartThread((CUT_THREADROUTINE)solverThread, &plan[i]);

    printf("main(): waiting for GPU results...\n");
    cutWaitForThreads(threadID, nkernels);

Я взял эту стратегию из одного из примеров CUDA Code SDK. Как я уже говорил ранее, этот код иногда работает, а в другой раз дает странные результаты. Мне нужна помощь с исправлением этого кода ...

Ответы [ 2 ]

2 голосов
/ 20 июля 2011

Во-первых, я не эксперт в любой области воображения, просто из моего опыта.

Я не понимаю, почему для этого нужны несколько потоков хоста. Кажется, вы управляете одним устройством и пропускаете его несколькими потоками. Как я это делал (псевдокод)

{
create a handle

allocate an array of streams equal to the number of streams you want

for(int n=0;n<NUM_STREAMS;n++)
{
   cudaStreamCreate(&streamArray[n]);
}

}

Оттуда вы можете просто передавать потоки в вашем массиве различным асинхронным вызовам (cudaMemcpyAsync (), потоки ядра и т. Д.), А остальное управляет устройство. У меня были странные проблемы с масштабируемостью для нескольких потоков (не пытайтесь создавать потоки по 10 Кб, у меня проблемы с 4-8 на GTX460), поэтому не удивляйтесь, если вы столкнетесь с ними. Удачи,

Джон

1 голос
/ 22 июля 2011

Моя ставка в том, что

BLOCK_N, THREAD_N

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

В качестве примечания, потоки полезны для совмещения вычислений с передачей памяти.Синхронизация потока после каждого асинхронного вызова вообще бесполезна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...