Використання декількох ядер вимагає явного виявлення паралелізму рівня потоку в ОС, що зазвичай вимагає від програміста написати багатопотокової програми. (Або запускати однопоточну програму кілька разів на різних входах, як-от компіляція make -j4
)
Однак компілятори для деяких мов підтримують автоматичну паралелізацію. Наприклад, C або C ++ з OpenMP може скласти звичайний for()
цикл у програму, яка запускає кілька потоків.
#pragma omp parallel for
for(int i = 0; i < 1000000; ++i)
{
A[i] = B[i] * constant + C[i];
}
Але все-таки це має статися, коли ви писали або складали програму. Немає можливості для поточного обладнання та ОС використовувати кілька ядер для прискорення однопотокової програми.
Пов'язане: Як одна нитка працює на декількох ядрах? : відповідь: вони ні. Але існують і інші види паралелізму, як -от паралелізм на рівні інструкцій, який одне ядро CPU знаходить і використовує для запуску одного потоку швидше, ніж одна інструкція одночасно.
Моя відповідь на це питання полягає в деяких деталях того, як сучасні процесори знаходять і використовують дрібнозернистий паралелізм на рівні інструкцій. (Здебільшого фокусується на x86). Це лише частина того, як працюють звичайні процесори, маючи декілька інструкцій під час польоту одночасно, і це не те, що потрібно спеціально включати. (Існують лічильники продуктивності, за допомогою яких можна побачити, скільки інструкцій за годинник вдалося виконати процесору під час виконання програми, хоча й інших заходів.)
Зауважте, що RPi3 використовує порядок процесорних ядер ARM Cortex-A53 . Кожне ядро - це 2-широкий суперскаляр (2 інструкції на годинник, як дозволяє ILP), але не може переупорядкувати інструкції, щоб знайти більше паралелізму на рівні інструкцій та приховати затримку.
Все-таки процесор є конвеєрним, тому загальна кількість інструкцій в польоті (від вибору та декодування аж до етапу списання в кінці конвеєра) є значною. Якщо залежність від даних не обмежує можливості, на кожному етапі конвеєра, над яким працює центральний процесор, можуть бути дві інструкції з пропускною здатністю 2 інструкції на добу. (Ось що означає 2-широке значення.)
Він не може виконувати інструкції не в порядку, але при ретельному упорядкуванні інструкцій (як правило, компілятором), він все ще може приховати затримку інструкції, яка потребує декількох циклів, щоб її вихід був готовий. (наприклад, завантаження, навіть якщо воно потрапляє в кеш-пам'ять або множина, займе декілька циклів, порівняно з тим, що наступний цикл буде готовий). Трюк полягає в тому, щоб замовити інструкції asm, щоб існувало кілька незалежних інструкцій між тією, яка створює результат, і тією, яка її використовує.
Наявність програмного забезпечення (компілятора) статичних інструкцій для планування є більш крихким, ніж обладнання, яке може здійснювати внутрішній впорядкування, зберігаючи ілюзію виконання програмного порядку. Компіляторам дуже важко виконати таку роботу, як навіть невелике вікно поза замовленням для впорядкування інструкцій, оскільки помилки кешу непередбачувані, і важко проаналізувати ланцюги залежностей між функціональними викликами під час компіляції. А кількість реєстрів обмежена без апаратного реєстру-перейменування.
Все це - малий комфорт, коли ваш код працює повільніше, ніж вам би хотілося. Звичайно, у Cortex-A53 є багато класних речей під кришкою, але в Cortex-A57 є більше цікавих матеріалів під капотом (як, наприклад, виконання до 3 інструкцій на годинник поза замовленням) і навіть більше в великий процесор x86 на зразок Skylake (не кажучи вже про відмінності тактових частот).
Cortex-A53 є досить фантастичним порівняно з https://en.wikipedia.org/wiki/Classic_RISC_pipeline, як оригінальні MIPS, про які ви дізналися б у класі комп'ютерної архітектури, але за сучасними мірками це досить низько.