2016-07-04 2 views
0

Я закончил писать ядро ​​OpenCL для расчетов термодинамики и наблюдал действительно странную ошибку. Мое ядро ​​выглядит следующим образом:OpenCL использование программы аварийных ошибок регистра

__kernel void energy(... float3 dest, int nlocal, ...){ 
    int i = get_global_id(0); 
    float3 ev = {0.0f, 0.0f, 0.0f}; 
    for(...){ 
     //some thermo calculations, adding values to evx and evy 
     ev.x +=...; 
     ev.y +=...; 
    } 

    //Then I want to save the result in dest[i]. 
    //Program exits at next two line 
    dest[i].x = ev.x; 
    dest[i].y = ev.y; 

я получаю "неотображённые Memory" и Segfault ошибку. Я получаю ту же ошибку при попытке распечатать значение с помощью printf. Похоже, программа не может прочитать значение. Запись на него работает хотя! (Возможно, из-за некоторых оптимизаций компилятора) Теперь, если я использую другое значение регистра с плавающей запятой, я получаю ту же ошибку. Но если я изменю последние строки на что-то вроде этого (без использования ev.x или ev.y)

dest[i].x = i/nlocal*3.1f 
dest[i].y = ...; 

все будет, как ожидается, и я не получаю сообщение об ошибке.

Это тоже работает:

int i = ... 
float3 = {0.0f, ...} 
dest[i].x = ev.x; 

Но как-то после фактического расчета не представляется возможным больше.

Программа работает на архитектуре Nvidia K40m, Kepler.

+0

Проблема также может быть здесь: 'эв. x + = ...; ev.y + = ...; '. CL компилятор просто удалит код, который не влияет на выходной массив. Отправьте пример воспроизводимого кода, иначе мы не сможем вам помочь. – DarkZeros

+0

Спасибо за вашу помощь, я изменил свой код. Сейчас это все ядро. – Noahnder

ответ

1

Это выглядит подозрительно в вашем коде:

kernel(... __global int* neigh 
    __global int* neighs = neigh+i; 
    ... 
    int j = neighs[k*n]; 
    ... 

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

Также возможно, что ваши векторы просто не правильно рассчитаны, размеры должны быть:

res, nneigh = GLOBAL_SIZE 
neighs = max(nneigh[])*n 
x = max(neighs[]) 

А также возможно ты создать буферы меньше, чем они должны быть (помните, что они являются поплавки, и float3 , которые используют 32 бита и 128 бит на элемент). CL API-вызовы определяются в байтах (вы должны использовать sizeof()), а не в элементах.

+0

Думаю, я нашел проблему, вызвавшую segfault. Я передал sizeof (numneigh) дважды, а не sizeof (рс). Теперь я получаю ошибку OutOfResources, когда я использую ev.x или ev.y ... Когда я пишу другие значения для res, все идет так, как ожидалось. – Noahnder

+0

_ Похоже, вы передаете массив указателей в рсе, затем получаете указатель и используете его._ - для меня это больше похоже на доступ к 2D сплющенному массиву. @Noahnder также стоит включить код хоста, как уже упоминалось, должно быть что-то не так с размерами буферов OpenCL. Если вы записываете другие значения в res, остальная часть кода оптимизируется, поэтому вы в основном не используете его, и проблема исчезает. – doqtor

+0

@doqtor Я бы счел более логичным использовать 'neighs [k * n + i]' вместо того, чтобы получать указатель на элемент i, а затем смещать его снова в основном измерении. Кажется неестественным. Вот почему я догадался, что, возможно, у него есть массив указателей в «ржанах», и он делал это, чтобы сделать его компиляцией. Я согласен с тем, что код хоста необходим для отладки этих проблем. – DarkZeros

0

Хорошо, я нашел ответ, и приведенный выше код работает. Я изменил параметры ядра для лучшего понимания и безоговорочно исправил ошибку, когда я разместил здесь код.

int numneigh = nneigh[i] (stands for number of neighbors) is correct 
in the original code I did this: 
int numneigh = neigh[i] (the neighbors) 

Спасибо за помощь, и ваше предположение, что что-то не так с ржать/nneigh было правильным, даже если ошибка не в коде размещен выше: P