Biên dịch với g ++ bằng nhiều lõi


174

Câu hỏi nhanh: cờ trình biên dịch để cho phép g ++ sinh ra nhiều phiên bản của chính nó để biên dịch các dự án lớn nhanh hơn (ví dụ 4 tệp nguồn tại một thời điểm cho CPU đa lõi)?


Nó sẽ thực sự giúp đỡ? Tất cả các công việc biên dịch của tôi bị ràng buộc I / O thay vì ràng buộc CPU.
Brian Knoblauch

5
Ngay cả khi chúng bị ràng buộc I / O, bạn vẫn có thể giữ tải I / O cao hơn khi các bit nặng của CPU xảy ra (chỉ với một phiên bản g ++ sẽ có các khoảng trống) và có thể đạt được hiệu quả I / O nếu bộ lập lịch có nhiều lựa chọn hơn về Những gì cần đọc từ đĩa tiếp theo. Kinh nghiệm của tôi là việc sử dụng hợp lý make -jhầu như luôn mang lại kết quả tốt.
Flexo

1
@BrianKnoblauch Nhưng trên máy của tôi (thực tế hoặc trong VirtualBox), CPU bị ràng buộc, tôi thấy rằng CPU đang bận rộn thông qua lệnh 'top' khi biên dịch.

1
Ngay cả khi chúng bị ràng buộc I / O, chúng ta có thể sử dụng cờ '-pipe' của gcc để giảm đau.

chỉ thấy điều này trong google: gcc.gnu.org/onlinesocs/libstdc++/manual/ mẹo
Jim Michaels

Câu trả lời:


240

Bạn có thể làm điều này với make - với gnu làm cho nó là cờ -j (điều này cũng sẽ giúp ích cho máy không xử lý).

Ví dụ: nếu bạn muốn 4 công việc song song thực hiện:

make -j 4

Bạn cũng có thể chạy gcc trong một đường ống với

gcc -pipe

Điều này sẽ dẫn các giai đoạn biên dịch, cũng sẽ giúp giữ cho các lõi bận rộn.

Nếu bạn cũng có sẵn máy móc, bạn có thể kiểm tra distcc , trang này cũng sẽ biên dịch cho các máy đó.


36
Số của bạn phải là 1,5 lần số lõi bạn có.
Mark Beckwith

2
Cảm ơn. Tôi tiếp tục cố gắng chuyển "-j #" cho gcc thông qua CFLAGS / CPPFLAGS / CXXFLAGS. Tôi đã hoàn toàn quên rằng "-j #" là một tham số cho GNU make (và không phải cho GCC).
chriv

33
Tại sao tùy chọn -j cho GNU Make cần gấp 1,5 lần số lõi CPU?
cắn

28
Số 1,5 là do vấn đề ràng buộc I / O được ghi nhận . Đó là một quy tắc của ngón tay cái. Khoảng 1/3 công việc sẽ chờ I / O, vì vậy các công việc còn lại sẽ sử dụng các lõi có sẵn. Một số lớn hơn lõi là tốt hơn và bạn thậm chí có thể lên cao gấp 2 lần . Xem thêm: Gnu đưa ra -jlập luận
tiếng ồn vô nghĩa

4
@JimMichaels Có thể là do các phụ thuộc được đặt kém trong dự án của bạn, (mục tiêu bắt đầu xây dựng ngay cả khi các phụ thuộc của nó chưa sẵn sàng) để chỉ việc xây dựng tuần tự kết thúc thành công.
Antonio

42

Không có cờ như vậy và có một hoạt động chống lại triết lý Unix là mỗi công cụ chỉ thực hiện một chức năng và thực hiện tốt chức năng đó. Sinh sản các quá trình biên dịch là khái niệm công việc của hệ thống xây dựng. Những gì bạn có thể đang tìm kiếm là cờ -j (công việc) để GNU thực hiện, một la

làm -j4

Hoặc bạn có thể sử dụng pmake hoặc các hệ thống tạo song song tương tự.



3
"Unix pedantry không hữu ích" Điều tốt là nó không phải là pedantry sau đó, biên tập viên ẩn danh. Cuộn lại. Người đánh giá vui lòng chú ý hơn đến những gì bạn đang làm.
Các cuộc đua nhẹ nhàng trong quỹ đạo

12

Mọi người đã đề cập makenhưng bjamcũng hỗ trợ một khái niệm tương tự. Sử dụng bjam -jxhướng dẫn bjam để xây dựng lên xcác lệnh đồng thời.

Chúng tôi sử dụng cùng một tập lệnh xây dựng trên Windows và Linux và sử dụng tùy chọn này giảm một nửa thời gian xây dựng của chúng tôi trên cả hai nền tảng. Đẹp.


9

makesẽ làm điều này cho bạn. Điều tra -j-lchuyển đổi trong trang người đàn ông. Tôi không nghĩ g++là song song.


+1 để đề cập đến -ltùy chọn (không bắt đầu một công việc mới trừ khi tất cả các công việc trước đó đã chấm dứt). Mặt khác, có vẻ như công việc của trình liên kết bắt đầu với không phải tất cả các tệp đối tượng được xây dựng (vì một số phần tổng hợp vẫn đang tiếp diễn), do đó công việc của trình liên kết không thành công.
NGI

8

Nếu sử dụng make, vấn đề với -j. Từ man make:

  -j [jobs], --jobs[=jobs]
       Specifies the number of jobs (commands) to run simultaneously.  
       If there is more than one -j option, the last one is effective.
       If the -j option is given without an argument, make will not limit the
       number of jobs that can run simultaneously.

Và đáng chú ý nhất, nếu bạn muốn tập lệnh hoặc xác định số lượng lõi bạn có sẵn (tùy thuộc vào môi trường của bạn và nếu bạn chạy trong nhiều môi trường, điều này có thể thay đổi rất nhiều), bạn có thể sử dụng chức năng Python phổ biến cpu_count() :

https://docs.python.org/3/l Library / multiprocessing.html # multiprocessing.cpu_count

Như thế này:

make -j $(python3 -c 'import multiprocessing as mp; print(int(mp.cpu_count() * 1.5))')

Nếu bạn đang hỏi tại sao 1.5tôi sẽ trích dẫn tiếng ồn của người dùng trong một bình luận ở trên:

Số 1,5 là do vấn đề ràng buộc I / O được ghi nhận. Đó là một quy tắc của ngón tay cái. Khoảng 1/3 công việc sẽ chờ I / O, vì vậy các công việc còn lại sẽ sử dụng các lõi có sẵn. Một số lớn hơn lõi là tốt hơn và bạn thậm chí có thể lên cao gấp 2 lần.


5
Hầu hết người dùng Linux có thể sẽ thích ngắn hơn: make -j`nproc` với nprocGNU Coreutils.
Ciro Santilli 郝海东 冠状 病 事件

Nếu bạn đang sử dụng SSD, I / O sẽ không gây ra nhiều vấn đề. Chỉ cần xây dựng dựa trên nhận xét của Ciro ở trên, bạn có thể làm điều này: make -j $(( $(nproc) + 1 ))(đảm bảo bạn đặt khoảng trắng nơi tôi có chúng).
Ed K

Đề xuất hay sử dụng python, trên các hệ thống nprockhông khả dụng, ví dụ như trong manylinux1các thùng chứa, nó tiết kiệm thêm thời gian bằng cách tránh chạy yum update/ yum install.
cuốc vào

7

distcc cũng có thể được sử dụng để phân phối các biên dịch không chỉ trên máy hiện tại mà còn trên các máy khác trong một trang trại đã cài đặt distcc.


+1, distcc là một công cụ hữu ích cần có trong kho vũ khí của một người cho các bản dựng lớn.
Flexo

Có vẻ như cũng có một số ít hoạt động "như" distcc: stackoverflow.com/questions/5374106/distribution-make/
mẹo

3

Tôi không chắc chắn về g ++, nhưng nếu bạn đang sử dụng GNU Make thì "make -j N" (trong đó N là số lượng chủ đề có thể tạo) sẽ cho phép thực hiện nhiều công việc g ++ nhiều lần (rất lâu như các tập tin không phụ thuộc vào nhau).


2
không N ist không phải là số lượng chủ đề! Nhiều người hiểu nhầm điều đó, nhưng -j Nnói rằng làm cho bao nhiêu quá trình cùng một lúc nên được sinh ra, không phải là chủ đề. Đó là lý do tại sao nó không hoạt động như MS cl -MT(thực sự đa luồng).
Sebi2020

2

GNU song song

Tôi đã thực hiện một chuẩn tổng hợp tổng hợp và không thể bận tâm để viết Makefile, vì vậy tôi đã sử dụng:

sudo apt-get install parallel
ls | grep -E '\.c$' | parallel -t --will-cite "gcc -c -o '{.}.o' '{}'"

Giải trình:

  • {.} lấy đối số đầu vào và loại bỏ phần mở rộng của nó
  • -t in ra các lệnh đang được chạy để cho chúng ta một ý tưởng về sự tiến bộ
  • --will-cite xóa yêu cầu trích dẫn phần mềm nếu bạn công bố kết quả bằng cách sử dụng nó ...

parallel tiện lợi đến mức tôi thậm chí có thể tự kiểm tra dấu thời gian:

ls | grep -E '\.c$' | parallel -t --will-cite "\
  if ! [ -f '{.}.o' ] || [ '{}' -nt '{.}.o' ]; then
    gcc -c -o '{.}.o' '{}'
  fi
"

xargs -P cũng có thể chạy các công việc song song, nhưng sẽ thuận tiện hơn một chút khi thực hiện thao tác mở rộng hoặc chạy nhiều lệnh với nó: Gọi nhiều lệnh thông qua xargs

Liên kết song song được hỏi tại: gcc có thể sử dụng nhiều lõi khi liên kết không?

TODO: Tôi nghĩ rằng tôi đã đọc ở đâu đó rằng quá trình biên dịch có thể được giảm xuống thành phép nhân ma trận, vì vậy có lẽ cũng có thể tăng tốc độ biên dịch tệp đơn cho các tệp lớn. Nhưng tôi không thể tìm thấy một tài liệu tham khảo bây giờ.

Đã thử nghiệm trong Ubuntu 18.10.

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.