5 điểm bởi GN⁺ 2025-05-17 | 1 bình luận | Chia sẻ qua WhatsApp
  • Python free-threaded được thiết kế để tận dụng hiệu quả phần cứng đa lõi
  • Trong CPython 3.14, độ an toàn luồng và hiệu năng của các mô-đun cốt lõi đã được cải thiện đáng kể
  • Vẫn còn nhiều gói quan trọng chưa hỗ trợ bản dựng free-threaded
  • Bất kỳ ai cũng có thể cùng thúc đẩy sự phát triển này thông qua báo cáo từ môi trường sử dụng thực tế và đóng góp cho cộng đồng

Tổng quan

Tuần trước, CPython 3.14.0b1 đã được công bố, và tuần này PyCon 2025 bắt đầu tại Pittsburgh
Hai sự kiện này là những cột mốc quan trọng đối với việc phát hành và ổn định hóa Python free-threaded
Bài viết này nhìn lại chặng đường trong một năm qua, đồng thời giải thích cách đội ngũ Quansight đã đóng vai trò then chốt trong việc thử nghiệm áp dụng bản dựng free-threaded vào các quy trình sản xuất thực tế với phụ thuộc phức tạp

Ý nghĩa và sự cần thiết của Python free-threaded

  • Hỗ trợ Python free-threaded cho phép khai thác toàn bộ tài nguyên tính toán của phần cứng hiện đại, nơi CPU và GPU đa lõi đã trở nên phổ biến
  • Với cách tiếp cận GIL (Global Interpreter Lock) truyền thống, muốn tận dụng đầy đủ các thuật toán song song thì cần các cách lách và tinh chỉnh riêng
  • Thông thường người ta dùng multiprocessing thay vì mô-đun threading, nhưng cách này có chi phí tạo tiến trình lớn và việc sao chép dữ liệu cũng kém hiệu quả
  • Với các gói Python có chứa mã native, bản dựng free-threaded không thể tương thích ngay, nên bắt buộc phải rà soát mã để đảm bảo an toàn luồng
  • Việc gỡ bỏ GIL đòi hỏi những thay đổi cấu trúc sâu trong trình thông dịch CPython, đồng thời cũng làm lộ ra các vấn đề cấu trúc trong những gói hiện có

Các thành quả chính

  • Cùng với đội ngũ Python runtime của Meta, họ đã đóng góp hỗ trợ Python free-threaded cho nhiều gói và dự án như sau
    • Công cụ đóng gói và workflow như meson, meson-python, setup-python GitHub Actions, packaging, pip, setuptools
    • Trình tạo binding như Cython, pybind11, f2py, PyO3
    • Các gói cốt lõi của hệ sinh thái PyData như NumPy, SciPy, PyArrow, Matplotlib, pandas, scikit-learn, scikit-image
    • Các phụ thuộc quan trọng có lượt tải cao trên PyPI như Pillow, PyYAML, yarl, multidict, frozenlist
  • Các gói phổ biến chưa hỗ trợ như CFFI, cryptography, PyNaCl, aiohttp, SQLAlchemy, grpcio cùng các thư viện machine learning như safetensors, tokenizers cũng đang được xử lý dần
  • Các nhà phát triển lõi CPython trong đội Quansight đã đưa các cải tiến sau vào phiên bản 3.14
    • Mô-đun warnings giờ mặc định hoạt động an toàn luồng trong bản dựng free-threaded
    • Cải thiện các vấn đề nghiêm trọng về an toàn luồng của asyncio và tăng khả năng mở rộng song song
    • Cải thiện toàn diện về an toàn luồng trong mô-đun ctypes
    • Tăng hiệu năng của garbage collector free-threaded
    • Tối ưu hóa cơ chế deferred reference countingadaptive specializing interpreter
    • Sửa nhiều lỗi và bổ sung an toàn luồng trên diện rộng
  • Họ cũng đã viết một hướng dẫn toàn diện1 cho việc hỗ trợ Python free-threaded, cung cấp tài liệu tham khảo thực tiễn để nhiều gói hơn có thể áp dụng trong tương lai

Hiện trạng hệ sinh thái Python free-threaded

  • Một năm trước, vào thời điểm phát hành 3.13.0b1, việc cài đặt phần lớn các gói Python trên bản dựng free-threaded gần như hỏng hoàn toàn
  • Nguyên nhân khiến quá trình build thất bại không phải là vấn đề nền tảng, mà chủ yếu do các tùy chọn mặc định chưa được hỗ trợ hoặc những giả định nhỏ bị phá vỡ
  • Trong một năm qua, họ đã phối hợp với cộng đồng để giải quyết nhiều vấn đề, và đặc biệt Cython 3.1.0 hỗ trợ chính thức đã trở thành bước ngoặt lớn
  • Vẫn còn các gói có chứa mã biên dịch nhưng chưa cung cấp wheel free-threaded
    Có thể theo dõi tiến độ của chúng trong các bảng theo dõi thủ công và tự động2

Các thách thức trước mắt

  • Hiện tại, bản dựng Python free-threaded đang ở giai đoạn cần được thử nghiệm và nhận phản hồi trong các workflow thực tế
  • Những workflow mà chi phí dùng multiprocessing cao có thể đặc biệt được cải thiện hiệu năng, nhưng việc rà soát độ ổn định luồng chi tiết cho từng gói là bắt buộc
  • Nhiều thư viện cung cấp cấu trúc dữ liệu có thể thay đổi, nhưng tài liệu về an toàn luồng hoặc bảo đảm an toàn thực tế vẫn còn thiếu
  • Với các gói lớn và có nhiều di sản, thường thiếu người có thể nắm đầy đủ mã nguồn, khiến việc hỗ trợ bị chậm lại
  • Ở cấp độ cộng đồng, cần có nỗ lực nhằm bảo đảm tính bền vững trong việc duy trì các gói cốt lõi

Cách đóng góp

  • Có thể tham khảo hướng dẫn đóng góp trong hướng dẫn chính thức
  • Việc theo dõi các vấn đề của toàn hệ sinh thái và các tài liệu tương thích quan trọng được quản lý trong kho free-threaded-compatibility5
  • Có thể tham gia thảo luận và đóng góp qua Discord cộng đồng do Quansight-Labs tổ chức6

Thông tin về bài nói sắp tới tại PyCon

  • Tác giả bài viết và thành viên nhóm Lysandros Nikolaou sẽ thuyết trình tại PyCon 2025
  • Họ dự định chia sẻ các ví dụ porting thực tế và kinh nghiệm rút ra từ quá trình triển khai, đồng thời cũng sẽ cung cấp video ghi hình trên YouTube
  • Họ tin rằng bản dựng free-threaded là tương lai của ngôn ngữ Python và rất kỳ vọng được góp phần biến điều đó thành hiện thực
  • Họ hy vọng những nỗ lực hôm nay sẽ trở thành bước ngoặt mở ra tương lai cho hệ sinh thái gói phong phú và đồ sộ mà hàng triệu lập trình viên sử dụng mỗi ngày

1 bình luận

 
GN⁺ 2025-05-17
Ý kiến trên Hacker News
  • Nhiều người dùng multiprocessing, và có nhắc đến việc chi phí tạo process là khá đắt

    • Có tính năng SharedMemory, nhưng không hiểu vì sao nó không được dùng thường xuyên hơn

    • Nhấn mạnh rằng trải nghiệm dùng ShareableList là rất tốt

    • Trên Unix, tốc độ tạo process ở mức dưới 1ms

      • Nhưng việc khởi động process thông dịch PYTHON có thể mất 30ms~300ms tùy số lượng import
      • Vì chênh lệch là 1 đến 2 bậc độ lớn nên số liệu chính xác rất quan trọng
      • CGI là ngoại lệ ở điểm này, còn với C·Rust·Go thì không thành vấn đề
      • Chia sẻ ví dụ sqlite.org cũng đang dùng cách mỗi request là một process riêng
    • ShareableList chỉ có thể chia sẻ scalar nguyên tử và bytes·chuỗi

      • Các object có cấu trúc của Python phát sinh chi phí tuần tự hóa như pickle dump và chi phí bộ nhớ do bản sao theo từng process
    • Đã có trải nghiệm rất thành công khi chia sẻ mảng numpy

      • Cách chia sẻ tường minh không phải là gánh nặng nếu so với độ khó debug các vấn đề do vô tình chia sẻ giữa các thread
      • Nhiều người đang đánh giá quá cao việc thread tốt hơn multiprocessing đến mức nào
      • Lo rằng khi GIL được gỡ bỏ thì việc debug các segfault ngẫu nhiên sẽ tăng lên
      • Nhắc đến việc mọi người cũng không phàn nàn quá nhiều về chuyện JavaScript không hỗ trợ threading dựa trên shared memory
      • Cách hiểu là JavaScript đủ nhanh nên ít cần điều đó hơn
      • Mong muốn cần có nhiều nỗ lực hơn để cải thiện hiệu năng cơ bản của Python
    • Vì process chết độc lập, nên nếu một process chết trong lúc đang sửa cấu trúc dữ liệu shared memory khi vẫn giữ lock thì rất khó phục hồi

      • Nêu ví dụ về cấu trúc shared memory của Postgres và việc phải kết thúc toàn bộ backend process
      • Với thread thì chúng chết cùng nhau nên người ta ít nhận thức được loại vấn đề này hơn
    • Shared memory chỉ hoạt động trên phần cứng chuyên dụng

      • Trong môi trường như AWS Fargate thì không có shared memory, phải dùng network hoặc filesystem nên độ trễ tăng lên
      • Cách nhân bản process bằng fork lại là một vấn đề khác
      • Theo kinh nghiệm thực tế, green thread và mô hình actor hiệu quả hơn nhiều
  • Tò mò liệu việc loại bỏ GIL có tác động nào khác đến mã Python đa luồng ngoài xử lý song song hay không

    • Hiểu rằng lý do GIL được giữ lại không phải vì multithread phụ thuộc vào GIL, mà vì việc bỏ GIL khiến việc triển khai interpreter và C extension phức tạp hơn, đồng thời làm chậm mã đơn luồng

    • Tò mò liệu Free-threaded Python có vẫn giữ bảo đảm cũ là có thể bị preempt ở bất kỳ ranh giới bytecode nào hay không

    • Hay là phải dùng nhiều lock hơn và cách viết cũng thay đổi theo

    • Free-threaded Python vẫn giữ hầu hết các bảo đảm như cũ

      • Tuy nhiên, khi chưa có free-threading thì người ta ít dùng threading hơn, nên các bug do bị preempt ở ranh giới này trên thực tế ít lộ ra
      • Khi đưa vào free-threading thì sẽ lộ ra nhiều bug hơn
      • Không còn cần dùng các cách lách bằng multiprocess nên mã người dùng sẽ đơn giản hơn; họ cho rằng cái giá là interpreter phức tạp hơn là hoàn toàn xứng đáng
      • Vấn đề làm C extension phức tạp hơn còn nghiêm trọng với sub-interpreter hơn là free-threading; đội ngũ numpy đã nói rõ họ không thể hỗ trợ sub-interpreter
      • numpy đã hỗ trợ free-threading, hiện chỉ còn sửa các bug còn lại
      • Việc tốc độ đơn luồng chậm đi một chút (mức một chữ số %) là trade-off có thể chấp nhận
    • Có thể tận dụng đa lõi, nhưng hiệu năng trên mỗi thread giảm và thư viện cần được làm lại

      • Khi thử với PyTorch, có người thấy dùng CPU gấp 10 lần nhưng thông lượng công việc chỉ bằng một nửa
      • Hy vọng sẽ được cải thiện theo thời gian, và rất vui vì đã chờ điều này suốt 20 năm
    • Race condition có thể xảy ra thường xuyên hơn, nên cần cẩn thận hơn khi viết Python đa luồng để đảm bảo độ tin cậy

  • Có tin Microsoft đã giải tán đội Faster Python

    • Vì không đạt dự báo kết quả kinh doanh năm 2025 nên đội không được duy trì

    • Sẽ theo dõi xem sau này CPython còn được bổ sung cải thiện hiệu năng nữa hay không, hoặc có công ty khác tài trợ hay không

    • Có vẻ Facebook (Meta) vẫn còn tài trợ một phần

    • Có nhắc đến việc tiến độ đã chậm rất nhiều so với cam kết của Microsoft

      • Gần đây hẳn họ đã biết các vấn đề nghiêm trọng về chính trị và quản trị; có ý kiến rằng nhân viên giỏi sẽ không muốn đóng góp vô ích rồi bị cả nhóm công kích
      • Chỉ trích tổ chức CPython là hứa quá nhiều, dồn việc cho phe thuận theo và đẩy những người phản biện giỏi ra ngoài
      • Trước đây không có những vấn đề như vậy, còn hiện tại là tự chuốc lấy
    • Dù kết quả này đáng tiếc, nhưng cũng nhắc rằng dự đoán của bản thân về việc không tin vào cam kết dài hạn của Microsoft đã đúng

    • Có tin đồn gần đây Google cũng dường như đã sa thải toàn bộ đội phát triển Python

      • Tò mò liệu cả hai có cùng chịu tác động thời thế hay có điểm chung nào không
    • Rất đáng tiếc, nhưng sắc thái là sau embrace & extend thì chỉ còn lại một bước cuối

  • Tò mò liệu có phải chỉ mình họ lo lắng về việc GIL biến mất khỏi Python hay không

    • Với bất kỳ ngôn ngữ nào, mã đa luồng phức tạp đều khó đáng tin cậy, và Python với tính động của nó còn khiến người ta thấy bất an hơn

    • Không phải chỉ một mình lo sợ trước thay đổi, dù cơ sở cho nỗi lo có thể là phi lý

      • GIL là technical debt thuần túy, nên cần loại bỏ vì lợi ích của cộng đồng
      • Dạo này trong Python, đa số dùng non-blocking IO và async thay cho thread
      • Nếu không dùng thread thì việc bỏ GIL không gây thay đổi gì; các thư viện C cũng an toàn ở chế độ đơn luồng
      • Chỉ cần cẩn thận nếu thực sự dùng thread
      • Mã Python thread ngây thơ trước đây bị GIL chặn nên hoạt động như đơn luồng, giờ có thể nhanh hơn một chút nhưng bug cũng có thể tăng lên
      • Giải pháp là либо không dùng thread, либо nếu dùng thì hãy học cho đúng cách
      • Sau này có lẽ sẽ có những abstraction tốt hơn, và mong cộng đồng sẽ bàn thêm về structured concurrency chẳng hạn
    • Bản thân đang tích cực dùng asyncio

      • Dù là đơn luồng nhưng vẫn có thể viết Python concurrent một cách thoải mái; dùng kiểu như Node.js
      • Với công việc web·network thì khuyến nghị cách này
    • Dự đoán trong lĩnh vực như ML/AI sẽ là cấu trúc mà chuyên gia làm trước các thư viện phức tạp rồi chuyển giao cho người dùng phổ thông

      • Có ngày càng nhiều trường hợp GIL của Python trở thành nút thắt cổ chai nghiêm trọng
      • Vì vậy đã đi học ngôn ngữ Go; có thể xem là hỗ trợ thread đúng nghĩa, ở mức thấp hơn Python nhưng trừu tượng hơn C/C++
      • Mô hình compiler cũng là bối cảnh quan trọng không kém threading
    • Có thể là đang gieo lo lắng không cần thiết, nhưng cũng nhắc lại rằng LLM đã được huấn luyện trên mã Python của vài chục năm qua dưới giả định GIL tồn tại

    • Có hay không có GIL chỉ liên quan đến những ai muốn chạy công việc đa lõi

      • Nếu hiện tại vẫn không quan tâm đến threading·multiprocessing thì thực tế không có thay đổi gì
      • Vấn đề race condition xảy ra bất kể có GIL hay không
  • Thường xuyên dùng Python nhưng không phải chuyên gia, thỉnh thoảng chỉ chạy đồng thời vài hàm đơn giản bằng concurrent.futures

    • Tò mò kiểu người dùng này về sau cần thay đổi điều gì

    • Thread không còn bị trói bởi GIL nên nhìn chung sẽ nhanh hơn

      • Nếu đã xử lý lock cho object dùng chung một cách đúng đắn thì không cần lo gì thêm
  • Chia sẻ cảm nhận từ 20 năm làm lập trình chuyên nghiệp với Python

    • Khi thật sự cần thread thì thường chỉ giới hạn ở các trường hợp không thể tránh message passing

      • Hệ sinh thái Python đã có cách lách cho tất cả những tình huống như vậy
      • Vì đủ loại cạm bẫy khi xử lý nhiều thread (như lock), nên sau này có thể chỉ còn cần ở một số thư viện·domain cụ thể
      • Nếu muốn vắt tối đa hiệu năng chỉ bằng Python thuần, có thể tận dụng thư viện dựa trên native code (ví dụ: Pypy, numba)
      • Bước đột phá hiệu năng của Python rốt cuộc là lập trình async; rất khuyên nên học
    • Cũng đã dùng Python lâu gần như vậy và đồng ý, nhưng diễn đạt hơi khác

      • Vì thread trong Python quá tệ nên đã phát triển nhiều cách lách để tránh nó
      • Từng muốn tăng gấp đôi tốc độ tác vụ CPU-bound bằng thread nhưng vướng GIL, rồi chuyển sang multiprocessing; phát sinh chi phí do tuần tự hóa cấu trúc dữ liệu, kiểu dùng gấp đôi số lõi mà chỉ nhanh 1,5 lần là trải nghiệm kém hiệu quả
      • Nếu có hỗ trợ thread tốt thì có rất nhiều môi trường muốn tận dụng; vì từ trước đến nay không có nên mới phải dùng đủ loại cách tiếp cận thay thế
      • Nếu phù hợp với bài toán thì rất khuyên dùng async (glyph, bạn đã đúng!)
  • Dù là ảnh AI, nhưng thấy lạ vì con rắn lại được vẽ với hai cái đuôi

    • Có ý kiến phụ họa là cứ lặng lẽ bỏ qua; đùa rằng hễ bài về Python mà chèn hình con rắn thì thường đó là tín hiệu không đáng để bận tâm lắm

    • Đề xuất tên đùa là Confusoborus

  • Chỉ ra rằng con rắn trong ảnh header trông như có hai cái đuôi

    • Đùa rằng có vẻ như nó đã tạo ra thread thứ hai trong cùng một process
  • Ngoài hỗ trợ thư viện ra, tò mò liệu có ràng buộc nào khác khi chạy WSGI và worker Celery trong một process đơn hay không

    • Không có ràng buộc gì, chỉ là cách đó không phải tính năng hạng nhất của ngôn ngữ
      • Giải thích rằng GIL là vấn đề technical debt
      • Ngoài tính song song ra còn có những yếu tố khác cũng đòi hỏi phải gỡ GIL
  • Cho rằng đây là một công việc nền tảng cực lớn cho kỷ nguyên hiệu năng sắp tới