Чи гарантовано реалізацію BLAS, що дасть такий самий результат?


17

З огляду на дві різні реалізації BLAS, чи можемо ми очікувати, що вони будуть робити такі самі обчислення з плаваючою комою та повертати однакові результати? Або може статися, наприклад, що один обчислює скалярний продукт як та один як таким чином, можливо, даючи різний результат у плаваючій точці IEEE арифметичні?

((х1у1+х2у2)+х3у3)+х4у4
(х1у1+х2у2)+(х3у3+х4у4),

1
У цій темі є скарги на якість BLAS , шукайте CBLAS на сторінці. Це підказувало б, що вони не лише не дають однакового результату, але й не всі вони досить точні для будь-якого завдання ...
Szabolcs

Відповіді:


15

Ні, це не гарантується. Якщо ви використовуєте NETLIB BLAS без будь-яких оптимізацій, то, як правило, правда, що результати однакові. Але для будь-якого практичного використання BLAS та LAPACK використовується високооптимізована паралельна BLAS. Паралелізація викликає, навіть якщо вона працює лише паралельно всередині векторних регістрів ЦП, що порядок того, як оцінюються одиничні члени, змінюється і змінюється порядок підсумовування. Тепер випливає з відсутньої асоціативної властивості в стандарті IEEE, що результати не однакові. Тож саме те, що ви згадали, може статися.

У NETLIB BLAS скалярний продукт є лише циклом, розкрученим на коефіцієнт 5:

DO I = MP1,N,5
          DTEMP = DTEMP + DX(I)*DY(I) + DX(I+1)*DY(I+1) +
     $            DX(I+2)*DY(I+2) + DX(I+3)*DY(I+3) + DX(I+4)*DY(I+4)
END DO

і від компілятора залежить, якщо кожне множення додається до DTEMP негайно або якщо всі 5 компонентів підсумовуються першими і потім додаються до DTEMP. У OpenBLAS це залежно від архітектури більш складне ядро:

 __asm__  __volatile__
    (
    "vxorpd     %%ymm4, %%ymm4, %%ymm4               \n\t"
    "vxorpd     %%ymm5, %%ymm5, %%ymm5               \n\t"
    "vxorpd     %%ymm6, %%ymm6, %%ymm6               \n\t"
    "vxorpd     %%ymm7, %%ymm7, %%ymm7               \n\t"

    ".align 16                           \n\t"
    "1:                          \n\t"
        "vmovups                  (%2,%0,8), %%ymm12         \n\t"  // 2 * x
        "vmovups                32(%2,%0,8), %%ymm13         \n\t"  // 2 * x
        "vmovups                64(%2,%0,8), %%ymm14         \n\t"  // 2 * x
        "vmovups                96(%2,%0,8), %%ymm15         \n\t"  // 2 * x

    "vmulpd      (%3,%0,8), %%ymm12, %%ymm12 \n\t"  // 2 * y
    "vmulpd    32(%3,%0,8), %%ymm13, %%ymm13 \n\t"  // 2 * y
    "vmulpd    64(%3,%0,8), %%ymm14, %%ymm14 \n\t"  // 2 * y
    "vmulpd    96(%3,%0,8), %%ymm15, %%ymm15 \n\t"  // 2 * y

    "vaddpd      %%ymm4 , %%ymm12, %%ymm4 \n\t"  // 2 * y
    "vaddpd      %%ymm5 , %%ymm13, %%ymm5 \n\t"  // 2 * y
    "vaddpd      %%ymm6 , %%ymm14, %%ymm6 \n\t"  // 2 * y
    "vaddpd      %%ymm7 , %%ymm15, %%ymm7 \n\t"  // 2 * y

    "addq       $16 , %0	  	     \n\t"
	"subq	        $16 , %1            \n\t"      
    "jnz        1b                   \n\t"
...

який розбиває скалярний добуток на невеликі скалярні добутки довжиною 4 та підсумовує їх.

Використовуючи інші типові реалізації BLAS, такі як ATLAS, MKL, ESSL, ... ця проблема залишається тією ж, оскільки кожна реалізація BLAS використовує різні оптимізації для отримання швидкого коду. Але наскільки я знаю, потрібен штучний приклад, щоб викликати дійсно несправні результати.

Якщо необхідно, щоб бібліотека BLAS поверталася за тими ж результатами (біт-мудрі однакові), потрібно використовувати відтворювану бібліотеку BLAS, таку як:


8

Короткий відповідь

Якщо дві реалізації BLAS написані для виконання операцій в точно такому самому порядку, а бібліотеки були складені за допомогою тих же прапорів компілятора та з тим самим компілятором, то вони дадуть вам однаковий результат. Арифметика з плаваючою комою не є випадковою, тому дві однакові реалізації дадуть однакові результати.

Однак є різні речі, які можуть порушити цю поведінку заради виконання ...

Більш довгий відповідь

IEEE також визначає порядок виконання цих операцій, крім того, як повинна вестися кожна операція. Однак, якщо ви компілюєте свою реалізацію BLAS з такими параметрами, як "-ffast-math", компілятор може виконувати перетворення, які були б істинними в точній арифметиці, але не "правильні" в плаваючій точці IEEE. Канонічний приклад - неасоціативність додавання плаваючої точки, як ви вказували. При більш агресивних налаштуваннях оптимізації буде припускатися асоціативність, і процесор зробить якомога більше паралельних можливостей шляхом переупорядкування операцій.

а+бc


3
"Арифметика з плаваючою комою не випадкова" . Сумно, що це потрібно чітко сказати, але, здається, занадто багато людей думають, що це ...
труба

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

@TylerOlsen Це не стосується питання, і це не те, чому ці класи говорять такі речі, але IIRC, колись існував клас помилок компілятора, на які не можна було покластися рівність. Наприклад, if (x == 0) assert(x == 0) може іноді вийти з ладу, що з певної точки зору так само добре, як і випадкове.
Кирило

@Kirill Вибачте, я просто намагався зробити так, що багато людей ніколи не дізнаються, як працює плаваюча точка. Що стосується історичного моменту, то це щось жахливе, але це, мабуть, було вирішено ще до того, як я потрапив у гру.
Тайлер Олсен

@TylerOlsen На жаль, мій приклад неправильний. Це повинно бути if (x != 0) assert(x != 0)через арифметику розширеної точності.
Кирило

4

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

Докладаються певні зусилля для отримання відтворюваних реалізацій BLAS. Див. ReproBLAS та ExBLAS для отримання додаткової інформації.


1
Дивіться також функцію умовної чисельної відтворюваності (CNR) в останніх версіях MKL BLAS від Intel. Зрозумійте, що отримання цього рівня відтворюваності, як правило, сповільнить ваші обчислення та може значно уповільнити їх!
Брайан Борчерс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.