Kịch bản ứng dụng của tôi là như thế này: Tôi muốn đánh giá hiệu năng đạt được trên máy tính lõi tứ để xử lý cùng một lượng dữ liệu. Tôi có hai cấu hình sau:Cần suy nghĩ về lược tả đa luồng trong C trên Linux
i) 1-Process: Một chương trình không có luồng và xử lý dữ liệu từ 1M .. 1G, trong khi hệ thống được giả định chỉ chạy lõi đơn của lõi 4 nhân của nó.
ii) 4-threads-Process: Một chương trình có 4 luồng (tất cả các chuỗi hoạt động giống nhau) nhưng xử lý 25% dữ liệu đầu vào.
Trong chương trình tạo 4 chuỗi, tôi đã sử dụng các tùy chọn mặc định của pthread (tức là, không có bất kỳ pthread_attr_t cụ thể nào). Tôi tin rằng hiệu suất đạt được của cấu hình 4-thread so với cấu hình 1-Process nên gần gũi hơn với 400% (hoặc một nơi nào đó giữa 350% và 400%).
tôi cấu hình thời gian dành cho sự sáng tạo của đề giống như dưới đây:
timer_start(&threadCreationTimer);
pthread_create(&thread0, NULL, fun0, NULL);
pthread_create(&thread1, NULL, fun1, NULL);
pthread_create(&thread2, NULL, fun2, NULL);
pthread_create(&thread3, NULL, fun3, NULL);
threadCreationTime = timer_stop(&threadCreationTimer);
pthread_join(&thread0, NULL);
pthread_join(&thread1, NULL);
pthread_join(&thread2, NULL);
pthread_join(&thread3, NULL);
Kể từ khi tăng kích thước của dữ liệu đầu vào cũng có thể tăng lên trong những yêu cầu bộ nhớ của mỗi chủ đề, sau đó để tải tất cả các dữ liệu trước là chắc chắn không phải là một lựa chọn khả thi. Do đó, để đảm bảo không làm tăng yêu cầu bộ nhớ của mỗi luồng, mỗi luồng đọc dữ liệu theo các khối nhỏ, xử lý nó và đọc quá trình xử lý tiếp theo và vv. Do đó, cấu trúc của mã các chức năng của tôi chạy theo chủ đề là như thế này:
timer_start(&threadTimer[i]);
while(!dataFinished[i])
{
threadTime[i] += timer_stop(&threadTimer[i]);
data_source();
timer_start(&threadTimer[i]);
process();
}
threadTime[i] += timer_stop(&threadTimer[i]);
Biến dataFinished[i]
được đánh dấu true
bởi quá trình khi nó nhận được và xử lý tất cả dữ liệu cần thiết. Process()
biết khi nào để làm điều đó :-)
Trong hàm main, Tôi đang tính toán thời gian thực hiện bởi cấu hình 4-luồng như sau:
execTime4Thread = max(threadTime[0], threadTime[1], threadTime[2], threadTime[3]) + threadCreationTime
.
Và đạt được hiệu suất được tính bằng cách đơn giản
gain = execTime1process/execTime4Thread * 100
Vấn đề: On kích thước dữ liệu nhỏ xung quanh 1M để 4M, đạt được hiệu suất nói chung là tốt (giữa 350% đến 400%). Tuy nhiên, xu hướng tăng hiệu suất là giảm theo cấp số nhân với sự gia tăng kích thước đầu vào. Nó tiếp tục giảm cho đến khi một số kích thước dữ liệu tối đa 50M hoặc hơn, và sau đó trở nên ổn định khoảng 200%. Một khi nó đạt đến điểm đó, nó vẫn gần như ổn định cho dù chỉ 1GB dữ liệu.
Câu hỏi của tôi là ai cũng có thể đề xuất lý do chính của hành vi này (tức là hiệu suất giảm khi bắt đầu và sau đó vẫn ổn định sau này)?
Và đề xuất cách khắc phục điều đó?
Để biết thông tin của bạn, tôi cũng đã điều tra hành vi của threadCreationTime
và threadTime
cho mỗi chuỗi để xem điều gì đang xảy ra. Đối với 1M dữ liệu, giá trị của các biến này nhỏ và tăng kích thước dữ liệu cả hai biến này tăng theo cấp số nhân (nhưng threadCreationTime
sẽ vẫn gần như giống nhau bất kể kích thước dữ liệu và threadTime
sẽ tăng với tốc độ tương ứng với dữ liệu đang được xử lý).Sau khi tiếp tục tăng cho đến khi 50M hoặc hơn threadCreationTime
trở nên ổn định và threadTime
(giống như giảm hiệu suất trở nên ổn định) và threadCreationTime
tiếp tục tăng với tốc độ không đổi tương ứng với việc tăng dữ liệu cần xử lý (được coi là dễ hiểu).
Bạn có nghĩ rằng tăng kích thước ngăn xếp của từng chuỗi, xử lý thông tin ưu tiên hoặc giá trị tùy chỉnh của các loại thông số khác của trình lên lịch (sử dụng pthread_attr_init
) có thể giúp bạn không?
PS: Các kết quả thu được khi chạy các chương trình trong chế độ không an toàn của Linux có gốc (nghĩa là, HĐH tối thiểu đang chạy mà không có GUI và công cụ mạng).
Mô hình CPU của bạn là gì? – Tudor
Nhiều khả năng ô nhiễm chéo giữa bộ nhớ cache giữa các chủ đề. Bạn đã thử thay đổi kích thước của các khối dữ liệu chưa? Bạn cũng nên bao gồm việc tải dữ liệu trong các phép đo của mình vì nó có thể là nút cổ chai, tức là 2 lõi có thể làm bão hòa bus nhớ của bạn. (Ngoài ra, nếu bạn không làm điều đó, bạn nên đặt bộ hẹn giờ của bạn trên các dòng bộ nhớ cache khác nhau.) – Mats
@Mats: Bộ vi xử lý là Intel (R) Core (TM) 2 CPU Quad Q9950 @ 2.83GHz. Không, tôi chưa xác minh kích thước của đoạn dữ liệu. OK, tôi sẽ cố gắng thay đổi kích thước của đoạn dữ liệu. Tuy nhiên, tôi không hiểu ý bạn là gì bởi các dòng bộ nhớ cache. Làm cách nào để đặt bộ hẹn giờ vào bộ nhớ cache? – Junaid