Giải thuật 03/09/2026 8 phút

likely/unlikely: mách đúng cho compiler được ~0, mách sai mất 10% — một canh bạc lỗ

Thêm likely/unlikely tưởng tăng tốc nhánh rõ rệt. Tôi đo và thấy một canh bạc bất đối xứng xấu: mách đúng thì lợi gần như bằng không (bộ dự đoán nhánh động của CPU đã lo hướng), nhưng mách sai làm chậm 10%. Cái nó đổi chỉ là bố cục mã, không phải hướng đoán — nên hãy để PGO lo, đừng rắc theo cảm tính.

Giải thuật 03/09/2026 7 phút

Prefetch bằng tay — sách bảo cứu truy cập ngẫu nhiên, máy tôi lại nói ngược sạch

__builtin_prefetch nghe như nút tăng tốc cho code nghẽn bộ nhớ, nhất là truy cập ngẫu nhiên và con trỏ đuổi. Tôi đo trên máy này và mọi thứ lật ngược: prefetch giúp truy cập tuần tự (~1,5 lần), vô ích cho gather ngẫu nhiên, và bất lực với con trỏ đuổi. Một bài học về việc prefetch phụ thuộc phần cứng đến mức nào.

Giải thuật 03/09/2026 10 phút

std::async chạy 20.000 việc nhỏ chậm hơn tuần tự 1724 lần — API đẹp không đổi được vật lý

Tưởng future/async tự động nhanh và rẻ? Tôi đo bằng C++: future.get() là một điểm đồng bộ chặn tới khi promise set, và std::async mặc định tạo một luồng mới cho mỗi task — chạy hai vạn task nhỏ bằng async chậm hơn tuần tự 1724 lần. Future tiện cho một kết quả, không phải phép màu song song.

Giải thuật 03/09/2026 10 phút

Ghi một biến rồi đọc lại ngay: CPU có bắt bạn chờ không?

Trực giác bảo lệnh đọc phải đợi lệnh ghi xuống cache. Đo trên host ARM thì không: store buffer chuyền thẳng giá trị vừa ghi, ghi-đọc khớp chỉ 1,55 ns (~7 chu kỳ). Nhưng cái 'store-forwarding stall' mà dân x86 sợ chết khiếp, ở đây chỉ đắt thêm 18%. Thứ thật sự chi phối lại là chuyện khác.

Giải thuật 03/09/2026 9 phút

Mỗi luồng ghi biến riêng, không chia sẻ gì — vẫn chậm gấp đôi: bí ẩn false sharing

Tưởng hai biến khác nhau, mỗi luồng ghi biến của riêng mình thì không thể ảnh hưởng nhau? Tôi đo: chúng làm nhau chậm 2,05 lần ở 8 luồng vì tình cờ nằm chung một dòng cache 64 byte — false sharing. Căn lề mỗi biến sang một dòng riêng thì nhanh gấp đôi, dù logic không đổi một chữ. Bug hiệu năng vô hình trong mã nguồn.

Giải thuật 03/09/2026 10 phút

'Code tôi scale 8 lần trên 8 lõi' — 8 lần so với cái gì? Chọn sai mẫu số, con số nói dối

Tưởng speedup = thời gian 1 luồng / N luồng là đủ, và scaling tuyến tính tới số lõi? Tôi đo: 10 lõi chỉ cho 4,65x (không phải 10x), và nếu lấy baseline sai (bản song song 1 luồng thay vì tuần tự tốt nhất) thì con số bị thổi phồng đều 6,2 lần. Speedup là một phân số, và mẫu số nào cũng nói dối được.