CUDA 4.0 RC - множество хост-потоков на один GPU - поведение cudaStreamQuery и cudaStreamSynchronize - PullRequest
1 голос
/ 08 марта 2011

Я написал код, который использует множество потоков хоста (OpenMP) для одного GPU. Каждый поток имеет свой собственный поток CUDA для заказа запросов. Это выглядит очень похоже на приведенный ниже код:

#pragma omp parallel for num_threads(STREAM_NUMBER)
for (int sid = 0; sid < STREAM_NUMBER; sid++) {
    cudaStream_t stream;
    cudaStreamCreate(&stream);

    while (hasJob()) {

        //... code to prepare job - dData, hData, dataSize etc

        cudaError_t streamStatus = cudaStreamQuery(stream);
        if (streamStatus == cudaSuccess) {
             cudaMemcpyAsync(dData, hData, dataSize, cudaMemcpyHostToDevice, stream);
             doTheJob<<<gridDim, blockDim, smSize, stream>>>(dData, dataSize);
        else {
             CUDA_CHECK(streamStatus);
        }
        cudaStreamSynchronize(stream);
    }
    cudaStreamDestroy(stream);
}

И все было хорошо, пока я не получил много мелких работ. В этом случае время от времени cudaStreamQuery возвращает cudaErrorNotReady, что для меня неожиданно, поскольку я использую cudaStreamSynchronize. До сих пор я думал, что cudaStreamQuery всегда будет возвращать cudaSuccess, если он вызывается после cudaStreamSynchronize. К сожалению, оказалось, что cudaStreamSynchronize может завершиться, даже если cudaStreamQuery все еще возвращает cudaErrorNotReady.

Я изменил код на следующий, и все работает правильно.

#pragma omp parallel for num_threads(STREAM_NUMBER)
for (int sid = 0; sid < STREAM_NUMBER; sid++) {
    cudaStream_t stream;
    cudaStreamCreate(&stream);

    while (hasJob()) {

        //... code to prepare job - dData, hData, dataSize etc

        cudaError_t streamStatus;
        while ((streamStatus = cudaStreamQuery(stream)) == cudaErrorNotReady) {
             cudaStreamSynchronize();
        }
        if (streamStatus == cudaSuccess) {
             cudaMemcpyAsync(dData, hData, dataSize, cudaMemcpyHostToDevice, stream);
             doTheJob<<<gridDim, blockDim, smSize, stream>>>(dData, dataSize);
        else {
             CUDA_CHECK(streamStatus);
        }
        cudaStreamSynchronize(stream);
    }
    cudaStreamDestroy(stream);
}

Так что мой вопрос ... это ошибка или особенность?

РЕДАКТИРОВАТЬ: это похоже на JAVA

synchronize {
    while(waitCondition) {
         wait();
    }
}

Ответы [ 2 ]

2 голосов
/ 09 марта 2011

Что находится под

//... code to prepare job - dData, hData, dataSize etc

Есть ли у вас какие-либо функции типа cudaMemcpyAsync или в коде, который вы указали, единственная передача памяти?Это асинхронные функции, которые могут выйти рано, даже если код еще не находится в месте назначения.Когда это произойдет, cudaStreamQuery вернет cudaSuccess только при успешной передаче памяти.

Кроме того, hasJob() использует ли какую-либо функцию host-CUDA?

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

1 голос
/ 09 марта 2011

Ранее не замечал: cudaStreamSynchronize() должен принимать параметр (stream).Я не уверен, какой поток вы синхронизируете, когда параметр опущен, возможно, по умолчанию это поток 0.

...