В параллельном коде OpenMP будет ли какая-либо выгода для параллельной работы memset?

У меня есть блоки памяти, которые могут быть довольно большими (больше, чем кэш L2), и иногда я должен установить их на все ноль. memset хорош в серийном коде, но как насчет параллельного кода? Кто-нибудь испытывает, если вызов memset из параллельных streamов фактически ускоряет работу для больших массивов? Или даже с помощью простой openmp-параллели для циклов?

Люди в HPC обычно говорят, что одного streamа обычно недостаточно, чтобы насытить единую ссылку на память, что обычно верно для сетевых ссылок. Вот быстрый и грязный memsetter с поддержкой OpenMP, который я написал для вас, который заполняет нулями дважды 2 гигабайта памяти. И вот результаты с использованием GCC 4.7 с различным количеством streamов на разных архитектурах (максимальные значения из нескольких запущенных отчетов):

GCC 4.7, код, скомпилированный с -O3 -mtune=native -fopenmp :

Quad-socket Intel Xeon X7350 – четырехъядерный процессор Pre-Nehalem с отдельным controllerом памяти и фронтальной шиной

одно гнездо

 threads 1st touch rewrite 1 1452.223 MB/s 3279.745 MB/s 2 1541.130 MB/s 3227.216 MB/s 3 1502.889 MB/s 3215.992 MB/s 4 1468.931 MB/s 3201.481 MB/s 

(1-е касание выполняется медленно, так как команда нитей создается с нуля, а операционная система отображает физические страницы в виртуальное адресное пространство, зарезервированное malloc(3) )

Один stream уже насыщает полосу пропускания памяти на одном канале <-> NB. (NB = Северный мост)

1 нить на разъем

 threads 1st touch rewrite 1 1455.603 MB/s 3273.959 MB/s 2 2824.883 MB/s 5346.416 MB/s 3 3979.515 MB/s 5301.140 MB/s 4 4128.784 MB/s 5296.082 MB/s 

Для насыщения полной полосы памяти канала NB <-> памяти требуется два streamа.

Octo-socket Intel Xeon X7550 – 8- канальная система NUMA с окто-ядерными процессорами (отключена CMT)

одно гнездо

 threads 1st touch rewrite 1 1469.897 MB/s 3435.087 MB/s 2 2801.953 MB/s 6527.076 MB/s 3 3805.691 MB/s 9297.412 MB/s 4 4647.067 MB/s 10816.266 MB/s 5 5159.968 MB/s 11220.991 MB/s 6 5330.690 MB/s 11227.760 MB/s 

Для насыщения полосы пропускания одной линии памяти требуется не менее 5 streamов.

1 нить на разъем

 threads 1st touch rewrite 1 1460.012 MB/s 3436.950 MB/s 2 2928.678 MB/s 6866.857 MB/s 3 4408.359 MB/s 10301.129 MB/s 4 5859.548 MB/s 13712.755 MB/s 5 7276.209 MB/s 16940.793 MB/s 6 8760.900 MB/s 20252.937 MB/s 

Полоса пропускания масштабируется почти линейно с количеством streamов. Основываясь на односоставных наблюдениях, можно сказать, что для насыщения всех восьми каналов памяти потребуется не менее 40 streamов, распределенных как 5 streamов на сокет.

Основная проблема в системах NUMA – это политика хранения в первом касании – память выделяется на узле NUMA, где stream сначала касается виртуального адреса на определенной странице. Фиксирование нити (привязка к конкретным ядрам ЦП) имеет важное значение для таких систем, поскольку миграция streamов приводит к удаленному доступу, который медленнее. Поддержка pinnig доступна в большинстве случаев работы OpenMP. GCC с его libgomp имеет GOMP_CPU_AFFINITY окружения GOMP_CPU_AFFINITY , у Intel есть KMP_AFFINITY среды KMP_AFFINITY и т. Д. Кроме того, OpenMP 4.0 представил нейтральную для поставщиков концепцию мест .

Редактирование. Для полноты здесь приведены результаты запуска кода с массивом 1 GiB на MacBook Air с процессором Intel Core i5-2557M (двухъядерный процессор Sandy Bridge с поддержкой HT и QPI). Компилятор – это GCC 4.2.1 (assembly Apple LLVM)

 threads 1st touch rewrite 1 2257.699 MB/s 7659.678 MB/s 2 3282.500 MB/s 8157.528 MB/s 3 4109.371 MB/s 8157.335 MB/s 4 4591.780 MB/s 8141.439 MB/s 

Почему эта высокая скорость даже с одной нитью? Небольшое исследование с помощью gdb показывает, что memset(buf, 0, len) преобразуется компилятором OS X в bzero(buf, len) и что разрешенная версия с поддержкой SSE4.2 с именем bzero$VARIANT$sse42 обеспечивается libc.dylib и используется во время выполнения. Он использует инструкцию MOVDQA для нуля 16 байт памяти одновременно. Вот почему даже с одним streamом пропускная способность памяти почти насыщена. Одноstreamовая версия с поддержкой AVX с использованием VMOVDQA может сразу же обнулить 32 байта и, возможно, насытить ссылку на память.

Важное сообщение здесь состоит в том, что иногда векторизация и multithreading не являются ортогональными для ускорения операции.

Ну, всегда есть кеш L3 …

Однако очень вероятно, что это будет связано уже с пропускной способностью основной памяти; добавление большего количества параллелизма вряд ли улучшит ситуацию.

  • Скорость компиляции Java и скорость компиляции Scala
  • clflush для аннулирования строки кэша через функцию C
  • jQuery hasClass () - проверьте несколько classов
  • Когда и почему базы данных объединяются дорого?
  • Сравнение C # и OrderBy
  • StringBuilder / StringBuffer против оператора «+»
  • Почему я должен использовать CDN от Google для jQuery?
  • Android - предотrotation белого экрана при запуске
  • Количество разделов в RDD и производительность в Spark
  • jQuery: первый против .first ()
  • Разница в производительности между Java 8 lambdas и анонимными внутренними classами
  • Interesting Posts

    Можно ли сохранить каждую веб-страницу, которую вы посещаете?

    Более одного «Открыть xxxxx здесь как администратор»

    Получение и маршрутизация телефонных звонков через компьютер

    Что такое InputStream & Output Stream? Почему и когда мы их используем?

    компонент java swing не может быть разрешен

    Dlink DIR-615 неожиданно перестает работать – оранжевый интернет-свет

    Генератор случайных чисел генерирует только одно случайное число

    Программное обеспечение для рисования / редактирования синтаксиса операторов SQL

    Как начать работу с Jenkins после успешной работы нескольких одновременных восходящих рабочих мест?

    Gimp – объединить альфа из одного слоя, с изображением rgb другого

    Определение переменных переменных с использованием LESS CSS

    Как применить gradleиентное обрезание в TensorFlow?

    CORS в ASP.NET MVC5

    Автоматический запуск Notepad ++ macro

    Получить путь изображения от ACTION_IMAGE_CAPTURE Intent

    Давайте будем гением компьютера.