Я пишу приложение OpenCL на ma c с использованием c ++, и в некоторых случаях происходит сбой в зависимости от размера работы. Сбой программы из-за SIGABRT.
Есть ли способ получить дополнительную информацию об ошибке? Почему поднимается SIGABRT? Могу ли я его поймать?
РЕДАКТИРОВАТЬ: я понимаю, что эта программа dooz ie, однако я попытаюсь объяснить это на случай, если кто-то захочет нанести удар.
Посредством отладки я обнаружил, что причиной SIGABRT было истечение времени ожидания одного из ядер.
Программа представляет собой 3D-рендеринг на основе плиток. Это OpenCL-реализация этого алгоритма: https://github.com/ssloy/tinyrenderer
Экран разделен на плитки размером 8x8. Одно из ядер (тайлер) вычисляет, какие полигоны перекрывают каждую плитку, сохраняя результаты в структуре данных под названием tilePolys
. Последующее ядро (растеризатор), который запускает один рабочий элемент на плитку, выполняет итерацию по списку полисов, занимающих плитку, и растеризует их.
Сканер выполняет запись в целочисленный буфер, который представляет собой список списков полигонов индексы. Каждый список имеет фиксированный размер (polysPerTile
+ 1 для счетчика), где первый элемент является счетчиком, а последующие polysPerTile
элементы являются индексами многоугольников в плитке. Существует один такой список на плитку.
По некоторым причинам в некоторых случаях тайлер записывает очень большое число поли (13172746
) в один из списков плитки в tilePolys
. Это приводит к растеризации в l oop в течение длительного времени.
Странно то, что индекс, в который записывается большое число, никогда не доступен тайлеру.
Код ядра тайлера приведен ниже:
// this kernel is executed once per polygon
// it computes which tiles are occupied by the polygon and adds the index of the polygon to the list for that tile
kernel void tiler(
// number of polygons
ulong nTris,
// width of screen
int width,
// height of screen
int height,
// number of tiles in x direction
int tilesX,
// number of tiles in y direction
int tilesY,
// number of pixels per tile (tiles are square)
int tileSize,
// size of the polygon list for each tile
int polysPerTile,
// 4x4 matrix representing the viewport
global const float4* viewport,
// vertex positions
global const float* vertices,
// indices of vertices
global const int* indices,
// array of array-lists of polygons per tile
// structure of list is an int representing the number of polygons covering that tile,
// followed by [polysPerTile] integers representing the indices of the polygons in that tile
// there are [tilesX*tilesY] such arraylists
volatile global int* tilePolys)
{
size_t faceInd = get_global_id(0);
// compute vertex position in viewport space
float3 vs[3];
for(int i = 0; i < 3; i++) {
// indices are vertex/uv/normal
int vertInd = indices[faceInd*9+i*3];
float4 vertHomo = (float4)(vertices[vertInd*4], vertices[vertInd*4+1], vertices[vertInd*4+2], vertices[vertInd*4+3]);
vertHomo = vec4_mul_mat4(vertHomo, viewport);
vs[i] = vertHomo.xyz / vertHomo.w;
}
float2 bboxmin = (float2)(INFINITY,INFINITY);
float2 bboxmax = (float2)(-INFINITY,-INFINITY);
// size of screen
float2 clampCoords = (float2)(width-1, height-1);
// compute bounding box of triangle in screen space
for (int i=0; i<3; i++) {
for (int j=0; j<2; j++) {
bboxmin[j] = max(0.f, min(bboxmin[j], vs[i][j]));
bboxmax[j] = min(clampCoords[j], max(bboxmax[j], vs[i][j]));
}
}
// transform bounding box to tile space
int2 tilebboxmin = (int2)(bboxmin[0] / tileSize, bboxmin[1] / tileSize);
int2 tilebboxmax = (int2)(bboxmax[0] / tileSize, bboxmax[1] / tileSize);
// loop over all tiles in bounding box
for(int x = tilebboxmin[0]; x <= tilebboxmax[0]; x++) {
for(int y = tilebboxmin[1]; y <= tilebboxmax[1]; y++) {
// get index of tile
int tileInd = y * tilesX + x;
// get start index of polygon list for this tile
int counterInd = tileInd * (polysPerTile + 1);
// get current number of polygons in list
int numPolys = atomic_inc(&tilePolys[counterInd]);
// if list is full, skip tile
if(numPolys >= polysPerTile) {
// decrement the count because we will not add to the list
atomic_dec(&tilePolys[counterInd]);
} else {
// otherwise add the poly to the list
// the index is the offset + numPolys + 1 as tilePolys[counterInd] holds the poly count
int ind = counterInd + numPolys + 1;
tilePolys[ind] = (int)(faceInd);
}
}
}
}
Мои теории таковы:
- Я неправильно реализовал функции atomi c для чтения и увеличения счетчика
- Я использую неправильный формат чисел, приводящий к записи мусора в
tilePolys
- Одно из моих других ядер непреднамеренно записывает в
tilePolys
буфер
Я не думаю, что оно последнее, хотя, если вместо записи faceInd
в tilePolys
, я пишу постоянное значение, большое число поли исчезает.
tilePolys[counterInd+numPolys+1] = (int)(faceInd); // this is the problem line
tilePolys[counterInd+numPolys+1] = (int)(5); // this fixes the issue