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.

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

Hàm 'nóng nhất' trong profiler lại vô can: 8 luồng chỉ chạy như 1,27 lõi vì bận chờ khóa

Tưởng hàm nóng nhất trong profiler là chỗ cần tối ưu, và CPU bận nghĩa là thiếu CPU? Tôi đo: một chương trình 8 luồng chỉ đạt song song hiệu quả 1,27 lõi vì chờ khóa 81% thời gian — mà hàm 'nóng' nhất lại hoàn toàn vô can. Đọc profiler đa luồng phải nhìn CPU/wall và thời gian chờ.

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

volatile không cứu code đa luồng: đếm chung vẫn mất 50%, và -O2 giấu luôn cuộc đua

Tưởng biến chung đọc/ghi bình thường vẫn chạy được, và volatile là đủ cho đa luồng? Tôi đo: hai luồng tăng một biến non-atomic mất ~50% cập nhật, đọc cờ chung non-atomic bị -O2 hoist thành treo vĩnh viễn — chỉ atomic mới đảm bảo. Và trớ trêu, -O2 gập mất cuộc đua ngay trong phép đo về nó.

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

8 luồng chậm hơn 1 luồng dù tôi không viết một khóa nào — thủ phạm nằm trong rand()

Tưởng thư viện chuẩn thread-safe nên gọi thoải mái từ nhiều luồng, và code không có khóa thì phải scale? Tôi đo: rand() có khóa ẩn khiến tổng throughput sụp từ 258 xuống 6,5 triệu op/s ở 2 luồng, 8 luồng vẫn chậm hơn 1 luồng — trong khi rand_r() cùng thuật toán scale 5,1 lần.

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

Cùng một cách song song hóa: vòng này SIMD chỉ nhanh 1,12 lần, vòng kia 2,49 lần

Tưởng vector hóa cho Nx, đa luồng cho số-lõi lần, nhân lại ra tích? Tôi đo: một vòng memory-bound chỉ được 1,12 lần từ SIMD dù mã máy có lệnh vector (băng thông chặn), còn vòng compute-bound được 2,49 lần từ SIMD ngay trên một lõi. Tăng tốc phụ thuộc nút thắt, không phải kỹ thuật.

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

Một lần chạy nói 'tối ưu này chậm 2,9 lần' — lặp 15 lần lấy min: hóa ra nhanh 4,36 lần

Tưởng chạy một lần mỗi bên rồi so là đủ để biết một thay đổi đồng thời có đáng? Tôi đo: một lần chạy trúng nhiễu (outlier 13ms) đảo ngược cả kết luận — nói padded chậm 2,9 lần trong khi thật ra nó nhanh 4,36 lần. Nhiễu chỉ cộng, không trừ — nên phải lặp và lấy min.