{"id":32681,"date":"2025-12-08T05:00:00","date_gmt":"2025-12-08T04:00:00","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=32681"},"modified":"2025-12-08T12:39:03","modified_gmt":"2025-12-08T11:39:03","slug":"python-bez-gil-a","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/python-bez-gil-a\/","title":{"rendered":"Python bez GIL-a"},"content":{"rendered":"\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\u201e&#8230;O co chodzi, o co chodzi&#8230;\u201d<\/p>\n\n\n\n<p>Piotrek Szumowski w programie <a href=\"https:\/\/www.youtube.com\/watch?v=Qerim8L1V0I&amp;t=263s\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >Enzymy i Pioruny<\/a><\/p>\n<\/blockquote>\n\n\n\n<p>No w\u0142a\u015bnie, o co chodzi? GIL (Global Interpreter Lock) to mechanizm bezpiecze\u0144stwa wprowadzony w CPythonie w celu uproszczenia zarz\u0105dzania pami\u0119ci\u0105 w intrepreterze. Zapewnia, \u017ce tylko jeden <strong>w\u0105tek<\/strong> mo\u017ce wykonywa\u0107 kod bajtowy Pythona w danym momencie.<\/p>\n\n\n\n<p>Skutki? Nawet je\u015bli mamy 32-rdzeniowy procesor, klasyczne w\u0105tki w Pythonie nie potrafi\u0105 w pe\u0142ni wykorzysta\u0107 go do oblicze\u0144. W efekcie, przez lata rekomendowanym sposobem na r\u00f3wnoleg\u0142e przetwarzanie zada\u0144 obci\u0105\u017caj\u0105cych procesor <strong>by\u0142y procesy<\/strong> (ang. multiprocessing).<\/p>\n\n\n\n<p>Jednak ka\u017cde z tych podej\u015b\u0107 ma swoje zalety i ograniczenia:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>W\u0105tki \u2013 lekkie, szybkie w tworzeniu, wsp\u00f3\u0142dziel\u0105 pami\u0119\u0107, ale skutecznie ograniczone przez GIL w kontek\u015bcie CPU-bound.<\/li>\n\n\n\n<li>Procesy \u2013 dzia\u0142aj\u0105 niezale\u017cnie, omijaj\u0105 GIL, ale kosztuj\u0105 wi\u0119cej zasob\u00f3w (czas uruchomienia, kopiowanie danych).<\/li>\n<\/ul>\n\n\n\n<p><strong>W wersji <a href=\"https:\/\/docs.python.org\/3\/whatsnew\/3.13.html\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >Python 3.13<\/a><\/strong> pojawia si\u0119 <strong>eksperymentalna mo\u017cliwo\u015b\u0107 wy\u0142\u0105czenia GIL-a \u2013 i w\u0142a\u015bnie to przetestuj\u0119 w tym artykule.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Instalacja\/Konfiguracja<\/strong><\/h2>\n\n\n\n<p>Nie mo\u017cemy jeszcze oficjalnie zainstalowa\u0107 wersji Pythona z opcj\u0105 wy\u0142\u0105czania GIL-a. Sam autor \u2013 Sam Gross \u2013 w swoim <a href=\"https:\/\/github.com\/colesbury\/nogil\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >repozytorium<\/a> odsy\u0142a w celu instalacji na stron\u0119 <a href=\"https:\/\/py-free-threading.github.io\/installing-cpython\/\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >Python Free-Threading Guide<\/a>.<\/p>\n\n\n\n<p>Aby zainstalowa\u0107 Pythona w wersji bez GIL-a, mamy do wyboru:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Wykorzystanie gotowej zbudowanej binarki \u2013 <a href=\"https:\/\/py-free-threading.github.io\/tracking\/\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >strona do sprawdzenia kompatybilno\u015bci<\/a>.<\/li>\n\n\n\n<li>Zainstalowanie <a href=\"https:\/\/www.python.org\/download\/pre-releases\/\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >wersji testowych Pythona<\/a>.<\/li>\n\n\n\n<li>U\u017cycie obrazu kontenera.<\/li>\n\n\n\n<li>Zainstalowanie kernelu Jupytera.<\/li>\n<\/ul>\n\n\n\n<p>Wybra\u0142em opcj\u0119 instalacji Pythona bez GIL-a poprzez instalator Pythona.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"655\" height=\"400\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/Dodatkowa-opcja-instalacji-Pythona-w-wersji-bez-GIL-a.png\" alt=\"Dodatkowa opcja instalacji Pythona w wersji bez GIL-a\" class=\"wp-image-32801\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/Dodatkowa-opcja-instalacji-Pythona-w-wersji-bez-GIL-a.png 655w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/Dodatkowa-opcja-instalacji-Pythona-w-wersji-bez-GIL-a-300x183.png 300w\" sizes=\"(max-width: 655px) 100vw, 655px\" \/><figcaption class=\"wp-element-caption\">Ryc. 1 Dodatkowa opcja instalacji Pythona w wersji bez GIL-a<\/figcaption><\/figure>\n\n\n\n<p>W miejscu instalacji znajdowa\u0107 b\u0119dzie si\u0119 wersja docelowa Pythona oraz wersja z mo\u017cliwo\u015bci\u0105 wy\u0142\u0105czenia GIL-a.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"849\" height=\"570\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image2.png\" alt=\"Python w wersji oficjalnej oraz eksperymentalnej w folderze instalacyjnym\" class=\"wp-image-32684\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image2.png 849w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image2-300x201.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image2-768x516.png 768w\" sizes=\"(max-width: 849px) 100vw, 849px\" \/><figcaption class=\"wp-element-caption\">Ryc. 2 Python w wersji oficjalnej oraz eksperymentalnej w folderze instalacyjnym<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Co sprawdzimy? <\/strong><\/h2>\n\n\n\n<p>W tym artykule nie poprzestan\u0119 na teorii. Przeprowadz\u0119 praktyczne por\u00f3wnanie trzech tryb\u00f3w wsp\u00f3\u0142bie\u017cnej pracy:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>W\u0105tki w standardowym CPythonie z w\u0142\u0105czonym GIL-em.<\/li>\n\n\n\n<li>Procesy w CPythonie.<\/li>\n\n\n\n<li>W\u0105tki w eksperymentalnym CPythonie z wy\u0142\u0105czonym GIL-em.<\/li>\n<\/ul>\n\n\n\n<p>Dla ka\u017cdego z przypadk\u00f3w przeanalizuj\u0119 czas wykonania zada\u0144 obliczeniowych. <strong>Celem jest sprawdzenie, czy wy\u0142\u0105czenie GIL-a rzeczywi\u015bcie przynosi realny zysk w kontek\u015bcie wielow\u0105tkowo\u015bci<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>\u015arodowisko testowe<\/strong><\/h3>\n\n\n\n<p>Do przeprowadzenia bada\u0144 wykorzysta\u0142em Procesor AMD Ryzen 5 7500F maj\u0105cy 6 rdzeni i 12 w\u0105tk\u00f3w, 32GB RAM na Windowsie 11. Kod do bada\u0144 zosta\u0142 uruchomiony w PyCharmie z wykorzystaniem Pythona w wersji 3.13.5 i 3.13.5t.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Test 1.<\/strong><\/h3>\n\n\n\n<p>W pierwszym te\u015bcie u\u017cyty zosta\u0142 prosty wz\u00f3r wykorzystuj\u0105cy obliczenia arytmetyczne:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"64\" height=\"50\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image3.png\" alt=\"\" class=\"wp-image-32686\"\/><\/figure>\n\n\n\n<p>Rysunki poni\u017cej przedstawiaj\u0105 por\u00f3wnanie czasu wykonania 1 000 000 operacji arytmetycznych przy u\u017cyciu r\u00f3\u017cnych metod wsp\u00f3\u0142bie\u017cno\u015bci: proces\u00f3w oraz w\u0105tk\u00f3w z w\u0142\u0105czonym i wy\u0142\u0105czonym GIL-em.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"640\" height=\"480\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image4.png\" alt=\"Czas pracy 4 proces\u00f3w\" class=\"wp-image-32688\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image4.png 640w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image4-300x225.png 300w\" sizes=\"(max-width: 640px) 100vw, 640px\" \/><figcaption class=\"wp-element-caption\">Ryc. 3 Czas pracy 4 proces\u00f3w<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"982\" height=\"354\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/4.jpg\" alt=\"Por\u00f3wnanie czas\u00f3w pracy 4 w\u0105tk\u00f3w z w\u0142\u0105czonym i wy\u0142\u0105czonym GIL-em\" class=\"wp-image-32690\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/4.jpg 982w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/4-300x108.jpg 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/4-768x277.jpg 768w\" sizes=\"(max-width: 982px) 100vw, 982px\" \/><figcaption class=\"wp-element-caption\">Ryc. 4 Por\u00f3wnanie czas\u00f3w pracy 4 w\u0105tk\u00f3w z w\u0142\u0105czonym i wy\u0142\u0105czonym GIL-em<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"640\" height=\"480\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image7.png\" alt=\"Czas pracy 12 proces\u00f3w\" class=\"wp-image-32692\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image7.png 640w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image7-300x225.png 300w\" sizes=\"(max-width: 640px) 100vw, 640px\" \/><figcaption class=\"wp-element-caption\">Ryc. 5 Czas pracy 12 proces\u00f3w<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"987\" height=\"359\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/6.jpg\" alt=\"Por\u00f3wnanie czas\u00f3w pracy 12 w\u0105tk\u00f3w z w\u0142\u0105czonym i wy\u0142\u0105czonym GIL-em\" class=\"wp-image-32694\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/6.jpg 987w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/6-300x109.jpg 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/6-768x279.jpg 768w\" sizes=\"(max-width: 987px) 100vw, 987px\" \/><figcaption class=\"wp-element-caption\">Ryc. 6 Por\u00f3wnanie czas\u00f3w pracy 12 w\u0105tk\u00f3w z w\u0142\u0105czonym i wy\u0142\u0105czonym GIL-em<\/figcaption><\/figure>\n\n\n\n<p>Na Rysunku 3. widoczna jest wyra\u017ana r\u00f3wnoleg\u0142o\u015b\u0107 pracy proces\u00f3w \u2013 zadania s\u0105 roz\u0142o\u017cone pomi\u0119dzy procesy niezale\u017cnie, co skutkuje najkr\u00f3tszym czasem wykonania dla 4 pracownik\u00f3w (oko\u0142o 4,5 s).<\/p>\n\n\n\n<p>Rysunek 4. pokazuje wyra\u017any wp\u0142yw GIL-a na wydajno\u015b\u0107 w\u0105tk\u00f3w. W przypadku w\u0105tk\u00f3w z aktywnym GIL-em, czas wykonania znacz\u0105co wzrasta (oko\u0142o 14,5 s), a zadania s\u0105 wykonywane niemal\u017ce sekwencyjnie. Po jego wy\u0142\u0105czeniu czas spada do oko\u0142o 5 s, co wskazuje, \u017ce praca w\u0105tk\u00f3w jest bardziej r\u00f3wnoleg\u0142a.<\/p>\n\n\n\n<p>Na rysunkach 5. i 6. mo\u017cna r\u00f3wnie\u017c zauwa\u017cy\u0107, \u017ce tworzenie nowych w\u0105tk\u00f3w\/proces\u00f3w zajmuje czas, ale nie w przypadku, gdy GIL jest wy\u0142\u0105czony. Ich praca zaczyna si\u0119 praktycznie w tym samym momencie. Ponadto, praca w\u0105tk\u00f3w bez GIL-a, ko\u0144czy si\u0119 o oko\u0142o p\u00f3\u0142 sekundy szybciej ni\u017c proces\u00f3w.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Test 2.<\/strong><\/h3>\n\n\n\n<p>Drugi test dotyczy obliczania <a href=\"https:\/\/pl.wikipedia.org\/wiki\/Zbi%C3%B3r_Mandelbrota\" rel=\"nofollow\" >zbi<\/a><a href=\"https:\/\/pl.wikipedia.org\/wiki\/Zbi%C3%B3r_Mandelbrota\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >o<\/a><a href=\"https:\/\/pl.wikipedia.org\/wiki\/Zbi%C3%B3r_Mandelbrota\" rel=\"nofollow\" >ru Mandlebrota<\/a>. Stosuje on obliczenia z wykorzystaniem liczb urojonych, a rezultatem jest poni\u017csza grafika.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"640\" height=\"480\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image10.png\" alt=\"Mandelbrot\" class=\"wp-image-32700\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image10.png 640w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image10-300x225.png 300w\" sizes=\"(max-width: 640px) 100vw, 640px\" \/><figcaption class=\"wp-element-caption\">Ryc. 7 Mandelbrot<\/figcaption><\/figure>\n\n\n\n<p>Do przeprowadzonego badania wykorzystano zbi\u00f3r o wielko\u015bci 1200&#215;1200 oraz ograniczeniu iteracji 150.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"640\" height=\"480\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image11.png\" alt=\"Czas pracy 4 proces\u00f3w\" class=\"wp-image-32704\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image11.png 640w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image11-300x225.png 300w\" sizes=\"(max-width: 640px) 100vw, 640px\" \/><figcaption class=\"wp-element-caption\">Ryc. 8 Czas pracy 4 proces\u00f3w<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"989\" height=\"361\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/9.jpg\" alt=\"Por\u00f3wnanie czas\u00f3w pracy 4 w\u0105tk\u00f3w z w\u0142\u0105czonym i wy\u0142\u0105czonym GIL-em\" class=\"wp-image-32708\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/9.jpg 989w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/9-300x110.jpg 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/9-768x280.jpg 768w\" sizes=\"(max-width: 989px) 100vw, 989px\" \/><figcaption class=\"wp-element-caption\">Ryc. 9 Por\u00f3wnanie czas\u00f3w pracy 4 w\u0105tk\u00f3w z w\u0142\u0105czonym i wy\u0142\u0105czonym GIL-em<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"640\" height=\"480\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image14.png\" alt=\"Czas pracy 12 proces\u00f3w\" class=\"wp-image-32718\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image14.png 640w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image14-300x225.png 300w\" sizes=\"(max-width: 640px) 100vw, 640px\" \/><figcaption class=\"wp-element-caption\">Ryc. 10 Czas pracy 12 proces\u00f3w<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"1004\" height=\"361\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/11.jpg\" alt=\"Por\u00f3wnanie czas\u00f3w pracy 12 w\u0105tk\u00f3w z w\u0142\u0105czonym i wy\u0142\u0105czonym GIL-em\" class=\"wp-image-32720\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/11.jpg 1004w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/11-300x108.jpg 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/11-768x276.jpg 768w\" sizes=\"(max-width: 1004px) 100vw, 1004px\" \/><figcaption class=\"wp-element-caption\">Ryc. 11 Por\u00f3wnanie czas\u00f3w pracy 12 w\u0105tk\u00f3w z w\u0142\u0105czonym i wy\u0142\u0105czonym GIL-em<\/figcaption><\/figure>\n\n\n\n<p>Tym razem, ze wzgl\u0119du na to, \u017ce praca zosta\u0142a podzielona wierszami, pracownicy na g\u00f3rze oraz dole grafiki nie mieli zbyt du\u017co pracy, co mo\u017cemy zauwa\u017cy\u0107 na powy\u017cszych rysunkach, gdzie czas dla pracownik\u00f3w 0, 1, 2, 9, 10 i 11 jest najkr\u00f3tszy. Zachowanie w\u0105tk\u00f3w i proces\u00f3w by\u0142o zbli\u017cone do obserwowanego w pierwszym te\u015bcie.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Por\u00f3wnanie czas\u00f3w<\/strong><\/h3>\n\n\n\n<p>Przegl\u0105daj\u0105c powy\u017csze wykresy, zauwa\u017cy\u0142em, \u017ce cho\u0107 czasy pracy proces\u00f3w i w\u0105tk\u00f3w bez GIL-a ko\u0144cz\u0105 si\u0119 w podobnym momencie, to procesy potrzebuj\u0105 oko\u0142o p\u00f3\u0142 sekundy na utworzenie. W zwi\u0105zku z tym postanowi\u0142em przyjrze\u0107 si\u0119 jeszcze danym, takim jak warto\u015bci minimalne, maksymalne i \u015brednie faktycznego czasu pracy.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"463\" height=\"251\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image17-1.png\" alt=\"\" class=\"wp-image-32722\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image17-1.png 463w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image17-1-300x163.png 300w\" sizes=\"(max-width: 463px) 100vw, 463px\" \/><\/figure>\n\n\n\n<p>Jak zauwa\u017cy\u0142em, <strong>czasy pracy s\u0105 cz\u0119sto lepsze dla proces\u00f3w, je\u015bli nie uwzgl\u0119dniamy czasu potrzebnego na ich uruchomienie.<\/strong><\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Analiza zu\u017cycia CPU i zachowania schedulera w Windowsie<\/strong><\/h3>\n\n\n\n<p>Ostatni\u0105 rzecz\u0105, na kt\u00f3r\u0105 spojrza\u0142em, jest praca procesor\u00f3w rejestrowana przez system Windows.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"940\" height=\"711\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/12.jpg\" alt=\"Por\u00f3wnanie wykorzystania zasob\u00f3w procesora przez 1 w\u0105tek\" class=\"wp-image-32726\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/12.jpg 940w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/12-300x227.jpg 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/12-768x581.jpg 768w\" sizes=\"(max-width: 940px) 100vw, 940px\" \/><figcaption class=\"wp-element-caption\">Ryc. 12 Por\u00f3wnanie wykorzystania zasob\u00f3w procesora przez 1 w\u0105tek<\/figcaption><\/figure>\n\n\n\n<p>Wida\u0107 wyra\u017anie, \u017ce do pracy wykorzystywane s\u0105 2 CPU \u2013 10 oraz 11. Dlaczego pracuj\u0105 dwie jednostki CPU, skoro zadanie mia\u0142 wykonywa\u0107 tylko jeden w\u0105tek? M\u00f3j procesor ma 6 rdzeni, a ka\u017cdy z nich obs\u0142uguje 2 w\u0105tki (Hyper-Threading lub Simultaneous multithreading). Windows Scheduler w tym przypadku stara si\u0119 r\u00f3wnomiernie roz\u0142o\u017cy\u0107 obci\u0105\u017cenie w ramach jednego rdzenia.<\/p>\n\n\n\n<p><strong>Co jednak, gdy do pracy zaci\u0105gniemy 2 w\u0105tki?<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" width=\"467\" height=\"1024\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image20-467x1024.png\" alt=\"Zu\u017cycie zasob\u00f3w przez 2 w\u0105tki przy wy\u0142\u0105czonym GIL-u\" class=\"wp-image-32734\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image20-467x1024.png 467w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image20-137x300.png 137w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image20.png 583w\" sizes=\"(max-width: 467px) 100vw, 467px\" \/><figcaption class=\"wp-element-caption\">Ryc. 13 Zu\u017cycie zasob\u00f3w przez 2 w\u0105tki przy wy\u0142\u0105czonym GIL-u<\/figcaption><\/figure>\n\n\n\n<p>Tym razem oba w\u0105tki w ramach jednego rdzenia pracuj\u0105 na maksymalnych obrotach. Czy w takim razie mo\u017cliwe by\u0142oby roz\u0142o\u017cenie pracy pomi\u0119dzy 2 rdzenie, czyli 4 w\u0105tki? Tak, niemniej jest to zale\u017cne od algorytmu schedulera w Windowsie oraz tego, jak Windows stara si\u0119 minimalizowa\u0107 migracj\u0119 w\u0105tk\u00f3w. Wspomniane zachowanie uda\u0142o mi si\u0119 zaobserwowa\u0107 przy pracy 8 w\u0105tk\u00f3w, gdzie minimalnie mog\u0142yby by\u0107 zaj\u0119te tylko 4 rdzenie.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" width=\"470\" height=\"1024\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image21-470x1024.png\" alt=\"Zu\u017cycie zasob\u00f3w przez 8 w\u0105tk\u00f3w przy wy\u0142\u0105czonym GIL-u\" class=\"wp-image-32736\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image21-470x1024.png 470w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image21-138x300.png 138w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image21.png 588w\" sizes=\"(max-width: 470px) 100vw, 470px\" \/><figcaption class=\"wp-element-caption\">Ryc. 14 Zu\u017cycie zasob\u00f3w przez 8 w\u0105tk\u00f3w przy wy\u0142\u0105czonym GIL-u<\/figcaption><\/figure>\n\n\n\n<p>Co ciekawe tym razem do pracy zosta\u0142y zaci\u0105gni\u0119te wszystkie rdzenie. W\u0105tki dzia\u0142aj\u0105ce na parach logicznych rdzeni (np. CPU0 i CPU1) wsp\u00f3\u0142dziel\u0105 ten sam fizyczny rdze\u0144. Dlatego cz\u0119\u015b\u0107 z nich wygl\u0105da na mniej aktywn\u0105 \u2013 system rozdziela prac\u0119 nier\u00f3wnomiernie, ale faktycznie obci\u0105\u017cony jest ca\u0142y rdze\u0144.<\/p>\n\n\n\n<p>Praca wszystkich 12 w\u0105tk\u00f3w wygl\u0105da z kolei nast\u0119puj\u0105co:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"894\" height=\"519\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/13.jpg\" alt=\"Por\u00f3wnanie wykorzystania zasob\u00f3w procesora dla 12 w\u0105tk\u00f3w\" class=\"wp-image-32738\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/13.jpg 894w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/13-300x174.jpg 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/13-768x446.jpg 768w\" sizes=\"(max-width: 894px) 100vw, 894px\" \/><figcaption class=\"wp-element-caption\">Ryc. 15 Por\u00f3wnanie wykorzystania zasob\u00f3w procesora dla 12 w\u0105tk\u00f3w<\/figcaption><\/figure>\n\n\n\n<p>Zgodnie z oczekiwaniami wszystkie procesory s\u0105 ob\u0142o\u017cone prac\u0105.<\/p>\n\n\n\n<p>Uda\u0142o mi si\u0119 r\u00f3wnie\u017c raz zaobserwowa\u0107 migracj\u0119 w\u0105tk\u00f3w \u2013 takie zjawisko mo\u017ce powodowa\u0107 chwilowe spadki wydajno\u015bci.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" width=\"478\" height=\"1024\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image22-478x1024.png\" alt=\"Migracja zasob\u00f3w dla 1 w\u0105tku z w\u0142\u0105czonym GIL-em\" class=\"wp-image-32740\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image22-478x1024.png 478w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image22-140x300.png 140w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image22.png 597w\" sizes=\"(max-width: 478px) 100vw, 478px\" \/><figcaption class=\"wp-element-caption\">Ryc. 16 Migracja zasob\u00f3w dla 1 w\u0105tku z w\u0142\u0105czonym GIL-em<\/figcaption><\/figure>\n\n\n\n<p>Podsumowuj\u0105c, <strong>Windows skutecznie rozdziela w\u0105tki w ramach rdzeni, a przy wi\u0119kszej liczbie w\u0105tk\u00f3w anga\u017cuje wszystkie dost\u0119pne jednostki<\/strong>. Wida\u0107 te\u017c, \u017ce GIL znacz\u0105co ogranicza wykorzystanie dost\u0119pnych zasob\u00f3w.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Niespodziewane problemy<\/strong><\/h2>\n\n\n\n<p>Podczas przygotowywania \u015brodowiska do test\u00f3w, nie oby\u0142o si\u0119 bez problem\u00f3w.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Biblioteki<\/strong><\/h3>\n\n\n\n<p>Wersja Pythona bez w\u0105tk\u00f3w jest niekompatybilna z niekt\u00f3rymi bibliotekami.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"617\" height=\"39\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image23.png\" alt=\"kod\" class=\"wp-image-32742\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image23.png 617w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image23-300x19.png 300w\" sizes=\"(max-width: 617px) 100vw, 617px\" \/><\/figure>\n\n\n\n<p>Z pocz\u0105tku my\u015bla\u0142em, \u017ce rozwi\u0105zaniem tego jest instalacja starszej wersji numpy. W moim przypadku Python==3.13.5 bez w\u0105tk\u00f3w wydawa\u0142 si\u0119 by\u0107 niekompatybilny z numpy==2.3.1, przez co zacz\u0105\u0142em eksperymentowa\u0107 z starszymi wersjami numpy, jak polecali do\u015bwiadczeni specjali\u015bci na StackOverflow.<\/p>\n\n\n\n<p>W pewnym momencie wersja numpy==2.2.0 zacz\u0119\u0142a dzia\u0142a\u0107 i my\u015bla\u0142em, \u017ce downgrade rozwi\u0105za\u0142 problem. Jednak pr\u00f3ba otworzenia \u015brodowiska na innym komputerze sko\u0144czy\u0142a si\u0119 mas\u0105 frustracji, gdy\u017c \u017cadna wersja nie pomaga\u0142a mi rozwi\u0105za\u0107 tego problemu.<\/p>\n\n\n\n<p>Ostatecznie stwierdzi\u0142em, \u017ce g\u0142\u00f3wnym problemem nie by\u0142a sama wersja numpy, ale pr\u00f3ba u\u017cycia proces\u00f3w w Pythonie zbudowanym bez pe\u0142nego wsparcia dla nich.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"609\" height=\"118\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image24.png\" alt=\"kod\" class=\"wp-image-32744\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image24.png 609w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/image24-300x58.png 300w\" sizes=\"(max-width: 609px) 100vw, 609px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Pomiary czas\u00f3w<\/strong><\/h3>\n\n\n\n<p>Do pomiar\u00f3w czasu nie wykorzysta\u0142em dok\u0142adniejszych narz\u0119dzi jak perf_counter() czy cpu_counter() ze wzgl\u0119du na to, \u017ce korzystaj\u0105 one z w\u0142asnych punkt\u00f3w pocz\u0105tkowych. Bez wsp\u00f3\u0142dzielonej pami\u0119ci mo\u017ce to prowadzi\u0107 do ujemnych czas\u00f3w lub b\u0142\u0119dnych wynik\u00f3w.<\/p>\n\n\n\n<p>W swoim rozwi\u0105zaniu postanowi\u0142em wykorzysta\u0107 time() z racji na to, \u017ce bazuje ona na czasie globalnym.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>threading i multiprocessing VS concurrent.futures<\/strong><\/h3>\n\n\n\n<p>Dlaczego u\u017cy\u0142em ProcessPoolExecutor i ThreadPoolExecutor? Odpowied\u017a jest bardzo prosta \u2013 \u0142atwiejsze zarz\u0105dzanie maksymaln\u0105 liczb\u0105 w\u0105tk\u00f3w lub proces\u00f3w. Na potrzeby tego badanie nie by\u0142o konieczno\u015bci w\u0142asnej synchronizacji pracy dla poszczeg\u00f3lnych pracownik\u00f3w.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Czy usuni\u0119cie GIL-a jest bezpieczne?<\/strong><\/h2>\n\n\n\n<p>Nie. Na chwil\u0119 obecn\u0105 jego usuni\u0119cie wi\u0105\u017ce si\u0119 z du\u017cymi zmianami w interpreterze CPythona i niesie ryzyko wprowadzenia trudnych do wykrycia b\u0142\u0119d\u00f3w, o kt\u00f3rych Sam wspomina w <a href=\"https:\/\/docs.google.com\/document\/d\/18CXhDb1ygxg-YXNBJNzfzZsDFosB5e6BfnXLlejd9l0\/edit?tab=t.0\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >artykule<\/a>.<\/p>\n\n\n\n<p>Nawet je\u015bli uda si\u0119 zwi\u0119kszy\u0107 wydajno\u015b\u0107 w kodzie wielow\u0105tkowym, mo\u017ce to kosztowa\u0107 wydajno\u015b\u0107 w kodzie jednow\u0105tkowym, kt\u00f3ry to dominuje w wi\u0119kszo\u015bci zastosowa\u0144 Pythona.<\/p>\n\n\n\n<p>Wraz z usuni\u0119ciem GIL-a pojawi\u0105 si\u0119 klasyczne problemy wsp\u00f3\u0142bie\u017cno\u015bci. U\u017cytkownicy b\u0119d\u0105 musieli rozwa\u017cy\u0107 ryzyka takie jak wy\u015bcigi po zasoby, deadlocki itp.<\/p>\n\n\n\n<p>Autor wspomnianego wy\u017cej artyku\u0142u zauwa\u017ca r\u00f3wnie\u017c, \u017ce rozszerzenia napisane w C b\u0119d\u0105 wymaga\u0142y ponownej kompilacji i\/lub modyfikacji, aby by\u0142y bezpieczne w \u015brodowisku bez GIL-a. Cz\u0119\u015b\u0107 z nich wymaga\u0142aby ochrony danych globalnych.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/oferty-pracy\/\" target=\"_blank\" rel=\"noreferrer noopener\"><img decoding=\"async\" width=\"737\" height=\"170\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/praca-m.jpg\" alt=\"oferty pracy\" class=\"wp-image-32746\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/praca-m.jpg 737w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/praca-m-300x69.jpg 300w\" sizes=\"(max-width: 737px) 100vw, 737px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong><strong>Podsumowanie<\/strong><\/strong><\/h2>\n\n\n\n<p>Testy pokazuj\u0105, \u017ce w\u0105tki dzia\u0142aj\u0105ce bez GIL-a maj\u0105 du\u017cy potencja\u0142 \u2013 szczeg\u00f3lnie w kr\u00f3tkich, lekkich zadaniach (CPU-bound). Tworz\u0105 si\u0119 szybciej ni\u017c procesy, a ich czasy wykonania s\u0105 bardzo zbli\u017cone. Procesy wci\u0105\u017c wygrywaj\u0105 przy d\u0142u\u017cszych obci\u0105\u017ceniach, ale nowa wersja Pythona to krok w stron\u0119 prawdziwej wsp\u00f3\u0142bie\u017cno\u015bci.<\/p>\n\n\n\n<p>Dla dog\u0142\u0119bniejszego zroumienia r\u00f3\u017cnic odsy\u0142am Was do artyku\u0142\u00f3w:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/medium.com\/@bfortuner\/python-multithreading-vs-multiprocessing-73072ce5600b\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >Intro to Threads and Processes in Python<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/towardsdatascience.com\/multithreading-vs-multiprocessing-in-python-3afeb73e105f\/\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >Multithreading vs. Multiprocessing in Python<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.stratascratch.com\/blog\/python-threading-like-a-pro\/\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >Python Threading Like a Pro<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/py-free-threading.github.io\/\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >Dokumentacji free-threading Pythona<\/a><\/li>\n<\/ul>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;32681&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;5&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;4.2&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;4.2\\\/5 ( votes: 5)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;Python bez GIL-a&quot;,&quot;width&quot;:&quot;116.3&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 116.3px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            4.2\/5 ( votes: 5)    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u201e&#8230;O co chodzi, o co chodzi&#8230;\u201d Piotrek Szumowski w programie Enzymy i Pioruny No w\u0142a\u015bnie, o co chodzi? GIL (Global &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/python-bez-gil-a\/\">Continued<\/a><\/p>\n","protected":false},"author":764,"featured_media":32749,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1314],"tags":[4591,1546,1512,563,584],"class_list":["post-32681","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development-na-twardo","tag-gil","tag-przeglad-narzedzi","tag-poradnik","tag-embedded","tag-python"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/12\/Programming.jpg","category_names":["Development na twardo"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/32681"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/users\/764"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/comments?post=32681"}],"version-history":[{"count":2,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/32681\/revisions"}],"predecessor-version":[{"id":32803,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/32681\/revisions\/32803"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media\/32749"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media?parent=32681"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/categories?post=32681"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/tags?post=32681"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}