Intel Parallel Studio XE 2016: нові можливості компілятора C/C++


Минулого тижня вийшла нова версія компілятора С/С++ від Intel — 16.0 aka Parallel Studio XE Composer Edition for C++. Істотно розширилася підтримка нових стандартів (C11, C++14, OpenMP 4.1), можливості по роботі з Xeon Phi, вийшли нові версії бібліотек і ще багато всього «смачного». Давайте детальніше поглянемо на те, що з'явилося в останньому релізі. Поїхали!

  • Додана підтримка SIMD операторів для роботи з цілочисельними типами SSE на Лінуксі. Тепер наступні оператори працюють: + — * / & | ^ += -= *= /= &= |= ^= == != > < >= <=
    Простий приклад, який раніше не компилировался (не забуваємо инклудить immintrin.h):
    __m128i x,y,z;
    x = y + z;
    

    Варто відзначити, що це працює тільки на Лінуксі. Компілятор на Windows так само свариться: operation not supported for these simd operands
    Крім того, підтримуються тільки 128 і 256 біт SIMD типи, і тільки форма з двома операндами, як у прикладі. Самі операнди повинні бути одного типу, наприклад, типи SSE від Intel не можуть використовуватися разом з GNU типами, оголошеними з атрибутом vector_size.
  • Істотно розширилася підтримка стандартів. Мабуть, це напрям розвитку компілятора можна так само віднести до однієї з найголовніших у новій версії.
    Так, якщо у версії з 15 стандарту C11 (для мови С, не плутати з С++11) підтримувалися тільки бінарні літерали (починаються з префікса 0b або 0B), то зараз є практично . Останній загальнодоступний драфт стандарту можна знайти на тут у вільному доступі. Хорошою оглядової статті російською про С11 я не знайшов, тому про кожну можливість мови напишу більш детально. Не забуваємо, що при компіляції потрібно вказувати ключ /Qstd=c11 Windows -std=c11 на Linux і Mac OS X для того, щоб все це запрацювало:
    • Нові ключові слова (як в C++11) для вирівнювання даних _Alignas _Alignof, що дозволяють піти від компиляторозависимых рішень:
      // масив cacheline вирівняно по 64 байта
      _Alignas(64) char cacheline[64];
      printf("Alignment of char = %d\n", _Alignof(char));
      

      Про необхідність і значимість вирівнювання даних я вже писав раніше.
    • Вирази, які не залежать від типу, з використанням ключового слова _Generic. Це свого роду «шаблони» З с++. Наприклад, наступний макрос для добування квадратного кореня sqrt(x) транслюється в sqrtl(x), sqrt(x) або sqrtf(x) в залежності від типу параметра x:
      #define sqrt(x) _Generic((x), long double: sqrtl, default: sqrt, float: sqrtf)(x)
      

      А адже раніше доводилося добре потрудитися, щоб реалізувати це ручками самому!
    • Спецификатор функції _Noreturn дозволяє оголошувати функції, які ніколи не повертаються в викликає код. Це дозволяє уникати попереджень від компілятора для функцій, у яких немає return'а, а так само включати ряд оптимізацій, які можна виконувати тільки над «безповоротними» функціями.
      _Noreturn void func (); // func never returns
      

    • Нове ключове слово _Static_assert, що дозволяє видавати помилку компіляції у випадку, якщо вираз дорівнює нулю. Простий приклад:
      // помилка під час компіляції
      static_assert(sizeof(int) < sizeof(char), "app requires sizeof(char) to be less than char");
      error: static assertion failed with "app requires sizeof(char) to be less than char"
      

      На відміну від директив #if #error дозволяє відловлювати помилки, які важко знайти під час препроцессинга.
    • Анонімні структури та об'єднання. Це некомерційне товариство анонімних алкоголіків… Жартую, просто перевірив вашу концентрацію. Вони використовуються для вкладення структур і об'єднань. Наприклад:
      struct T // C11
      {
      int m;
      union //анонімне об'єднання
      {
      char * index;
      int key;
      };
      };
      struct T t;
      t.key=1300; //прямий доступ до члена об'єднання key 
      

    • Особливість стандарту С11 в тому, що він стандартизує багатопоточність в мові С. Звичайно ж, розробники вже давним-давно використовують блага паралельності в З, але, тим не менш, через бібліотеки та інші розширення мови. Зараз же це прописано в стандарті.
      Так, одне з нових ключових слів, які підтримуються компілятором Intel, _Thread_local. З його допомогою можна вказати, що змінна не є спільною для потоків і кожен з них отримує свою локальну копію.
  • За стандартами С і С++, компілятор не зобов'язаний дотримуватися пріоритет для обчислення виразів у дужках. Наприклад, далеко не факт, що додавання B C у вираженні A+(B+C) буде виконано в першу чергу, що призводить до розходжень у чисельних результати. Нарешті з'явилася опція компілятора, яка відключає оптимізацію, міняє порядок підсумовування (реассоциацию) для типів з плаваючою точкою. Тепер, якщо використовуються опції -fprotect-parens (Linux* OS і OS X*) або /Qprotect-parens (Windows*), порядок виконання операцій буде визначатися розставленими дужками. Використання цієї опції може дещо сповільнити виконання коду. За замовчуванням, компілятор не включає дану опцію.
  • Повністю реалізувавши підтримку З++11 у версії 15.0, розробники компілятора впритул зайнялися наступним – С++14, який зараз буде підтримуватися більш ніж на половину. Аналогічно С11, страничка, на якій відстежується підтримка різних можливостей стандарту в різних версіях компілятора. Включити підтримку З++14 можна опцією /Qstd=c++14 Windows -std=c++14 на Linux і Mac OS X.
    Отже, що ж тепер підтримується починаючи з нового релізу:
    • Узагальнені лямбда-функції
    • Захоплення виразів для лямбда-функцій
    • Роздільниками розрядів
    • Атрибут [[deprecated]]
    • Висновок типу значення, що повертається, для функцій
    • Агрегатна ініціалізація класів з инициализаторами полів
    Більш детальний опис цих можливостей стандарту можна без зусиль знайти в мережі, наприклад, на Вікі, або в інших постах на Хабре (Ч1 і год.2 основні підприємства).
    Так само з'явилася підтримка макросівFeature Test macros), які дозволяють визначати підтримку тієї або іншої можливості стандарту компілятором, або наявності хедера. Цей функціонал поки ще не в стандарті С++14, а лише TR, але обіцяє незабаром. Простий приклад:
    #if __cpp_binary_literals
    int const packed_zero_to_three = 0b00011011;
    #else
    int const packed_zero_to_three = 0x1B;
    #endif
    

    Тепер ми дуже легко можемо визначити, чи підтримуються компілятором бінарні літерали. Більш детально (наприклад, знайти табличку з іменами макросів __cpp_binary_literals, __cpp_digit_separators і т. д.) ознайомитися з цією корисною можливістю можна здесь.
  • Додана дуже корисна директива pragma block_loop, що дозволяє контролювати оптимізацію з поділом циклів на блоки (loop blocking), про яку я докладно писав у цьому пості.
  • Підтримка чергової версії стандарту OpenMP 4.1 (Technical Report 3), в основному розширює можливості по роботі з оффлодом (вивантаженні) обчислень на співпроцесор Xeon Phi та інші можливі прискорювачі:
    • З'явилася нова директива omp target enter data для того, щоб мапить змінні співпроцесор (можливо задавати to alloc для опції map). Якщо директива omp target мапила змінні і виконувала код на пристрої, то omp target data тільки займається даними. Відповідно, тепер є і директива omp target exit data для unmap'a змінних (можливо задавати from, release delete для опції map).
    • Поліпшені можливості по асинхронного виконання коду. target регіон тепер є завданням (task), тому можливий асинхронний оффлод з допомогою існуючої моделі роботи з завданнями та опції nowait для директиви omp task.
    • Опція depend для директиви omp task, що дозволяє реалізувати вивантаження з залежностями
    • Нові модифікатори always delete для опції map
    Крім того, що в рамках OpenMP 4.1 істотно розширюються можливості по роботі з прискорювачами, так само доопрацьована специфічна для компілятора Intel реалізація роботи з співпроцесорами:
    • Якщо раніше було неможливо передавати через покажчик поле об'єкта для вивантаження на співпроцесор у вигляді ptr->field, то тепер це обмеження прибрано. При цьому з'явилася можливість передати структури, поля якої є покажчиками. Самі структури в цьому випадку передаються побитово, покажчики копіюються, а от поля структур, на які вони вказують, немає.
    • Стало можливим виділяти пам'ять тільки на сопроцессоре, не виділяючи пам'ять на хості, з допомогою модифікаторів targetptr preallocated.
    • З'явилося поняття stream (і нова опція stream для директиви pragma offload) – логічної черзі для выгрузок. З її допомогою тепер можна вивантажити кілька незалежних обчислень на Xeon Phi з одного CPU потоку. Порядок роботи такий:
      Спочатку, створюємо стрім з допомогою API функції _Offload_stream_create:
      OFFLOAD_STREAM* handle = _Offload_stream_create(
      int device, // Intel® MIC Architecture device number
      int number_of_cpus); // Threads allocated to the stream
      

      І оффлодим в стрім з допомогою директиви offload опції stream, вказуючи при цьому сигнальне значення для ідентифікації вивантаження. Це допоможе визначити, чи виконаний той чи інший оффлод:
      // Issue offload to a stream identify and with signal value s1
      #pragma offload ... stream(handle) signal(s1)
      { ... }
      ...
      // Issue offload to a stream identify and with signal value s2
      #pragma offload ... stream(handle) signal(s2)
      { ... }
      ...
      // Check if offload with signal value s1 has completed
      if (_Offload_signaled(s1)) ...
      

      Набагато більше деталей можна знайти в нашій документації, яка була відчутно розширено з виходом нової версії.



    Крім усього перерахованого, природно вийшли нові версії всіх бібліотек (Intel IPP, TBB, MKL), де теж можна знайти багато всього цікавого. Крім того, на додаток до відомих «трехбуквенным», додалася нова бібліотека Intel DAAL, про яку я вже розповідав в окремому пості.Мій список поліпшень і доповнень не є повним, але я постарався розповісти про найбільш значущих речах. За бортом огляду залишилися зміни в Intel Cilk™ Plus, нові лістинги з анотаціями від компілятора, поліпшення швидкості компіляції і ще багато дрібних доопрацювань. Пробуємо саму свіжу версію, яка все так же доступна з пробної ліцензією на 30 днів (без будь-яких функціональних обмежень і з повною підтримкою) і ділимося з нами вашим досвідом!

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.