Откуда мы знаем, что код является потокобезопасным?

Я следую этот урок чтобы понять, как снять блокировки, используя VTUNE
Эта страница говорит следующее после сбора результатов Vtune:

Определите самые горячие строки кода

Нажмите кнопку навигации горячей точки
перейти к строке кода, которая заняла больше всего времени ожидания. VTune Amplifier
выделяет строку 170, входящую в критическую секцию rgb_critical_section
в функции draw_task. Функция draw_task ждала
почти 27 секунд, пока выполнялась эта строка кода и большая часть
время процессор был использован недостаточно. За это время критическое
раздел был оспорен 438 раз.

Раздел rgb_critical — это место, где находится приложение
сериализация. Каждый поток должен ждать критического раздела, чтобы быть
доступны, прежде чем он может продолжить. Только один поток может быть в
критический раздел за один раз. Вам нужно оптимизировать код, чтобы сделать его
более одновременно.

Я мог следовать этому уроку, пока не достиг следующего раздела: Снять замок

Снять замок

Rgb_critical_section был введен для защиты вычислений от
многопоточный доступ. Краткий анализ показывает, что код является потоком
безопасный и критический раздел на самом деле не нужен.

Мой вопрос: как мы узнаем, что код безопасен для потоков?

Как и предполагалось, я прокомментировал эти строки (EnterCritical … и LeaveCritical …) и увидел огромный прирост производительности, но я не понял, почему этот критический раздел не требуется? Какой анализ говорит нам об этом?

Соответствующий код находится здесь в analy_locks.cpp:

public:
void operator () (const tbb::blocked_range <int> &r) const {

unsigned int serial = 1;
unsigned int mboxsize = sizeof(unsigned int)*(max_objectid() + 20);
unsigned int * local_mbox = (unsigned int *) alloca(mboxsize);
memset(local_mbox,0,mboxsize);

for (int y=r.begin(); y!=r.end(); ++y) {
drawing_area drawing(startx, totaly-y, stopx-startx, 1);

// Enter Critical Section to protect pixel calculation from multithreaded access (Needed?)
//  EnterCriticalSection(&rgb_critical_section);

for (int x = startx; x < stopx; x++) {
color_t c = render_one_pixel (x, y, local_mbox, serial, startx, stopx, starty, stopy);
drawing.put_pixel(c);
}

// Exit from the critical section
//  LeaveCriticalSection(&rgb_critical_section);

if(!video->next_frame()) tbb::task::self().cancel_group_execution();
}
}

draw_task () {}

};

1

Решение

Что-то является потокобезопасным, если глобальное состояние (то есть состояние вне этого конкретного потока) не изменяется. Нам сложно сказать, что render_one_pixel а также drawing.put_pixel на самом деле, и в каком порядке это может быть необходимо выполнить.

Предполагая, что порядок звонков put_pixel(c) не имеет значения (или какой поток делает вызов), было бы безопасно удалить критический раздел здесь. Если требуется строгий порядок, я не уверен, что критический раздел в любом случае является правильным решением. (Те же правила, безусловно, применяются к render_one_pixel, если оно меняет какое-то глобальное состояние, что, конечно, также должно быть учтено в «Безопасно ли это»).

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]