19 điểm bởi GN⁺ 2025-09-04 | 3 bình luận | Chia sẻ qua WhatsApp
  • Thông thường, giới hạn hiệu năng máy chủ được đánh giá bằng % sử dụng CPU từ các công cụ giám sát như top, nhưng trên thực tế chỉ số này không phản ánh hiệu năng theo tuyến tính
  • Kết quả thử nghiệm với stress-ng trong môi trường Ryzen 9 5900X cho thấy, khi mức sử dụng là 50% thì khối lượng công việc thực tế đã đạt 60~100%, tạo ra độ lệch lớn so với chỉ số
  • Nguyên nhân chính là hyper-threadingturbo boost, khi việc chia sẻ tài nguyên giữa các lõi logic và sự thay đổi xung nhịp làm méo mó chỉ số
  • Vì vậy, thay vì chỉ nhìn vào mức sử dụng CPU đơn thuần, so sánh benchmark khối lượng công việc thực tế có thể xử lý với thông lượng hiện tại là chỉ số chính xác hơn
  • Nếu diễn giải mức sử dụng CPU theo cách tuyến tính thì sẽ gây ra sai số lớn trong ước tính hiệu năng, nên khi lập kế hoạch hệ thống cần có cách tiếp cận dựa trên benchmark

Sự không khớp giữa chỉ số sử dụng CPU của máy chủ và thông lượng thực tế

  • Khi vận hành máy chủ, nhiều người muốn biết hệ thống có đang gần mức sử dụng tối đa hay không
  • Thông thường, họ tham chiếu giá trị cao nhất trong các chỉ số mạng, bộ nhớ, CPU thông qua các công cụ giám sát như top
  • Tuy nhiên, trên thực tế có vấn đề là chỉ số sử dụng CPU và khối lượng công việc có thể xử lý không tăng theo tuyến tính

Môi trường và phương pháp thử nghiệm

  • Thí nghiệm dựa trên Ubuntu Desktop + Ryzen 9 5900X (12 lõi/24 luồng)
  • Bật Precision Boost Overdrive (Turbo)
  • Mô phỏng nhiều mức tải khác nhau (1~24 worker, 1~100% mức sử dụng) bằng stress-ng
  • Chỉ số đo lường: mức sử dụng CPU do hệ thống báo cáo và lượng tính toán thực tế (Bogo ops)

Tóm tắt kết quả

  • Tải CPU thông thường: ở mức sử dụng 50%, thông lượng thực tế là 60~65%
  • Phép toán số nguyên 64-bit: ở mức sử dụng 50%, thông lượng thực tế là 65~85%
  • Phép toán ma trận (Matrix math): ở mức sử dụng 50%, thông lượng thực tế là 80~100%
    • Trên thực tế, ngay cả khi worker bổ sung không còn đóng góp vào hiệu năng, mức sử dụng CPU vẫn tăng

Phân tích nguyên nhân

  • Hyper-threading

    • Cấu trúc gồm 12 lõi vật lý + 12 lõi logic
    • Với từ 12 worker trở xuống, chúng được phân bố tối ưu lên các lõi vật lý; nhưng khi vượt quá, hiệu năng giảm do chia sẻ lõi logic
    • Đặc biệt trong phép toán SIMD (phép toán ma trận), do không có tài nguyên chia sẻ phù hợp nên không thể tăng hiệu năng
  • Turbo boost

    • Khi tải thấp: 4.9GHz → khi full load: 4.3GHz, tức xung nhịp giảm 15%
    • Công thức tính mức sử dụng CPU (= busy cycles / total cycles) bị méo mó
      • Khi mẫu số (tổng số chu kỳ) giảm, mức tăng của tỷ lệ sử dụng bị đánh giá cao hơn khối lượng công việc thực tế

Hàm ý thực tiễn

  • Mức sử dụng CPU không phải là chỉ số hiệu năng tuyệt đối
  • Khi tính toán dung lượng máy chủ và dự đoán hiệu năng:
    • 1. Đo thông lượng tối đa bằng benchmark
    • 2. Giám sát thông lượng thời gian thực
    • 3. So sánh hai giá trị để đánh giá liệu hệ thống có đang tiến gần giới hạn hiệu năng hay không
  • Do khác biệt rất lớn tùy theo kiến trúc CPU (AMD vs Intel), hiệu quả hyper-threading, và cách turbo hoạt động, nên cần phân tích theo từng bộ xử lý

Kết luận

  • Mức sử dụng CPU chỉ đơn thuần là tỷ lệ chu kỳ bận, không phản ánh chính xác hiệu năng xử lý thực tế
  • Ngay cả khi "mức sử dụng 50%", hệ thống vẫn có thể đã ở 80~100% hiệu năng tối đa nếu được tận dụng hiệu quả
  • Vì vậy, giám sát hiệu năng và lập kế hoạch hệ thống nên tập trung vào thông lượng công việc dựa trên benchmark thay vì mức sử dụng CPU

3 bình luận

 
ifmkl 2025-09-07

Trong môi trường cấu hình HPC thực tế, về cơ bản người ta sẽ tắt hyper-threading và cấu hình cụm.

 
GN⁺ 2025-09-04
Ý kiến Hacker News
  • Tôi không nghĩ CPU utilization là dối trá, vì nó đo một đại lượng được định nghĩa rõ ràng; nhưng khi mọi người cố ngoại suy từ đó để xây dựng mô hình dung lượng, họ sẽ gặp cảnh thực tế lệch khỏi kỳ vọng
    Hyperthreading (SMT) và Turbo (clock scaling) chỉ là một vài trong số nhiều biến số gây ra tính phi tuyến; băng thông bộ nhớ dùng chung giữa các core, dung lượng interconnect, bộ nhớ đệm của bộ xử lý cũng đều là những tài nguyên sẽ bị “cạn kiệt” khi tải tăng lên
    Ở tầng phần mềm cũng vậy, ví dụ các hiện tượng như spinlock có thể tạo tác động phi tuyến lên utilization
    Phần lớn chỉ số CPU utilization lấy trung bình trong khoảng dài từ vài giây đến 1 phút, trong khi những điều quan trọng với hiệu năng của server nhạy cảm với độ trễ lại xảy ra trong vài chục đến vài trăm mili giây
    Vì thế utilization lấy trung bình nhiều giây không thể phân biệt được mẫu burst với mẫu mượt
    Nhưng cách được đề xuất, tức là “benchmark xem server có thể xử lý bao nhiêu việc trước khi xảy ra lỗi hoặc độ trễ không thể chấp nhận được”, về bản chất cũng không ổn định
    Khi cố tìm điểm server bắt đầu mất ổn định, số đo sẽ trở nên rất noisy, và theo lý thuyết hàng đợi thì gần điểm tới hạn, mọi nhiễu đều bị khuếch đại
    Ngoài ra, bản thân “lượng công việc mà server đang làm” cũng thường được định nghĩa một cách không ổn định (là RPS à? Chi phí mỗi request khác nhau, IPC cũng thay đổi theo thời điểm)
    Cuối cùng thì khoảng tin cậy rút ra từ cách tiếp cận load test cũng không khác mấy so với việc tạo mô hình thực nghiệm từ chỉ số utilization. Tiền đề vẫn là phải đo utilization cho đúng

    • Nếu biết dùng perf hay ftrace, bạn có thể lấy được các metric bộ xử lý cực kỳ chi tiết trong ngắn hạn để nhìn trực tiếp các nguyên nhân như CPU stall do cache miss hay memory access, ảnh hưởng của scheduler, v.v.
      Nhưng đa số mọi người dù có được các chỉ số như IPC, cache hit rate thì cũng không biết phải làm gì với chúng
      Sau cùng, thứ mà đa số thật sự quan tâm là độ trễ và utilization
      Nói hơi thô thì với phần lớn workload, trước khi CPU utilization vượt 80% thì độ trễ chưa có vấn đề gì lớn
      Nhưng trên mức đó, nó bắt đầu ảnh hưởng nghiêm trọng đến độ trễ của workload
      Ảnh hưởng tới độ trễ đến mức nào thì phải tự đo workload của mình mới biết
      Việc nhạy cảm với độ trễ đến đâu cũng khác nhau theo tổ chức và mục tiêu, và đôi khi tối ưu throughput còn quan trọng hơn
      Nếu quan tâm cả độ trễ lẫn throughput thì hãy đo cả hai và tự quyết định trade-off phù hợp

    • Tôi nghĩ một trong các điểm cốt lõi là chính định nghĩa của “khối lượng công việc” cũng rất lung lay
      Ví dụ workload xử lý request người dùng thật trên một dịch vụ public-facing rất khác với workload huấn luyện AI ở backend chỉ lặng lẽ tính toán trên dữ liệu đã tích lại
      Cách của tôi là, trong môi trường CPU hiện đại đa core có hyperthread nơi burst gần như không thể tránh khỏi, CPU utilization 60% đã được xem là server đang “tải cao”
      Nếu trên 60% trong một phần đáng kể của ngày thì tôi cho rằng nên tách bớt công việc ra (chủ yếu xét theo dịch vụ phản hồi request người dùng)
      Trước đây tiêu chí như vậy thường dẫn đến việc phải cân nhắc cloud autoscaling
      Giờ thì server hơn 100 core giá quanh 30 nghìn USD cũng có thể dùng được, nên tình hình còn phức tạp hơn
      Nếu là bây giờ, tôi sẽ thiên về cách hybrid: provision hơi dư phần cứng server thật, rồi mở rộng khi cần bằng dịch vụ cloud (hoặc internal cloud dựa trên Kubernetes)
      StackOverflow thời kỳ đầu đã vận hành lượng traffic khổng lồ rất hiệu quả với rack chuyên dụng và uplink 10Gbps, và giờ làm kiểu đó còn dễ hơn nữa
      Tóm lại, theo tiêu chí của tôi, nếu CPU load giữ ở mức 65% trong hơn 30 phút thì đã có thể xem là sử dụng hiệu quả như 100% rồi, và cần mở rộng trong thời gian sớm

    • Trong keynote gần đây của IEEE Hot Interconnects cũng có nhắc tới ví dụ tinh chỉnh độ trễ của Ultra Ethernet
      Nhìn ở thang 2 giây hay 5 giây thì thấy phẳng, nhưng nếu soi ở thang 100ms thì hiện tượng frame burst hiện ra rất rõ
      Tức là nếu cửa sổ đo của profiling không khớp với workload thực tế thì có thể đưa ra kết luận sai kiểu false negative, và điều đó sẽ khiến vấn đề tệ hơn

    • Hoàn toàn đồng ý với điểm đã nêu
      Chính tính không tuyến tính của CPU utilization làm cho con số % tự nó lệch khỏi thực tế
      Tức là điều bị gọi là dối trá chỉ là CPU utilization được đo bằng đơn vị %

    • Nếu hai workload đều ghi nhận 100% CPU usage, nhưng một bên tiêu thụ điện nhiều hơn hẳn và cũng làm nhiệt độ CPU tăng vọt, thì sẽ nảy sinh câu hỏi: có phải trên thực tế workload đó đang tận dụng nhiều tài nguyên transistor hơn không?

  • Dù CPU utilization không phải thước đo hoàn hảo, trên thực tế nó vẫn hữu ích
    Ngay cả với kinh nghiệm SRE khá đơn giản, tôi từng kết hợp số CPU utilization với lý thuyết hàng đợi cho các tác vụ CPU-bound để ước tính quy mô server trước các sự kiện lớn, và ngay cả khi dùng ngưỡng %CPU được đề xuất bảo thủ hơn nhiều so với cách “truyền thống”, kết quả vẫn tốt hơn hẳn về hiệu quả chi phí
    Điểm mấu chốt là: nếu một thước đo hơi thiếu chính xác nhưng dùng được ngoài hiện trường thì đừng lo lắng quá mức, cứ tận dụng nó
    Tuy vậy, lý do tôi luôn giữ CPU utilization trong production không vượt 40% là để chừa một chút headroom cho nhiều tình huống khác nhau
    Điều đáng tiếc là tác giả chưa đưa ra được cơ sở logic đủ thuyết phục cho lập luận “phải tránh utilization cao theo lý thuyết hàng đợi”

    • Tôi nghĩ một metric hơi lỏng lẻo nhưng được dùng đúng chỗ trong thực tế thì đã là đủ
      Ví dụ chỉ lấy trung bình/giá trị lớn nhất đơn giản của percentile metric theo từng host, hay tính percentile khi tổng hợp cuối cùng từ histogram cấp host, thì theo kinh nghiệm của tôi việc chuyển giữa hai cách này cũng không tạo khác biệt lớn trong vận hành thực tế
      Có những người quá bận tâm chuyện đúng sai một cách chặt chẽ về mặt toán học, nhưng trong vận hành đời thực thì nhiều khi không ảnh hưởng mấy

    • 40% thật ra là một mức utilization khá thoáng, khá nhiều dư địa

    • Tôi nghĩ nếu xem CPU% cùng với loadavg thì có thể nắm tình trạng hệ thống khá tốt
      Nếu loadavg cao mà CPU% thấp thì có thể hệ thống đang bị kẹt ở mạng hoặc I/O, hoặc đang chờ vì system call gì đó
      Trong trường hợp này nếu chỉ nhìn CPU% thì có thể bỏ sót chỗ đang thật sự khổ sở

    • Tôi có cảm giác như đã từng nghe chính câu chuyện này rồi
      Nội dung tác giả nhắc tới đã được lặp lại suốt hàng chục năm trong sách về lý thuyết hàng đợi, vậy mà cách viết lại như thể mới phát hiện ra bây giờ, điều đó khá lạ

  • Tôi nhớ đến bài "CPU Utilization is Wrong" của Brendan Gregg
    Ý chính của bài blog đó là CPU utilization chỉ xem “trạng thái” CPU đang bận như một chỉ số, và thậm chí khi CPU đang chờ cũng bị coi là busy
    Còn IPC là thước đo để nắm được lượng công việc hữu ích thực sự ẩn bên trong trạng thái bận đó

    • Tôi thắc mắc vì sao những người tên Brendan lại quan tâm đến vấn đề CPU utilization đến vậy
      Nếu còn Brendan nào khác thì mong có người giải thích thêm
  • Tôi nghĩ không nên tính hiệu năng do hyperthread mang lại là gấp đôi
    Trong thực tế, kể cả tận dụng hyperthread tốt thì nhiều trường hợp cũng chỉ thêm được khoảng 15~30% hiệu năng. Trong khi đó, độ trễ có thể tăng gấp đôi
    Khi core utilization tăng thì nhất định cũng phải tính đến việc xung nhịp giảm, nên luôn phải cẩn thận với tính phi tuyến trong đời thực
    Chỉ với thông tin OS cung cấp thôi, nếu tính cả hiệu ứng hyperthread và việc giảm xung thì đã có thể ước lượng utilization chính xác hơn nhiều
    Hơn nữa, việc mô hình hóa cả những hiện tượng như giới hạn băng thông cache/bộ nhớ hay pipeline stall dẫn đến suy giảm hiệu năng, theo tôi cũng không phải là chuyện quá khó

    • Yếu tố làm mọi thứ phức tạp hơn là hiệu quả của hyperthread khác nhau rất lớn tùy kiến trúc CPU và workload
      Ví dụ cách triển khai của AMD (đặc biệt là Zen mới) có xu hướng cho hiệu năng độc lập hơn Intel nhiều (giả sử không bị nghẽn băng thông bộ nhớ)

    • Nếu là ứng dụng memory-bound thì thường dễ thấy scaling tốt hơn nhờ hyperthread
      Dự án renderer tôi từng phụ trách trước đây bị memory-bound, và chỉ riêng hyperthread cũng mang lại mức tăng hiệu năng 60~70%

    • Trước đây tôi từng chạy một benchmark đơn giản bằng POV-Ray trên i7-3770K (4C/8T)
      Từ 1 thread lên 2 thread thì đúng gấp đôi, từ 2 lên 4 cũng gấp đôi, còn từ 4 lên 8 thì chỉ tăng được 15%
      Nếu là một benchmark kỳ lạ cố tình lặp đi lặp lại cache miss thì có lẽ SMT gần như có thể kéo được hiệu năng gấp đôi, nhưng tính thực tế thì đáng nghi
      P/S: Tôi đang nghĩ hay là chạy lại bài test POV-Ray. Lâu lắm rồi nên thấy hơi nhớ

  • Có vẻ tác giả nhận ra rằng hiệu năng không tăng tuyến tính theo con số %CPU utilization, rồi từ đó kết luận rằng chính %CPU utilization là “dối trá”
    Ngay cả khi không có hyperthread hay giảm xung, và cả trong trường hợp tưởng như ít biến số như Apple silicon, scaling cũng không ra tỷ lệ chính xác
    Khi bắt đầu dùng nhiều core cùng lúc, các nghẽn tài nguyên ngoài CPU như overhead truyền dữ liệu thường xuyên trở thành vấn đề, nên tình huống tương tự xảy ra khá phổ biến

    • Apple silicon cũng giảm xung khá mạnh, nhất là ở các mẫu không quạt (tản nhiệt thụ động)
  • Cách tác giả dùng thuật ngữ core gây nhầm lẫn và không theo chuẩn
    Họ gọi 5900X là hệ thống 24 core, nhưng thực tế đó là 12 core vật lý với 24 hyperthread đang hoạt động
    12 cái là core vật lý, 12 cái còn lại là thread gắn lên từng core tương ứng
    Dù có 2 bộ instruction pipeline thì chúng vẫn chia sẻ các functional unit bên trong

    • Vài năm trước, khi giải thích hyperthreading cho đứa em không rành, tôi từng dùng một phép so sánh khá nhớ đời: nó giống như cuộn giấy vệ sinh hai lớp
      Bạn không thể tách 24 cái ra riêng rẽ, nhưng nó gần giống việc dùng bộ 12 cái đó hữu ích hơn gấp đôi

    • Sau khi nhận phản hồi, tôi đã sửa cách mô tả thành 12 core / 24 thread
      Chỉ là do OS của tôi hiển thị utilization theo 24 core nên trước đó hơi bị rối

    • Sẽ khá thú vị nếu Intel đưa ra software-defined core
      Theo hướng ngược lại với hyperthreading, hai hay nhiều core sẽ chia sẻ tài nguyên để biến thành “một core lớn”
      Xem liên kết bằng sáng chế dưới đây
      https://patents.google.com/patent/EP4579444A1/en

    • Nếu một cặp SMT chạy cùng loại workload thì hiệu quả SMT sẽ giảm vì tranh chấp tài nguyên nội bộ và execution unit
      Nếu workload hoàn toàn khác nhau thì mức boost lại có thể lớn hơn
      Giờ với CPU hiện đại còn có thêm biến số như P-core, E-core, turbo/không turbo nên tình hình càng phức tạp
      Có nghiên cứu cho thấy thêm SMT mang lại cải thiện hiệu năng trên mỗi watt tốt hơn thêm turbo, điều đó rất thú vị

  • Câu chuyện này thật sự rất đồng cảm
    Hồi trước có lần tôi giải thích với quản lý rằng CPU server đã lên 60% nên không còn dư địa nữa, và ông ấy nhìn tôi với vẻ khá kỳ lạ
    Khi đó mà có đúng phần giải thích kiểu này thì tốt biết mấy

    • Nếu giải thích kèm lý thuyết hàng đợi thì hiệu quả sẽ tăng vọt
      Dưới 60% thì độ trễ do hàng đợi hầu như có thể bỏ qua
      Từ hơn 70% trở đi thì độ trễ bắt đầu tăng thấy rõ, và từ 80% thì gần như nhân đôi
      Trong kinh nghiệm thực tế của tôi, mục tiêu là 65% theo P95 time, và nó gần như khớp với mốc lý thuyết
      Tóm lại, quy tắc thực chiến là “60% là giới hạn sử dụng, từ 80% thì độ trễ bùng nổ”

    • Nhưng điều này có thể hoàn toàn khác tùy workload
      Nhất là trong thời đại server CPU 32 core như hiện nay thì lại càng như vậy

  • CPU utilization rất hay không vận hành theo cách người ta kỳ vọng
    Bình thường với loại bài này tôi tưởng sẽ nói về cách con số utilization trên Linux/Windows bị méo, nhưng thực tế lại có rất nhiều trường hợp CPU nhàn rỗi hoặc bị downclock vì nghẽn RAM
    Thực ra CPU utilization chỉ là thứ mà OS (dù là Windows hay Linux) dùng để tính xem mỗi core được gán thread trong bao lâu
    Nhưng ngay cả khi thread đó đang chờ 100% bên trong memcpy thì nó vẫn được ghi là utilization
    Điểm mạnh của hyperthread là nếu một thread bị kẹt ở AVX/vector unit còn thread kia bị kẹt ở memcpy/RAM đơn giản, thì có thể nâng mức sử dụng của các unit khác nhau lên, từ đó cải thiện cả hiệu năng lẫn utilization tổng thể
    Kết luận là CPU Utilization từ lâu đã là một chủ đề khó hiểu theo trực giác, và cứ luôn có thêm những góc nhìn mới được phát hiện
    Dù vậy đây vẫn luôn là một chủ đề thú vị

  • Điều thật sự “dối trá” là tin rằng hyperthread core hoạt động y hệt core thật
    Cuối cùng vì đã dùng nó hơn 20 năm, người ta quên mất bản chất ban đầu và cứ lặp đi lặp lại việc ngộ ra vì sao số đo hiệu năng lại kỳ cục
    Một điểm nữa là bộ xử lý về căn bản chỉ có “đang chạy” (100%) hoặc “đang chờ” (0%)
    Việc gán cho nó một con số % ở giữa thực chất chỉ là giá trị trung bình trong một đơn vị thời gian nhất định

  • Tôi từng có một cuộc trò chuyện như thế này
    Quản lý: CPU utilization đã 100%, có nên chuyển server sang instance lớn hơn không?
    Tôi: “Nhưng lúc này CPU có thật sự đang làm công việc hữu ích không?”
    Kết quả là ngay cả busy waiting cũng được ghi vào CPU utilization, nên có những lúc chỉ số tăng lên nhưng chẳng liên quan gì tới công việc hữu ích thực sự

 
jjjajh 2025-09-04

Là cách diễn đạt đúng.