Мы пишем приложение, критичное к производительности, которое имеет 3 основных параметра:
N_steps (около 10000)
N_nodes (от 20 до 5000)
N_size (диапазон около 1k-10k)
Алгоритм по существу имеет такую форму
for (int i=0; i<N_steps; i++)
{
serial_function(i);
parallel_function(i,N_nodes);
}
, где
parallel_function(i,N_nodes) {
#pragma omp parallel for schedule (static) num_threads(threadNum)
for (int j=0; j<N_nodes j++)
{
Local_parallel_function(i,j) //complexity proportional to N_size
}
}
и Local_parallel_function - это функция, выполняющая линейную алгебру, и обычно она имеет время выполнения около 0,01-0,04 секунды или даже больше, и это время выполнения должно быть довольно стабильным в цикле. К сожалению, проблема носит последовательный характер, поэтому я не могу написать внешний цикл по-другому.
Я заметил во время профилирования, что в функции NtYieldExecution тратится огромное количество времени (до 20%, если я использую HT на 4 ядрах).
Я провел несколько тестов, играя с параметрами, и обнаружил, что этот процент:
Скорее всего, для OpenMP параллельный цикл в настоящее время недостаточно велик, и его уменьшение или более дорогая в вычислительном отношении функция помогает сократить эти издержки.
Чтобы лучше понять, я скачал Intel Profiler и получил следующие результаты:
Область, выделенная красным, - это время вращения, а потоки сверху - это те, которые были созданы OpenMP.
Есть предложения о том, как управлять и уменьшить этот эффект?
Я использую Windows 10, Visual Studio 15.9.5 и OpenMP. К сожалению, похоже, что Intel Compiler не может скомпилировать одну зависимую библиотеку, поэтому я застрял с Microsoft.