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

Cùng tổng O(n), một cách nhanh gấp 24 lần: lời kết sê-ri

Kết sê-ri 45 phần bằng một phép đo gói trọn luận điểm: cùng 10 triệu số nguyên, cùng phép tính tổng O(n), nhưng mảng liền mạch chạy 0,225 ns mỗi phần tử còn mảng con trỏ rải rác 5,48 ns — chênh 24 lần chỉ vì cache và con trỏ, thứ mà Big-O hoàn toàn giấu. Bài học cả sê-ri: đừng đoán, hãy đo — và đo cho đúng.

Hệ điều hành 03/09/2026 9 phút

Thêm luồng thứ hai, thông lượng sụp 8 lần: và cả sau khi chia khóa nó vẫn tụt vì một kẻ giết vô hình

Thêm luồng vào một khóa chung làm thông lượng SỤP: 226 xuống 27 triệu ops/giây khi lên 2 luồng — mở rộng âm. Chia nhỏ khóa vẫn tụt sau 2 luồng vì chia sẻ giả (các biến chung dòng cache). Chỉ khi đệm mỗi luồng ra riêng một dòng cache mới scale gấp 6. 'Song song' cần độc lập cả về khóa lẫn dòng cache.

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

Cùng số phép cộng, tách 8 biến ra nhanh gấp 6,7 lần

Cùng số phép tính thì cùng thời gian? Đo ra: cộng dồn một mảng bằng một biến tích lũy tốn 0,569 ns mỗi phép cộng, nhưng dùng 8 biến độc lập rồi gộp cuối chỉ tốn 0,085 ns — nhanh 6,7 lần dù y hệt số phép cộng. Khác biệt là đồ thị phụ thuộc: chuỗi phụ thuộc phải chờ từng bước, còn các phép độc lập chạy song song trong một lõi (ILP).

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

SIMD nhanh gấp 4 lần — hoặc gấp 0, tùy vòng lặp

Trình biên dịch -O2 tự vector hóa hết mọi vòng lặp số? Đo ra: một kernel tính từng phần tử độc lập nhanh 3,9 lần khi vector hóa (NEON 128-bit gói 4 float mỗi lệnh), nhưng một vòng có phụ thuộc — y[i] cần y[i-1] — thì không vector hóa được, vector và scalar bằng nhau y hệt. SIMD nhanh N lần chỉ khi vòng vector hóa được và compute-bound.

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

Đảo byte tôi tự viết bằng shift/mask nhanh ngang builtin — vì gcc nhận ra tôi đang làm gì

Phải dùng builtin/intrinsics mới nhanh, viết C tay luôn chậm? Tôi đo và thấy đúng nửa: builtin thắng rõ ở phép C không có cách viết tự nhiên (popcount nhanh 1,8 lần), nhưng nhiều phép compiler tự nhận mẫu — đảo byte viết tay bằng shift/mask cũng ra đúng một lệnh rev, bằng builtin. Đo trước khi cho rằng viết tay là chậm.

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

Gói 4 trường vào 1 số: nhỏ 4 lần, shift/mask miễn phí

Gói nhiều trường vào một từ chỉ tiết kiệm bộ nhớ mà làm chậm CPU vì shift/mask? Đo ra: một bản ghi 4 trường nhỏ gói vào một uint32 nhỏ hơn 4 lần (16 → 4 byte), và shift/mask khi đọc gần như miễn phí — duyệt khối lớn còn nhanh hơn 1,1 lần nhờ cache, mảng nóng thì hòa. Nhưng lợi ích chính là bộ nhớ, không phải tốc độ: throughput chỉ nhanh 1,1 lần chứ không tỉ lệ với mức nén.