10

Nói rằng tôi chạy một quá trình đơn luồng đơn giản như hình dưới đây:Tại sao một tiến trình luồng đơn thực thi trên một số bộ xử lý/lõi?

public class SirCountALot { 
    public static void main(String[] args) { 
     int count = 0; 
     while (true) { 
      count++; 
     } 
    } 
} 

(Đây là Java bởi vì đó là những gì tôi đang quen thuộc với, nhưng tôi nghi ngờ nó không thực sự quan trọng)

Tôi có một bộ xử lý i7 (4 lõi, hoặc 8 đếm siêu phân luồng), và tôi đang chạy Windows 7 64-bit vì vậy tôi đã kích hoạt Sysinternals Process Explorer để xem xét việc sử dụng CPU, và như mong đợi tôi thấy nó đang sử dụng khoảng 20% của tất cả CPU có sẵn.

Graph showing 20% CPU usage across all cores

Nhưng khi tôi chuyển đổi các tuỳ chọn hiển thị 1 biểu đồ cho mỗi CPU, tôi thấy rằng thay vì 1 trong 4 "lõi" được sử dụng, sử dụng CPU được lan truyền trên tất cả các lõi:

Graph showing erratic CPU usage on each core totaling around 20% usage

Thay vào đó những gì tôi mong đợi là 1 lõi tối đa, nhưng điều này chỉ xảy ra khi tôi đặt ái lực cho quy trình thành một lõi đơn.

Graph showing most of recent CPU usage to be confined to first core

Tại sao khối lượng công việc được phân chia trên các lõi riêng biệt? Sẽ không chia nhỏ khối lượng công việc trên một số lõi lộn xộn với bộ nhớ đệm hoặc phải chịu các hình phạt hiệu suất khác?

Có phải vì lý do đơn giản là ngăn ngừa quá nóng của một lõi không? Hoặc là có một số lý do sâu sắc hơn?

Chỉnh sửa: Tôi biết rằng hệ điều hành có trách nhiệm lên lịch, nhưng tôi muốn biết tại sao nó "phiền". Chắc chắn từ một quan điểm ngây thơ, gắn bó một (chủ yếu *) quá trình đơn luồng đến 1 lõi là đơn giản hơn cách & hiệu quả hơn để đi?

* Tôi nói chủ yếu là đơn luồng bởi vì có nhiều theads ở đây, nhưng chỉ có 2 trong số họ đang làm bất cứ điều gì:

Screenshot showing number of threads from Eclipse Screenshot showing number of threads in Process Explorer process properties

+2

nitpick nhỏ; nói rằng đây là một quá trình đơn luồng sẽ không chính xác. JVM nội bộ sinh ra nhiều luồng cho các mục đích dọn dẹp như finalizers, garbage collectors vv. Hoàn toàn có thể để có được công việc thực hiện bởi mỗi thread, các chủ đề JVM được ánh xạ tới các chủ đề h/w thực, một lần nữa có thể giải thích sự lây lan. –

+0

Tôi đoán Caspar có nghĩa là các chủ đề _non-daemon_. – Santosh

+0

@ SanjayT.Sharma Vâng, tôi đã đơn giản hóa một chút và có lẽ đã đưa ra một chương trình mẫu bằng ngôn ngữ không được quản lý;) Tuy nhiên, như tôi đã nói, tôi nghi ngờ không phải JVM đang làm điều này (và nếu nó là ánh xạ JVM -> HW chủ đề và đó là trách nhiệm, tại sao các bản đồ liên tục thay đổi?) – Caspar

Trả lời

17

Hệ điều hành có trách nhiệm lập kế hoạch. Nó là miễn phí để ngăn chặn một sợi và khởi động lại nó trên một CPU khác. Nó sẽ làm điều này ngay cả khi không có gì khác máy đang làm.

Quá trình được di chuyển xung quanh CPU vì hệ điều hành không cho rằng có bất kỳ lý do gì để tiếp tục chạy chuỗi trên cùng một CPU mỗi lần.

Vì lý do này tôi đã viết một thư viện cho các chủ đề khóa cho CPU nên nó sẽ không di chuyển xung quanh và sẽ không bị gián đoạn bởi các luồng khác. Điều này làm giảm độ trễ và cải thiện thông lượng nhưng lốp xe lên một CPU cho chủ đề đó. Điều này làm việc cho Linux, có lẽ bạn có thể điều chỉnh nó cho Windows. https://github.com/peter-lawrey/Java-Thread-Affinity/wiki/Getting-started

+0

Nó ngắt một quá trình nhiều lần mỗi giây. (100/s trên Linux) Có nhiều công việc phải nhớ nơi mà một quá trình được chạy lần cuối và cố gắng gán cho CPU đó ưu tiên cho bất kỳ cái nào khác, thay vào đó nó gán nó cho CPU miễn phí tiếp theo. –

+0

Tôi đoán tôi không đủ rõ ràng; Tôi biết rằng hệ điều hành không lập kế hoạch, và bạn có thể thấy trong đồ thị thứ 2 tôi đã thiết lập độ sâu cho quá trình để nó chỉ sử dụng lõi đầu tiên. Những gì tôi muốn biết là * tại sao * không hệ điều hành lịch trình các chủ đề "hoạt động" duy nhất trên tất cả các lõi có sẵn? – Caspar

+0

Câu hỏi ngược lại là lý do tại sao sẽ tiếp tục gán một luồng trở lại cùng một CPU thay vì chỉ gán nó cho CPU miễn phí tiếp theo (đó là những gì nó làm). Sử dụng vòng robin hoạt động tốt cho dù có bao nhiêu CPU đang bận. Gán cho cùng một CPU mỗi lần có thể để lại một CPU rất bận (với hai luồng chạy trên nó) trong khi các CPU khác không hoạt động. –

1

Tôi cũng mong chờ này cũng có thể được thực hiện trên mục đích của CPU và hệ điều hành như vậy là để thử và lan truyền tải nhiệt trên CPU die ...

Vì vậy, nó sẽ xoay (unique/đơn) chủ đề từ cốt lõi đến cốt lõi.

Và đó thừa nhận có thể là một cuộc tranh cãi chống lại cố gắng để chiến đấu này quá khó (đặc biệt là, trong thực tế, bạn thường sẽ thấy những cải thiện tốt hơn bằng cách đơn giản điều chỉnh/cải tiến ứng dụng riêng của mình anyway)

+0

Thú vị. Bạn có biết rằng Windows/Linux làm điều này cho chắc chắn, hoặc nó là một giả thuyết? (Ngoài ra, chào mừng bạn đến stackoverflow:) – Leeor

+0

Tôi đã thấy điều này rõ ràng xảy ra trên OSX và Windows. Tôi mong đợi tương tự cho Linux nhưng không bao giờ cụ thể cố gắng để xác minh nó. – Camlin

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