Когда Inspector мышей не ловит

Недавно я столкнулся с одним интересным случаем. В процессе анализа приложения одного из наших пользователей обнаружил, что Inspector диагностирует data race там, где, по-идее его (или ее) быть не должно. Причем после нескольких десятков минут усиленного обмозговывания проблемы, мозг вскипел и отказался дальше работать. Честно говоря, хотелось вывести на чистую воду разработчиков тредчекера, и с позором предать их анафеме.

Ниже представлен урезанный пример, который сам по себе не вызовет такую ошибку (не хочу загромождать колонку реальным примером, который займет пару экранов), но показателен по сути.

void function1(int **ppBuffer)

{

	#pragma omp parallel for

	for(int x = 0; x < 10; x++)

	for(int y = 0; y< 10; y++)

		ppBuffer[x][y] = 10;

	return;

}


void function2(int **ppBuffer1, int **ppBuffer2)

{

	#pragma omp parallel for

	for(int x = 0; x < 10; x++){

	for(int y = 0; y< 10; y++)

	{

		j = y + 1;

		ppBuffer2[x][y] = ppBuffer1[i][j];

	}}

	return;

}

int main(void)

{

	...//some code here including allocation ppBuffer1,2

	function1(ppBuffer1);

	function2(ppBuffer1, ppBuffer2);

	return 0;

}


Инспектор выдал ошибку Data Race, указывая в качестве событий чтение буфера памяти в функции function2 и запись буфера памяти в функции function1. Результаты диагностики представлены для реального примера.



На самом деле, тем, кто знаком с fork/join моделью OpenMP такая ошибка кажется невероятной, даже с учетом того, что выделение памяти для буфера организовано так, что она берется из одного массива, выделенного из кучи единственным оператором (это по-началу меня зацепило и увело в неправильном направлении). Дело в том, что функции function1 и function2, хотя и выполняют параллельный код, вызываются одна за другой в main, и точка возврата из function1 практически являеся join-точкой для потоков, созданных внутри нее. А значит, даже если функции оперируют одним и тем же, разделяемым буфером памяти, они не могут создать такую ситуацию Race Condition по определению модели OpenMP.

В чем же оказалась проблема. Проблема как всегда в том, что никто не читает документацию и Release Notes. Последний документ говорит:
"Intel® Parallel Inspector supports analysis of applications built with Intel® Parallel Composer, Intel® C++ Compiler Professional Edition version 10.0 or higher, and/or Microsoft Visual C++* 2005 or 2008. Applications that use OpenMP* and are built with the Microsoft* compiler must link to the OpenMP* compatibility library as supplied by an Intel compiler", как бы намекая на возможные проблемы с Microsoft compiler.

Еще, надо было внимательно следить за сообщениями во время анализа Inspector'а, который предупреждал о том, что обнаружены проблемы с OpenMP run-time. Такое поведение обусловлено тем, что программа была слинкована с Microsoft OpenMP run-time библиотекой (vcomp.dll), а Inspector не поддерживает каких либо других OpenMP библиотек времени исполнения кроме Intel. Сделано это не специально, чтобы насолить Microsoft и надсмеяться над их поддержкой устаревшего стандарта OpenMP 2.5, а в силу сложившихся обстоятельств, одним из которых является то, что Intel поддерживает более новую версию стандарта OpenMP.

Значит ли это, что Inspector непргоден для анализа OpenMP-приложений, скомпилированных в MSVS? Нет. Это ограничение легко обойти. Для этого достаточно слинковаться с Intel OpenMP run-time библиотекой, явно передав линкеру ее имя (да-да, вам таки придется разыскать компилятор Intel).

Для Microsoft Visual Studio IDE необходимо изменить следующие настройки проекта:
Project Properties -> Linker -> Input -> Ignore Specific Library отправить в игнор vcomp.dll или vcompd.dll
Project Properties -> Linker -> Input -> Additional Dependencies -> вписать libiomp5md.lib

Для тех, кто использует компиляцию из командной строки, нужно модифицировать команду следующим образом:
icl /MD /openmp hello.cpp /link /NODEFAULTLIB:"vcomp.dll" libiomp5md.lib

Навсегда ли останется такое ограничение? Не знаю. Думаю, это вопрос свободных ресурсов и времени. Одно только могу гарантировать, Intel всегда стремиться сделать свои решения максимально совместимыми с Microsoft. Просто из-за того, что мышей слишком много, всех переловить просто физически не хватает времени.

For more complete information about compiler optimizations, see our Optimization Notice.
Tags: