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

volatile không làm biến nhanh hơn — nó làm code chậm 5 lần, và tôi vẫn cần nó

Nhiều người tưởng volatile cho nhanh hoặc cho an toàn đa luồng. Tôi đo thì ngược hẳn: volatile chặn tối ưu nên chậm 5,1 lần, vì mỗi lần chạm biến là một chuyến bộ nhớ thật. Nó đúng cho MMIO, cờ ngắt, và biến sink khi đo — nhưng nó KHÔNG phải atomic và không hề an toàn đa luồng.

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

Rào bộ nhớ sinh 0 lệnh máy mà vẫn làm code chậm 5,8 lần — cái đắt nằm ở đâu?

Rào bộ nhớ là một lệnh CPU đắt tiền luôn có mặt? Tôi đo và bất ngờ: rào biên dịch sinh 0 lệnh máy mà vẫn chậm 5,8 lần vì nó chặn tối ưu, còn rào phần cứng có lệnh dmb thật lại nhanh hơn. Cái giá thật là tối ưu bị tước đi, không phải bản thân lệnh rào — và nó vô hình trong assembly.

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

Vòng chép byte tự viết của tôi chậm hơn memcpy 25 lần — thủ phạm là một chữ tôi quên

memcpy là lời gọi thư viện, và vòng chép byte tay nhanh ngang nó? Tôi đo và sai cả hai. memcpy kích thước hằng được inline thẳng thành lệnh vector, 0 lời gọi; còn vòng chép byte tay chậm 25 lần vì compiler sợ hai con trỏ trùng địa chỉ nên không dám tối ưu. Thêm restrict là nó nhanh bằng memcpy ngay.

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

gcc 'biết' hàm này luôn chia cho 7 — mà ở -O2 vẫn không thèm tối ưu, vì sao?

Tôi tưởng compiler tự chuyên biệt bất kỳ hàm nào gọi với hằng số. Đo lần đầu ở -O2 ra 1,0× — chẳng lợi gì. Hóa ra bản clone chuyên biệt chỉ bật ở -O3: khi đó hằng được nướng vào, phép chia hóa thành nhân ma thuật, nhanh 1,3 lần. Một tối ưu có trong compiler khác hẳn với nó đang chạy.

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

Đổi chỗ hai dòng for, code chậm đi 16,9 lần — và -O3 chỉ cứu số nguyên, không cứu float

Cùng một phép cộng ma trận, đổi thứ tự hai vòng lồng là chênh 16,9 lần vì cache. Tôi tưởng compiler chịu thua chuyện này. Đo ra -O3 tự đảo thứ tự cứu số nguyên (về 1,0×), nhưng với float thì bó tay — vì đảo thứ tự cộng làm đổi kết quả làm tròn. Ranh giới nằm ở một chỗ rất tinh vi.

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

Cùng một hàm constexpr: một chỗ chạy 0,227 ns, chỗ kia 45625 ns — khác nhau ở đâu?

Đánh dấu constexpr là chắc chắn tính sẵn lúc biên dịch, 0 chi phí? Tôi đo và phát hiện chữ đó hứa ít hơn tưởng. Đặt kết quả vào biến constexpr thì nó thành literal đọc 0,227 ns; gọi đúng hàm ấy với đầu vào động thì nó chạy nguyên vòng lặp lúc chạy, 45625 ns. Ngữ cảnh mới quyết định, không phải từ khóa.