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

-march=native nhanh 2,66 lần — rồi làm vỡ build ngay trước mắt tôi

Cứ bật -march=native cho nhanh? Tôi đo và thấy hai mặt: -march đúng mở khóa lệnh dotprod cho kernel int8 nhanh 2,66 lần thật, nhưng -march=native trong container này còn không build nổi vì assembler từ chối lệnh gcc phát ra. Rủi ro mong manh của nó hiện ngay lúc build, chưa nói tới SIGILL lúc chạy trên máy khác.

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

Chia cho 7 gần như miễn phí, chia cho một biến đắt gấp 2,7 lần — cùng một dấu gạch chéo

Chia là chia, tốn như nhau? Tôi đo và thấy cùng dấu / cho hai chi phí khác hẳn: chia cho hằng số biến thành nhân magic + dịch (vector hóa được, gần như miễn phí), còn chia cho biến là udiv đắt 2,7 lần. Nhưng trong chuỗi phụ thuộc, cái mẹo magic lại không thắng — lợi ở thông lượng, không ở độ trễ.

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

-Os cho binary nhỏ nhất mà tôi tưởng phải chậm — hóa ra có kernel nó chỉ thua -O2 9%

-Os luôn chậm hơn -O2 vì bỏ tối ưu? Tôi đo cả kích thước lẫn tốc độ và cái nhãn chậm chỉ đúng nửa: -Os cho mã nhỏ nhất trong nhóm tối ưu, và tốc độ thì hỗn hợp — kernel số học nặng chậm 66% vì mất vector, nhưng kernel nhiều nhánh chỉ chậm 9%. Nó là điểm đánh đổi khác, không phải bản chậm.

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 7 phút

Compiler âm thầm dời khối xử-lý-lỗi ra cuối hàm — nhưng đồng hồ của tôi gần như không nhúc nhích

Tách đường nóng khỏi đường lạnh nghe như tăng tốc rõ. Tôi đo: compiler đã tự đẩy khối unlikely xuống cuối hàm, thân vòng nóng sạch bong không một lệnh lạnh — nhưng thời gian chỉ đổi ~1%, chìm trong nhiễu. Vì đây là tối ưu bố cục i-cache, chỉ hiện lợi ở quy mô lớn, không ở một vòng nhỏ.

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

Gộp hai vòng làm một tưởng nhanh hơn — tôi đo, nó chậm đi 2,75 lần

Ghép hai vòng thành một để bớt overhead thì luôn nhanh hơn? Tôi đo và bất ngờ: ghép hai vòng cùng đọc một mảng nhanh 1,8 lần, nhưng ghép hai vòng mỗi vòng ghi một mảng lại chậm 2,75 lần. Thứ quyết định không phải số vòng, mà là số luồng bộ nhớ đan xen trong thân — một bài toán locality.