Сборник Broken GLSL Spinlock/GLSL Locks

У меня есть настройка, в которой мне нужно заблокировать, прочитать некоторые данные, обработать, записать некоторые данные, а затем разблокировать. С этой целью я сделал текстуру блокировки в виде layout(r32ui) coherent uniform uimage2D. Аналогично объявляются данные критической секции.

К сожалению, все мои попытки спин-блокировки не предотвращают условия гонки, что приводит к неправильным результатам. Я пробовал несколько разных подходов.

Я подумал, что соберу всю информацию, которую смогу найти о блокировке GLSL, вместе с моими результатами (GTX 580M). Я добавил ответ сообщества Wiki с этим исчерпывающим списком. Я был бы признателен за правки/комментарии о возможных проблемах, которые каждый из них представляет, в конечном итоге создав список допустимых подходов.


person imallett    schedule 03.02.2014    source источник


Ответы (1)


Я стандартизировал текстуру блокировки, чтобы она была img0.

Тип блокировки 1:

Деформации потоков имеют общий счетчик программ. Если один поток захватит замок, другие потоки в варпе все равно останутся в петле. На практике это компилируется, но приводит к взаимоблокировке.

Примеры: StackOverflow, OpenGL.org

while (imageAtomicExchange(img0,coord,1u)==1u);

//<critical section>
memoryBarrier();

imageAtomicExchange(img0,coord,0);

Тип блокировки 2:

Чтобы обойти проблему типа 1, вместо этого пишут условно. Ниже я иногда записывал цикл как цикл do-while, но цикл while тоже работает неправильно.

Тип блокировки 2.1:

Первое, что нужно попробовать, это простой цикл. Видимо из-за глючной оптимизации это может привести к вылету (в последнее время не пробовал).

Пример: NVIDIA

bool have_written = false;
while (true) {
    bool can_write = (imageAtomicExchange(img0,coord,1u)!=1u);

    if (can_write) {
        //<critical section>
        memoryBarrier();

        imageAtomicExchange(img0,coord,0);
        break;
    }
}

Тип блокировки 2.2:

В приведенном выше примере используется imageAtomicExchange(...), что может быть не первым, что нужно попробовать. Наиболее интуитивно понятным является imageAtomicCompSwap(...). К сожалению, это не работает из-за глючной оптимизации. Это (должно быть) иначе звучит.

Пример: StackOverflow

bool have_written = false;
do {
    bool can_write = (imageAtomicCompSwap(img0,coord,0u,1u)==0u);

    if (can_write) {
        //<critical section>
        memoryBarrier();

        imageAtomicExchange(img0,coord,0);
        have_written = true;
    }
} while (!have_written);

Тип блокировки 2.3:

Переключение обратно с imageAtomicCompSwap(...) на imageAtomicExchange(...) является другим распространенным вариантом. Отличие от версии 2.1 заключается в способе завершения цикла. Это не работает правильно для меня.

Примеры: StackOverflow, StackOverflow

bool have_written = false;
do {
    bool can_write = (imageAtomicExchange(img0,coord,1u)!=1u);

    if (can_write) {
        //<critical section>
        memoryBarrier();

        imageAtomicExchange(img0,coord,0);
        have_written = true;
    }
} while (!have_written);
person Community    schedule 03.02.2014