GNU thực hiện: số lượng công việc có nên bằng số lõi CPU trong một hệ thống?


87

Dường như có một số tranh cãi về việc liệu số lượng công việc trong GNU tạo ra được cho là bằng với số lõi hay bạn có thể tối ưu hóa thời gian xây dựng bằng cách thêm một công việc bổ sung có thể được xếp hàng đợi trong khi những công việc khác "làm việc" hay không .

Nó tốt hơn để sử dụng -j4hoặc -j5trên một hệ thống lõi tứ?

Bạn đã thấy (hoặc thực hiện) bất kỳ điểm chuẩn nào hỗ trợ cái này hay cái kia chưa?


8
Chỉ cần cho tip, bạn có thể sử dụng make `nproc`để làm cho kịch bản CPU độc lập :)
VivienG

Nếu bạn có một hỗn hợp các công thức có ràng buộc io và ràng buộc cpu, thì bạn có khả năng muốn nhiều hơn NCPU. Cũng xem xét thêm các tùy chọn -lX. Đây thực sự không phải là một câu hỏi có thể trả lời được, ngoài "nó phụ thuộc vào phần cứng của bạn và thực hiện các nhiệm vụ."
James Moore

Về mặt kỹ thuật có thể thấy một sự cải thiện. Bạn cần một đĩa chậm, không đủ ram và nhiều tệp mã nguồn nhỏ. Dễ dàng hơn vào một thập kỷ trước.
Hans Passant

Câu trả lời:


56

Tôi sẽ nói điều tốt nhất nên làm là tự đánh giá nó trên môi trường và khối lượng công việc cụ thể của bạn. Có vẻ như có quá nhiều biến (kích thước / số lượng tệp nguồn, bộ nhớ khả dụng, bộ nhớ đệm trên đĩa, liệu thư mục nguồn và tiêu đề hệ thống của bạn có nằm trên các đĩa khác nhau hay không, v.v.) cho câu trả lời một kích thước phù hợp với tất cả.

Kinh nghiệm cá nhân của tôi (trên MacBook Pro 2 lõi) là -j2 nhanh hơn đáng kể so với -j1, nhưng ngoài ra (-j3, -j4, v.v.) thì không có tốc độ nào có thể đo lường được. Vì vậy, đối với môi trường của tôi, "công việc == số lõi" có vẻ là một câu trả lời tốt. (YMMV)


57

Tôi đã chạy dự án gia đình của mình trên máy tính xách tay 4 nhân với siêu phân luồng và ghi lại kết quả. Đây là một dự án khá nặng về trình biên dịch nhưng nó bao gồm một bài kiểm tra đơn vị 17,7 giây ở cuối. Các biên dịch không chuyên sâu về IO; có rất nhiều bộ nhớ khả dụng và nếu không muốn nói là phần còn lại nằm trên ổ SSD nhanh.

1 job        real   2m27.929s    user   2m11.352s    sys    0m11.964s    
2 jobs       real   1m22.901s    user   2m13.800s    sys    0m9.532s
3 jobs       real   1m6.434s     user   2m29.024s    sys    0m10.532s
4 jobs       real   0m59.847s    user   2m50.336s    sys    0m12.656s
5 jobs       real   0m58.657s    user   3m24.384s    sys    0m14.112s
6 jobs       real   0m57.100s    user   3m51.776s    sys    0m16.128s
7 jobs       real   0m56.304s    user   4m15.500s    sys    0m16.992s
8 jobs       real   0m53.513s    user   4m38.456s    sys    0m17.724s
9 jobs       real   0m53.371s    user   4m37.344s    sys    0m17.676s
10 jobs      real   0m53.350s    user   4m37.384s    sys    0m17.752s
11 jobs      real   0m53.834s    user   4m43.644s    sys    0m18.568s
12 jobs      real   0m52.187s    user   4m32.400s    sys    0m17.476s
13 jobs      real   0m53.834s    user   4m40.900s    sys    0m17.660s
14 jobs      real   0m53.901s    user   4m37.076s    sys    0m17.408s
15 jobs      real   0m55.975s    user   4m43.588s    sys    0m18.504s
16 jobs      real   0m53.764s    user   4m40.856s    sys    0m18.244s
inf jobs     real   0m51.812s    user   4m21.200s    sys    0m16.812s

Kết quả cơ bản:

  • Chia tỷ lệ đến số lõi làm tăng hiệu suất gần như tuyến tính. Thời gian thực giảm từ 2,5 phút xuống 1,0 phút (nhanh gấp 2,5 lần), nhưng thời gian thực hiện trong quá trình biên dịch đã tăng từ 2,11 lên 2,50 phút. Hệ thống hầu như không nhận thấy bất kỳ tải bổ sung nào trong bit này.
  • Việc chia tỷ lệ từ số lõi đến số lượng chủ đề đã tăng tải người dùng lên rất nhiều, từ 2,50 phút lên 4,38 phút. Điều này gần như tăng gấp đôi rất có thể là do các phiên bản trình biên dịch khác muốn sử dụng cùng một tài nguyên CPU cùng một lúc. Hệ thống đang tải nhiều hơn một chút với các yêu cầu và chuyển đổi tác vụ, khiến thời gian sử dụng chỉ còn 17,7 giây. Ưu điểm là khoảng 6,5 giây với thời gian biên dịch là 53,5 giây, giúp tăng tốc 12%.
  • Việc chia tỷ lệ từ số lượng chỉ đến số lượng chỉ đôi không tăng tốc đáng kể. Thời điểm 12 và 15 rất có thể là những bất thường thống kê mà bạn có thể bỏ qua. Tổng thời gian thực hiện tăng lên một chút, cũng như thời gian hệ thống. Cả hai rất có thể là do chuyển đổi tác vụ tăng lên. Không có lợi cho điều này.

Dự đoán của tôi ngay bây giờ: Nếu bạn làm việc gì đó khác trên máy tính của mình, hãy sử dụng số lõi. Nếu bạn không, hãy sử dụng số lượng chỉ. Vượt quá nó cho thấy không có lợi ích. Tại một thời điểm nào đó, chúng sẽ bị giới hạn bộ nhớ và sụp đổ do đó, làm cho quá trình biên dịch chậm hơn nhiều. Dòng "inf" đã được thêm vào một ngày sau đó, khiến tôi nghi ngờ rằng có một số điều chỉnh nhiệt cho 8+ công việc. Điều này cho thấy rằng đối với kích thước dự án này, không có giới hạn bộ nhớ hoặc thông lượng có hiệu lực. Đó là một dự án nhỏ, với 8GB bộ nhớ để biên dịch.


Theo stackoverflow.com/questions/56272639/… , bạn có thể có được lợi thế khi chạy nhiều tác vụ hơn so với CPU nhưng chỉ khi các tác vụ của bạn dành một phần đáng kể thời gian chờ đợi I / O mạng. Đối với các nhiệm vụ biên dịch, đây không phải là trường hợp.
ivan_pozdeev

30

Cá nhân tôi, sử dụng make -j ntrong đó n là "số lõi" + 1.

Tuy nhiên, tôi không thể đưa ra lời giải thích khoa học: Tôi đã thấy rất nhiều người sử dụng các cài đặt tương tự và họ đã cho tôi kết quả khá tốt cho đến nay.

Dù sao, bạn cũng phải cẩn thận vì một số chuỗi trang điểm đơn giản là không tương thích với --jobstùy chọn và có thể dẫn đến kết quả không mong muốn. Nếu bạn đang gặp phải lỗi phụ thuộc lạ, chỉ cần cố gắng makekhông --jobs.


19
Lời giải thích (mặc dù không thể đảm bảo tính khoa học của nó) là "+ 1" cung cấp thêm một công việc chạy trong khi bất kỳ ai trong số n công việc khác đang thực hiện I / O.
Laurynas Biveinis

@LaurynasBiveinis: Nhưng sau đó các công việc luôn chạy trên các lõi khác nhau, ít nhất là thường xuyên hơn với một thiết lập thận trọng hơn, nơi một công việc có cơ hội ở trên cùng một lõi trong một khoảng thời gian dài hơn. Có ưu và nhược điểm ở đây ...
krlmlr

1
Số lõi + 1 cũng là cài đặt mặc định của tôi. Một vấn đề là, trong bất kỳ hệ thống lớn hợp lý nào, dường như trì hoãn việc liên kết và thực hiện tất cả các bước liên kết với nhau. Tại thời điểm này, bạn đã sử dụng hết RAM. Bah!
bobbogo

4
một số chuỗi thực hiện đơn giản là không tương thích với tùy chọn --jobs -> Điều này có nghĩa là bạn đã thiếu các phụ thuộc. Sửa lỗi trang điểm của bạn nếu bạn gặp phải lỗi này.
dascandy

7

Cuối cùng, bạn sẽ phải thực hiện một số điểm chuẩn để xác định con số tốt nhất để sử dụng cho bản dựng của mình, nhưng hãy nhớ rằng CPU không phải là tài nguyên duy nhất quan trọng!

Ví dụ: nếu bạn có một bản dựng phụ thuộc nhiều vào đĩa, thì việc tạo ra nhiều công việc trên một hệ thống đa lõi có thể thực sự chậm hơn , vì đĩa sẽ phải làm thêm công việc di chuyển đầu đĩa qua lại để phục vụ tất cả các công việc khác nhau (tùy thuộc vào nhiều yếu tố, chẳng hạn như hệ điều hành xử lý ổ đĩa đệm tốt như thế nào, hỗ trợ xếp hàng lệnh riêng của đĩa, v.v.).

Và sau đó bạn đã có lõi "thực" so với siêu phân luồng. Bạn có thể có hoặc không được hưởng lợi từ các công việc sinh sản cho mỗi siêu luồng. Một lần nữa, bạn sẽ phải đánh giá điểm chuẩn để tìm ra.

Tôi không thể nói rằng tôi đã thử cụ thể #cores + 1 , nhưng trên hệ thống của chúng tôi (Intel i7 940, 4 lõi siêu phân luồng, nhiều RAM và ổ VelociRaptor) và bản dựng của chúng tôi (bản dựng C ++ quy mô lớn thay thế CPU và tôi / O ràng buộc) có rất ít sự khác biệt giữa -j4 và -j8. (Có thể tốt hơn 15% ... nhưng không nơi nào tốt gấp đôi.)

Nếu tôi đi ăn trưa, tôi sẽ sử dụng -j8, nhưng nếu tôi muốn sử dụng hệ thống của mình cho bất cứ thứ gì khác trong khi nó đang xây dựng, tôi sẽ sử dụng một số thấp hơn. :)


1
Có vẻ tuyệt vời, nhưng tôi đang bối rối vì sao bạn sẽ không chỉ mất mà + 15% mỗi lần bằng cách sử dụng-j 8
sg

1
@sg: j8 đã thực sự đánh thuế vào hệ thống mà tôi đã mô tả trong bài đăng gốc của mình ... máy vẫn sử dụng được , nhưng chắc chắn là nó kém phản hồi hơn. Vì vậy, nếu tôi vẫn muốn sử dụng nó tương tác cho các tác vụ khác (thường làm việc trên mã khác và có thể là bản dựng DLL đơn lẻ không thường xuyên), tôi sẽ dành một vài lõi cho các bit tương tác.
ijprest

@sg: Đây là ít vấn đề hơn trên các hệ thống mới hơn của chúng tôi ... Tôi nghi ngờ chủ yếu là do chúng tôi đang chạy SSD. (Tôi nghĩ bây giờ chúng ta hoàn toàn bị ràng buộc bởi CPU mà chúng ta sẽ chuyển sang ổ SSD ... chúng tôi đã thử xây dựng hoàn toàn trên ổ RAM mà hầu như không có cải tiến nào.) Nhưng tôi vẫn sẽ để trống một vài lõi nếu tôi làm bất cứ điều gì hơn là chỉnh sửa văn bản đơn giản ở phía trước.
ijprest

5

Tôi vừa có một proc Athlon II X2 Regor với Foxconn M / B và bộ nhớ G-Skill 4GB.

Tôi đặt 'cat / proc / cpuinfo' và 'free' vào cuối phần này để những người khác có thể xem thông số kỹ thuật của tôi. Đó là Athlon II x2 lõi kép với RAM 4GB.

uname -a on default slackware 14.0 kernel is 3.2.45.

Tôi đã tải xuống mã nguồn hạt nhân bước tiếp theo (linux-3.2.46) vào / archive4;

đã giải nén nó ( tar -xjvf linux-3.2.46.tar.bz2);

cd'd vào thư mục ( cd linux-3.2.46);

và sao chép cấu hình hạt nhân mặc định over ( cp /usr/src/linux/.config .);

được sử dụng make oldconfigđể chuẩn bị cấu hình hạt nhân 3.2.46;

sau đó chạy thực hiện với các câu thần chú khác nhau của -jX.

Tôi đã kiểm tra thời gian của mỗi lần chạy bằng cách đưa ra lệnh sau thời gian, ví dụ: 'time make -j2'. Giữa mỗi lần chạy, tôi 'rm -rf' cây linux-3.2.46 và rút gọn lại, sao chép /usr/src/linux/.config mặc định vào thư mục, chạy make oldconfig và sau đó thực hiện lại kiểm tra 'make -jX' của tôi .

đơn giản "make":

real    51m47.510s
user    47m52.228s
sys     3m44.985s
bob@Moses:/archive4/linux-3.2.46$

như trên nhưng với make -j2

real    27m3.194s
user    48m5.135s
sys     3m39.431s
bob@Moses:/archive4/linux-3.2.46$

như trên nhưng với make -j3

real    27m30.203s
user    48m43.821s
sys     3m42.309s
bob@Moses:/archive4/linux-3.2.46$

như trên nhưng với make -j4

real    27m32.023s
user    49m18.328s
sys     3m43.765s
bob@Moses:/archive4/linux-3.2.46$

như trên nhưng với make -j8

real    28m28.112s
user    50m34.445s
sys     3m49.877s
bob@Moses:/archive4/linux-3.2.46$

'cat / proc / cpuinfo' cho kết quả:

bob@Moses:/archive4$ cat /proc/cpuinfo
processor       : 0
vendor_id       : AuthenticAMD
cpu family      : 16
model           : 6
model name      : AMD Athlon(tm) II X2 270 Processor
stepping        : 3
microcode       : 0x10000c8
cpu MHz         : 3399.957
cache size      : 1024 KB
physical id     : 0
siblings        : 2
core id         : 0
cpu cores       : 2
apicid          : 0
initial apicid  : 0
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 5
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmo
v pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rd
tscp lm 3dnowext 3dnow constant_tsc nonstop_tsc extd_apicid pni monitor cx16 p
opcnt lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowpre
fetch osvw ibs skinit wdt npt lbrv svm_lock nrip_save
bogomips        : 6799.91
clflush size    : 64
cache_alignment : 64
address sizes   : 48 bits physical, 48 bits virtual
power management: ts ttp tm stc 100mhzsteps hwpstate

processor       : 1
vendor_id       : AuthenticAMD
cpu family      : 16
model           : 6
model name      : AMD Athlon(tm) II X2 270 Processor
stepping        : 3
microcode       : 0x10000c8
cpu MHz         : 3399.957
cache size      : 1024 KB
physical id     : 0
siblings        : 2
core id         : 1
cpu cores       : 2
apicid          : 1
initial apicid  : 1
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 5
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmo
v pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rd
tscp lm 3dnowext 3dnow constant_tsc nonstop_tsc extd_apicid pni monitor cx16 p
opcnt lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowpre
fetch osvw ibs skinit wdt npt lbrv svm_lock nrip_save
bogomips        : 6799.94
clflush size    : 64
cache_alignment : 64
address sizes   : 48 bits physical, 48 bits virtual
power management: ts ttp tm stc 100mhzsteps hwpstate

sản lượng 'miễn phí':

bob@Moses:/archive4$ free
             total       used       free     shared    buffers     cached
Mem:       3991304    3834564     156740          0     519220    2515308

1
Chỉ make -jlàm gì trên hệ thống đó? Make có nhiệm vụ kiểm tra tải và chia tỷ lệ số lượng quy trình dựa trên tải.
docwhat

1
make -jkhông giới hạn số lượng công việc. Điều này thường là tai hại đối với một dự án có quy mô vừa hoặc lớn vì nhanh chóng có nhiều công việc được phân chia hơn mức RAM có thể hỗ trợ. Tùy chọn bạn cần hạn chế theo tải là -l [load], kết hợp với-j
Matt G

5

Cả hai đều không sai. Để yên tâm với bản thân và với tác giả của phần mềm bạn đang biên dịch (các hạn chế đa luồng / đơn luồng khác nhau áp dụng ở cấp phần mềm), tôi khuyên bạn nên sử dụng:

make -j`nproc`

Lưu ý: nproclà lệnh linux sẽ trả về số lõi / luồng (CPU hiện đại) có sẵn trên hệ thống. Đặt nó dưới dấu tick `như trên sẽ chuyển số cho lệnh make.

Thông tin bổ sung: Như ai đó đã đề cập, việc sử dụng tất cả các lõi / luồng để biên dịch phần mềm có thể khiến hộp của bạn gần chết (không phản hồi) theo đúng nghĩa đen và thậm chí có thể mất nhiều thời gian hơn so với việc sử dụng ít lõi hơn. Như tôi đã thấy một người dùng Slackware ở đây đã đăng, anh ta có CPU lõi kép nhưng vẫn cung cấp thử nghiệm lên đến j 8, điều này đã ngừng khác biệt ở j 2 (chỉ có 2 lõi phần cứng mà CPU có thể sử dụng). Vì vậy, để tránh hộp không phản hồi, tôi khuyên bạn nên chạy nó như sau:

make -j`nproc --ignore=2`

Điều này sẽ chuyển đầu ra của nprocđến makevà trừ đi 2 lõi từ kết quả của nó.


3

Chỉ như một giới thiệu:

Từ Spawning Multiple Build Jobsphần trong LKD :

với n là số lượng công việc sẽ sinh ra. Thực hành thông thường là tạo ra một hoặc hai công việc cho mỗi bộ xử lý. Ví dụ: trên máy vi xử lý kép, người ta có thể làm

$ make j4


liên kết bị hỏng, đây có phải là trích dẫn từ Phát triển nhân Linux của Robert Love không?
Behrooz

Vâng, nó là từ cuốn sách đó.
Nan Xiao,

1

Từ kinh nghiệm của tôi, phải có một số lợi ích về hiệu suất khi thêm việc làm thêm. Nó chỉ đơn giản là vì đĩa I / O là một trong những cổ chai bên cạnh CPU. Tuy nhiên, không dễ dàng để quyết định số lượng công việc phụ vì nó có tính liên kết cao với số lượng lõi và loại đĩa đang được sử dụng.


1

Nhiều năm sau, phần lớn các câu trả lời này vẫn đúng. Tuy nhiên, đã có một chút thay đổi: Việc sử dụng nhiều công việc hơn số lõi vật lý của bạn hiện mang lại một tốc độ thực sự đáng kể. Như một phụ lục cho bảng của Dascandy, đây là thời gian của tôi để biên dịch một dự án trên AMD Ryzen 5 3600X trên linux. (Đồ chơi bột, cam kết c6f653ac3cef03acfbc44e8f29f11e1b301f1ca2)

Tôi khuyên bạn nên tự kiểm tra, nhưng tôi đã nhận thấy với đầu vào từ những người khác rằng việc sử dụng số lõi logic của bạn để tính công việc hoạt động tốt trên Zen. Bên cạnh đó, hệ thống dường như không bị mất khả năng phản hồi. Tôi tưởng tượng điều này cũng áp dụng cho các CPU Intel gần đây. Xin lưu ý rằng tôi cũng có một ổ SSD, vì vậy có thể đáng để bạn tự kiểm tra CPU của mình.

scons -j1 --release --native  120.68s user 9.78s system 99% cpu 2:10.60 total
scons -j2 --release --native  122.96s user 9.59s system 197% cpu 1:07.15 total
scons -j3 --release --native  125.62s user 9.75s system 292% cpu 46.291 total
scons -j4 --release --native  128.26s user 10.41s system 385% cpu 35.971 total
scons -j5 --release --native  133.73s user 10.33s system 476% cpu 30.241 total
scons -j6 --release --native  144.10s user 11.24s system 564% cpu 27.510 total
scons -j7 --release --native  153.64s user 11.61s system 653% cpu 25.297 total
scons -j8 --release --native  161.91s user 12.04s system 742% cpu 23.440 total
scons -j9 --release --native  169.09s user 12.38s system 827% cpu 21.923 total
scons -j10 --release --native  176.63s user 12.70s system 910% cpu 20.788 total
scons -j11 --release --native  184.57s user 13.18s system 989% cpu 19.976 total
scons -j12 --release --native  192.13s user 14.33s system 1055% cpu 19.553 total
scons -j13 --release --native  193.27s user 14.01s system 1052% cpu 19.698 total
scons -j14 --release --native  193.62s user 13.85s system 1076% cpu 19.270 total
scons -j15 --release --native  195.20s user 13.53s system 1056% cpu 19.755 total
scons -j16 --release --native  195.11s user 13.81s system 1060% cpu 19.692 total
( -jinf test not included, as it is not supported by scons.)

Các thử nghiệm được thực hiện trên Ubuntu 19.10 w / a Ryzen 5 3600X, Samsung 860 Evo SSD (SATA) và RAM 32 GB

Lưu ý cuối cùng: Những người khác sử dụng 3600X có thể có thời gian tốt hơn tôi. Khi thực hiện bài kiểm tra này, tôi đã bật chế độ Eco, làm giảm tốc độ của CPU một chút.


0

ĐÚNG! Trên 3950x của tôi, tôi chạy -j32 và nó tiết kiệm hàng giờ biên dịch! Tôi vẫn có thể xem youtube, duyệt web, v.v. trong khi biên dịch mà không có bất kỳ sự khác biệt nào. Bộ xử lý không phải lúc nào cũng được chốt ngay cả với nvme 1TB 970 PRO hoặc 1TB Auros Gen4 nvme và 64GB 3200C14. Ngay cả khi nó là như vậy, tôi không nhận thấy giao diện người dùng khôn ngoan. Tôi dự định thử nghiệm với -j48 trong tương lai gần trong một số dự án lớn sắp tới. Tôi mong đợi, như bạn có thể làm, sẽ thấy một số cải tiến ấn tượng. Những người vẫn sử dụng lõi tứ có thể không đạt được mức lợi nhuận tương tự ....

Bản thân Linus vừa nâng cấp lên mức 3970x và bạn có thể đặt cược số đô la dưới cùng của mình, anh ấy ít nhất đang chạy -j64.

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.