Апаратне прискорення корпоративних обчислень

«Прискорені обчислення» (Accelerated Computing) – модель обчислень, при якій в тандемі з традиційними CPU застосовуються вузькоспеціалізовані співпроцесори («прискорювачі»). Основним завданням співпроцесорів є высокопараллельное виконання інтенсивної обчислювальної навантаження і вивільнення ресурсів CPU для інших потреб програми («offloading»).

Хорошими прикладами таких «прискорювачів» можуть служити GPU від NVIDIA або співпроцесори Xeon Phi, без яких не обходиться практично жоден проект у сфері наукових або інженерних обчислень. Проте в корпоративному секторі подібні технології практично не застосовувалися (якщо не рахувати використання GPU фермах віртуалізації робочих місць).

Саме тому вихід серверів на чіпі Oracle SPARC M7, що містить крім ядер загального призначення спеціалізовані співпроцесори Data Analytics Accelerators (DAX), можна вважати відправною точкою у проникненні «прискорених обчислень» на корпоративний ринок.

Основним завданням DAX є прискорення in-memory обчислень за рахунок розвантаження основних ядер шляхом виконання операцій пошуку по вмісту оперативної пам'яті на сопроцессорах.

У разі необхідності перенесення операції пошуку на DAX ядро загального призначення формує запит і передає його на виконання «прискорювачів», після чого продовжує виконання основного коду. При цьому відбувається автоматичне розпаралелювання задачі по всім акселераторам чіпа, а потім збір результатів (схоже на MapReduce) в кеші чіпа і повідомлення ядра про завершення операції. Співпроцесори підключені до L3-кешу чіпа, що дозволяє забезпечити швидке взаємодія з ядрами загального призначення і передачу результатів пошуку:



Варто зазначити, що для забезпечення можливості пошуку по даним з допомогою DAX вони повинні розташовуватися в пам'яті в спеціальному форматі (In-Memory Column Store). Характерною властивістю цього формату є можливість зберігання даних в стислому вигляді (алгоритм стиснення – пропрієтарний Oracle Zip), що дозволяє розмістити в оперативній пам'яті більший обсяг інформації та позитивно впливає на швидкість обробки даних акселераторами за рахунок економії пропускної здатності шини, що зв'язує чіп і оперативну пам'ять. При пошуку декомпресія виконується апаратно, засобами DAX, і не впливає на продуктивність. Іншою особливістю є наявність індексів, що містять мінімальні і максимальні значення для кожного з безлічі сегментів пам'яті (In-Memory Compression Units – IMCUs), складових In-Memory Column Store. Виходить, що «прискорення» вибірки має свою ціну – довгий первинне розміщення даних у пам'яті, під час якого відбувається їх стиснення і попередній аналіз (свого роду індексування).

Основним споживачем даної технології на даний момент є СУБД Oracle Database 12c, що використовує DAX для прискорення операцій пошуку з таблиць, розташованих в In-Memory Column Store. СУБД автоматично переносить частину операцій на DAX, що призводить до значного прискорення деяких запитів.

Однак нам в "Інфосистеми Джет" було цікаво вивчити технологію DAX без проміжного «чорного ящика» у вигляді СУБД Oracle Database, що приховує цікаві подробиці і створює додаткові накладні витрати, що не дозволяють точно оцінити переваги, створювані використанням співпроцесорів.

Використання співпроцесорів DAX сторонніх додатків
На початку березня 2016 року Oracle відкрила API доступу до DAX для незалежних розробників (Open DAX API). Тепер DAX можна використовувати не тільки в СУБД Oracle Database, але і в будь-яких інших додатках.

Oracle запросила всіх бажаючих своє хмара протестувати DAX не тільки з СУБД, але і з використанням SDK для різних мов програмування (C, Python і Java). Оскільки низькорівневий API, призначений для взаємодії безпосередньо з апаратною частиною співпроцесора, досить складний, для ознайомлення з новою технологією крім самого SDK було запропоновано використати додаткову бібліотеку, надає високорівневі засоби для роботи з даними (libvector), розташованими в оперативній пам'яті. Саме на її основі і був зроблений ряд тестів для перевірки роботи DAX.

Компоненти SDK


Сценарій тестування
В якості тест-кейсу розглядалася проста аналітична задача – пошук значень у розташованому в пам'яті цілочисельному масиві, що задовольняють заданій умові. У вигляді SQL-запиту цю задачу можна було б записати так:

SELECT value values FROM WHERE value BETWEEN value_low AND value_high;

Завдання планувалося вирішувати двома способами – класичним перебором всіх елементів і з допомогою співпроцесорів DAX.

Реалізація
На мові C рішення цієї задачі виглядало приблизно наступним чином:

#define RANDOM_SEED 42
int *values, *results;
int low = VALUE_LOW, high = VALUE_HIGH;

values = generate_random_values_array(NUM_VALUES, RANDOM_SEED);
results = malloc(NUM_VALUES * sizeof(int));

for (i=0; i<NUM_VALUES; i++) {
if (values[i] >= low && values[i] <= high) {
results[n] = values[i];
n++;
}
}

Зазначимо, що при пошуку відразу відбувається збереження результатів в новий масив. Ще раз відзначимо, що вищенаведений код виконується на ядрі основного процесора.

Для DAX пошук і отримання результатів розділені на дві операції:

#include < vector.h> /* DAX */

#define RANDOM_SEED 42

int low = VALUE_LOW, high = VALUE_HIGH;
vector valuesVec, bitVec, resultsVec;

valuesVec = generate_random_values_vector(NUM_VALUES, RANDOM_SEED);

/* Пошук */
bitVec = vector_in_range(valuesVec, &low, &high);

/* Підрахунок кількості значень, удовлетворяюших умові */
n = bit_vector_count(bitVec);

/* Витяг значень, удовлетворяюших умові */
resultsVec = vector_extract(valuesVec, bitVec);

У випадку з DAX операція пошуку значень (функція vector_in_range), що задовольняють умові, повертає бітовий вектор (bit vector), на основі якого ще одним запитом (vector_extract) формується новий вектор з результатами. Шукані записи будуть вилучені з своїх IMCU і записані в нові IMCU, з якими знову можна працювати через DAX.

Такий підхід дозволяє ефективно працювати з наборами даних типу ключ/значення, коли потрібно знайти ключі, значення яких задовольняють умові. У цьому разі в пам'яті формуються два масиви даних – вектор ключів і вектор значень:

vector keysVec, valuesVec;
int low = VALUE_LOW, high = VALUE_HIGH;

populateKeyValueVectors(&keysVec, &valueVec);

Виконується пошук по вектору значень з допомогою DAX, результатом якого є бітова карта:

bitVec = vector_in_range(valuesVec, &low, &high);

Для отримання шуканих елементів отримана бітова карта застосовується з допомогою DAX до вектора ключів:

resultsVec = vector_extract(keysVec, bitVec);

До того ж над безліччю бітових векторів можна проводити операції типу AND і OR, тобто перекладати на DAX об'єднання результатів декількох порівнянь, як, наприклад, у запиті:

SELECT part FROM parts WHERE mass > 100 AND volume < 30;

Наші експерименти з об'єднанням через AND двох бітових векторів показали перевагу виклику, виконаного на DAX:

bit_vector_and2(bitVec1, bitVec2);

Перед поелементним (з елементами типу long) об'єднанням бітових карт на процесорі виду:

for (i=0; i<elemcount; i++) {
resultsRegularBitMap[i] = regularBitMap1[i] & regularBitMap2[i];
}

у 3-6 разів по швидкості виконання в залежності від кількості елементів.

Але повернемося до програми. Елементами нашого масиву будуть випадкові цілі числа, а пошук виконуватиметься за діапазону від -109 до 109 (тобто приблизно половина чисел буде задовольняти умові).

Ми запустили обидва варіанти реалізації нашого тесту кілька разів на кількостях чисел в масиві від 1 мільйона до 500 мільйонів і виміряли час виконання пошуку і час копіювання результатів в новий масив, з яким можна знову працювати. Для класичного перебору не має сенсу розділяти ці дві операції, т. к. копіювати в новий масив доведеться або адресу елемента (8 байт), або сам елемент (4 байта).

Результати
Отже, нижче представлений графік залежності часу пошуку й отримання даних від кількості елементів масиву:


Використання DAX показало 2-кратну перевагу над простим перебором. Якщо порівнювати тільки пошук (без збереження знайдених значень, тобто при виконанні операції виду “SELECT COUNT (*)" або у цілях отримання бітової карти), то швидкість пошуку через DAX більш ніж у 5 разів вище.

Стежити за використанням співпроцесорів в системі можна за допомогою утиліти busstat, що збирає метрики продуктивності з різних компонентів процесора (busstat -w dax 30 1). Під час виконання наших тестів ми спостерігали розпаралелювання запитів на 8 з 32 співпроцесорів DAX (в кожному процесорі M7 їх вісім). При використанні декількох користувальницьких процесів паралельно завантаження буде відображатися на всіх 32 сопроцессорах.

Безумовно, можна реалізувати всі алгоритми DAX програмно (що і було реалізовано в Oracle Database In-Memory Option до появи DAX), зробити додаткові оптимізації і отримати ще більш вражаючі результати, ніж з DAX (особливо якщо вручну розпаралелити завдання на всі процесорні нитки SPARC M7). Але призначення DAX в тому, щоб перекласти роботу ядер процесора на спеціалізовані співпроцесори. Тобто в цілому важливий не сам приріст продуктивності, а саме можливість розвантаження основного CPU.

Інші цікаві моменти
У числі прикладів коду для DAX інженери Oracle реалізували підтримку додатку для Apache Spark. За запевненням виробника, при використанні DAX продуктивність зросла в 6 разів. Суть оптимізації полягала в безлічі операцій з растровими картами через DAX, що вийшло набагато швидше, ніж на процесорі.

Висновки
Перенесення виконання програмної логіки з процесорів на спеціалізовані пристрої в черговий раз довів свою доцільність. Особливо такої «гарячої» зараз області як In-Memory Computing.

Можливість використовувати DAX через відкритий API може залучити в світ SPARC нові програмні продукти.

Однак подібні функції можуть бути реалізовані в майбутньому і на платформі Intel на вже існуючих апаратних рішеннях – з використанням співпроцесора Xeon Phi. Як мінімум дослідження в цій області вже ведуться:

  1. Rethinking SIMD Vectorization for In-Memory Databases.
  2. Design of an In-Memory Database Engine Using Intel Xeon Phi Coprocessors.
Post Scriptum
Тестові програми збиралися за допомогою компілятора Solaris Studio 12.4. Використовувався максимальний рівень оптимізації (-xO5), з допомогою якого вдавалося значно прискорити «класичні» обчислення. Вихідні коди доступні на github.

SPARC M7 і DAX – офіційний реліз Oracle.



Стаття підготовлена Дмитром Глушенком, системним архітектором Центру проектування обчислювальних комплексів компанії «Інфосистеми Джет». Ми будемо раді вашим конструктивним коментарям.
Джерело: Хабрахабр

0 коментарів

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