Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Эффективное использование   x86-совместимых CPU   Многопоточность, векторные расширения         Алексей Тутубалин         ...
Производительность CPU 2005-2012:Практически постоянна?          Выросла в 32-64 раза?Производительность CPU =        • Мн...
Локальная параллельность• Только в хотспотах  – Замена обычных циклов - параллельными  – Замена обычных команд – векторным...
ЛОКАЛЬНАЯ МНОГОПОТОЧНОСТЬ
Схема работы• Fork/join на месте  длинных циклов• Накладные расходы  – n*1-10µsec на каждый поток• Методы реализации  – По...
OpenMP• Простой синтаксис: #pragma в  последовательном коде#pragma omp parallel forfor(i=0;i<N;i++)     a[i] = b[i]+c[i];•...
OpenMP• Чужеродность для С++  – Нет поддержки exceptions• Не все компиляторы поддерживают• Бывают ошибки в рантайме (или  ...
Параллельные библиотекиIntel TBB: суммирование вектора
Итого1. Это работает !2. Эффективность:  – Обычно 75-85% (3-3.5x speedup на 4-core)  – >90% для «гигабайт» данных3. Дополн...
SIMD-КОМАНДЫ (SSE, AVX)
SSE/AVX: что это такое?• SSE: одновременные операции  над 128-битными векторамиaddps xmm0,xmm1означает:for(i=0;i<4;i++)   ...
X86: много сортов SIMD• Под что код делать будем?  – 6 версий SSE  – 2 версии AVX• Чем новее версия  – Тем больше вкусных ...
SSE/AVX: что умеетЧто есть:                 Что есть:• Команды                 • 16 (8) регистров  – Load/store           ...
SSE/AVX: упаковка данныхСтандартный ООП-вариант        Structure of Arrays (SoA)Array Of Structures (AoS)                 ...
SSE: выравнивание• До Intel Core-i7:  – aligned (16 байт) load/store – сильно быстрее    (~4 раза для Core2Duo)• Начиная с...
С/C++: выравнивание• Переменные и поля в структурах:Gcc: int bar[64] __attribute_((aligned(16)));MSVC:__declspec(align(16)...
Откуда берется SSE/AVX-код?1. Генерирует C/C++ компилятор   (автоматическая векторизация)2. Пишется руками  – макросы комп...
Compiler intrinsics: нудную работу     должен делать компиляторСтандартные типы данных            Макросы для команд      ...
Ручной код: compiler intrinsicsC: 277 Mpix/sec (8.8 Gb/sec)       SSE/AVX: 584 Mpix/sec (18.6 Gb/s)компилятор частично век...
SIMD: Итого1.   Это не больно!2.   Выигрыш в 2-4 раза - запросто3.   Трудный старт4.   Где брать информацию:     – Intel S...
ПАРАЛЛЕЛЬНЫЕ/SIMD ЯЗЫКИ
Intel SPMD Program Compiler (ISPC)• SPMD – Single Program, Multiple Data• Метафора: «пишем программу для одного SIMD-  эле...
ISPC: пример и синтаксисСложение векторов   Расширение C:                    • uniform – разделяемая копия                ...
ISPC: многопоточность
ISPC: практика
OpenCL• Стандарт для «гетерогенных вычислений»• Платформы: CPU/GPU• Особенности  –   Компиляция на лету  –   Двойная буфер...
Позитив• Ускорение в 10-15 раз – достижимо• Вероятно, потребуется рефакторинг  Но только один раз:  – Параллельный код неп...
Презентация (со ссылками) доступна:www.slideshare.net/AlexTutubalinЯ иногда пишу на эти темы:blog.lexa.ru/tags/sseСПАСИБО ...
ДОПОЛНИТЕЛЬНЫЕ МАТЕРИАЛЫ
Bandwidth vs Latency             Bandwidth    LatencyRAM,1980       13 MB/s      225 ns    • Случайный доступ -RAM, 2000  ...
BW/Latency: решения• Нужно не зависеть от Latency:  – Последовательный код  – Нет зависимости по данным  – Последовательны...
Векторизация С/C++: алиасингСложение двух векторов:void sum_vec(float *s1,float *s2, float *d, int N){       for(int i=0;i...
Векторизация в C++ компиляторах• «Обычный код» (после базовых правок выравнивания и  алиасинга):   – Личный опыт: ускорени...
Модификация кода для успешной        векторизацииНе векторизуется      Векторизуетсяfor(i=0;i<LEN;i++){   for(i=0;i<LEN;i+...
ISPC: ускорение(для поставляемых примеров)
OpenCL: корни в GPGPU• Много отдельных  потоков (Work Items)• Объединенных в блоки  с быстрой общей  памятью (Work Groups)...
OpenCL: сложение векторов
Upcoming SlideShare
Loading in …5
×

Эффективное использование x86-совместимых CPU (Алексей Тутубалин)

1,754 views

Published on

  • Be the first to comment

Эффективное использование x86-совместимых CPU (Алексей Тутубалин)

  1. 1. Эффективное использование x86-совместимых CPU Многопоточность, векторные расширения Алексей Тутубалин lexa@lexa.ru CTO @LibRaw LLC
  2. 2. Производительность CPU 2005-2012:Практически постоянна? Выросла в 32-64 раза?Производительность CPU = • Многоядерность частота * (число инструкций – С 2005 по 2012: рост в 4-8на такт) раз• Тактовая частота • SSE, AVX 2005 – 2.5-3.6 Ghz – 2005: 2 операции на такт 2012 – 1.8-3.5 Ghz – 2012: 16 операций на такт• Инструкции/такт после Intel Core2 => роста очень медленный
  3. 3. Локальная параллельность• Только в хотспотах – Замена обычных циклов - параллельными – Замена обычных команд – векторными (SIMD: SSE, AVX)• Сопутствующие изменения – Редизайн/рефакторинг структур данных – Изменения в алгоритмах
  4. 4. ЛОКАЛЬНАЯ МНОГОПОТОЧНОСТЬ
  5. 5. Схема работы• Fork/join на месте длинных циклов• Накладные расходы – n*1-10µsec на каждый поток• Методы реализации – Полуавтоматически: OpenMP – Вручную: threading-библиотеки
  6. 6. OpenMP• Простой синтаксис: #pragma в последовательном коде#pragma omp parallel forfor(i=0;i<N;i++) a[i] = b[i]+c[i];• Возможности: reduction, atomics, critical sections, режим доступа к переменным:sum=0.0;#pragma omp parallel for reduction(+:sum)for(i=0;i<N;i++) sum+=vector[i];
  7. 7. OpenMP• Чужеродность для С++ – Нет поддержки exceptions• Не все компиляторы поддерживают• Бывают ошибки в рантайме (или компиляторе)• Альтернатива: Cilk Plus (Intel C++, gcc 4.8 branch)
  8. 8. Параллельные библиотекиIntel TBB: суммирование вектора
  9. 9. Итого1. Это работает !2. Эффективность: – Обычно 75-85% (3-3.5x speedup на 4-core) – >90% для «гигабайт» данных3. Дополнительный код: – 1-20 строк на каждую точку оптимизации
  10. 10. SIMD-КОМАНДЫ (SSE, AVX)
  11. 11. SSE/AVX: что это такое?• SSE: одновременные операции над 128-битными векторамиaddps xmm0,xmm1означает:for(i=0;i<4;i++) xmm0[i]+=xmm1[i];• AVX: вектор 128 или 256 бит, 3-адресность:vaddps ymm0,ymm1,ymm2означает:for(i=0;i<8;i++) ymm0[i]=ymm1[i]+ymm2[i];
  12. 12. X86: много сортов SIMD• Под что код делать будем? – 6 версий SSE – 2 версии AVX• Чем новее версия – Тем больше вкусных команд – И тем уже поддержка
  13. 13. SSE/AVX: что умеетЧто есть: Что есть:• Команды • 16 (8) регистров – Load/store • Типы данных – Арифметика – Целые: 8, 16, 32, 64 бит – Сравнения, min, max – Плавающие: 32, 64 – Конверсия типов Чего нет: – Битовые операции • Flow control – Перестановка элементов вектора • Scatter/gather – Dot Product, CRC32, AES, S TRCMP
  14. 14. SSE/AVX: упаковка данныхСтандартный ООП-вариант Structure of Arrays (SoA)Array Of Structures (AoS) class foo_vector {class foo { vector<float> x,y,z; float x,y,z; };void calc_z(){z=A*x+B*y;} foo_vector::calc_z()}; for(..) z[i]=A*x[i]+B*y[i];vector<foo> fv(..);for(…..) fv[i].calc_z(); calc_z() – хорошо векторизуется:• for(..)calc_z() – плохо – 2 чтения векторизуется: – 3 оп. арифметики – 4-8 чтений – 1 запись – 3 оп. арифметики – 4 записи
  15. 15. SSE: выравнивание• До Intel Core-i7: – aligned (16 байт) load/store – сильно быстрее (~4 раза для Core2Duo)• Начиная с Core-i7: – Почти нет разницы (<10%)
  16. 16. С/C++: выравнивание• Переменные и поля в структурах:Gcc: int bar[64] __attribute_((aligned(16)));MSVC:__declspec(align(16)) float baz[32];• Простые аллокации: – MSVC: _aligned_malloc(size, align)/_aligned_free() – Gcc: _mm_malloc(size, align)/_mm_free()• STL: выравнивающий аллокатор:std::vector<T, AlignmentAllocator<T, 16> > foo;Все элементы вектора выровнены на 16:class __attribute__ ((aligned (16))) Foo { __attribute__ ((aligned (16))) float bar[4];};std::vector<Foo, AlignmentAllocator<Foo, 16> > baz;У последнего примера – проблемы с Microsoft STL (починено в VS2012)
  17. 17. Откуда берется SSE/AVX-код?1. Генерирует C/C++ компилятор (автоматическая векторизация)2. Пишется руками – макросы компилятора (compiler intrinsics) – ассемблер
  18. 18. Compiler intrinsics: нудную работу должен делать компиляторСтандартные типы данных Макросы для команд __m128__m128 => SSE-регистр _mm_add_ps(__m128,__m128)(float[4] или int16[8] или еще 6вариантов) => addps (или vaddps) Компилятор:__m128d => double[2] • Распределяет регистры • Подставляет адреса C-Типы AVX-256: переменных__m256 => float[8] • Генерирует код под целевую архитектуру (SSE, AVX)__m256d => double[4] • Может переупорядочить команды
  19. 19. Ручной код: compiler intrinsicsC: 277 Mpix/sec (8.8 Gb/sec) SSE/AVX: 584 Mpix/sec (18.6 Gb/s)компилятор частично векторизовал
  20. 20. SIMD: Итого1. Это не больно!2. Выигрыш в 2-4 раза - запросто3. Трудный старт4. Где брать информацию: – Intel Software Developers Manual, Vol 2A & 2B – MSDN: руководство по Visual Studio, много мелких примеров по _mm-макросам – Собирать по крупицам… 
  21. 21. ПАРАЛЛЕЛЬНЫЕ/SIMD ЯЗЫКИ
  22. 22. Intel SPMD Program Compiler (ISPC)• SPMD – Single Program, Multiple Data• Метафора: «пишем программу для одного SIMD- элемента, компилятор расширит на весь вектор»• x86: SSE2, SSE4, AVX, AVX2, Xeon Phi• Поддерживается Intel: BSD-license, opensource, http://ispc.github.com
  23. 23. ISPC: пример и синтаксисСложение векторов Расширение C: • uniform – разделяемая копия переменной на все параллельные/SIMD потоки varying – приватная копия • foreach/foreach_tiled – SIMD- цикл (тело цикла векторизуется) запускается • launch - запуск задачи • Встроенные переменные: programIndex – номер SIMD- lane programCount – ширина SIMD taskIndex – номер задачи • Далее – см. документацию
  24. 24. ISPC: многопоточность
  25. 25. ISPC: практика
  26. 26. OpenCL• Стандарт для «гетерогенных вычислений»• Платформы: CPU/GPU• Особенности – Компиляция на лету – Двойная буферизация – Отдельный внешний рантайм – Громоздкий API• Применение – Для больших объемов вычислений – Если планируется переход на GPU-расчеты
  27. 27. Позитив• Ускорение в 10-15 раз – достижимо• Вероятно, потребуется рефакторинг Но только один раз: – Параллельный код неплохо масштабируется – Рефакторинг для CPU => годится для GPU• Но лучше – сразу писать эффективно, помня о грядущей паралельности
  28. 28. Презентация (со ссылками) доступна:www.slideshare.net/AlexTutubalinЯ иногда пишу на эти темы:blog.lexa.ru/tags/sseСПАСИБО ЗА ВНИМАНИЕ!ВОПРОСЫ?
  29. 29. ДОПОЛНИТЕЛЬНЫЕ МАТЕРИАЛЫ
  30. 30. Bandwidth vs Latency Bandwidth LatencyRAM,1980 13 MB/s 225 ns • Случайный доступ -RAM, 2000 1600 MB/s 52 ns (~125x) (~4.5x) медленныйRAM, 2012 12800 MB/s 35ns – «Память – это новый диск» (~1000x) (~6.5x) – «Диск – это новая лента»HDD, 1980 0.6 MB/s 48 msHDD, 2000 86 MB/s 5.7 ms • У CPU – то же самое!! (~150x) (~8.5x) • Кэши – немного спасаютHDD,2012 300 MB/s ~5 ms (~500x) (~10x) • LAN – приятное10 Mbit 1 MB/s 3000 µsec исключение из общегоEthernet правила56Gbit ~5000 MB/s 0.7 µsecInfiniband (5000x) (~4300x)
  31. 31. BW/Latency: решения• Нужно не зависеть от Latency: – Последовательный код – Нет зависимости по данным – Последовательный доступ к памяти (и диску) – Prefetch в кэши• А любая случайность – зло: – Обращение по указателю – Синхронизация (!) – Не предсказанный условный переход – Случайный disk seek
  32. 32. Векторизация С/C++: алиасингСложение двух векторов:void sum_vec(float *s1,float *s2, float *d, int N){ for(int i=0;i<N;i++) d[i] = s1[i]+ s2[i];}Вызов:float A[SZ]; sum_vec(A,A+1,A+2,SZ-2);Решение: restrict (C99), __restrict__(gcc C++), __restrict (MSVC):void sum_vec(float * __restrict__ s1,float* __restrict__ s2, float* __restrict__ d….Но:• Алиасинг бывает и на this• В библиотечных классах – может не быть указан restrict
  33. 33. Векторизация в C++ компиляторах• «Обычный код» (после базовых правок выравнивания и алиасинга): – Личный опыт: ускорения «в разы» компилятор не дает, нужно вручную. – Чужой опыт: «An Evaluation of Vectorizing Compilers» (2011) http://polaris.cs.uiuc.edu/~garzaran/doc/pact11.pdf Для кода Media Bench II получили: • Intel C++/GCC: среднее ускорение 1.2 раза. • Ручной ассемблерный код: ускорение 2.7 раза.• Нужны серьезные правки кода, см. например Program Optimization Trough Loop Vectorization https://wiki.engr.illinois.edu/download/attachments/114 688007/9-Vectorization.pdf
  34. 34. Модификация кода для успешной векторизацииНе векторизуется Векторизуетсяfor(i=0;i<LEN;i++){ for(i=0;i<LEN;i++){ sum = 0.0; sum[i] = 0.0; for(j=0;j<LEN;j++) for(j=0;j<LEN;j++) sum+=A[j][i]; sum[i]+=A[j][i]; B[i] = sum; B[i] = sum[i];} }
  35. 35. ISPC: ускорение(для поставляемых примеров)
  36. 36. OpenCL: корни в GPGPU• Много отдельных потоков (Work Items)• Объединенных в блоки с быстрой общей памятью (Work Groups)• Блоков много, порядок исполнения не определен• Общая глобальная (медленная) память
  37. 37. OpenCL: сложение векторов

×