Trình biên dịch JIT cho C, C ++ và các lượt thích


33

Có trình biên dịch đúng lúc nào cho các ngôn ngữ được biên dịch, chẳng hạn như C và C ++ không? (Những cái tên đầu tiên xuất hiện trong đầu là Clang và LLVM! Nhưng tôi không nghĩ họ hiện đang hỗ trợ nó.)

Giải trình:

Tôi nghĩ phần mềm có thể được hưởng lợi từ phản hồi cấu hình thời gian chạy và tối ưu hóa mạnh mẽ việc biên dịch lại các điểm nóng khi chạy, ngay cả đối với các ngôn ngữ được biên dịch sang máy như C và C ++.

Tối ưu hóa theo hướng dẫn hồ sơ thực hiện một công việc tương tự, nhưng với sự khác biệt, JIT sẽ linh hoạt hơn trong các môi trường khác nhau. Trong PGO, bạn chạy nhị phân của mình trước khi phát hành nó. Sau khi bạn phát hành nó, nó sẽ không sử dụng phản hồi môi trường / đầu vào được thu thập trong thời gian chạy. Vì vậy, nếu mô hình đầu vào được thay đổi, đó là thăm dò hình phạt hiệu suất. Nhưng JIT hoạt động tốt ngay cả trong điều kiện đó.

Tuy nhiên, tôi nghĩ rằng nó còn gây tranh cãi khi hiệu suất biên dịch JIT vượt trội so với chi phí hoạt động của chính nó.


1
Tài nguyên ngoài chủ đề.
DeadMG

1
Không chắc nó có phù hợp với câu hỏi không, nhưng đối với tương lai khả năng sử dụng, tôi thấy gói Cxx hữu ích trong ngôn ngữ Julia .. nó cung cấp cho bạn lời nhắc C ++ tương tác tương tự như được mô tả trong câu trả lời @ PhilippClaßen.
Antonello

GCC 9 hiện có trình biên dịch jit gcc.gnu.org/onlinesocs/jit/intro/index.html
user3071643

Câu trả lời:


33

[Xem lịch sử chỉnh sửa cho một câu trả lời hoàn toàn khác về cơ bản đã lỗi thời.]

Có, có một vài trình biên dịch JIT cho C và / hoặc C ++.

CLing (như bạn có thể đoán từ trò chơi) dựa trên Clang / LLVM. Nó hoạt động như một thông dịch viên. Đó là, bạn cung cấp cho nó một số mã nguồn, ra lệnh cho nó chạy và nó chạy. Sự nhấn mạnh ở đây chủ yếu là sự tiện lợi và biên dịch nhanh, không tối ưu hóa tối đa. Như vậy, mặc dù về mặt kỹ thuật là một câu trả lời cho chính câu hỏi, điều này thực sự không phù hợp với ý định của OP.

Một khả năng khác là NativeJIT . Điều này phù hợp với câu hỏi hơi khác nhau. Cụ thể, nó không chấp nhận mã nguồn C hoặc C ++, và biên dịch nó và thực thi nó. Thay vào đó, nó là một trình biên dịch nhỏ mà bạn có thể biên dịch vào chương trình C ++ của mình. Nó chấp nhận một biểu thức về cơ bản được biểu thị dưới dạng EDSL bên trong chương trình C ++ của bạn và tạo mã máy thực tế từ đó, sau đó bạn có thể thực thi. Điều này phù hợp hơn nhiều với một khung công tác nơi bạn có thể biên dịch hầu hết chương trình của mình với một trình biên dịch bình thường, nhưng có một vài biểu thức mà bạn sẽ không biết cho đến thời gian chạy, mà bạn muốn thực hiện với một cái gì đó đạt tốc độ thực thi tối ưu.

Đối với mục đích rõ ràng của câu hỏi ban đầu, tôi nghĩ rằng điểm cơ bản của câu trả lời ban đầu của tôi vẫn tồn tại: trong khi trình biên dịch JIT có thể thích ứng với những thứ như dữ liệu thay đổi từ lần thực hiện này sang lần thực hiện tiếp theo hoặc thậm chí thay đổi linh hoạt trong một lần thực hiện, thực tế là điều này tạo ra sự khác biệt tương đối ít nhất là một quy tắc chung. Trong hầu hết các trường hợp, chạy trình biên dịch trong thời gian chạy có nghĩa là bạn cần phải từ bỏ khá nhiều tối ưu hóa, vì vậy, điều tốt nhất bạn thường hy vọng là nó sẽ nhanh như trình biên dịch thông thường sẽ tạo ra.

Mặc dù có thể đưa ra các tình huống trong đó thông tin có sẵn cho trình biên dịch JIT có thể cho phép nó tạo mã tốt hơn đáng kể so với trình biên dịch thông thường, nhưng các trường hợp này xảy ra trong thực tế dường như khá bất thường (và trong hầu hết các trường hợp tôi đã có thể xác minh Nó xảy ra, nó thực sự là do một vấn đề trong mã nguồn, không phải với mô hình biên dịch tĩnh).


1
Tại sao JIT không lưu tệp giống như bộ đệm để họ có thể bỏ qua việc học lại mọi thứ từ đầu?
JohnMudd

3
@JohnMudd: Tôi nghi ngờ lý do là bảo mật. Ví dụ, sửa đổi mã được lưu trong bộ nhớ cache, rồi lần sau khi VM khởi động, nó sẽ thực thi mã tôi đặt ở đó thay vì những gì nó đã viết ở đó.
Jerry Coffin

4
OTOH, nếu bạn có thể sửa đổi bộ đệm, bạn cũng có thể sửa đổi các tệp nguồn.
dùng3125367

1
@ user3125367: Có, nhưng trong nhiều trường hợp, trình biên dịch thực hiện kiểm tra nhiều loại khác nhau và có thể bỏ qua nếu bạn tải mã được biên dịch trực tiếp từ bộ đệm. Tất nhiên phụ thuộc vào JIT - Java thực hiện rất nhiều công việc thực thi khi tải một tệp. Class (đã biên dịch), nhưng nhiều thứ khác làm ít hơn rất nhiều (gần như không có, trong nhiều trường hợp).
Jerry Coffin

11

Vâng, có trình biên dịch JIT cho C ++. Từ góc độ hiệu suất thuần túy, tôi nghĩ Tối ưu hóa hướng dẫn hồ sơ (PGO) vẫn vượt trội.

Tuy nhiên, điều đó không có nghĩa là việc biên dịch JIT chưa được sử dụng trong thực tế. Ví dụ: Apple sử dụng LLVM làm JIT cho đường ống OpenGL của họ. Đó là một miền nơi bạn có nhiều thông tin hơn trong thời gian chạy, có thể được sử dụng để loại bỏ rất nhiều mã chết.

Một ứng dụng thú vị khác của JIT là Cling, một trình thông dịch C ++ tương tác dựa trên LLVM và Clang: https://root.cern.ch/cling

Đây là một phiên mẫu:

[cling]$ #include <iostream>
[cling]$ std::cout << "Hallo, world!" << std::endl;
Hallo, world!
[cling]$ 3 + 5
(int const) 8
[cling]$ int x = 3; x++
(int) 3
(int const) 3
[cling]$ x
(int) 4

Nó không phải là một dự án đồ chơi nhưng nó thực sự được sử dụng trong CERN, ví dụ, để phát triển mã cho Máy Va chạm Hadron Lớn.


7

C ++ / CLI bị loại bỏ. Cấp, C ++ / CLI không phải là C ++ nhưng nó khá gần. Điều đó nói rằng JIT của Microsoft không thực hiện các loại tối ưu hóa hành vi thời gian chạy siêu thông minh / dễ thương mà bạn đang hỏi, ít nhất là theo hiểu biết của tôi. Vì vậy, điều này thực sự không có ích.

http://nestedvm.ibex.org/ biến MIPS thành mã byte Java mà sau đó sẽ bị loại bỏ. Vấn đề với cách tiếp cận này từ câu hỏi của bạn là bạn sẽ vứt đi rất nhiều thông tin hữu ích vào thời điểm nó đến với JIT.


2

Đầu tiên, tôi giả sử bạn muốn một jit truy tìm hơn là một phương pháp jit.

Cách tiếp cận tốt nhất cần thực hiện là biên dịch mã thành llvm IR, sau đó thêm mã theo dõi, trước khi tạo ra một tệp thực thi riêng. Khi một khối mã được sử dụng đủ tốt và một khi đủ thông tin về các giá trị (không phải các loại như trong ngôn ngữ động) của các biến đã được thu thập thì mã có thể được biên dịch lại (từ IR) với các bộ bảo vệ dựa trên các giá trị của các biến.

Tôi dường như nhớ rằng đã có một số tiến bộ trong việc tạo ra jit ac / c ++ trong tiếng kêu dưới tên libclang.


1
AFAIK, libclang là hầu hết các chức năng kêu vang được coi là một thư viện. vì vậy, bạn có thể sử dụng nó để phân tích mã nguồn để tạo màu cú pháp tinh vi, gợi ý, duyệt mã, v.v.
Javier

@Javier, nghe có vẻ đúng. Tôi nghĩ rằng có một chức năng trong thư viện đã lấy const char * của mã nguồn và tạo ra llvm ir, nhưng nghĩ bây giờ, có lẽ tốt hơn là jit dựa trên ir thay vì nguồn.
dan_waterworth
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.