Câu hỏi Làm thế nào tôi có thể cấu hình mã C ++ chạy trên Linux?


Tôi có một ứng dụng C ++, chạy trên Linux, mà tôi đang trong quá trình tối ưu hóa. Làm thế nào tôi có thể xác định những khu vực nào của mã của tôi đang chạy chậm?


1499
2017-12-17 20:29


gốc


Nếu bạn sẽ cung cấp thêm dữ liệu về ngăn xếp phát triển của mình, bạn có thể nhận được câu trả lời tốt hơn. Có trình biên dịch từ Intel và Sun nhưng bạn phải sử dụng trình biên dịch của họ. Đó có phải là một lựa chọn không? - Nazgob
Nó đã được trả lời trên liên kết sau: stackoverflow.com/questions/2497211/… - Kapil Gupta
Hầu hết các câu trả lời là code profilers. Tuy nhiên, đảo ngược ưu tiên, bí danh bộ nhớ cache, tranh chấp tài nguyên, v.v. tất cả có thể là các yếu tố trong việc tối ưu hóa và hiệu suất. Tôi nghĩ mọi người đọc thông tin mã chậm của tôi. Câu hỏi thường gặp đang đề cập đến chủ đề này. - artless noise
CppCon 2015: Chandler Carruth "Điều chỉnh C ++: Điểm chuẩn, CPU và Trình biên dịch! Oh My!" - 865719
Tôi thường sử dụng pstack một cách ngẫu nhiên, phần lớn thời gian sẽ in ra một chồng điển hình nhất, nơi chương trình hầu hết thời gian, do đó chỉ vào nút cổ chai. - Jose Manuel Gomez Alvarez


Các câu trả lời:


Nếu mục tiêu của bạn là sử dụng một hồ sơ, hãy sử dụng một trong những gợi ý.

Tuy nhiên, nếu bạn đang vội vàng và bạn có thể tự ngắt chương trình của mình trong trình gỡ lỗi trong khi nó đang bị chậm một cách chủ quan, có một cách đơn giản để tìm ra các vấn đề về hiệu suất.

Chỉ cần tạm dừng nó nhiều lần, và mỗi lần nhìn vào ngăn xếp cuộc gọi. Nếu có một số mã đang lãng phí một số phần trăm thời gian, 20% hoặc 50% hoặc bất cứ điều gì, đó là xác suất mà bạn sẽ bắt nó trong hành động trên mỗi mẫu. Vì vậy, đó là khoảng tỷ lệ phần trăm của mẫu mà bạn sẽ thấy nó. Không có phỏng đoán được giáo dục yêu cầu. Nếu bạn có một phỏng đoán về vấn đề là gì, điều này sẽ chứng minh hoặc bác bỏ nó.

Bạn có thể gặp nhiều vấn đề về hiệu suất với các kích thước khác nhau. Nếu bạn làm sạch bất kỳ một trong số họ, những cái còn lại sẽ chiếm tỷ lệ lớn hơn, và dễ dàng hơn để phát hiện, trên các lần truy cập tiếp theo. Điều này hiệu ứng phóng đại, khi kết hợp nhiều vấn đề, có thể dẫn đến các yếu tố tăng tốc thực sự lớn.

Caveat: Các lập trình viên có xu hướng hoài nghi về kỹ thuật này trừ phi họ đã tự sử dụng nó. Họ sẽ nói rằng profilers cung cấp cho bạn thông tin này, nhưng điều đó chỉ đúng nếu họ lấy mẫu toàn bộ ngăn xếp cuộc gọi, và sau đó cho phép bạn kiểm tra một bộ mẫu ngẫu nhiên. (Tóm tắt là nơi mà cái nhìn sâu sắc bị mất.) Đồ thị cuộc gọi không cung cấp cho bạn thông tin tương tự, bởi vì

  1. họ không tóm tắt ở cấp độ giảng dạy, và
  2. họ đưa ra tóm tắt khó hiểu trong sự hiện diện của đệ quy.

Họ cũng sẽ nói rằng nó chỉ hoạt động trên các chương trình đồ chơi, khi thực sự nó hoạt động trên bất kỳ chương trình nào, và nó có vẻ hoạt động tốt hơn trên các chương trình lớn hơn, bởi vì chúng có xu hướng có nhiều vấn đề hơn để tìm kiếm. Họ sẽ nói đôi khi tìm thấy những thứ không phải là vấn đề, nhưng điều đó chỉ đúng nếu bạn thấy điều gì đó Một lần. Nếu bạn thấy một vấn đề trên nhiều hơn một mẫu, nó là có thật.

P.S. Điều này cũng có thể được thực hiện trên các chương trình đa luồng nếu có cách thu thập các mẫu ngăn xếp cuộc gọi của nhóm luồng tại một thời điểm, như trong Java.

P.P.S Như một tổng quát thô, bạn càng có nhiều lớp trừu tượng trong phần mềm của mình, bạn càng có nhiều khả năng thấy rằng đó là nguyên nhân của các vấn đề về hiệu năng (và cơ hội để tăng tốc).

Nhập: Nó có thể không được rõ ràng, nhưng kỹ thuật lấy mẫu ngăn xếp hoạt động tốt như nhau trong sự hiện diện của đệ quy. Lý do là thời gian sẽ được lưu bằng cách loại bỏ một lệnh được xấp xỉ bởi phần mẫu chứa nó, bất kể số lần nó có thể xảy ra trong một mẫu.

Một phản đối tôi thường nghe là: "Nó sẽ dừng lại ở đâu đó ngẫu nhiên, và nó sẽ bỏ lỡ vấn đề thực sự". Điều này xuất phát từ việc có khái niệm trước về vấn đề thực sự là gì. Một đặc tính quan trọng của các vấn đề hiệu năng là chúng thách thức các kỳ vọng. Lấy mẫu cho bạn biết một cái gì đó là một vấn đề, và phản ứng đầu tiên của bạn là không tin. Điều đó là tự nhiên, nhưng bạn có thể chắc chắn nếu nó tìm thấy một vấn đề nó là có thật, và ngược lại.

THÊM: Hãy để tôi giải thích Bayes về cách nó hoạt động. Giả sử có một số hướng dẫn I (gọi hoặc nói cách khác) đang ở trên ngăn xếp cuộc gọi một số phần f thời gian (và do đó chi phí nhiều). Để đơn giản, giả sử chúng ta không biết f là, nhưng giả sử là 0,1, 0,2, 0,3, ... 0,9, 1,0 và xác suất trước của mỗi khả năng này là 0,1, vì vậy tất cả các chi phí này đều có khả năng giống nhau trước.

Sau đó giả sử chúng tôi chỉ lấy 2 mẫu ngăn xếp và chúng tôi thấy hướng dẫn I trên cả hai mẫu, quan sát được chỉ định o=2/2. Điều này cho chúng ta ước tính mới về tần số f của I, theo điều này:

Prior                                    
P(f=x) x  P(o=2/2|f=x) P(o=2/2&&f=x)  P(o=2/2&&f >= x)  P(f >= x)

0.1    1     1             0.1          0.1            0.25974026
0.1    0.9   0.81          0.081        0.181          0.47012987
0.1    0.8   0.64          0.064        0.245          0.636363636
0.1    0.7   0.49          0.049        0.294          0.763636364
0.1    0.6   0.36          0.036        0.33           0.857142857
0.1    0.5   0.25          0.025        0.355          0.922077922
0.1    0.4   0.16          0.016        0.371          0.963636364
0.1    0.3   0.09          0.009        0.38           0.987012987
0.1    0.2   0.04          0.004        0.384          0.997402597
0.1    0.1   0.01          0.001        0.385          1

                  P(o=2/2) 0.385                

Cột cuối cùng nói rằng, ví dụ: xác suất f > = 0,5 là 92%, tăng so với giả định trước là 60%.

Giả sử các giả định trước khác nhau. Giả sử chúng ta giả định P (f = 0,1) là 0,991 (gần như chắc chắn), và tất cả các khả năng khác gần như không thể (0,001). Nói cách khác, sự chắc chắn trước của chúng ta là I rẻ. Sau đó, chúng tôi nhận được:

Prior                                    
P(f=x) x  P(o=2/2|f=x) P(o=2/2&& f=x)  P(o=2/2&&f >= x)  P(f >= x)

0.001  1    1              0.001        0.001          0.072727273
0.001  0.9  0.81           0.00081      0.00181        0.131636364
0.001  0.8  0.64           0.00064      0.00245        0.178181818
0.001  0.7  0.49           0.00049      0.00294        0.213818182
0.001  0.6  0.36           0.00036      0.0033         0.24
0.001  0.5  0.25           0.00025      0.00355        0.258181818
0.001  0.4  0.16           0.00016      0.00371        0.269818182
0.001  0.3  0.09           0.00009      0.0038         0.276363636
0.001  0.2  0.04           0.00004      0.00384        0.279272727
0.991  0.1  0.01           0.00991      0.01375        1

                  P(o=2/2) 0.01375                

Bây giờ nó nói P (f> = 0,5) là 26%, tăng so với giả định trước là 0,6%. Vì vậy Bayes cho phép chúng tôi cập nhật ước tính chi phí có thể có của I. Nếu số lượng dữ liệu nhỏ, nó không cho chúng ta biết chính xác chi phí là gì, chỉ là nó đủ lớn để có giá trị sửa chữa.

Tuy nhiên, một cách khác để nhìn vào nó được gọi là Quy tắc kế thừa. Nếu bạn lật một đồng xu 2 lần, và nó đi lên đứng đầu cả hai lần, những gì hiện cho bạn biết về trọng lượng có thể xảy ra của đồng xu? Cách được tôn trọng để trả lời là nói rằng đó là bản phân phối Beta, với giá trị trung bình (số lần truy cập + 1) / (số lần thử + 2) = (2 + 1) / (2 + 2) = 75%.

(Điều quan trọng là chúng ta thấy I nhiều hơn một lần. Nếu chúng ta chỉ nhìn thấy nó một lần, điều đó không cho chúng ta biết nhiều ngoại trừ f > 0.)

Vì vậy, ngay cả một số lượng rất nhỏ các mẫu có thể cho chúng tôi biết rất nhiều về chi phí của hướng dẫn mà nó thấy. (Và nó sẽ thấy chúng với tần số, trung bình, tỷ lệ với chi phí của chúng. n mẫu được lấy, và f là chi phí, sau đó I sẽ xuất hiện trên nf+/-sqrt(nf(1-f)) mẫu. Thí dụ, n=10, f=0.3, đó là 3+/-1.4 mẫu.)


THÊM, để cung cấp cho một cảm giác trực quan cho sự khác biệt giữa đo và lấy mẫu ngẫu nhiên chồng:
Hiện nay có những trình thu thập mẫu, ngay cả trên đồng hồ treo tường, nhưng những gì đi ra là các phép đo (hoặc đường nóng, hoặc điểm nóng, từ đó "nút cổ chai" có thể dễ dàng ẩn). Những gì họ không cho bạn thấy (và họ dễ dàng có thể) là những mẫu thực tế. Và nếu mục tiêu của bạn là tìm thấy nút cổ chai, số lượng bạn cần xem là, Trung bình, 2 chia cho phần thời gian cần. Vì vậy, nếu phải mất 30% thời gian, 2 / .3 = 6.7 mẫu, tính trung bình, sẽ hiển thị nó và cơ hội 20 mẫu sẽ hiển thị là 99.2%.

Dưới đây là một minh họa off-the-cuff của sự khác biệt giữa kiểm tra các phép đo và kiểm tra các mẫu ngăn xếp. Các nút cổ chai có thể là một đốm lớn như thế này, hoặc rất nhiều những cái nhỏ, nó làm cho không có sự khác biệt.

enter image description here

Đo lường là ngang; nó cho bạn biết phần nào của các thói quen cụ thể về thời gian. Lấy mẫu là dọc. Nếu có cách nào để tránh toàn bộ chương trình đang làm gì vào lúc đó, và nếu bạn thấy nó trên mẫu thứ hai, bạn đã tìm thấy nút cổ chai. Đó là những gì tạo ra sự khác biệt - nhìn thấy toàn bộ lý do cho thời gian được chi tiêu, không chỉ là bao nhiêu.


1194
2018-04-21 04:09



Điều này về cơ bản là một hồ sơ lấy mẫu của người nghèo, điều này thật tuyệt vời, nhưng bạn có nguy cơ bị một mẫu quá nhỏ có thể cho bạn kết quả giả mạo hoàn toàn. - Crashworks
@ Crash: Tôi sẽ không tranh luận về "người đàn ông nghèo" một phần :-) Đó là sự thật rằng đo lường chính xác thống kê đòi hỏi nhiều mẫu, nhưng có hai mục tiêu mâu thuẫn - đo lường và vị trí vấn đề. Tôi đang tập trung vào thứ hai, mà bạn cần độ chính xác của vị trí, không chính xác của biện pháp. Vì vậy, ví dụ, có thể có, giữa ngăn xếp, một chức năng gọi A (); chiếm 50% thời gian, nhưng nó có thể ở một hàm B lớn khác, cùng với nhiều lệnh gọi khác đến A () không tốn kém. Tóm tắt chính xác về thời gian hoạt động có thể là một đầu mối, nhưng mọi mẫu ngăn xếp khác sẽ xác định vấn đề. - Mike Dunlavey
... thế giới dường như nghĩ rằng một biểu đồ cuộc gọi, được chú thích với số lượng cuộc gọi và / hoặc thời gian trung bình, là đủ tốt. Không phải vậy. Và phần buồn là, đối với những người lấy mẫu cuộc gọi ngăn xếp, thông tin hữu ích nhất là ngay trước mặt họ, nhưng họ vứt nó đi, vì lợi ích của "thống kê". - Mike Dunlavey
Tôi không có ý là không đồng ý với kỹ thuật của bạn. Rõ ràng là tôi dựa khá nhiều vào các trình thu thập mẫu đi bộ. Tôi chỉ chỉ ra rằng có một số công cụ làm điều đó một cách tự động ngay bây giờ, điều quan trọng là khi bạn đã qua thời điểm nhận hàm từ 25% đến 15% và cần phải hạ thấp từ 1,2% xuống 0,6%. - Crashworks
Cảm ơn bạn rất nhiều vì ý tưởng này. Tôi chỉ sử dụng nó và tôi đã có thể xác định và cải thiện một số tắc nghẽn nghiêm trọng năm ánh sáng nhanh hơn bất kỳ phương pháp khác mà tôi đã thử trong quá khứ. Tôi tăng tốc lên 60 lần. Tôi rùng mình trước ý nghĩ của tất cả mã gỡ lỗi thời gian mà tôi đang cân nhắc thêm. - ErikE


Bạn có thể dùng Valgrind với các tùy chọn sau

valgrind --tool=callgrind ./(Your binary)

Nó sẽ tạo ra một tập tin gọi là callgrind.out.x. Sau đó bạn có thể sử dụng kcachegrind công cụ để đọc tệp này. Nó sẽ cung cấp cho bạn một phân tích đồ họa của những thứ với kết quả như những dòng chi phí bao nhiêu.


472
2017-12-17 20:34



valgrind là tuyệt vời, nhưng được cảnh báo rằng nó sẽ làm cho chương trình của bạn darn chậm - neves
Kiểm tra cũng Gprof2Dot cho một cách thay thế tuyệt vời để hình dung đầu ra. ./gprof2dot.py -f callgrind callgrind.out.x | dot -Tsvg -o output.svg - Sebastian
@neves Có Valgrind không phải là rất hữu ích về tốc độ cho hồ sơ "gstreamer" và "opencv" ứng dụng thời gian thực. - enthusiasticgeek
stackoverflow.com/questions/375913/… là một phần soluton cho vấn đề tốc độ. - Tõnu Samuel
@Sebastian: gprof2dot hiện đang ở đây: github.com/jrfonseca/gprof2dot - John Zwinck


Tôi cho rằng bạn đang sử dụng GCC. Các giải pháp tiêu chuẩn sẽ được để hồ sơ với gprof.

Hãy chắc chắn để thêm -pg để biên dịch trước khi lập hồ sơ:

cc -o myprog myprog.c utils.c -g -pg

Tôi chưa thử nhưng tôi đã nghe những điều tốt đẹp về google-perftools. Nó chắc chắn là giá trị một thử.

Câu hỏi liên quan đây.

Một vài buzzwords khác nếu gprof không thực hiện công việc cho bạn: Valgrind, Intel VTune, Mặt trời DTrace.


296
2017-08-17 11:48



Tôi đồng ý rằng gprof là tiêu chuẩn hiện hành. Chỉ cần một lưu ý, mặc dù, Valgrind được sử dụng để hồ sơ rò rỉ bộ nhớ và các khía cạnh khác liên quan đến bộ nhớ của chương trình của bạn, không phải để tối ưu hóa tốc độ. - Bill the Lizard
Bill, Trong bộ phần mềm âm nhạc bạn có thể tìm thấy callgrind và massif. Cả hai đều khá hữu ích đối với ứng dụng hồ sơ - dario minonne
@ Bill-the-Lizard: Một số nhận xét về gprof : stackoverflow.com/questions/1777556/alternatives-to-gprof/… - Mike Dunlavey
Xem thêm thông tin về gprof của tôi dưới đây, stackoverflow.com/a/6540100/823636 - Rob_before_edits
gprof -pg chỉ là một xấp xỉ lược tả callstack. Nó chèn các cuộc gọi mcount để theo dõi các chức năng nào đang gọi các chức năng khác. Nó sử dụng lấy mẫu dựa trên thời gian tiêu chuẩn cho, uh, thời gian. Sau đó nó apportions lần lấy mẫu trong một hàm foo () trở lại người gọi của foo (), trong proprtion để numberr của các cuộc gọi. Vì vậy, nó không phân biệt giữa các cuộc gọi của các chi phí khác nhau. - Krazy Glew


Các hạt nhân mới hơn (ví dụ: hạt nhân Ubuntu mới nhất) đi kèm với các công cụ 'hoàn thiện' mới (apt-get install linux-tools) AKA perf_events.

Chúng đi kèm với các trình thu thập mẫu cổ điển (người đàn ông trang) cũng như tuyệt vời Biểu đồ thời gian!

Điều quan trọng là những công cụ này có thể hệ thống hồ sơ và không chỉ xử lý hồ sơ - chúng có thể hiển thị sự tương tác giữa các luồng, các tiến trình và hạt nhân và cho phép bạn hiểu các phụ thuộc lập lịch và I / O giữa các tiến trình.

Alt text


216
2018-05-22 21:44



Công cụ tuyệt vời! Có anyway cho tôi để có được một cái nhìn "bướm" điển hình mà bắt đầu từ "main-> func1-> fun2" phong cách? Tôi không thể hình dung ra điều đó ... perf reportdường như cung cấp cho tôi tên hàm với cha mẹ gọi ... (vì vậy nó giống như một cái nhìn bướm ngược) - kizzx2
Will, perf có thể hiển thị timechart của hoạt động thread; với thông tin số CPU được thêm vào? Tôi muốn xem khi nào và thread nào đang chạy trên mọi CPU. - osgx
@ kizzx2 - bạn có thể sử dụng gprof2dot và perf script. Công cụ rất đẹp! - dashesy
Ngay cả các hạt nhân mới hơn như 4.13 có eBPF cho lược tả. Xem brendangregg.com/blog/2015-05-15/ebpf-one-small-step.html và brendangregg.com/ebpf.html - Andrew Stern
Một bài giới thiệu thú vị khác cho perf tồn tại tại archive.li/9r927#selection-767.126-767.271   (Tại sao các vị thần SO quyết định xóa trang đó khỏi cơ sở tri thức SO ở bên ngoài tôi ....) - ragerdl


Tôi sẽ sử dụng Valgrind và Callgrind làm cơ sở cho bộ công cụ lược tả của tôi. Điều quan trọng cần biết là Valgrind về cơ bản là một máy ảo:

(wikipedia) Valgrind thực chất là một ảo   máy sử dụng chỉ trong thời gian (JIT)   kỹ thuật biên dịch, bao gồm   biên dịch lại động. Không có gì từ   chương trình gốc được chạy   trực tiếp trên bộ xử lý máy chủ.   Thay vào đó, Valgrind đầu tiên dịch   chương trình thành một biểu mẫu đơn giản, tạm thời   được gọi là đại diện trung gian   (IR), là bộ xử lý trung tính,   Biểu mẫu dựa trên SSA. Sau khi chuyển đổi,   một công cụ (xem bên dưới) là miễn phí để làm   bất kỳ biến đổi nào nó muốn   trên IR, trước khi Valgrind dịch   IR trở lại vào mã máy và cho phép   bộ xử lý máy chủ chạy nó.

Callgrind là một profiler xây dựng dựa trên đó. Lợi ích chính là bạn không phải chạy aplication của bạn trong nhiều giờ để có được kết quả đáng tin cậy. Ngay cả một lần chạy thứ hai cũng đủ để có được kết quả đáng tin cậy, vững chắc, bởi vì Callgrind là một không thăm dò Hồ sơ.

Một công cụ xây dựng trên Valgrind là Massif. Tôi sử dụng nó để sử dụng bộ nhớ hồ sơ heap. Nó hoạt động tuyệt vời. Những gì nó làm là nó cung cấp cho bạn các bức ảnh chụp sử dụng bộ nhớ - thông tin chi tiết NHỮNG GÌ giữ tỷ lệ phần trăm bộ nhớ, và WHO đã đặt nó ở đó. Thông tin này có sẵn tại các thời điểm khác nhau của thời gian chạy ứng dụng.


65
2018-06-30 19:30





Đây là câu trả lời cho Câu trả lời Gprof của Nazgob.

Tôi đã sử dụng Gprof trong vài ngày qua và đã tìm thấy ba hạn chế đáng kể, một trong số đó tôi chưa thấy tài liệu ở bất kỳ nơi nào khác (chưa):

  1. Nó không hoạt động đúng trên mã đa luồng, trừ khi bạn sử dụng cách giải quyết

  2. Biểu đồ cuộc gọi bị nhầm lẫn bởi con trỏ hàm. Ví dụ: Tôi có một hàm gọi là đa luồng () cho phép tôi đa luồng một hàm được chỉ định trên một mảng được chỉ định (cả hai đều được truyền làm đối số). Tuy nhiên, Gprof xem tất cả các cuộc gọi tới đa luồng () tương đương với mục đích thời gian tính toán dành cho trẻ em. Vì một số hàm tôi chuyển sang đa luồng () mất nhiều thời gian hơn so với các hàm khác, nên biểu đồ cuộc gọi của tôi hầu hết là vô ích. (Đối với những người tự hỏi nếu luồng là vấn đề ở đây: không, đa luồng () có thể tùy chọn, và đã làm trong trường hợp này, chạy tất cả mọi thứ tuần tự trên chỉ gọi thread).

  3. Nó nói rằng đây "... số liệu số cuộc gọi được bắt nguồn bằng cách đếm, không lấy mẫu. Chúng hoàn toàn chính xác ...". Tuy nhiên, tôi tìm thấy biểu đồ cuộc gọi của tôi cho tôi 5345859132 + 784984078 làm số liệu thống kê cuộc gọi đến hàm được gọi nhiều nhất của tôi, trong đó số đầu tiên được gọi là cuộc gọi trực tiếp và cuộc gọi đệ quy thứ hai (tất cả đều là từ chính nó). Vì điều này ngụ ý rằng tôi đã có một lỗi, tôi đặt các bộ đếm dài (64 bit) vào mã và chạy lại một lần nữa. Số của tôi: 5345859132 trực tiếp và 78094395406 cuộc gọi tự đệ quy. Có rất nhiều chữ số ở đó, vì vậy tôi sẽ chỉ ra các cuộc gọi đệ quy tôi đo là 78bn, so với 784m từ Gprof: hệ số 100 khác nhau. Cả hai lần chạy đều là chuỗi đơn và không được tối ưu hóa, một mã được biên dịch -g và -pg khác.

Đây là GNU Gprof (GNU Binutils cho Debian) 2.18.0.20080103 chạy dưới Debian 64 bit, nếu điều đó giúp bất cứ ai.


49
2018-06-08 08:01



dường như nó có thể lấy mẫu stackoverflow.com/a/11143125/32453 - rogerdpack
Có, nó lấy mẫu, nhưng không lấy mẫu số. Thật thú vị, sau liên kết của bạn cuối cùng dẫn tôi đến một phiên bản cập nhật của trang hướng dẫn tôi liên kết đến trong bài viết của tôi, URL mới: sourceware.org/binutils/docs/gprof/…  Điều này lặp lại câu trả lời một phần (iii) câu trả lời của tôi, nhưng cũng nói "Trong các ứng dụng đa luồng, hoặc các ứng dụng đơn luồng liên kết với các thư viện đa luồng, số đếm chỉ xác định nếu hàm đếm là an toàn chỉ." Lưu ý: hãy cẩn thận rằng hàm đếm số đếm trong glibc không phải là chủ đề an toàn). " - Rob_before_edits
Điều này không rõ ràng với tôi nếu điều này giải thích kết quả của tôi trong (iii). Mã của tôi đã được liên kết -lpthread -lm và khai báo cả một "pthread_t * thr" và một "pthread_mutex_t nextLock = PTHREAD_MUTEX_INITIALIZER" biến tĩnh ngay cả khi nó đang chạy đơn luồng. Tôi thường giả định rằng "liên kết với các thư viện đa luồng" có nghĩa là thực sự sử dụng các thư viện đó, và ở mức độ lớn hơn điều này, nhưng tôi có thể sai! - Rob_before_edits


Câu trả lời để chạy valgrind --tool=callgrind không hoàn toàn không có một số tùy chọn. Chúng tôi thường không muốn hồ sơ 10 phút của thời gian khởi động chậm theo Valgrind và muốn hồ sơ chương trình của chúng tôi khi nó đang làm một số nhiệm vụ.

Vì vậy, đây là những gì tôi khuyên bạn nên. Chạy chương trình trước:

valgrind --tool=callgrind --dump-instr=yes -v --instr-atstart=no ./binary > tmp

Bây giờ khi nó hoạt động và chúng ta muốn bắt đầu lược tả chúng ta nên chạy trong một cửa sổ khác:

callgrind_control -i on

Điều này biến hồ sơ trên. Để tắt và dừng toàn bộ tác vụ, chúng tôi có thể sử dụng:

callgrind_control -k

Bây giờ chúng tôi có một số tập tin có tên callgrind.out. * Trong thư mục hiện tại. Để xem kết quả lược tả, hãy sử dụng:

kcachegrind callgrind.out.*

Tôi đề nghị trong cửa sổ tiếp theo để nhấp vào tiêu đề cột "Tự", nếu không nó cho thấy rằng "chính ()" là nhiệm vụ tốn thời gian nhất. "Tự" cho thấy mỗi hàm của chính nó mất nhiều thời gian, chứ không phải cùng với người phụ thuộc.


47
2018-02-23 21:28



Bây giờ trên một số lý do callgrind.out. * Tệp luôn trống. Việc thực thi callgrind_control -d rất hữu ích để buộc kết xuất dữ liệu vào đĩa. - Tõnu Samuel
Tôi đang bối rối về những hướng dẫn này. bạn đang nói thế à trong khi chương trình đang chạy, chúng ta có thể thực thi callgrind_control trong cửa sổ khác để bật / tắt lược tả? có vẻ như với tôi như nó muốn được cách tốt hơn để thiết kế một chương trình tối thiểu bao gồm chỉ những gì bạn muốn hồ sơ, và sau đó hồ sơ toàn bộ chương trình. - dbliss
Không thể. Bối cảnh bình thường của tôi là một cái gì đó giống như toàn bộ MySQL hoặc PHP hoặc một số điều lớn tương tự. Thường thì thậm chí không biết những gì tôi muốn tách ra lúc đầu. - Tõnu Samuel
Hoặc trong trường hợp của tôi, chương trình của tôi thực sự tải một loạt dữ liệu vào bộ nhớ cache LRU và tôi không muốn cấu hình nó. Vì vậy, tôi buộc tải một tập hợp con của bộ nhớ đệm lúc khởi động và cấu hình mã chỉ sử dụng dữ liệu đó (cho phép CPU OS + quản lý việc sử dụng bộ nhớ trong bộ nhớ cache của tôi). Nó hoạt động, nhưng tải bộ nhớ cache chậm và CPU chuyên sâu trên mã mà tôi đang cố gắng để cấu hình trong một bối cảnh khác nhau, vì vậy callgrind tạo ra kết quả bị ô nhiễm nặng. - Code Abominator
đó cũng là CALLGRIND_TOGGLE_COLLECT để bật / tắt thu thập theo chương trình; xem stackoverflow.com/a/13700817/288875 - Andre Holzner


Sử dụng Valgrind, callgrind và kcachegrind: 

valgrind --tool=callgrind ./(Your binary)

tạo ra callgrind.out.x. Đọc nó bằng cách sử dụng kcachegrind.

Sử dụng gprof (add -pg): 

cc -o myprog myprog.c utils.c -g -pg 

(không tốt cho nhiều chủ đề, con trỏ hàm)

Sử dụng google-perftools: 

Sử dụng lấy mẫu thời gian, cho thấy các nút thắt I / O và CPU được tiết lộ.

Intel VTune là tốt nhất (miễn phí cho mục đích giáo dục).

Khác: Các công cụ AMD Codeanalyst, OProfile, 'perf' (apt-get install linux-tools)


8
2018-03-17 12:20



Tôi không đồng ý với câu trả lời của bạn, nhưng tôi đồng ý với lịch sử của bạn - kỹ thuật, CS, trình độ sau đại học và giảng dạy nâng cao. Chúc may mắn. - Mike Dunlavey


Đối với các chương trình đơn luồng, bạn có thể sử dụng igprof, The Profular Ignominous: https://igprof.org/ .

Nó là một hồ sơ lấy mẫu, dọc theo dòng câu trả lời ... dài ... của Mike Dunlavey, trong đó món quà sẽ bọc kết quả trong một cây gọi có thể duyệt được, được chú thích bằng thời gian hoặc bộ nhớ dành cho mỗi chức năng, hoặc tích lũy hoặc mỗi chức năng.


4
2017-11-28 18:21





Đây là hai phương pháp tôi sử dụng để tăng tốc mã của mình:

Đối với các ứng dụng CPU bị ràng buộc:

  1. Sử dụng trình lược tả trong chế độ DEBUG để xác định các phần có vấn đề trong mã của bạn
  2. Sau đó chuyển sang chế độ RELEASE và nhận xét các phần có vấn đề về mã của bạn (không cho nó biết gì) cho đến khi bạn thấy các thay đổi về hiệu suất.

Đối với các ứng dụng liên kết I / O:

  1. Sử dụng trình lược tả trong chế độ RELEASE để xác định các phần có vấn đề trong mã của bạn.

N.B.

Nếu bạn không có hồ sơ, hãy sử dụng hồ sơ của người nghèo. Nhấn tạm dừng trong khi gỡ lỗi ứng dụng của bạn. Hầu hết các bộ phát triển sẽ đột nhập vào hội đồng với số dòng nhận xét. Bạn đang có khả năng thống kê đất ở một khu vực đang ăn hầu hết các chu kỳ CPU của bạn.

Đối với CPU, lý do cho việc định hình DEBUG chế độ là vì nếu bạn đã cố gắng lược tả GIẢI PHÓNG chế độ, trình biên dịch sẽ giảm toán học, các vòng vector hóa và các hàm nội tuyến có xu hướng kết thúc mã của bạn thành một mớ hỗn độn không thể sửa được khi nó được lắp ráp. Một mớ hỗn độn không thể sửa chữa có nghĩa là hồ sơ của bạn sẽ không thể xác định rõ ràng những gì đang mất quá lâu bởi vì hội đồng có thể không tương ứng với mã nguồn theo tối ưu hóa. Nếu bạn cần hiệu suất (ví dụ: thời gian nhạy cảm) của GIẢI PHÓNG , tắt các tính năng gỡ lỗi khi cần để giữ hiệu suất có thể sử dụng được.

Đối với I / O-bound, profiler vẫn có thể xác định các hoạt động I / O trong GIẢI PHÓNG bởi vì các hoạt động I / O được liên kết bên ngoài với một thư viện chia sẻ (phần lớn thời gian) hoặc trong trường hợp xấu nhất, sẽ dẫn đến một vector ngắt sys-call (cũng dễ dàng nhận dạng bởi profiler).


2



Phương pháp của người nghèo hoạt động tốt cho I / O bị ràng buộc vì CPU bị ràng buộc, và tôi khuyên bạn nên thực hiện tất cả các điều chỉnh hiệu năng trong chế độ DEBUG. Khi bạn hoàn thành điều chỉnh, sau đó bật RELEASE. Nó sẽ làm cho một sự cải tiến nếu chương trình là CPU-ràng buộc trong mã của bạn. Đây là một đoạn video thô sơ nhưng ngắn của quá trình. - Mike Dunlavey
Tôi sẽ không sử dụng DEBUG để xây dựng hồ sơ hiệu suất. Thường thì tôi đã thấy rằng các phần quan trọng về hiệu suất trong chế độ DEBUG được tối ưu hóa hoàn toàn trong chế độ phát hành. Một vấn đề khác là việc sử dụng các xác nhận trong mã gỡ lỗi làm tăng thêm nhiễu cho hiệu suất. - gast128
Bạn đã đọc bài của tôi chưa? "Nếu bạn cần hiệu suất (ví dụ: thời gian nhạy cảm) của chế độ RELEASE, hãy tắt các tính năng gỡ lỗi khi cần để giữ hiệu suất có thể sử dụng", "Sau đó chuyển sang chế độ RELEASE và nhận xét các phần có vấn đề của mã của bạn (Cho nó không có gì) cho đến khi bạn thấy thay đổi về hiệu suất. "? Tôi đã nói kiểm tra các khu vực có vấn đề có thể xảy ra trong chế độ gỡ lỗi và xác minh những vấn đề đó trong chế độ phát hành để tránh những cạm bẫy bạn đã đề cập. - seo