TGViewer
Находки в опенсорсе Находки в опенсорсе @opensource_findings · 12.6K subscribers
Post #884 8.87K
Ковыряем внутрянку nogil

Некоторое время назад я прислал безобидный PR, который исправлял поведение list.insert в nogil сборках CPython. Изменений на 3 строчки. И в ревью случилось два интересных момента.

Во-первых, я случайно удалил оптимизацию.

Было:


PyObject **items;
items = self->ob_item;
items[i+1] = items[i];
items[where] = Py_NewRef(v);



0x0000000000132860 <+96>: sub rdx,0x1
0x0000000000132864 <+100>: sub rax,0x8
0x0000000000132868 <+104>: mov rcx,QWORD PTR [rax]
0x000000000013286b <+107>: mov QWORD PTR [rax+0x8],rcx
0x000000000013286f <+111>: cmp rsi,rdx
0x0000000000132872 <+114>: jle 0x132860 <ins1+96>


Стало:


self->ob_item[i+1] = self->ob_item[i];
self->ob_item[where] = Py_NewRef(v);



0x0000000000132858 <+88>: mov rdx,QWORD PTR [r12+0x28]
0x000000000013285d <+93>: lea rcx,[rax*8+0x0]
0x0000000000132865 <+101>: mov rdi,QWORD PTR [rdx+rax*8]
0x0000000000132869 <+105>: sub rax,0x1
0x000000000013286d <+109>: mov QWORD PTR [rdx+rcx*1+0x8],rdi
0x0000000000132872 <+114>: cmp rsi,rax
0x0000000000132875 <+117>: jle 0x132858 <ins1+88>


В питоне есть аналогичная оптимизация. Использовать


items = self.items
for _ in whatever:
some_func(items)


более оптимально, чем


for _ in whatever:
some_func(self.items)


если у вас много объектов в whatever.


LOAD_NAME 3 (self)
LOAD_ATTR 8 (items) # <- won't happen when `items = self.items`
CALL 1


Во-вторых, когда мне указали на ошибку, я понял, что я так до конца и не понял разницу между FT_ATOMIC_STORE_PTR_RELAXED и FT_ATOMIC_STORE_PTR_RELEASE.

А вот тут потребуется пояснительная бригада. Смотрите, при использовании nogil, у нас теперь несколько потоков, который выполняют сишный код (который генерирует нужный ASM). И там есть своя специфика. Начнем с того, что есть специальное понятие – Memory Ordering. Базово – как и в каком порядке будут идти обращения от CPU к памяти. Что становится критически важно, когда у нас появляется multi-threading.

Базово, у нас может быть несколько видов memory ordering:
- memory_order_relaxed – Relaxed operation: there are no synchronization or ordering constraints imposed on other reads or writes, only this operation's atomicity is guaranteed
- memory_order_release – A store operation with this memory order performs the release operation: no reads or writes in the current thread can be reordered after this store. All writes in the current thread are visible in other threads that acquire the same atomic variable and writes that carry a dependency into the atomic variable become visible in other threads that consume the same atomic

Полный референс.

__atomic_store_n(&x->ob_item[0], &first, __ATOMIC_RELEASE) будет скомпилировано в


lea rdx, [rsp+12]
mov QWORD PTR [rax], rdx


__atomic_store_n(&x->ob_item[0], &first, __ATOMIC_RELAXED) скомпилируется в


mov rax, QWORD PTR [rbx]
mov QWORD PTR [rax], rdx


Как можно увидеть: в первом случае происходит непосредственное вычисление адреса rsp+12 инструкцией lea. А во втором случае – мы просто работаем со значением в регистре rbx.

Полный пример на godbolt. Тема для меня новая, продолжаю изучать.

Обсуждение: а вы думали, что nogil – оно просто?

| Поддержать | YouTube | GitHub | Чат |
GitHub gh-129643: Fix `PyList_Insert` in free-threading builds by sobolevn · Pull Request #129680 · python/cpython Addressing @colesbury's comment here: #129643 (comment) Issue: PyList_SetItem missing atomic store #129643
  • 🤯 93
  • 👍 34
  • 🔥 12
  • ❤ 5
More from @opensource_findings
  1. Sep 28, 2026Еще анонсы докладов на бесплатную конференцию 17 октября в НН Регистрация: https://itgorky…
  2. Sep 25, 2026Монадические выражения в Python. Наконец-то! Продолжаем разговор про интересные PEPы. Пого…
  3. Sep 15, 2026PEPы в Python окончательно вышли из-под контроля Давайте посмотрим, что происходит с ПЕПам…
  4. Sep 10, 2026Большая бесплатная конференция в Нижнем Новгороде 17 октября Регистрация: https://itgorky.…
  5. Sep 1, 2026Post #985
  6. Aug 24, 2026JIT могут удалить из CPython! PEP-836: https://peps.python.org/pep-0836 JIT в CPython имее…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →