1 điểm bởi GN⁺ 2024-05-18 | 1 bình luận | Chia sẻ qua WhatsApp
  • Bend là một ngôn ngữ lập trình song song bậc cao, hướng tới việc kết hợp sức biểu đạt như Python·Haskell với khả năng thực thi song song quy mô lớn kiểu CUDA, và chạy trên runtime HVM2
  • Hỗ trợ hàm bậc cao có closure, cấp phát đối tượng nhanh, đệ quy không giới hạn, continuation, nhưng vẫn chạy trên phần cứng song song như GPU mà không cần ký hiệu song song hóa tường minh như tạo thread, lock, mutex hay atomic
  • Mục tiêu thiết kế hiện tại là khả năng mở rộng hiệu năng theo số lượng lõi, hỗ trợ hơn 10.000 thread đồng thời, nhưng phiên bản hiện tại có thể có hiệu năng đơn lõi thấp và việc cải thiện sinh mã·tối ưu hóa vẫn đang tiếp tục
  • Cách chạy được chia thành bend run-rs, bend run-c, bend run-cu; với mã có thể song song hóa, chỉ cần đổi lệnh chạy là có thể thực thi song song trên trình thông dịch C hoặc trình thông dịch CUDA
  • Hỗ trợ Windows vẫn đang được phát triển nên WSL2 là giải pháp thay thế, và hiện tại việc chạy trên GPU chỉ hỗ trợ NVIDIA GPU

Mô hình lập trình mà Bend hướng tới

  • Bend là một ngôn ngữ lập trình chạy trên phần cứng song song quy mô lớn trong khi vẫn giữ được trải nghiệm của ngôn ngữ bậc cao
  • Cung cấp các tính năng của những ngôn ngữ giàu sức biểu đạt như Python và Haskell
    • Cấp phát đối tượng nhanh
    • Hàm bậc cao có closure
    • Đệ quy không giới hạn
    • Continuation
  • Chạy trên phần cứng song song quy mô lớn như GPU giống CUDA, với mục tiêu tăng tốc gần tuyến tính dựa trên số lượng lõi
  • Không cần phải tự viết các phần sau để chạy song song
    • Tạo thread
    • Lock
    • Mutex
    • Atomic
  • Runtime sử dụng HVM2

Các giới hạn và lưu ý hiện tại

  • Bend tập trung vào việc mở rộng hiệu năng theo số lượng lõi, và được thiết kế để hỗ trợ hơn 10.000 thread đồng thời
  • Phiên bản hiện tại có thể có hiệu năng đơn lõi thấp
  • Hiệu năng được kỳ vọng sẽ cải thiện khi kỹ thuật sinh mã và tối ưu hóa phát triển hơn
  • Hỗ trợ Windows vẫn đang được phát triển, và có thể dùng WSL2 như một giải pháp thay thế
  • Hỗ trợ GPU hiện tại chỉ dành cho NVIDIA GPU

Cài đặt và cách chạy

  • Cả Linux và Mac đều cần cài Rust
  • Bản C của Bend dùng GCC, và README khuyến nghị GCC 12.x trở xuống
  • Để dùng CUDA runtime, cần cài CUDA Toolkit 12.x cho Linux
  • HVM2 được cài bằng cargo install hvm, còn Bend được cài bằng cargo install bend-lang
  • Lệnh chạy chương trình Bend được chia theo từng backend thực thi
    • bend run <file.bend>: mặc định dùng trình thông dịch C, chạy song song
    • bend run-rs <file.bend>: dùng trình thông dịch Rust, chạy tuần tự
    • bend run-c <file.bend>: dùng trình thông dịch C, chạy song song
    • bend run-cu <file.bend>: dùng trình thông dịch CUDA, chạy song song quy mô lớn
  • Có thể biên dịch thành tệp C/CUDA độc lập bằng gen-cgen-cu
  • Trình sinh mã vẫn đang ở giai đoạn đầu và chưa trưởng thành như các compiler như GCC hay GHC
  • Có thể dùng cờ -s để xem số reduction, thời gian chạy và số interaction mỗi giây

Ví dụ cộng tuần tự và cộng song song

  • Ví dụ phép cộng trong README so sánh hai cách viết mã cộng các số từ start đến target
  • Phiên bản tuần tự có cấu trúc cộng start hiện tại vào kết quả của Sum(start + 1, target)
    • Phép tính tiếp theo phụ thuộc vào kết quả cộng trước đó
    • Không thể chuyển sang bước tiếp theo trước khi phép tính hiện tại kết thúc, nên không thể song song hóa
    • Ví dụ gọi Sum(1, 1_000_000), kèm chú thích rằng có thể vượt quá giá trị tối đa của kiểu số trong Bend
  • Phiên bản có thể song song hóa chia đôi phạm vi rồi tính đệ quy tổng của nửa trái và nửa phải
    • Phép tính (3 + 4) không phụ thuộc vào phép tính (1 + 2)
    • Hai phép tính có thể diễn ra đồng thời nên có thể thực thi song song
  • Trong Bend, nếu mã có thể chạy song song thì chỉ cần đổi lệnh chạy là sẽ thực thi song song

Ví dụ hiệu năng của Bitonic Sorter

  • README đưa ra bitonic sorter được triển khai bằng xoay cây bất biến như một ví dụ về tốc độ
  • Đây là kiểu thuật toán vốn không dễ được kỳ vọng sẽ chạy nhanh trên GPU, nhưng Bend dùng cách tiếp cận chia để trị để chạy trên nhiều thread
  • Không cần tạo thread hay quản lý lock một cách tường minh
  • Kết quả benchmark như sau
    • bend run-rs: CPU, Apple M3 Max, 12.15 giây
    • bend run-c: CPU, Apple M3 Max, 0.96 giây
    • bend run-cu: GPU, NVIDIA RTX 4090, 0.21 giây
  • Có thể xem các thuật toán khác trong examples folder

Tài liệu tham khảo

  • Công nghệ nền tảng của Bend có thể xem trong paper về HVM2
  • Tài liệu chính thức vẫn đang được hoàn thiện, và phần giải thích sâu hơn có trong GUIDE.md
  • Danh sách tính năng có trong FEATURES.md
  • Bend được phát triển bởi HigherOrderCO

1 bình luận

 
GN⁺ 2024-05-18
Ý kiến trên Hacker News
  • Tôi thử chuyển ví dụ sum sang Python thuần thì với pypy3 mất 4,478 giây trên một luồng, còn Python 3.12 mất 1 phút 42,148 giây.
    Trong khi đó, phiên bản Bend một luồng đã chạy đến phút thứ 42 trên laptop của tôi, dùng 6GB bộ nhớ mà vẫn chưa kết thúc. Môi trường là 12th Gen Intel(R) Core(TM) i7-1270P, Ubuntu 24.04.
    Nếu chậm như vậy ở một ví dụ rất đơn giản thì khó kỳ vọng gì ở các tác vụ phức tạp, và tôi tò mò liệu nó đã được kiểm thử hay phát triển trên môi trường ngoài Mac/aarch64 chưa. Sau này tôi định chạy lại với tham số -s.

    • Chạy suốt 42 phút rất có khả năng là bug. Chúng tôi chưa kiểm thử nhiều trên môi trường ngoài M3 Max, và cũng biết rằng trên CPU không phải của Apple thì chậm hơn 2 lần, nên sẽ cải thiện.
      Trong ví dụ sum, Bend chịu bất lợi lớn là cấp phát 2 nút IC cho mỗi phép toán số, còn Python thì không. Chúng tôi dự định sớm tránh được điều này như HVM1, nhưng HVM2 hiện chưa triển khai.
      Phần lớn công việc với Bend đã dành cho việc làm cho bộ đánh giá song song hoạt động đúng, và việc chạy closure cùng đệ quy không giới hạn trên GPU là cực kỳ khó. Vì chúng tôi vừa mới hoàn tất phần đó nên gần như chưa đầu tư vào tối ưu vi mô, và phần sinh mã của HVM2 hiện vẫn còn rất tệ.
      Nếu so với các ví dụ như Bitonic Sort, nơi hai bên cấp phát lượng tương đương nhau, có thể sẽ thấy hiệu năng thực tế một cách công bằng hơn. HVM1 trên một lõi chậm hơn GHC khoảng 3 lần, và tôi nghĩ HVM2 cũng sẽ sớm đạt đến mức đó.
      Tôi hiểu rằng câu “hiện còn tệ nhưng sẽ tốt lên” có thể làm cụt hứng. Dù vậy, nền tảng đã xong, nên tối ưu vi mô là phần dễ nhất, và tôi tin hiệu năng sẽ tăng mạnh từ đây.
    • Tôi không có lợi ích liên quan trong cuộc tranh luận này, nhưng đệ quy gần với việc kiểm tra mức hiệu quả của compiler/interpreter khi tạo và hủy call stack hơn là kiểm tra hiệu năng tính toán.
      Ngôn ngữ này nhắm tới các ứng dụng GPU nặng về tính toán và vẫn đang ở giai đoạn đầu. Đệ quy không phải ứng dụng mục tiêu, và tôi nghĩ khó xem đây là benchmark phù hợp.
    • Thread trên GPU và CPU có ý nghĩa khác nhau; trên GPU nó gần với SIMD lane hơn.
      Nó giống việc ISPC có thể biên dịch để thực thi đồng thời 32 lời gọi hàm cho mỗi thread CPU. Ví dụ, nếu dùng dữ liệu 16-bit trên AVX512, có thể có 32 lõi × 2 SMT thread mỗi lõi × 32 thực thi do compiler tạo ra = 2048 thực thi diễn ra đồng thời.
    • Python rất yếu ở đệ quy, đó là một trong những lý do nó không phù hợp với lập trình hàm, nên đây có thể không phải benchmark công bằng.
      Một cách triển khai kiểu Python có lẽ sẽ dùng vòng lặp và trạng thái có thể thay đổi.
    • Tôi không hiểu vì sao cần +0. Chẳng phải đó là phép toán không làm gì sao?
  • Có nhiều phản ứng tiêu cực trong thread này, nhưng chỉ riêng việc làm được đến mức này cũng khiến tôi muốn gửi kudos tới tác giả.
    Trong các dự án tương tự, tôi chỉ biết đến Futhark, nhưng vì cú pháp kiểu Haskell nên có thể khá khó hiểu với lập trình viên phổ thông quen C/C++/Python/JS/Java, v.v.
    Điều đáng tiếc nhất là khác với Futhark, nó chỉ nhắm tới CUDA hoặc multicore. Futhark có thể nhắm tới OpenCL, CUDA, ISPC, HIP, CPU một lõi, CPU đa lõi. Tôi nghĩ các vấn đề hiệu năng mà người khác chỉ ra hoàn toàn có thể giải quyết được.

    • ILGPU cũng đáng xem thử. Nó đã có từ lâu và khá tốt, nhưng tiếc là không được biết đến nhiều.
      Ví dụ ngắn: https://github.com/m4rs-mt/ILGPU/blob/master/Samples/SimpleM...
      Nó cũng hỗ trợ các tính năng nâng cao như inline PTX assembly: https://github.com/m4rs-mt/ILGPU/blob/master/Samples/InlineP...
    • Chapel được dùng khá nhiều trong tính toán hiệu năng cao.
      NVIDIA cũng đã tài trợ các biến thể Haskell, .NET, Java, Julia trên CUDA, có cả Python JIT, và họ cũng đang hợp tác với phía Mojo.
    • ParaSail cũng là một ngôn ngữ đi theo hướng này: https://github.com/parasail-lang/parasail
      Nó được tạo ra bởi Tucker Taft, người tham gia thiết kế Ada từ năm 1995, và một số tính năng song song của ParaSail đã được đưa vào Ada 2022.
  • OP mang đến một trong những thứ hay nhất gần đây trên HN, nên tôi thấy tiếc khi có vẻ chỉ nhận toàn những lời phê bình dài, dù rõ ràng đây vẫn là phiên bản sơ khai.

    • HN gần giống một cộng đồng muốn đăng những thứ mới hoặc độc đáo. Khi ai đó muốn khen, họ thường bấm upvote một bình luận đã có hơn là viết thêm một bình luận “tuyệt quá” khác.
      Ngược lại, cách phê bình đúng thì có giới hạn, còn cách sai thì rất nhiều, nên phê bình có thể đa dạng vô tận. Vì vậy chỉ có vài bình luận tích cực, còn đa số trông như phê bình hoặc “giá mà cũng làm cái này”. Đây không hẳn là lỗi của cá nhân nào, mà gần với văn hóa kỹ sư ngày nay.
    • Nếu đó là dự án của tôi, tôi sẽ khá biết ơn khi mọi người phê bình. Nhờ vậy mới phát triển được.
      Nếu người ta chỉ giấu những sự thật phũ phàng sau tràng pháo tay thì thế giới sẽ sụp đổ.
    • Nó đã nhận 905 upvote, nên có thể nói phản ứng tích cực cũng đủ nhiều rồi.
      Phê bình cũng có nghĩa là người ta quan tâm và tham gia vào ý tưởng cũng như cách tiếp cận, nên thường là một tín hiệu tích cực.
    • Không phê bình các dự án mới mẻ và tham vọng là một chuẩn mực xã hội tốt. Những nỗ lực như vậy nên được khuyến khích và không nên bị làm nản lòng.
      Nhưng phê bình các dự án đưa ra tuyên bố dễ gây hiểu lầm, thiếu căn cứ hoặc sai sự thật cũng là một chuẩn mực xã hội tốt. Vì nó khiến những tuyên bố như vậy giảm đi.
    • Những thứ tuyệt nhất thường cũng là những thứ khó hiểu nhất.
      Thứ khó hiểu thường tạo cảm giác bị đe dọa, và phê bình là phản ứng phổ biến trước mối đe dọa, cũng là cách đáp lại cần ít hiểu biết nhất.
  • Trang chủ được làm thật sự rất tốt. Nhìn vào là thấy rõ ngay nó làm gì
    Những người làm về “combinator” thường hay muốn dùng rất nhiều thuật ngữ chuyên môn đáng sợ, nhưng OP thực sự cho thấy ý tưởng đơn giản đằng sau công cụ. Mình thích vì nó trái ngược với kiểu tiếp cận học thuật: cho xem đến từng chi tiết cuối cùng nhưng lại không nói rốt cuộc chuyện gì đang diễn ra. Cần có nhiều cách làm như thế này hơn

  • Về lý thuyết thì rất hay và mình cũng hiểu đề xuất giá trị, nhưng nói thật là mình không nghĩ thứ này sẽ trở thành một công cụ có liên quan trong thực tế
    Đây là ghi chú sau ấn tượng ban đầu và sau khi lướt qua bài báo. Mình biết đây là phần mềm ở giai đoạn rất sớm
    Bend trông giống một DSL rất hạn chế. Không có FFI, không có cách tương tác với buffer nguyên thủy, và định dạng số thực dấu phẩy động 24-bit cũng kỳ lạ
    Có lý do khiến IC không trở thành xu hướng chủ đạo. Hiệu năng nhiều khả năng sẽ tiếp tục tệ, và việc duyệt đồ thị không hợp với phần cứng
    Giả định về optimal reduction là hợp lệ, nhưng rốt cuộc bạn vẫn phải viết kernel theo cách có thể song song hóa. Tức là không được có phụ thuộc dữ liệu và cũng phải tính đến việc dùng đệ quy
    Không có ví dụ nghiêm túc nào so sánh trực tiếp mã Bend/HVM với chương trình OMP/CUDA tương đương. Rất khó đánh giá độ phức tạp triển khai giảm được bao nhiêu và hiệu năng ở mức nào
    Trong tính toán song song hiệu năng cao ngoài đời thực, cấu trúc dạng cây hầu như không có, và mảng mới là vua. Đó là do các đặc tính vật lý của cách bộ nhớ hoạt động ở cấp phần cứng. Thứ phù hợp nhất với buffer bộ nhớ liên tục có thể thay đổi là vòng lặp. Nếu HVM triển khai được điều này thì mình sẽ theo dõi
    Hiện tại nó gần như bị cô lập hoàn toàn với dữ liệu bên ngoài, rất chậm, và trông như một ngôn ngữ còn nửa vời đặt một lớp trừu tượng khổng lồ lên trên phần cứng. Nó cũng không tận dụng được các tính năng như cache nhiều tầng, tensor core, SIMD, thao tác nguyên tử
    Xin lỗi nếu nghe hơi gay gắt, nhưng mình vẫn thấy phần triển khai kỹ thuật và nền tảng lý thuyết rất thú vị. Chỉ là mình vẫn chưa bị thuyết phục về tính hữu dụng của nó trong thế giới thực

    • Cảm ơn phản hồi. Đính chính vài điểm: chúng tôi có dùng cache nhiều tầng, và nếu dùng đúng có thể đạt hiệu năng cao hơn 5 lần
      FFI đã được triển khai rồi nhưng chưa công bố. Lý do là chúng tôi muốn ra mắt nó cùng với phần render đồ họa, và mình nghĩ nó sẽ khá ấn tượng
      Haskell/GHC cũng dùng đồ thị và cây, nhưng không ai nói nó không thực dụng. Đúng là mảng là vua, nhưng rất nhiều thuật toán hiện đại không hợp với mảng, như compiler, type checker, solver, lại được triển khai bằng Haskell
      Lý do chính khiến IC chưa nhanh là vì chưa có ai thực sự làm tốt phần tối ưu hóa cấp thấp trên nó. Tất cả các triển khai trước đây đều cực kỳ kém hiệu quả, và công việc của mình đến nay cũng chủ yếu dành thời gian để khiến nó chạy đúng trên GPU
      Như chuyện hiện còn chưa có vòng lặp, lời giải chỉ đơn giản là thêm vòng lặp. Nếu bạn nghĩ ở đó có một giới hạn mang tính bản chất, có lẽ bạn sẽ ngạc nhiên
      HVM2 cuối cùng đã trở thành một thuật toán đúng và có thể mở rộng, và giờ là lúc tối ưu hiệu năng cấp thấp thực sự
    • Về điểm 5, cây tuy khác với cách triển khai kiểu khoa học máy tính thông thường nhưng được dùng khá rộng rãi
      Trong các thuật toán Fast Multipole hoặc Barnes-Hut, người ta dùng thứ tự Morton hoặc thứ tự H-index để giảm các phép tính từng cặp O(n²) xuống lần lượt còn O(n), O(n log n). Barnes-Hut phổ biến hơn trong vật lý thiên văn, còn Fast Multipole thường thấy hơn trong động lực học phân tử hóa học
  • 10 năm trước mình đã học 15-210, môn thuật toán song song ở CMU. Môn học giải thích rằng khi định luật Moore chạm giới hạn, tính song song sẽ là tương lai của điện toán, và điều đó thuyết phục mình muốn thử nghiệm
    Nhưng không có nhiều lựa chọn lập trình song song đa dụng. Ngay cả SML dùng trong lớp cũng không song song, và ở cuối có một phần dùng extension và CUDA, nhưng theo mình nhớ thì khá hạn chế
    Sau đó nhờ Rust mình đã thử nghiệm được một chút với multithreading, và nhờ Shadertoy mình có thể làm các việc sáng tạo bằng shader. Nhưng một ngôn ngữ song song đa dụng trên GPU thì mình rất háo hức được tự tay thử

    • Ngày nay 210 thực sự là song song. Dùng MaPLe(https://github.com/MPLLang/mpl) thì có thể chạy mã kiểu 210 và đạt hiệu năng cạnh tranh với C/C++
      Nếu bạn thích 210, có thể bạn cũng sẽ thích https://futhark-lang.org/. Đây là ngôn ngữ thuộc họ ML, biên dịch xuống GPU và có hiệu năng tốt
    • Xu hướng máy móc chuyển sang đa nhân là một trong những lý do mình quyết định học Elixir
  • Ý tưởng rất hay, nhưng nếu mình không bỏ sót gì thì nó trông rất chậm
    Mình viết một vòng lặp đơn giản bằng C++ để cộng từ 0 đến 2³⁰; không tối ưu, chạy đơn luồng trên laptop của mình mất 1,7 giây, tương đương hiệu năng của Bend trên RTX 4090. Thêm -O3 thì vòng lặp được vector hóa và chạy dưới 80ms

    • Bend hiện chưa có tối ưu hóa lời gọi đuôi. Nó đang cấp phát một stack dài 1 tỷ, trong khi C chỉ chạy một vòng lặp
      Nếu so với một chương trình C thực sự thực hiện cấp phát, Bend có khả năng nhanh hơn chỉ với vài thread
      Phần sinh mã của Bend hiện vẫn rất tệ, nhưng đây là những quả thấp dễ hái. Phần lớn công sức đã dồn vào việc làm cho bộ đánh giá song song rất khó kia chạy đúng
      Mình biết nghe như kiểu “hãy tin tôi”, nhưng khi bắt đầu biên dịch thủ tục, sinh vòng lặp, v.v. thì hiệu năng đơn luồng sẽ tốt hơn nhiều. Chỉ là hiện vẫn chưa làm thôi
      Thực ra mình cũng nghĩ có lẽ nên đợi thêm một chút trước khi đăng lên
    • Bạn nên kiểm tra bằng objdump xem vòng lặp có thật sự được vector hóa hay compiler đã tối ưu bỏ toàn bộ
      Vòng lặp đó gây tràn số nguyên có dấu, và trong C++ đây là hành vi không xác định. Compiler có thể hợp pháp cho ra bất kỳ kết quả nào
      Để tránh điều này, cần khai báo sumunsigned. Tràn số nguyên không dấu được định nghĩa rõ, và tối ưu hóa vẫn xảy ra nhưng ít nhất tính đúng đắn được bảo đảm
    • Khi biên dịch bằng clang với -O3, vòng lặp bị loại bỏ hoàn toàn: https://godbolt.org/z/M1rMY6qM9
      Có lẽ đây không phải là so sánh công bằng
    • Điểm mấu chốt có vẻ là Bend cấp cao hơn C++ rất nhiều
      Tất nhiên mình cũng có thể đang hiểu sai ý chính
  • Muốn chúc mừng tác giả. Đây thật sự là một công trình rất tuyệt
    Tạo ra tự động song song hóa đúng đắn không hề dễ, và bạn hoàn toàn có quyền tự hào. Mình mong chờ xem dự án sẽ phát triển ra sao

  • Tôi không hiểu vì sao lại có nhiều phản ứng tiêu cực như vậy. Trông giống như một đám đông giận dữ đang bới móc các lỗ hổng trong README, như những bot cố bẻ lái ngữ cảnh và ý định của bài viết
    Tranh cãi hàng giờ liền mà không bỏ ra nổi 2 phút để đọc cho đúng thì thật thiếu hiểu biết và tàn nhẫn. OP đã đi được đến đây với một dự án một người, nên tôi mong họ tiếp tục đẩy tới

  • Tôi đã tò mò không biết HVM2 biên dịch các interaction net sang, ví dụ như SPIR-V, hay giống HVM gốc, là một interpreter chạy trên GPU
    Trước đây tôi từng thử biên dịch interaction net sang C theo cách rút gọn chương trình càng nhiều càng tốt, nhưng không rút gọn input, và xử lý nó như tối ưu hóa toàn chương trình. Tôi nghĩ nhắm đến shader language cũng không quá khó
    Nhìn vào repository thì thấy nói rằng nó cung cấp một ngôn ngữ IR cấp thấp để chỉ định các net HVM2 và một compiler sang C/CUDA: https://github.com/HigherOrderCO/HVM
    Nhưng nhìn lại thì HVM2 CUDA runtime có vẻ giống một interpreter duyệt đồ thị trong bộ nhớ và áp dụng các bước rút gọn: https://github.com/HigherOrderCO/HVM/blob/5de3e7ed8f1fcee6f2...
    Điều tôi nói đến là một cách duyệt interaction net để khôi phục các term gần với biểu thức lambda calculus, rồi hạ xuống C theo từng mảnh nhỏ nhằm tối thiểu hóa overhead runtime
    Động cơ thực tế là Bend khó có thể đánh bại các GPU kernel viết tay trong những workload như ML. Về lý thuyết, HVM có thể đóng vai trò lớp keo ghép các kernel tính toán và song song hóa thứ tự thực thi, nhưng để làm vậy cần một FFI tốt
    Interaction net khó dịch qua ranh giới FFI, nhưng nếu đặt các node kernel tính toán FFI bên trong interaction network và biên dịch net sang C, ta có thể khôi phục một FFI hợp lý mà không có overhead dịch
    Một lựa chọn khác là triển khai HVM bằng phần cứng; tôi đang nghịch thử một chút trên FPGA còn dư

    • Nó vừa là interpreter chạy trên GPU, vừa là compiler sang C native và CUDA
      Không trực tiếp nhắm đến SPIR-V, nhưng đó là mục tiêu
      Compiler C đem lại mức tăng tốc như kỳ vọng, tức 3–4 lần và sắp tới còn hơn nữa, nhưng CUDA runtime không đạt được mức tăng tốc đáng kể so với phiên bản không biên dịch
      Tôi cho rằng nguyên nhân là warp divergence. Trong các procedure chưa biên dịch, mọi lời gọi hàm có thể được gộp vào một hàm mở rộng kiểu interpreter “đa dụng” duy nhất, và các thread trong warp có thể rút gọn mà không cần rẽ nhánh. Chúng tôi sẽ nghiên cứu sâu hơn phần này trong thời gian tới