У меня есть небольшой парсер, который я пытаюсь оптимизировать.
Он читает кучу файлов (тысяча в типичном использовании) заполняет vector<code_file>
code_file - это структура, которая, среди прочего, содержит содержимое файла.
второй шаг (более длинный и тот, который я пытаюсь оптимизировать) проходит через вектор и для каждого файла parse( it )
, который заполняет структуру code_file. никакая модификация задействованного вектора.
for( auto it = code_files.begin(); it != code_files.end(); ++it )
{
parseCodeFile( *it );
}
Кажется, он достаточно параллелизуем, но на самом деле он работает хуже, если я использую parallel_for вместо for for на моей четырехъядерной машине... функция parseCodeFile не имеет блокировки.
Я пробовал с профилировщиком, и я заметил, что он тратит почти 50% времени в std::_Lockit::_Lockit
(25%) и std::_Lockit::~_Lockit
(25%)
Есть ли способ избежать этого?
Я видел это сообщение: Что делает std :: _ lockit? но я запускаю его в выпуске, и определения выглядят нормально:
_SECURE_SCL=0
_HAS_ITERATOR_DEBUGGING=0
_ITERATOR_DEBUG_LEVEL=0
Некоторая дополнительная информация: функция синтаксического анализа, очевидно, выполняет много строковых манипуляций, она использует некоторые дополнительные утилиты, такие как boost :: trim и boost :: starts_with, скомпилированные с помощью Visual Studio 2010.
Просто угадайте, так как я не вижу весь ваш код, но заметьте, что code_files
может меняться по длине внутри parseCodeFile
. Если он перераспределит, то UB, но сжатие может быть безопасным. MSVC++ просто не знает и должен перепроверить .end()
.
Конечно, это немного не важно для parallel_for
. Вы не показываете этот код, но он задокументирован как работающий только с интегральными типами. Microsoft может описать ее как STL-подобную, но это явно не означает, что STL-like будет поддерживать итераторы.
parallel_for
- это то, что мы не можем судить без кода, конечно. Вы используете разделяй и властвуй? (Хотя диапазон достаточно велик, разделите диапазон на две части и создайте поток для обработки второй половины) Или простое разбиение (Разбейте диапазон на N частей, создайте N потоков)? Мотивация для первого - то, что вы можете иметь N / 2 потоков, создающих N / 2 потоков параллельно.