2013-05-15 37 views
12

Máy mac của tôi được trang bị 16 lõi.Giảm hiệu suất khi tăng số lượng lõi

System.out.println(Runtime.getRuntime().availableProcessors()); //16 

Tôi đang chạy mã bên dưới để xem hiệu quả của việc sử dụng lõi của tôi. Các chủ đề 'CountFileLineThread' chỉ đơn giản là đếm số lượng các dòng trong một tập tin (Có 133 tập tin trong một thư mục)

Tôi đang ghi chép trên dòng này:

ExecutorService es = Executors.newFixedThreadPool(NUM_CORES); 

đâu NUM_CORES là giữa 1-16

Bạn sẽ lưu ý từ kết quả dưới 5 lõi mà hiệu suất bắt đầu giảm xuống. Tôi sẽ không mong đợi một 'sản phẩm giảm dần' cho 6 lõi trở lên (btw, đối với 7 lõi ​​phải mất hơn 22 phút, xin chào?!?!) Câu hỏi của tôi là tại sao?

enter image description here

public class TestCores 
{ 
    public static void main(String args[]) throws Exception 
    { 
    long start = System.currentTimeMillis(); 
    System.out.println("START"); 

    int NUM_CORES = 1; 

    List<File> files = Util.getFiles("/Users/adhg/Desktop/DEST/"); 
    System.out.println("total files: "+files.size()); 
    ExecutorService es = Executors.newFixedThreadPool(NUM_CORES); 
    List<Future<Integer>> futures = new ArrayList<Future<Integer>>(); 
    for (File file : files) 
    { 
     Future<Integer> future = es.submit(new CountFileLineThread(file)); 
     futures.add(future); 
    } 

    Integer total = 0; 

    for (Future<Integer> future : futures) 
    { 
     Integer result = future.get(); 
     total+=result; 
     System.out.println("result :"+result); 

    } 

    System.out.println("----->"+total); 

    long end = System.currentTimeMillis(); 
    System.out.println("END. "+(end-start)/1000.0); 
} 
} 
+13

Vì thử nghiệm của bạn đang làm tệp I/O, có thể bạn đã đạt được điểm với chuỗi thứ 6 mà bạn hiện đang làm quá nhiều I/O và do đó làm chậm mọi thứ xuống. – cmbaxter

+2

Tôi nghĩ rằng đây là một công việc bị ràng buộc IO chứ không phải là một công việc ràng buộc CPU. Thêm nhiều chuỗi chỉ làm cho truy cập đĩa cứng không đều trên đĩa điều hướng giữa nhiều tệp khác nhau (trái với vị trí liên tiếp cho một tệp, được mong đợi trên đĩa được phân mảnh thường xuyên trong hệ điều hành hiện đại). – nhahtdh

+1

Trong loại thử nghiệm này, chỉ số lõi của chúng không có liên quan khi mã của bạn chỉ hoạt động trong bộ nhớ. Khi bạn đã thêm I/O, trong khi một chủ đề đọc một tệp, tất cả những người khác cần phải đợi. –

Trả lời

19

tôi thêm này như một lời nhận xét, nhưng tôi sẽ ném nó vào đó là câu trả lời quá. Bởi vì thử nghiệm của bạn đang làm tập tin I/O, bạn có thể nhấn một điểm với chủ đề thứ 6 mà bạn đang làm quá nhiều I/O và do đó làm chậm mọi thứ xuống. Nếu bạn thực sự muốn thấy lợi ích của 16 lõi bạn có, bạn nên viết lại chuỗi đọc tập tin của mình để sử dụng I/O không bị chặn.

+0

cảm ơn, có ý nghĩa; Tôi đã học được điều gì đó mới mẻ. – adhg

5

Linh cảm của tôi là bạn có thể đã đặt quá nhiều gánh nặng lên đĩa I/O khiến bạn làm chậm mọi thứ xuống! Xem hiệu suất I/O trong "Activity Monitor" (nếu bạn đang sử dụng OSX). Trên Linux, sử dụng lệnh vmstat để có ý tưởng về những gì đang diễn ra. [Nếu bạn thấy rất nhiều trao đổi hoặc tỷ lệ cao của đọc/s và ghi/s sau đó bạn đi]


vài điều tôi nhận thấy:

CountFileLineThread không có trong mã. Hãy đặt nó để chúng ta có thể thấy chính xác những gì đang xảy ra.

Tiếp theo,

for (Future<Integer> future : futures) 
{ 
    Integer result = future.get(); 
    total+=result; 
    System.out.println("result :"+result); 

} 

Ở đây, lưu ý rằng bạn đang bị chặn trên trên kết quả của sự đầu tiên Task (future.get()). Trong khi đó các kết quả khác có thể đã có sẵn nhưng bạn không thể nhìn thấy chúng cho đến khi kết thúc đầu tiên. Sử dụng CompletionService để thay đổi kết quả theo thứ tự mà chúng kết thúc để đo lường tốt hơn. Nó không quan trọng mặc dù kể từ khi bạn muốn tất cả các chủ đề được thực hiện trước khi kết thúc bộ đếm thời gian mặc dù.

Một điểm khác: Chặn I/O là khóa. Nó không quan trọng, mỗi se, bao nhiêu lõi bạn có nếu các nhiệm vụ bị chặn trên I/O, mạng, vv Bộ xử lý hiện đại có những gì Hyper Threading và họ có thể chạy một thread chờ đợi để được chạy nếu hiện đang thực hiện các khối thread . Ví dụ: nếu tôi có 16 lõi và tôi sinh ra 16 Chủ đề yêu cầu họ đọc 1 GB tệp, tôi sẽ không nhận được bất kỳ cải tiến hiệu suất nào chỉ bằng cách có nhiều lõi hơn. Nút cổ chai là đĩa và bộ nhớ.

1

Thêm bộ vi xử lý gây ra tất cả các loại sự cố, nhưng chủ yếu là chúng phải thực hiện đồng bộ hóa giữa các bộ xử lý. Khóa cấp tác vụ trong hệ thống tệp, v.v. có thể trở thành vấn đề, nhưng thậm chí nhiều vấn đề hơn là sự đồng bộ giữa các lõi phải xảy ra chỉ để duy trì kết hợp bộ nhớ cache, theo dõi các trang đã thay đổi, v.v.Tôi không biết có bao nhiêu lõi trên mỗi chip mà bạn có (đã từ bỏ việc theo dõi công cụ đó khoảng 10 năm trước), nhưng nói chung khi bạn bắt đầu đồng bộ hóa hiệu suất off-chip, hãy đi xuống các ống.

Tôi sẽ thêm rằng JVM có thể tạo sự khác biệt lớn ở đây. Cần có thiết kế JVM cẩn thận để giảm thiểu số lượng các dòng bộ nhớ cache được chia sẻ (và được cập nhật thường xuyên) và nỗ lực đáng kinh ngạc là cần thiết để làm cho GC hoạt động hiệu quả trong một môi trường đa lõi.

Các vấn đề liên quan