Số lượng chủ đề tối ưu trên mỗi lõi


280

Giả sử tôi có CPU 4 nhân và tôi muốn chạy một số quy trình trong khoảng thời gian tối thiểu. Quá trình này là lý tưởng song song, vì vậy tôi có thể chạy các đoạn của nó trên một số lượng vô hạn của các luồng và mỗi luồng mất cùng một lượng thời gian.

Vì tôi có 4 lõi, tôi không mong đợi bất kỳ sự tăng tốc nào bằng cách chạy nhiều luồng hơn lõi, vì một lõi chỉ có khả năng chạy một luồng duy nhất tại một thời điểm nhất định. Tôi không biết nhiều về phần cứng, vì vậy đây chỉ là dự đoán.

Có một lợi ích để chạy một quá trình song song trên nhiều luồng hơn lõi? Nói cách khác, quá trình của tôi sẽ kết thúc nhanh hơn, chậm hơn hay trong cùng một khoảng thời gian nếu tôi chạy nó bằng 4000 luồng chứ không phải 4 luồng?

Câu trả lời:


253

Nếu các luồng của bạn không thực hiện I / O, đồng bộ hóa, v.v. và không có gì khác đang chạy, 1 luồng trên mỗi lõi sẽ giúp bạn có hiệu suất tốt nhất. Tuy nhiên điều đó rất có thể không phải là trường hợp. Thêm nhiều chủ đề thường giúp, nhưng sau một số điểm, chúng gây ra một số suy giảm hiệu suất.

Cách đây không lâu, tôi đã thực hiện kiểm tra hiệu năng trên máy 2 nhân bốn chạy ứng dụng ASP.NET trên Mono dưới một tải khá tốt. Chúng tôi đã chơi với số lượng luồng tối thiểu và tối đa và cuối cùng chúng tôi phát hiện ra rằng đối với ứng dụng cụ thể đó trong cấu hình cụ thể đó, thông lượng tốt nhất nằm ở khoảng giữa 36 và 40 luồng. Bất cứ điều gì bên ngoài những ranh giới thực hiện tồi tệ hơn. Bài học kinh nghiệm? Nếu tôi là bạn, tôi sẽ kiểm tra với số lượng chủ đề khác nhau cho đến khi bạn tìm thấy số phù hợp cho ứng dụng của mình.

Một điều chắc chắn: chủ đề 4k sẽ mất nhiều thời gian hơn. Đó là rất nhiều chuyển đổi bối cảnh.


21
Tôi nghĩ câu trả lời của Gonzalo là tốt. Tôi chỉ cần thêm rằng bạn nên thử nghiệm và đo lường. Chương trình của bạn sẽ khác với chương trình của anh ấy hoặc của tôi hoặc của bất kỳ ai khác và chỉ các phép đo hành vi của chương trình của bạn sẽ trả lời đúng câu hỏi của bạn. Việc thực hiện các chương trình song song (hoặc đồng thời) không phải là một lĩnh vực mà ở đó các kết luận tốt có thể được rút ra từ các nguyên tắc đầu tiên.
Đánh dấu hiệu suất cao

5
+1, + trả lời: điều làm tôi ngạc nhiên là việc có nhiều luồng hơn lõi dẫn đến hiệu suất tốt hơn, mặc dù nó có ý nghĩa nếu nhiều luồng hơn có nghĩa là chia sẻ thời gian lớn hơn so với các luồng cạnh tranh. Thật tuyệt khi ứng dụng của tôi có thể phát hiện ra sự khác biệt về hiệu suất và tự động điều chỉnh chính nó theo số lượng luồng tối ưu.
Juliet

12
Nó không làm bạn ngạc nhiên trong một kịch bản thế giới thực. Các luồng xử lý đang chờ các tài nguyên IO như truy cập đĩa, mạng, v.v. Và cũng chờ các tài nguyên không phải IO như các luồng khác kết thúc bằng các biến được chia sẻ. Những gì bạn thực sự muốn đạt được là số lượng luồng tối thiểu sao cho ít nhất một luồng trên mỗi lõi luôn có thể chạy.
tuần tra

4
1 luồng trên mỗi lõi không phải là tối ưu. Nó cần phải nhiều hơn một chút, tốt nhất là gấp đôi vì điều này sẽ cho phép một luồng khác chạy nếu một luồng tạm thời bị chặn. Ngay cả khi chỉ trên bộ nhớ. Đây là phần nhập nhiều hơn nếu bạn có các hệ thống (P4, I7, Sun Rock, v.v.) có tính năng SMT / HT)
Marco van de Voort

1
Do đó, "Điều đó rất có thể không phải là trường hợp" trong câu trả lời của tôi. Tìm đúng số phụ thuộc vào ứng dụng và kiến ​​trúc mà nó chạy.
Gonzalo

129

Tôi đồng ý với câu trả lời của @ Gonzalo. Tôi có một quy trình không thực hiện I / O và đây là những gì tôi đã tìm thấy:

nhập mô tả hình ảnh ở đây

Lưu ý rằng tất cả các luồng hoạt động trên một mảng nhưng phạm vi khác nhau (hai luồng không truy cập vào cùng một chỉ mục), vì vậy kết quả có thể khác nhau nếu chúng hoạt động trên các mảng khác nhau.

Máy 1.86 là máy macbook air có SSD. Mac khác là iMac với ổ cứng thông thường (tôi nghĩ đó là 7200 vòng / phút). Máy windows cũng có ổ cứng 7200 vòng / phút.

Trong thử nghiệm này, số lượng tối ưu bằng với số lõi trong máy.


14
+1 cho biểu đồ. Rõ ràng 1 luồng trên mỗi lõi là tốt nhất, nhưng thật thú vị khi hệ thống lõi tứ dường như không có số luồng cao hơn (dù sao <100) theo cách mà những người khác làm.
Jim Garrison

46
-1 cho biểu đồ! Đường cong mượt mà thông qua tọa độ x có giá trị nguyên? Bước nhảy tự nhiên từ 1 2 3 đến 10 20 30 đến 50 100? Và tọa độ y là bội số của 10 cộng 2 cho số đo tốt. Đây là Excel đang làm, phải không?
Spainedman

5
@Spacesman Đúng vậy. Các đường cong mượt mà có một cái nhìn đẹp hơn nhiều IMHO. : D
Motasim

22
@PascalvKooten, Vấn đề không phải là nó trông đẹp, nó thoạt nhìn lừa dối. Trước hết, trục y bắt đầu từ 42, phóng đại sự khác biệt rõ ràng giữa các máy được thử nghiệm. Thứ hai, sự tiến triển kỳ lạ của các giá trị trục x cho thấy rằng 'thời gian' không quy mô tuyến tính với 'số lượng luồng', điều này đặc biệt đúng với đường màu xanh. Tôi nghĩ vấn đề mà những người khác (bao gồm cả bản thân tôi) gặp phải là nó làm sai lệch dữ liệu.
pauluss86

13
@Spacesman Việc phê bình trên biểu đồ là điều nực cười nhất mà tôi đã gặp trong 24 giờ qua. Các biểu đồ giúp. Rất nhiều. Giai đoạn = Stage. Nó có thể được thực hiện tốt hơn? Không ai quan tâm. Đường cong mượt mà thay vì rời rạc? Đó là vấn đề của bạn???? Tôi cho rằng, tất cả các bạn sẽ không bao giờ đưa biểu đồ như vậy vào câu trả lời của họ vì bạn không có thêm thời gian / năng lượng để làm cho nó trông đẹp hơn. Đó là quan điểm của tôi.
tyrex

49

Tôi biết câu hỏi này khá cũ, nhưng mọi thứ đã phát triển từ năm 2009.

Hiện tại có hai điều cần tính đến: số lượng lõi và số lượng luồng có thể chạy trong mỗi lõi.

Với bộ xử lý Intel, số lượng luồng được xác định bởi Hyperthreading chỉ là 2 (khi khả dụng). Nhưng Hyperthreading cắt giảm thời gian thực hiện của bạn xuống hai, ngay cả khi không sử dụng 2 luồng! (tức là 1 đường ống được chia sẻ giữa hai quy trình - điều này tốt khi bạn có nhiều quy trình hơn, không tốt lắm nếu không. Nhiều lõi hơn chắc chắn tốt hơn!)

Trên các bộ xử lý khác, bạn có thể có 2, 4 hoặc thậm chí 8 luồng. Vì vậy, nếu bạn có 8 lõi, mỗi lõi hỗ trợ 8 luồng, bạn có thể có 64 tiến trình chạy song song mà không cần chuyển đổi ngữ cảnh.

"Không chuyển đổi ngữ cảnh" rõ ràng là không đúng nếu bạn chạy với một hệ điều hành tiêu chuẩn sẽ thực hiện chuyển đổi ngữ cảnh cho tất cả các loại khác ngoài tầm kiểm soát của bạn. Nhưng đó là ý chính. Một số HĐH cho phép bạn phân bổ bộ xử lý để chỉ ứng dụng của bạn có quyền truy cập / sử dụng bộ xử lý nói trên!

Từ kinh nghiệm của riêng tôi, nếu bạn có nhiều I / O, nhiều chủ đề là tốt. Nếu bạn có công việc đòi hỏi rất nhiều bộ nhớ (đọc nguồn 1, đọc nguồn 2, tính toán nhanh, viết) thì việc có nhiều luồng không giúp ích được gì. Một lần nữa, điều này phụ thuộc vào số lượng dữ liệu bạn đọc / ghi đồng thời (nghĩa là nếu bạn sử dụng SSE 4.2 và đọc các giá trị 256 bit, điều đó dừng tất cả các luồng trong bước của chúng ... nói cách khác, 1 luồng có thể dễ thực hiện hơn nhiều và có thể gần như nhanh hơn nếu không thực sự nhanh hơn. Điều này phụ thuộc vào kiến ​​trúc quy trình & bộ nhớ của bạn, một số máy chủ nâng cao quản lý phạm vi bộ nhớ riêng cho các lõi riêng biệt, vì vậy các luồng riêng biệt sẽ nhanh hơn khi giả sử dữ liệu của bạn được gửi đúng cách ... Kiến trúc, 4 quy trình sẽ chạy nhanh hơn 1 quy trình với 4 luồng.)


4
Có thể có những cái khác, nhưng cái tôi biết là bộ xử lý POWER của IBM. Họ có hệ thống với 4 hoặc 8 luồng trên mỗi bộ xử lý. Bây giờ họ có thể quay trong nhiều lõi hơn, vì vậy họ cung cấp 2 luồng cho mỗi lõi thay vì ...
Alexis Wilke

Điều này đã cũ, nhưng hầu hết Intel i5, i7 có cpu đa luồng, ví dụ như cpu của i7 thường có 4 lõi, nhưng 8 luồng.
Edgar.

4
Bộ xử lý không có chủ đề. Họ có lõi vật lý và logic. Với siêu phân luồng, một lõi vật lý duy nhất có chức năng như hai lõi logic. Tôi có một công nghệ khăng khăng rằng các bộ xử lý có các luồng là một thứ có thật, vì vậy tôi đã vẽ một bức tranh trên bảng trắng của một bộ xử lý với trục chính của sợi chỉ dính ra khỏi nó.

@TechnikEmpire Hãy xem intel.com/content/www/us/en/ Processors / core / Đây , có lẽ sau đó bạn có thể liên hệ với intel và vẽ chúng theo chủ đề.
g7k

24

Hiệu suất thực tế sẽ phụ thuộc vào mức độ tự nguyện của mỗi luồng sẽ làm. Ví dụ: nếu các luồng hoàn toàn KHÔNG có I / O và không sử dụng dịch vụ hệ thống nào (tức là chúng có giới hạn 100% cpu) thì 1 luồng trên mỗi lõi là tối ưu. Nếu các chủ đề làm bất cứ điều gì đòi hỏi phải chờ đợi, thì bạn sẽ phải thử nghiệm để xác định số lượng chủ đề tối ưu. 4000 luồng sẽ phải chịu chi phí lập kế hoạch đáng kể, do đó có lẽ cũng không tối ưu.


21

Câu trả lời phụ thuộc vào độ phức tạp của các thuật toán được sử dụng trong chương trình. Tôi đã đưa ra một phương pháp để tính toán số lượng luồng tối ưu bằng cách thực hiện hai phép đo thời gian xử lý Tn và Tm cho hai số lượng luồng tùy ý 'n' và 'm'. Đối với các thuật toán tuyến tính, số lượng chủ đề tối ưu sẽ là N = sqrt ((m n (Tm * (n-1) - Tn * (m-1))) / (n Tn-m Tm)).

Vui lòng đọc bài viết của tôi về các tính toán của số tối ưu cho các thuật toán khác nhau: pavelkazenin.wordpress.com


4
Tại sao nó bị hạ cấp? Tôi xin lỗi nhưng đây là câu trả lời tốt nhất cho câu hỏi này. gonzalo giải quyết phần táo bạo của câu hỏi và pkazen giải quyết tiêu đề. Cả hai câu trả lời đều rất hữu ích, nhưng câu trả lời pkazen có liên quan vì chúng tôi có một phương pháp có hệ thống để tính gần đúng số lượng luồng. Ông thậm chí còn đưa ra công thức cho các thuật toán linea.
tobiak777

1
Tôi đã không downvote nhưng nếu tôi đã làm thì sẽ dựa trên cơ sở rằng không có lời giải thích thực sự nào về lý do tại sao hoặc làm thế nào số lượng luồng tối ưu có thể liên quan đến độ phức tạp của thuật toán, hãy lưu lại bằng cách đọc toàn bộ bài viết được liên kết, là một bài đọc dài (vì sự phức tạp của bài viết). Ngoài ra, một số khía cạnh của bài viết đối với tôi không rõ ràng, quan trọng nhất là làm thế nào các kết quả thí nghiệm xác nhận lý thuyết.
Codebling

Ngoài ra, tôi tin rằng tính toán này giả định rằng bạn có số lượng lõi CPU vô hạn. Trong khi đây chắc chắn là thông tin có giá trị, câu hỏi đang đề cập đến các máy thật với số lượng lõi nhỏ.
Navneeth

9

Tôi nghĩ tôi sẽ thêm một góc nhìn khác ở đây. Câu trả lời phụ thuộc vào câu hỏi giả định tỷ lệ yếu hay tỷ lệ mạnh.

Từ Wikipedia :

Chia tỷ lệ yếu: cách thời gian giải pháp thay đổi theo số lượng bộ xử lý cho kích thước sự cố cố định trên mỗi bộ xử lý.

Mở rộng quy mô: cách thời gian giải pháp thay đổi theo số lượng bộ xử lý cho tổng kích thước sự cố cố định.

Nếu câu hỏi giả định tỷ lệ yếu thì câu trả lời của @ Gonzalo đủ. Tuy nhiên, nếu câu hỏi giả định mở rộng mạnh mẽ, có thêm điều gì đó để thêm. Trong quy mô mạnh, bạn giả định kích thước khối lượng công việc cố định, vì vậy nếu bạn tăng số lượng luồng, kích thước của dữ liệu mà mỗi luồng cần làm việc sẽ giảm. Trên các bộ nhớ CPU hiện đại, bộ nhớ truy cập rất tốn kém và nên duy trì trạng thái cục bộ bằng cách giữ dữ liệu trong bộ nhớ cache. Do đó, số lượng luồng tối ưu có thể được tìm thấy khi tập dữ liệu của từng luồng phù hợp với bộ đệm của từng lõi (Tôi sẽ không đi sâu vào chi tiết thảo luận về việc liệu đó có phải là bộ đệm L1 / L2 / L3 của hệ thống không.

Điều này đúng ngay cả khi số lượng luồng vượt quá số lõi. Ví dụ, giả sử có 8 đơn vị công việc tùy ý (hoặc AU) trong chương trình sẽ được thực hiện trên máy 4 lõi.

Trường hợp 1: chạy với bốn luồng trong đó mỗi luồng cần hoàn thành 2AU. Mỗi luồng mất 10 giây để hoàn thành ( với rất nhiều lỗi nhớ cache ). Với bốn lõi, tổng thời gian sẽ là 10 giây (10 giây * 4 luồng / 4 lõi).

Trường hợp 2: chạy với tám luồng trong đó mỗi luồng cần hoàn thành 1AU. Mỗi luồng chỉ mất 2 giây (thay vì 5s vì số lượng bộ nhớ cache bị giảm ). Với bốn lõi, tổng thời gian sẽ là 4 giây (2 giây * 8 luồng / 4 lõi).

Tôi đã đơn giản hóa vấn đề và bỏ qua các chi phí được đề cập trong các câu trả lời khác (ví dụ: chuyển đổi ngữ cảnh) nhưng hy vọng bạn nhận được rằng có thể có nhiều số luồng hơn số lõi có sẵn, tùy thuộc vào kích thước dữ liệu bạn ' đang đối phó với.


7

4000 chủ đề cùng một lúc là khá cao.

Câu trả lời là có hoặc không. Nếu bạn đang thực hiện nhiều lệnh chặn I / O trong mỗi luồng, thì có, bạn có thể hiển thị các tốc độ đáng kể khi thực hiện tối đa 3 hoặc 4 luồng trên mỗi lõi logic.

Tuy nhiên, nếu bạn không thực hiện nhiều thao tác chặn, thì việc thêm chi phí với luồng sẽ chỉ làm cho nó chậm hơn. Vì vậy, sử dụng một hồ sơ và xem nơi tắc nghẽn trong mỗi phần có thể song song. Nếu bạn đang thực hiện các tính toán nặng, thì hơn 1 luồng cho mỗi CPU sẽ không giúp ích. Nếu bạn đang thực hiện nhiều lần chuyển bộ nhớ, điều đó cũng không giúp được gì. Nếu bạn đang thực hiện nhiều I / O như truy cập đĩa hoặc truy cập internet, thì có nhiều luồng sẽ giúp đến một mức độ nhất định hoặc ít nhất làm cho ứng dụng phản ứng nhanh hơn.


7

Điểm chuẩn.

Tôi sẽ bắt đầu tăng số lượng luồng cho một ứng dụng, bắt đầu từ 1, rồi đi đến thứ gì đó như 100, chạy ba thử nghiệm cho mỗi số luồng và tạo cho mình một biểu đồ tốc độ hoạt động so với số luồng .

Bạn nên rằng trường hợp bốn luồng là tối ưu, với thời gian chạy tăng nhẹ sau đó, nhưng có thể không. Có thể ứng dụng của bạn bị giới hạn băng thông, tức là bộ dữ liệu bạn đang tải vào bộ nhớ là rất lớn, bạn đang nhận được rất nhiều lỗi bộ nhớ cache, v.v., sao cho 2 luồng là tối ưu.

Bạn không thể biết cho đến khi bạn kiểm tra.


3

Bạn sẽ tìm thấy có bao nhiêu luồng bạn có thể chạy trên máy của mình bằng cách chạy lệnh htop hoặc ps trả về số lượng quá trình trên máy của bạn.

Bạn có thể sử dụng trang man về lệnh 'ps'.

man ps

Nếu bạn muốn tính số lượng của tất cả quá trình người dùng, bạn có thể sử dụng một trong các lệnh sau:

  1. ps -aux| wc -l
  2. ps -eLf | wc -l

Tính số lượng của một quá trình người dùng:

  1. ps --User root | wc -l

Ngoài ra, bạn có thể sử dụng "htop" [Tham khảo] :

Cài đặt trên Ubuntu hoặc Debian:

sudo apt-get install htop

Cài đặt trên Redhat hoặc CentOS:

yum install htop
dnf install htop      [On Fedora 22+ releases]

Nếu bạn muốn biên dịch htop từ mã nguồn, bạn sẽ tìm thấy nó ở đây .


2

Lý tưởng là 1 luồng trên mỗi lõi, miễn là không có luồng nào sẽ chặn.

Một trường hợp điều này có thể không đúng: có các luồng khác đang chạy trên lõi, trong trường hợp đó, nhiều luồng hơn có thể cung cấp cho chương trình của bạn một lát cắt lớn hơn về thời gian thực hiện.


Nó phụ thuộc vào việc bạn có muốn các tiến trình nền của người dùng chạy như crap trong khi ứng dụng của bạn đang chạy không. Đối với vấn đề đó, bạn chỉ có thể đặt mức độ ưu tiên theo thời gian thực cho mỗi luồng và nhận được lượng điện năng tối đa. Nhưng người dùng thích đa nhiệm.
Earlz

2
Vâng, chúng tôi đang đối phó với một ứng dụng song song lý tưởng kỳ diệu. Nếu tôi từng tạo ra một thứ như vậy, tôi sẽ cảm thấy có quyền hog CPU nhiều như tôi muốn.
tuần tra

2

Một ví dụ về rất nhiều luồng ("nhóm luồng") so với mỗi lõi là việc triển khai máy chủ web trong Linux hoặc trong Windows.

Vì các socket được thăm dò trong Linux, rất nhiều luồng có thể làm tăng khả năng một trong số chúng bỏ phiếu đúng ổ cắm vào đúng thời điểm - nhưng chi phí xử lý chung sẽ rất cao.

Trong Windows, máy chủ sẽ được triển khai bằng Cổng hoàn thành I / O - IOCPs - điều này sẽ khiến sự kiện ứng dụng được điều khiển: nếu I / O hoàn thành, HĐH sẽ khởi chạy một luồng dự phòng để xử lý nó. Khi quá trình xử lý đã hoàn tất (thường là với một thao tác I / O khác như trong cặp phản hồi yêu cầu), luồng sẽ trở về cổng IOCP (hàng đợi) để chờ hoàn thành tiếp theo.

Nếu không có I / O nào hoàn thành thì không có xử lý nào được thực hiện và không có luồng nào được khởi chạy.

Thật vậy, Microsoft khuyến nghị không quá một luồng trên mỗi lõi trong các triển khai IOCP. Bất kỳ I / O nào cũng có thể được gắn vào cơ chế IOCP. IOC cũng có thể được đăng bởi ứng dụng, nếu cần thiết.


Tôi không biết bạn đang nói về Linux nào, nhưng các khối của tôi cho đến khi có kết nối. Tôi đề nghị bạn đọc một vài điều về select () và FD_SET () và các hàm / macro tương tự.
Alexis Wilke

Ok, vậy không có hình thức không đồng bộ nào trả về ngay lập tức?
Olof Forshell

Từ trang người được chọn ():timeout is an upper bound on the amount of time elapsed before select() returns. If both fields of the timeval structure are zero, then select() returns immediately. (This is useful for polling.) If timeout is NULL (no timeout), select() can block indefinitely.
Alexis Wilke

0

phát biểu từ quan điểm ràng buộc về tính toán và bộ nhớ (tính toán khoa học) 4000 luồng sẽ làm cho ứng dụng chạy rất chậm. Một phần của vấn đề là chi phí chuyển đổi ngữ cảnh rất cao và rất có thể là địa phương bộ nhớ rất kém.

Nhưng nó cũng phụ thuộc vào kiến ​​trúc của bạn. Từ nơi tôi nghe nói bộ xử lý Niagara được cho là có thể xử lý nhiều luồng trên một lõi bằng cách sử dụng một số loại kỹ thuật đường ống tiên tiến. Tuy nhiên tôi không có kinh nghiệm với những bộ xử lý đó.


0

Hy vọng điều này có ý nghĩa, Kiểm tra việc sử dụng CPU và Bộ nhớ và đặt một số giá trị ngưỡng. Nếu giá trị ngưỡng được vượt qua, không cho phép tạo luồng mới khác cho phép ...

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.