Як запрограмувати розподіл потоків на багатоядерних процесорах?


13

Я хотів би експериментувати з потоками на багатоядерному процесорі, наприклад, створити програму, яка використовує два різні потоки, які виконуються двома різними ядрами процесора.

Однак мені незрозуміло, на якому рівні нитки розподіляються між різними ядрами. Я можу уявити такі сценарії (залежно від реалізації операційної системи та мови програмування):

  1. Розподілом ниток керує операційна система. Нитки створюються за допомогою системних викликів ОС, і якщо процес відбувається на багатоядерному процесорі, ОС автоматично намагається виділити / запланувати різні потоки на різних ядрах.
  2. Розподіл ниток управляється реалізацією мови програмування. Виділення потоків до різних ядер вимагає спеціальних системних викликів, але бібліотеки стандартних потоків мови програмування автоматично справляються з цим, коли я використовую стандартну реалізацію потоку для цієї мови.
  3. Розподіл нитки повинен бути запрограмований чітко. У своїй програмі я повинен написати явний код, щоб виявити, скільки ядер доступно, і виділити різні потоки для різних ядер, використовуючи, наприклад, бібліотечні функції.

Щоб зробити питання більш конкретним, уявіть, що я написав свою багатопотокову програму на Java або C ++ для Windows або Linux. Чи буде мій додаток магічно бачити та використовувати декілька ядер під час роботи на багатоядерному процесорі (тому що всім керує або операційна система, або стандартна бібліотека потоків), чи потрібно змінювати код, щоб бути в курсі кількох ядер ?

Відповіді:


11

Чи буде мій додаток магічно бачити та використовувати декілька ядер під час роботи на багатоядерному процесорі (тому що всім керує або операційна система, або стандартна бібліотека потоків), чи потрібно змінювати код, щоб бути в курсі кількох ядер ?

Проста відповідь: Так, цим, як правило, керує операційна система або бібліотека з нарізками.

Підсистема різьблення в операційній системі присвоює потоки процесорам пріоритетно (ваш варіант 1). Іншими словами, коли нитка закінчила виконання для її розподілу часу або блокує, планувальник шукає наступний потік найвищого пріоритету і призначає це ЦП. Деталі відрізняються від операційної системи до операційної системи.

Однак, варіанти 2 (керовані мовою програмування) та 3 (явно) існують. Наприклад, бібліотека завдань та асинхронізація / очікування в останніх версіях .Net дають розробнику набагато простіший спосіб записати паралельний (тобто, який може працювати паралельно з самим собою) код. Мови функціонального програмування є внутрішньо паралельними, і деякі режими виконання, якщо можливо, виконують різні частини програми паралельно.

Що стосується варіанта 3 (явно), то Windows дозволяє встановити спорідненість потоку (вказавши, на яких процесорах може працювати потік). Однак це, як правило, непотрібно у всіх, крім найшвидших, критичних систем, що реагують на час реакції. Ефективний розподіл потоку до процесора залежить від апаратного забезпечення та дуже чутливий до інших програм, що працюють одночасно.

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


Дякуємо за пояснення (+1). Моя тестова програма - це реалізація сортування злиття. У фазі розщеплення я хочу створити різні потоки до тих пір, поки є наявні ядра. Наприклад, з двома ядрами кожна половина масиву буде відсортована за різною ниткою / ядром. Під час злиття зайві нитки будуть потім з'єднані / припинені.
Джорджіо

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

Дві половинки масиву можна сортувати незалежно, оскільки дані не поділяються. Тільки перший розбиття і останнє злиття повинні бути виконані одним потоком, що маніпулює всім масивом або списком, що містить дані. Це означає, що одне повне сканування даних не може бути виконане паралельно; всі решти сканування можуть.
Джорджіо

Звичайно, я також вважаю ваші приклади добрими кандидатами. На даний момент я просто більше знайомий з сортуванням злиття (і я реалізував непаралельну його версію), яка (можливо) зробить сортування злиття більш підходящим для мене як перша спроба.
Джорджіо

2
Я додам до цієї відповіді, що хороші операційні системи досить розумні, щоб врівноважувати витрати на завдання завдавати відрізок часу на іншому процесорі або ядрі з короткочасним голодуванням. У архітектурах, де це має значення, результат має тенденцію нагадувати автоматичну спорідненість. ОС була побудована для того, щоб якнайшвидше виконати всі завдання, і ви можете стріляти собі в ногу, прив’язуючи нитки до ядер і перешкоджаючи її здатності приймати ці рішення.
Blrfl

-1

Колись у мене було величезне середовище SGI IRIX. Тільки для цього, я написав невелику багатопотокову програму java (яка просто нічого, крім споживання циклів процесора), і створила в ній 12 ниток. Завдання охопило 12 процесорів в архітектурі NUMA. Можливо, я перегляну програму і запускаю її на Dell R910s і перевіряю ..


3
Ця відповідь дійсно не додає багато до існуючої відповіді. Можливо, якщо ви детальніше зупинилися на тому, чому JVM в системі SGI виділив нитки для основної ...
Джей Елстон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.