Я экспериментирую с новой функцией динамического параллелизма в CUDA 5.0 (GTK 110). Я сталкиваюсь с странным поведением, что моя программа не возвращает ожидаемый результат для некоторых конфигураций - не только неожиданный, но и другой результат с каждым запуском.Некоторые дочерние решетки не выполняются с динамическим параллелизмом CUDA
Теперь я думаю, что я нашел источник своей проблемы: кажется, что некоторые дочерние гриды (ядра, запущенные другими ядрами) иногда не выполняются, когда слишком много детских решеток порождено в то же время.
я написал небольшую тестовую программу, чтобы проиллюстрировать это поведение:
#include <stdio.h>
__global__ void out_kernel(char* d_out, int index)
{
d_out[index] = 1;
}
__global__ void kernel(char* d_out)
{
int index = blockIdx.x * blockDim.x + threadIdx.x;
out_kernel<<<1, 1>>>(d_out, index);
}
int main(int argc, char** argv) {
int griddim = 10, blockdim = 210;
// optional: read griddim and blockdim from command line
if(argc > 1) griddim = atoi(argv[1]);
if(argc > 2) blockdim = atoi(argv[2]);
const int numLaunches = griddim * blockdim;
const int memsize = numLaunches * sizeof(char);
// allocate device memory, set to 0
char* d_out; cudaMalloc(&d_out, memsize);
cudaMemset(d_out, 0, memsize);
// launch outer kernel
kernel<<<griddim, blockdim>>>(d_out);
cudaDeviceSynchronize();
// dowload results
char* h_out = new char[numLaunches];
cudaMemcpy(h_out, d_out, memsize, cudaMemcpyDeviceToHost);
// check results, reduce output to 10 errors
int maxErrors = 10;
for (int i = 0; i < numLaunches; ++i) {
if (h_out[i] != 1) {
printf("Value at index %d is %d, should be 1.\n", i, h_out[i]);
if(maxErrors-- == 0) break;
}
}
// clean up
delete[] h_out;
cudaFree(d_out);
cudaDeviceReset();
return maxErrors < 10 ? 1 : 0;
}
Программа запускает ядро в заданном количестве блоков (первый параметр) с заданным числом нитей каждый (второй параметр). Каждый поток в этом ядре запускает другое ядро с одним потоком. Это дочернее ядро напишет 1 в своей части выходного массива (который был инициализирован 0s).
В конце выполнения все значения в выходном массиве должны быть 1. Но как ни странно для некоторых размеров блоков и сеток некоторые из значений массива все равно равны нулю. Это в основном означает, что некоторые дочерние решетки не выполняются.
Это происходит только в том случае, если многие дочерние решетки появляются одновременно. В моей тестовой системе (Tesla K20x) это имеет место для 10 блоков, содержащих по 210 потоков. Однако 10 блоков с 200 потоками обеспечивают правильный результат. Но также 3 блока с 1024 потоками, каждая из которых вызывает ошибку. Странно, об ошибке не сообщается во время выполнения. Резервные гриды просто игнорируются планировщиком.
Есть ли у кого-то еще такая же проблема? Является ли это поведение документированным где-то (я ничего не нашел), или это действительно ошибка в среде выполнения устройства?
Это имеет смысл, спасибо за ответ! Я не знал, что можно использовать 'cudaGetLastError()' _inside_ ядро. Я также обнаружил, что можно увеличить ожидающий счет запуска, используя 'cudaDeviceSetLimit (cudaLimitDevRuntimePendingLaunchCount,)'. Было бы здорово, если бы вы могли добавить это к своему ответу. Еще раз спасибо! –
+1, освещая ответ. – JackOLantern