Eigen: як це працює: бібліотека, яка розумніші компілятора

Відео: SFML і Cmake збірка бібліотеки з початкових кодів

Eigen: як це працює: бібліотека, яка розумніші компілятора
Перед тим, як перейти безпосередньо до коду, потрібно зробити відступ і пояснити, як Eigen примудряється генерувати код, який можна порівняти за швидкістю з написаним вручну в оптимізованих під конкретне «залізо» бібліотеках BLAS і LAPACK.

Улюблена вправа в підручниках по С ++ - це створення класу, що інкапсулює вектори і матриці. Таких класів створені сотні, але всі вони мають вкрай низьку продуктивність і ніколи не використовуються для серйозних завдань. Компілятор С ++, на відміну від Fortran, навіть не підозрює, що вектори і матриці треба обробляти поелементно. В результаті, в сумі матриць:
matl = mat2 + mat3

спочатку буде обчислена права частина і привласнена тимчасового об`єкту. Потім тимчасовий об`єкт буде скопійований в mat1 і зруйнований. Ясно, що виклик конструктора і деструктора тимчасового об`єкта і копіювання даних абсолютно зайві.

Виявляється, що компілятору можна допомогти, зробивши за нього частину роботи за допомогою метапрограмування і шаблонів (expression templates). Класи, що використовують шаблони виразів, перетворять порядок дій у виразах шляхом рекурсивної підстановки шаблонів на етапі компіляції.

Скажімо, складання об`єктів обробляється перевантаженим оператором «+», який сам по собі нічого не робить з даними, а повертає особливий шаблонний клас «операція складання».

Цей клас в свою чергу має перевантажені оператори і може брати участь в більш складних виразах і т.п. На виході виходить абстрактне синтаксичне дерево правій частині вихідного вираження у вигляді шаблонних об`єктів, відомих на стадії компіляції. Це дерево «розкручується» в реальний код тільки при спрацьовуванні оператора присвоювання (обробці лівої частини виразу), тому говорять, що шаблони виразів є «ледачими» (lazy).




Дерево шаблонів містить тільки посилання на реальні масиви даних і порядок їх обробки, а оператор присвоювання пробігає масиви поелементно в циклі і формує результуючий масив. По суті шаблони виразів самі компілюють складну формулу в якесь проміжне уявлення і видають «дурному» компілятору «напівперетравле» код у вигляді явних циклів, які вже без проблем компілюються в оптимальний машинний код.

Раз вже ми робимо за компілятор половину роботи, то можна допомогти йому і з оптимізацією. Сучасні процесори виявляються набагато витонченішими, ніж припускають і програміст, і компілятор. Наприклад, такий код здається оптимальним, і поліпшити в ньому начебто нічого:
std :: vector v (N) -



for (int i = 0 i

Тим не менш, він використовує лише малу частку обчислювальної потужності процесора! Справа в тому, що сучасні процесори мають спеціальні набори інструкцій (Intel SSE, ARM NEON) для обробки даних пакетами по 128 біт. Це 4 числа типу float, тобто процесор може за один такт «прожувати» відразу 4 числа (це називають векторизацией). Обробляючи наш код, компілятор послідовно перебирає елементи масиву по 32 біта (розмір типу float), а решта 96 біт числового конвеєра ніяк не використовуються. Щоб включити векторизацію і завантажити числовий конвеєр на всі 100%, потрібно, по-перше, розташувати елементи масивів з 128-бітовим вирівнюванням, а по-друге, вручну викликати в циклі низькорівневі асемблерні SSE-інструкції для пакетів з 4 елементів масиву.

Компілятор Fortran сам вміє векторизовать операції з масивами, а бібліотеки BLAS і LAPACK або використовують можливості Fortran, або містять асемблерний код, оптимізований під конкретну процессорную архітектуру. В С ++ все потрібно робити вручну, а асемблер - це зовсім не те, з чим хоче працювати сучасний прикладний програміст ...

На щастя, Eigen містить потрібні асемблерні вставки для різних типів процесорів і викликає їх усередині шаблонів. Завдяки цьому, операції з об`єктами Eigen векторизуется і використовують всю обчислювальну потужність процесора.

Потрібно сказати, що векторизация відбувається в межах одного ядра процесора. Eigen НЕ распараллелівать обчислення за різними ядер, залишаючи програмісту право використовувати багатопоточність на свій розсуд.

Якщо ви до кінця не зрозуміли, як все це працює, то знайте, що не самотні. Деталі реалізації шаблонів вкрай складні - це вищий пілотаж програмування на С ++. Гарне уявлення про складність реального коду дає приклад з документації Eigen https://eigen.tuxfamily.org/dox/TopicInsideEigenExample.html, що описує, що відбувається «під капотом».

На щастя, програмісту абсолютно не обов`язково розбиратися в цих деталях - зовнішній API у Eigen надзвичайно простий. В наступній частині статті я приведу приклади коду і опишу специфіку роботи з бібліотекою.



Eigen досить часто оновлюється, так що, якщо Вам необхідний високошвидкісний мобільний інтернет в Швейцарії (https://cellhire.ru/ru/business/Switzerland_USB_modem_rental.html) для підтримки актуальної версії бібліотеки, то варто підібрати хорошого оператора. Ну а я Вам, в свою чергу, раджу зупинити свій вибір на Cellhire LLC, який пропонує найбільш гнучкі тарифні плани!

ІНШЕ

Вільний паскаль: gnu pascal фото

Вільний паскаль: gnu pascal

Відео: 0101 Free Pascal перша програма В GCC входить свій вільний компілятор Паскаля - gpc, який не має відношення до…

Seed7: бібліотеки фото

Seed7: бібліотеки

Відео: пентагональними призма з насіння льону. П`ятикутна призма. геометричні фігури.Стереометрія Якщо Сі або C ++ без…

Мова програмування vala фото

Мова програмування vala

Hello world! Розгляд будь-якої мови програмування традиційно належить починати з найпростішої програми «Hello…

Взаємодія chaiscript з c ++ фото

Взаємодія chaiscript з c ++

Відео: Jason Turner: Why and How To Add ScriptingІдеологія взаємодії ChaiScript і С ++ Скриптова мова ChaiScript…

» » Eigen: як це працює: бібліотека, яка розумніші компілятора