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

Bung vòng lặp 8 lần mà không nhanh hơn một tí nào?

Bung vòng lặp (unroll) luôn làm code nhanh hơn vì cắt chi phí vòng? Đo trên host ARM: bung một vòng cộng mảng 1x/2x/4x/8x với một biến tích lũy cho thời gian y hệt nhau — 0,2136 ns mỗi phần tử, không đổi, vì lõi out-of-order đã giấu hết chi phí vòng. Cái thật sự giúp là phá chuỗi phụ thuộc bằng nhiều biến độc lập (3,5 lần), còn khi memory-bound thì unroll vô ích. Và -O3 tự vector hóa còn nhanh hơn bung tay.

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

Căn lề dữ liệu đã lỗi thời? Một cú SIGBUS nói không

Căn lề là chuyện cũ, CPU nay đọc lệch thoải mái? Đo trên host ARM: đọc lệch mà vẫn nằm trong một dòng cache thì nhanh y hệt căn lề — hoàn toàn miễn phí. Nhưng bắc cầu hai dòng cache thì tốn: L1 chậm thêm 33%, RAM chậm gấp 2,2 lần vì phải nạp hai dòng. Và một atomic vắt qua ranh giới dòng thì không chậm — nó Bus Error, chương trình chết ngay.

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

RAM chậm trăm ns, sao vòng lặp vẫn chạy vèo vèo?

Chạm bộ nhớ RAM thì luôn tốn cả trăm nanô giây? Đo trên host ARM: duyệt một mảng 256 MB theo thứ tự tuần tự chỉ tốn 0,24 ns mỗi phần tử — kể cả duyệt lùi cũng vậy — vì bộ nạp trước đoán và kéo dòng cache về trước. Cùng mảng ấy, truy cập ngẫu nhiên tốn 101 ns, chênh 420 lần. Bộ nạp trước theo kịp cả bước đều rất lớn, chỉ chịu thua kiểu ngẫu nhiên.

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

100 cú chạm RAM mà chỉ tốn bằng 4 cú: phép màu MLP

Mỗi lần chạm hụt cache phải chờ xong mới tới lần sau, nên N lần miss tốn N lần độ trễ? Đo trên host ARM: đuổi một con trỏ ngẫu nhiên tốn 102 ns mỗi bước, nhưng đuổi 32 con trỏ độc lập song song chỉ còn 3,9 ns mỗi bước — nhanh 26 lần. Lõi thực thi ngoài thứ tự cho hàng chục lần chạm hụt bay cùng lúc. Cùng là truy cập RAM ngẫu nhiên, phụ thuộc hay độc lập chênh nhau 26 lần.

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

Dấu chia tốn 8 chu kỳ hay gần như 0? Tùy bạn viết

Nhân với chia đều là một phép toán nên tốn như nhau? Đo trên host ARM: chuỗi phép nhân số thực chạy 3,3 chu kỳ mỗi phép, nhưng chia số thực tốn 10,7 chu kỳ — gấp hơn ba lần, và gấp mười lần một phép cộng. Số nguyên udiv 8 chu kỳ so với mul 3,2. Nhưng chia cho hằng số thì trình biên dịch biến thành nhân, và lấy dư cho lũy thừa 2 thành phép AND — gần như miễn phí.

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

Cùng phép nhân, khi 3,2 chu kỳ khi 0,4: sao lại thế?

Mỗi lệnh CPU có một chi phí cố định? Đo trên host ARM: cùng một phép nhân tốn 3,2 chu kỳ khi nằm trong chuỗi phụ thuộc, nhưng chỉ 0,4 chu kỳ khi các phép độc lập — chênh 8 lần. Mỗi lệnh có HAI con số: độ trễ và thông lượng. Bất ngờ hơn: cả phép chia số thực cũng chồng được ~8 lần, dù tôi tưởng bộ chia làm từng cái một.