Q

Quản trị viên

Là một lập trình viên yêu công nghệ, thích viết blog để chia sẻ kiến thức, kinh nghiệm lập trình và những điều thú vị trong thế giới tech.

2300 bài viết · Website
Giải thuật 03/09/2026 8 phút

Một dòng trộn int với float, và 19 chu kỳ bốc hơi

Gán số nguyên cho biến float trông như miễn phí — 'đều là số' mà. Đo trên host ARM: một phép cộng int tốn ~1 chu kỳ, nhưng vòng chuyển khứ hồi (int)((float)v+1) trên chuỗi phụ thuộc tốn 4,3 ns — khoảng 19 chu kỳ, gấp 19 lần. int và float là hai thế giới riêng trong CPU, và các phép ép kiểu ngầm trong biểu thức trộn kích hoạt lệnh chuyển đổi mà bạn không hề viết ra.

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

Thêm phép tính vào vòng lặp mà không chậm hơn: vì sao?

Vòng lặp duyệt mảng lớn nhanh chậm do số phép tính? Đo trên host ARM bằng STREAM: copy (không phép tính), add, triad (nhân+cộng) đều đạt ~65-92 GB/s như nhau — nút cổ chai là băng thông bộ nhớ, không phải phép tính. Và một luồng đã đạt ~85% đỉnh, hai luồng bão hòa ~95 GB/s: trên lõi Apple này một core gần như dùng hết băng thông, khác hẳn server x86.

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

Mỗi luồng một biến riêng mà vẫn chậm gấp 2,6 lần?

Mỗi luồng ghi biến riêng của nó thì chạy song song thoải mái? Đo trên host ARM: tám luồng, mỗi luồng tăng một bộ đếm riêng, nhưng nếu tám bộ đếm nằm chung một dòng cache thì chậm gấp 2,6 lần so với khi mỗi bộ đếm được đệm ra dòng riêng — dù các biến hoàn toàn độc lập về logic. Đây là false sharing: dòng cache ping-pong giữa các lõi. Ghi thường không atomic vẫn trả giá.

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

Hạ memory_order cho nhanh: mẹo x86 đem nhầm sang ARM

seq_cst đắt hơn relaxed nhiều, cứ hạ memory_order là code nhanh? Đo trên host ARM: relaxed và seq_cst chênh nhau đúng 0 ns — cả một luồng lẫn tám luồng — vì thứ tự nằm sẵn trong lệnh ldar/stlr/ldadd. Cái thật sự đắt là tính atomic (RMW gấp 7 lần ghi thường) và nhất là tranh chấp: tám luồng đập chung một atomic chậm gấp 60 lần tám ô riêng.

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

Cái 'bộ đếm chu kỳ' của bạn không đếm chu kỳ đâu

Đọc bộ đếm chu kỳ của CPU là đếm được số chu kỳ? Đo trên host ARM: bộ đếm timer cntvct chạy tần số cố định 24 MHz, còn CPU chạy ~4,44 GHz — nên một tick bằng 41,67 ns, tức khoảng 185 chu kỳ CPU chứ không phải một. Và mỗi lần gọi steady_clock::now() tốn ~13 ns; đo đoạn ngắn hơn thế thì kết quả toàn là rác. Đây là cách đo cho đúng.

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

Cùng một mảng, chạm cách này nhanh hơn cách kia 424 lần

Truy cập bộ nhớ có một tốc độ cố định? Đo trên host ARM cùng một mảng 256MB, cùng số lần chạm: duyệt tuần tự tốn 0,24 ns mỗi phần tử (33 GB/s), nhưng đuổi con trỏ ngẫu nhiên tốn 101,7 ns — chênh 424 lần. Và ngẫu nhiên độc lập (nhờ song song mức bộ nhớ) chỉ 3,3 ns, nhanh 31 lần đuổi con trỏ. Ba trần khác nhau, chọn bởi cách bạn truy cập.