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

Tra thành viên: quét tuyến tính thắng ở n=8, còn nhị phân O(log n) không bao giờ nhanh nhất

Bài kết sê-ri: cùng một bài toán 'x có trong tập không', kẻ thắng đổi theo quy mô — quét tuyến tính nhanh nhất ở n=8, hash ở n lớn, bitset đè bẹp cả nếu biết miền khóa; và nhị phân O(log n) luôn kẹt giữa, không bao giờ nhanh nhất. Không có cấu trúc tốt nhất phổ quát — đo, đừng đoán.

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

-O0 chậm hơn -O2 gần 5 lần, còn -O3 gần như không hơn -O2 — cả hai điều tôi tưởng đều sai

Cùng một code C, -O0 chậm 4,6 lần -O2 — không phải vì làm nhiều phép tính hơn, mà vì giữ mọi biến trên ngăn xếp (72 lệnh load/store so với 26 khi lên -O1). Cú nhảy tốc độ lớn nhất nằm ở -O0 → -O1; còn -O2 và -O3 cho mã gần như y hệt. Số cao hơn không đảm bảo nhanh hơn.

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

Inline để bỏ lệnh gọi hàm ư? Tôi đo: bỏ call chỉ được 0,15 ns — lợi thật gấp mười lần thế, ở chỗ khác

Ai cũng bảo inline để khỏi tốn chi phí gọi hàm. Tôi đo và thấy bỏ một lệnh call chỉ tiết kiệm 0,15 ns — call trên CPU hiện đại gần như miễn phí. Lợi thật là tối ưu xuyên biên: gọi g(x,0) hằng số, inline giúp gấp hằng và khử nhánh chết, nhanh 1,8 lần. Nhưng inline hàm lớn vào 24 chỗ làm mã phình gấp đôi.

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

Vòng lặp 2 tỉ phép tính của tôi đo ra đúng 0 nano giây — vì gcc xóa sạch nó, và đó là bài học nền

Một vòng 2 tỉ phép tính mà kết quả không ai dùng đo ra đúng 0,00 ns — gcc -O2 xóa cả vòng, hàm chỉ còn ret. Thêm một volatile sink là số nhảy lên 1,37 ns thật. Khử mã chết còn xóa dead store và mã sau return, và đây chính là lý do mọi benchmark cần 'quan sát' kết quả.

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

Một hàm ba phép nhân, gcc rút thành đúng một con số nạp sẵn — nếu tôi cho nó biết đầu vào

Ai cũng biết compiler tính sẵn 2+3 thành 5. Tôi đo xem nó đi xa tới đâu: cùng một hàm ba phép nhân, khi đầu vào là hằng 100 thì gcc gấp toàn bộ thành một literal 64-bit (5 lệnh, 0 phép nhân, 0 ns); khi đầu vào từ volatile thì phải tính đủ (22 lệnh, 3 phép nhân, 0,99 ns). Ranh giới nằm ở một câu hỏi.

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

"Phải -O3 mới có vector hóa" — niềm tin này đã sai từ gcc 12, và tôi đo để chứng minh

Ai cũng bảo muốn compiler tự vector hóa SIMD thì phải bật -O3. Tôi đo trên gcc 13: -O2 đã sinh 26 lệnh NEON và nhanh gấp 2 lần -O1 scalar, còn -O3 cho mã y hệt. Và cách biết chắc vòng nào được vector hóa không phải đoán theo mức -O, mà là đọc -fopt-info-vec — compiler tự khai.