Подтвердить что ты не робот

Почему мой ядро ​​OpenCL терпит неудачу в драйвере nVidia, но не Intel (возможная ошибка драйвера)?

Я изначально написал программу OpenCL для вычисления очень больших эрмитовых матриц, где ядро ​​вычисляет одну пару записей в матрице (верхняя треугольная часть и ее нижнее треугольное дополнение).

В самом начале, я нашел очень странную проблему в том, что, если мой размер ядра равен 55, 27-й поток ядра не будет выполняться. Эта проблема возникает только при использовании драйвера nVidia и ускорения GPU. Когда я запускаю его с помощью драйвера Intel на процессоре, я считаю, что 27-й поток ядра выполняется просто отлично. Большие и меньшие размеры ядра, похоже, не проявляют этой проблемы.

Думая, что это может быть что-то в моем коде, я переложил свою проблему на следующее очень простое ядро:

__kernel void testIndex(__global float* outMatrix, unsigned int sizeN)
{
    //k is the linear kernel ID (related to but not exactly the linear index into the outMatrix)
    int k = get_global_id(0);
    //i'th index (Row or Y)
    int i = floor((2 * sizeN+1 - sqrt((float)((2 * sizeN + 1) * (2 * sizeN + 1) -8 * k) )) /2);

    //j'th index (Column or X)
    int j = k - sizeN * i + i * (i - 1) / 2;
    j += i;

    //Index bounds check... If we're greater than sizeN, we're an idle core.
    //(OpenCL will queue up a fixed block size of worker threads, some of them may be out of bounds)
    if(j >= sizeN || i >= sizeN)
    {
        return;
    }

    //Identity case. The original kernel did some special stuff here,
    //but I've just replaced it with the K index code.
    if(i == j)
    {
        outMatrix[i * sizeN +j] = k;
        return;
    }

    outMatrix[i * sizeN + j] = k;

    //Since we only have to calculate the upper triangle of our matrix,
    //(the lower triangle is just the complement of the upper),
    //this test sets the lower triangle to -9999 so it easier to see
    //how the indexing plays out...

    outMatrix[j * sizeN + i] = -9999.0;

 }

outMatrix - это выходная матрица, а sizeN - размер квадратной матрицы на стороне (т.е. матрица - размерN x sizeN).

Я вычисляю и выполняю мой размер ядра, используя следующий код хоста:

size_t kernelSize = elems * (elems + 1) / 2;
cl::NDRange globalRange(kernelSize);
cl::NDRange localRange(1);
cl::Event event;

clCommandQueue.enqueueNDRangeKernel(testKernel, cl::NullRange, globalRange, cl::NullRange, NULL, &event);
event.wait();

elems совпадает с размеромN (т.е. квадратным корнем из размера матрицы). В этом случае elems = 10 (таким образом, размер ядра равен 55).

Если я распечатаю матрицу, которую я прочитал, я получаю следующее (с использованием форматирования форматирования ublas):

[10,10] ((    0,     1,     2,     3,     4,     5,     6,     7,     8,    9),
        ((-9999,    10,    11,    12,    13,    14,    15,    16,    17,   18),
        ((-9999, -9999,    19,    20,    21,    22,    23,    24,    25,   26),
        ((-9999, -9999, -9999,  JUNK,    28,    29,    30,    31,    32,   33),
        ((-9999, -9999, -9999, -9999,    34,    35,    36,    37,    38,   39),
        ((-9999, -9999, -9999, -9999, -9999,    40,    41,    42,    43,   44), 
        ((-9999, -9999, -9999, -9999, -9999, -9999,    45,    46,    47,   48),
        ((-9999, -9999, -9999, -9999, -9999, -9999, -9999,    49,    50,   51),    
        ((-9999, -9999, -9999, -9999, -9999, -9999, -9999, -9999,    52,   53),   
        ((-9999, -9999, -9999, -9999, -9999, -9999, -9999, -9999, -9999,   54))

Где "JUNK" - это случайное значение, основанное на том, что происходит в этой памяти в то время. Это, конечно, подозрительно, так как 27 - это, в основном, точная точка на полпути в ядре.

Только для полноты результат матрицы считывается с использованием следующего кода:

boost::scoped_array<float> outMatrixReadback(new float[elems * elems]);
clCommandQueue.enqueueReadBuffer(clOutputMatrixBuffer, CL_TRUE, 0, elems * elems * sizeof(float), outMatrixReadback.get());

Я делаю (возможно, неверное) предположение, что, поскольку код отлично работает на процессоре Intel, в коде есть некоторая фундаментальная ошибка.

Итак, есть ли, возможно, некоторые сведения о том, что я не знаю при программировании OpenCL на карте nVidia, или я достаточно неудачен, чтобы найти ошибку драйвера?

Спецификации оборудования/ОС

  • nVidia GTX 770

  • RHEL Server release 6.4 (Сантьяго)

  • Intel OpenCL 1.2 4.4.4.0.134 заголовки SDK

  • Драйвер nVidia GeForce 384.69

  • Intel Xeon CPU E6520 @2,4 ГГц

4b9b3361