Эффективное использование (современных x86-совместимых) CPU
Проблема: однопоточная производительность CPU перестала расти: тактовая частота не растет, частые команды и так очень быстрые, суперскалярность почти не развивается. Привычный способ ускорения программ апгрейдом компьютера перестал работать. Развитие CPU сейчас идет в сторону увеличения параллельности:
- поддержки векторных операций (SIMD: single instruction, multiple data);
- увеличения числа процессорных ядер в одном корпусе.
К сожалению, эти новые возможности не могут быть использованы автоматически, старый код не станет сам параллельным и векторным, его придется полностью или частично переписывать.
SIMD-инструкции позволяют выполнять операции над «векторами» т.е. над несколькими элементами данных (например, сложить попарно 4 пары float-чисел одной командой). SIMD-блоки имеют высокую производительность, ее можно увеличивать дальше, удлиняя вектор.
Получение эффективного SIMD-кода возможно несколькими путями:
- Автоматическая векторизация «обычного» скалярного кода (C/C++: алиасинг!).
- Использование SIMD-оптимизированных библиотек.
- Написание ассемблера/compiler intrinsics руками.
- Использование «массивно-параллельных» языков программирования (OpenCL, ISPC).
Эффективное использование многопоточности требует от исполняемого кода минимума синхронизаций. Весьма эффективным подходом является «data-parallel» программирование (частным случаем которого является map-reduce в кластерных системах):
- Входные данные делятся на куски, которые обрабатываются независимо.
- Синхронизация требуется только в конце обработки.
При использовании этого подхода в коде возникают параллельные секции (возможно, с последовательным reduce после них), которые могут быть реализованы многими способами:
- Директивы компилятора или расширения языка (OpenMP, Cilk Plus).
- Библиотеки, реализующие многопоточность в терминах map-reduce (Intel TBB, QtConcurrent).
- Массивно-параллельные языки программирования (OpenCL, ISPC, CUDA-x86, Intel ArBB).
Массивно-параллельные языки программирования позволяют (в рамках своей семантики) получать эффективные программы, использующие и SIMD и многопоточность.
- OpenCL C-подобный язык + обвязка. Плюсы: программа GPGPU-ready. Минусы: double-buffering, несколько версий стандарта, громоздкая обвязка.
- Intel ISPC: C-подобный язык, похожий на OpenCL/CUDA, развивается Intel, BSD-license. Плюсы: эффективен, понятен, zero-copy. Минусы: вещь в себе, Intel может забросить проект, CPU-only.
CUDA-x86: привязка к одному вендору, смысл, только если есть готовый код (но проще перенести на OpenCL).