2013-11-19 4 views
1

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

Определение Hottest строк кода

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

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

Я был в состоянии следовать этому учебнику, пока я не достигну в следующий разделе: Remove the Lock

Снимите замок

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

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

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

Соответствующий код здесь в analyze_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() {} 

}; 
+0

Вопрос в том, осуществляется ли доступ к любой памяти более чем по одному потоку за раз. –

+1

Нельзя «кратко» рассуждать о безопасности потоков. Например, этот код был проанализирован шаг за шагом, чтобы устранить расы данных при использовании OpenMP здесь - http://www.viva64.com/en/b/0035/print/ – SChepurin

ответ

1

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

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

Смежные вопросы