это магия LCOW ( https://github.com/linuxkit/lcow )
вы правы, чтобы запустить контейнер, базовый KERNEL должен быть таким же, так как контейнер это просто абстракция, поэтому для запуска контейнера linux в windows есть две опции
https://docs.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/linux-containers
с WSL в Windows в будущем мы могли бы получить третий метод, который не знает, работает ли уже кто-то над ним.
Я считаю, что вам следует попробовать переместить все эти ветки (т.е. если) внутри цикла и сделать это в двух отдельных циклах, один для i
Вы, кажется, думаете, что если вы запускаете последовательный код в многопоточном режиме, он должен работать лучше. Это не дано. И часто это неправда. Распараллеливание цикла для выполнения в нескольких потоках или на нескольких процессорах не всегда приводит к повышению производительности. В большинстве случаев требуется реструктуризация. В вашем случае код даже не является хорошим последовательным кодом.
Любая книга по оптимизации последовательного кода, как правило, имеет номер 1 для циклов: удалите все условные операции. Стоимость тестов. Некоторые компиляторы (кстати, вы никогда не говорите, какую ОС / компилятор / процессор вы используете ... это имеет значение) могут попытаться оптимизировать условный код. Некоторые компиляторы (например, компилятор Sun C) даже позволяют запускать программу в режиме "collect". режим, в котором он генерирует информацию профиля времени выполнения о том, как часто выполняются ветви условного выражения, а затем позволяет вам повторно компилировать в режиме, который использует эти собранные данные для оптимизации сгенерированного кода. (См. Параметр -xprofile)
Первое правило оптимизации параллельного кода - сначала сделать максимально возможную последовательную оптимизацию. Затем распараллелить петли.
Перемещая условные выражения за пределы цикла и, как предлагает Metiu, переписывая код как два отдельных цикла, вы даете оптимизатору лучший источник для работы. Последовательный код работает лучше, а распараллеленный код удивительно параллелен.
Тем не менее, результаты могут отличаться в зависимости от ОС / компилятора / платформы.
См. Использование OpenMP и (См. Параметр -xprofile)
Первое правило оптимизации параллельного кода - сначала сделать максимально возможную последовательную оптимизацию. Затем распараллелить петли.
Перемещая условные выражения за пределы цикла и, как предлагает Metiu, переписывая код как два отдельных цикла, вы даете оптимизатору лучший источник для работы. Последовательный код работает лучше, а распараллеленный код удивительно параллелен.
Тем не менее, результаты могут отличаться в зависимости от ОС / компилятора / платформы.
См. Использование OpenMP и (См. Параметр -xprofile)
Первое правило оптимизации параллельного кода - сначала сделать максимально возможную последовательную оптимизацию. Затем распараллелить петли.
Перемещая условные выражения за пределы цикла и, как предлагает Metiu, переписывая код как два отдельных цикла, вы даете оптимизатору лучший источник для работы. Последовательный код работает лучше, а распараллеленный код удивительно параллелен.
Тем не менее, результаты могут отличаться в зависимости от ОС / компилятора / платформы.
См. Использование OpenMP и Программирование приложений Solaris
Metiu is right. You can't expect good performance from a loop that has conditional statements in it. This is just bad coding. Even for scalar performance.
Your boss needs to understand that OpenMP and parallelization in general are not magic. To get good performance out of a parallelized code requires that the basic code be optimized for scalar performance first.
The tests do not have to be removed. The loop needs to be restructured. And scalar performance will benefit also.
Это похоже на проблему с реализацией openmp компилятора GNU. Попробуйте другой компилятор. У Intel есть компилятор Linux, копию которого вы можете скачать и попробовать здесь.
Еще я заметил, что первые частные переменные, которые у вас появились, совершенно не нужны. При создании частных копий массива V_in могут возникнуть значительные накладные расходы, что может быть вашей проблемой.
Я бы сказал, что это одна из тех двух проблем, которые являются вашей проблемой.
Во-первых, попробуйте накачать кусок еще больше. Создание потока сопряжено с накладными расходами, так же как и выполнение новой работы для каждого потока, а размер зерна должен быть достаточно большим, чтобы подавить это.
Еще одна большая возможность:
Реализация сокращения в GOMP может быть очень плохой (это подсказывает данные вашего профиля), и он генерирует сообщения после каждого блока, а не накапливает их в каждом потоке, а затем собирает их в конце. Попробуйте выделить e_t_sum
и e_in_sum
как массивы с элементами nthreads
каждый, и добавить к e_t_sum [tid]
внутри цикла, затем перебрать их для вычисления глобальной суммы после завершения параллельного цикла.
Обратите внимание, что это создает потенциальную проблему ложного совместного использования, поскольку несколько элементов этих массивов будут находиться в пределах общих строк кэша, и несколько процессоров будут записывать в эту же строку кэша. Если вы запустите это на наборе ядер, которые совместно используют свой кеш, это будет нормально, но будет неприятным запахом в другом месте.
Другая возможность:
Возможно, вы столкнулись с ложным обменом в ваших обновлениях элементов ee_t. Убедитесь, что этот массив выровнен, и попробуйте размеры блоков, кратные размеру строки кэша. Одним из тонких намеков на эту патологию может быть часть петли, где i> c
занимает непропорционально больше времени, чем часть, где i