Рання спроба видалити Python GIL призвела до поганих результатів: Чому?


13

Цей пост від творця Python, Гвідо Ван Россума, згадує про ранню спробу видалити GIL з Python:

Це було випробувано раніше, із невтішними результатами, тому я неохоче докладаю багато зусиль до цього. У 1999 р. Грег Штейн (разом з Марком Хаммонд?) Виготовив виделку Python (1.5 я вважаю), що видалила GIL, замінивши його дрібнозернистими замками на всіх змінних структурах даних. Він також представив виправлення, які видалили багато спільнот глобальних змінних структур даних, які я прийняв. Однак після тестування було показано, що навіть на платформі з найшвидшим блокуванням примітиву (на той час Windows) він уповільнив однопотокове виконання майже вдвічі, що означає, що на двох процесорах ви можете отримати трохи більше роботи зроблено без GIL, ніж на одному процесорі з GIL. Цього було недостатньо, і пластир Грега відпав у небуття. (Дивіться опис Грега щодо виступу.)

Я навряд чи можу посперечатися з фактичними результатами, але мені справді цікаво, чому це сталося. Імовірно, головна причина того, що видалити GIL з CPython настільки складно, це через систему управління пам'яттю підрахунку посилань. Типова програма Python буде викликати Py_INCREFі Py_DECREFтисячі або мільйони разів, що робить його ключовий момент конкуруючого якщо ми повинні були обернути пасма навколо нього.

Але я не розумію, чому додавання атомних примітивів сповільнить одну програму з потоком. Припустимо, ми просто змінили CPython, щоб змінна refcount у кожному об'єкті Python була атомним примітивом. І тоді ми просто робимо атомний приріст (інструкція добування та додавання), коли нам потрібно збільшити кількість відліку. Це зробило б посилання підрахунку потоку Python безпечним і не повинно бути штрафом щодо продуктивності для однопотокового додатку, оскільки не буде суперечки щодо блокування.

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


1
Зауважте, що операція по знижці не буде єдиним місцем, яке потребує синхронізації. Цитата згадує "дрібнозернисті замки на всіх змінних структурах даних", які, я вважаю, включає щонайменше мутекс для кожного списку та об'єкта словника. Крім того, я не думаю, що атомні цілі операції є настільки ефективними, як неатомний еквівалент незалежно від суперечок, чи є у вас джерело для цього?

просто тому, що атомні операції проходять повільніше, ніж неатомні еквіваленти. Тільки тому, що це єдина інструкція, не означає, що це тривіально під кришкою. Дивіться це для деякої дискусії
Móż

Відповіді:


9

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

По суті, кожна реалізація Unix, яку я вивчав у 1990-х роках - AIX, DEC OSF / 1, DG / UX, DYNIX, HP-UX, IRIX, Solaris, SVR4 та SVR4 MP - все пройшло саме через цей тип " тонкозернистий замок - тепер він повільніше !! " проблема. СУБД, за якими я дотримувався - DB2, Ingres, Informix, Oracle та Sybase - вони теж пройшли через це.

Я чув, що "ці зміни нас не уповільнюють, коли ми працюємо однопотоково" мільйон разів. Це ніколи не виходить таким чином. Простий акт умовної перевірки "ми виконуємо багатопотокові чи ні?" додає реальних накладних витрат, особливо на високопрофільних процесорах. Атомні операції та епізодичні спін-блокування для забезпечення цілісності спільних структур даних потрібно викликати досить часто, і вони дуже повільні. Примітиви блокування / синхронізації першого покоління також були повільними. Більшість команд із впровадження додають декілька класів примітивів у різних "сильних сторонах", залежно від того, який захист від блокування потрібен у різних місцях. Потім вони усвідомлюють, де вони спочатку ляснули замикаючими примітивом, насправді не було правильним місцем, тому їм довелося профайлювати, проектуючи навколо знайдених вузьких місць, і систематично рото-до. Деякі з цих точок стикання врешті-решт отримали ОС або апаратне прискорення, але ця еволюція зайняла 3-5 років, мінімум. Тим часом версії в форматі MP або MT були кульгаючими.

В іншому випадку складні команди розвитку стверджують, що такі уповільнення в основному є постійним, непереборним фактом життя. IBM, наприклад, відмовився від включення SMP з підтримкою AIX щонайменше 5 років після змагань, при цьому твердий, що однопоточний був просто кращим. Sybase використовував деякі ті ж аргументи. Єдиною причиною, з якою деякі команди в кінцевому підсумку зійшли, було те, що продуктивність одного потоку вже не може бути розумно покращена на рівні ЦП. Вони були змушені або їхати в МП / МТ, або приймати продукт, що все більш неконкурентоспроможний.

Активна паралельність - HARD. І це оманливо. Всі кидаються в нього, думаючи, що "це не буде так погано". Потім вони потрапляють у п’ятницю і мусять пробиватися. Я бачив, як це відбувається як мінімум з десятка фірмових брендів, які добре фінансуються, розумні команди. Взагалі, здавалося, пройде щонайменше п’ять років після вибору багатопотокової передачі, щоб "повернутися туди, де вони повинні бути, продуктивні" з продуктами MP / MT; Більшість з них все ще значимо покращували ефективність / масштабованість MP / MT навіть через десять років після зміни.

Отже, я міркую, що за відсутності схвалення та підтримки GvR ніхто не брався за довгі зусилля щодо Python та його GIL. Навіть якби вони це робили сьогодні, це був би часовий проміжок Python 4.x, перш ніж ви сказали: "Ого! Ми справді перевершили горб MT!"

Можливо, є якась магія, яка відокремлює Python та його час виконання від усіх інших програм інфраструктурного стану - усі мовні режими роботи, операційні системи, монітори транзакцій та менеджери баз даних, які вже були раніше. Але якщо так, то це унікально або майже так. Всім іншим, щоб зняти GIL-еквівалент, знадобилося п'ять плюс років, наполегливих зусиль та інвестицій, щоб дістатися з MT-не до MT-hot.


2
+1 Знадобилося приблизно такий час, щоб багатопотокове Tcl з досить невеликою командою розробників. Код був безпечним для MT раніше, але мав неприємні проблеми з роботою, здебільшого в управлінні пам’яттю (я вважаю, що це дуже гаряча область для динамічних мов). Цей досвід насправді не передає Python ні в чому іншому, крім найбільш загальних термінів; дві мови мають абсолютно різні моделі різьблення. Просто… очікуйте гасла та очікуйте дивних помилок…
Доналі стипендіатів

-1

Ще одна дивна гіпотеза: У 1999 році Linux та інші Unices не мали такої синхронізації, як зараз futex(2)( http://en.wikipedia.org/wiki/Futex ). Вони з'явилися близько 2002 року (і були об'єднані в 2,6 близько 2004 року).

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


1
Чи є у вас щось на цьому? чи це майже спекуляція?

1
Цитата GvR описує продуктивність "на платформі з найшвидшим блокуванням примітиву (на той час Windows)", тому повільні блокування в Linux не є актуальними.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.