Kỹ thuật sửa lỗi Reed - Solomon


Đây là bài viết thuộc chủ đề nghiên cứu của nhóm ruby hardcore, được lược dịch chủ yếu từ bài viết này.


Background

Là người dùng cuối, chúng ta đã quá quen thuộc với việc click vào nút download A, quét một mã vạch B hay mua một cái đĩa CD C, thì chúng ta đều nhận được một kết quả thích hợp và đầy đủ dữ liệu. Hầu như tải về là cài đặt được, quét mã qr là hiện ra thông tin được, mua đĩa CD về là nghe được, vân vân… Nhưng hậu trường đằng sau của những sự tưởng như bình thường đó không hề bình thường chút nào, vì mọi thứ trên đời đều có khả năng phát sinh lỗi. Và làm sao có thể hạn chế tối đã những lỗi này, thậm chí ưu việt hơn là phát hiện ra lỗi và tự sửa nó, là một vấn đề rất khó.

Reed-solomon là một kỹ thuật trong rất nhiều kỹ thuật nhằm đảm bảo toàn vẹn dữ liệu. Nó cho phép phát hiện và sửa lỗi, được ứng dụng rất rộng rãi, từ những sản phẩm rất bình dân mà bạn thấy hằng ngày như đĩa CD, DVD, cao cấp hơn tí có mã QR, hay các công nghệ phức tạp như DSL, WiMAX, RAID 6, thậm chí cả công nghệ vũ trụ

Tưởng tượng một chút là ta mua cái đĩa về, mở lên thấy Ưng Hoàng Phúc hát mà thỉnh thoảng lại thấy giọng của Ngọc Trinh thì hay nhỉ :D

Nguyên lý chung

Cứ tưởng tượng thế này cho dễ. Trong 1 đoàn quân gửi đi đánh nhau, rất có thể có những người lính biến chất dọc đường. Làm sao để phát hiện và khôi phục lòng trung thành của những người lính này, thì bạn phải cài cắm người mà bạn tin vào trong đoàn quân đó, để chúng giám sát và báo lại cho bạn nếu có việc trên. Xịn hơn nữa, người được cài cắm có thể tự động khuyên nhủ mấy anh lính hư kia, đưa đoàn quân trở lại sự trung thành nhất, ko còn tạp chất.

Tư tưởng của kỹ thuật Reed-Solomon cũng vậy. Khi bạn gửi một số bit trên đường truyền (=gửi quân đi đánh), rất có thể có những bit bị sai lệch vì nhiễu trên kênh truyền (=lính biến chất), bạn sẽ phải đưa thêm những bit giám sát (=cài cắm người mà bạn tin) vào số bit trên, và truyền tải đi.

Việc cài cắm sẽ được thông qua bộ encoder, và bộ decoder sẽ lo việc khôi phục.

Các khái niệm kỹ thuật liên quan

Theo định nghĩa xịn ở đây:

A Reed-Solomon code is specified as RS(n,k) with s-bit symbols.

This means that the encoder takes k data symbols of s bits each and adds parity symbols to make an n symbol codeword.
There are n-k parity symbols of s bits each. A Reed-Solomon decoder can correct up to t symbols that contain errors in a codeword, where 2t = n-k.

Vietsub:

Mã Reed-Solomon được đặc tả là RS(n,k), với mỗi ký tự được cấu tạo từ s-bit.
Nghĩa là bộ mã hóa sẽ nhận k ký tự, sau đó thêm vào các ký tự kiểm tra để tạo ra codeword có độ lớn n ký tự.
Số ký tự kiểm tra là `n-k`, và số ký tự có thể được sửa tối đa là (n-k)/2

Ta có thể liên tưởng đến các khái niệm được nhắc tới với nguyên lý chung ở trên như sau:

  • symbols(ký tự): Có ý nghĩa như một anh lính. Anh lính này (symbol) được cấu tạo từ s-bit.
  • k data symbols: Có ý nghĩa như một đoàn quân trước khi được cài cắm người vào. Đoàn quân này có số lượng là k anh lính.
  • n symbol codeword: Có ý nghĩa như đoàn quân sau khi cài cắm người vào, có số lượng là n anh lính. (n > k)
  • n-k parity symbols(ký tự kiểm tra): Số lính mà ta cài cắm vào đoàn quân. Tất nhiên mỗi anh lính được cài vào vẫn được cấu tạo từ s-bit.
  • 2t = n-k: Reed-Solomon có thể sửa được tối đa t anh lính (symbols) biến chất trong đoàn quân, với 2t = n - k

Người ta bảo trăm nghe ko bằng một thấy, vậy dưới đây là hơn 100 lần nghe :v

Hình minh họa cấu tạo RS codeword

Một số tính chất

  1. Với một ký tự(symbol) được tạo nên từ s-bit, thì codeword n có độ dài ko quá $n=2^{s}\; -\; 1$ Ví dụ một ký tự có độ dài 8 bit (s=8) thì n <= 2^8 -1 = 255. Một mã RS điển hình là RS(255,223), ta sẽ có: n = 255, k = 223, s = 8, 2t = 32, t = 16

  2. Một symbol được coi là bị lỗi nếu 1 bit trong nó là lỗi hoặc tất cả các bit trong symbol đó là lỗi. Như vậy, với ví dụ cho RS(255,223) ở trên, mã RS này có thể sửa được 16 symbol lỗi (t=16).

  • Trong trường hợp xấu nhất, có 16 symbol riêng biệt nhau bị lỗi, và chỉ lỗi có 1 bit thôi. Lúc này, bộ giải mã chỉ có thể sửa được 16 * 1 = 16 bit lỗi.

  • Nhưng nếu như tất cả bit của cả 16 symbol đều lỗi, thì bộ decoder có thể sửa tới 16 * 8 = 128 bit lỗi. Vậy dễ nhận thấy là mã RS sẽ rất đắc lực trong trường hợp mà chuỗi các bit liên tiếp nhau bị lỗi.

  1. Một symbol được coi là bị xóa nếu như biết được vị trí của symbol bị xóa. Bộ decoder có thể sửa được tối đa t symbol lỗi và 2t symbol bị xóa. Khi dữ liệu đi qua bộ decoder sẽ có 3 trường hợp xảy ra:
  • 2e + r < 2t với e là số symbol lỗi, r là số symbol bị xóa, thì codeword n luôn đc bảo đảm là đúng.
  • Ngược lại, decoder sẽ báo là không thể khôi phục dữ liệu, hoặc:
  • decoder sẽ decode và khôi phục sai dữ liệu. Đây là trường hợp khi mà chính parity symbols mà chúng ta thêm vào bị lỗi trong quá trình truyền tải. (Đến người mình tin yêu còn phản mình thì có mà bấu víu vào trời :v)

Cài đặt cụ thể

Phần này rất dài, và đặc toán là toán, bạn nào dễ bị đau đầu thì ko nên đọc. Còn bạn nào đầu cứng thì có thể tham khảo ở link:

2 ví dụ trên tác giả viết rõ cho trường hợp áp dụng cho QR code, cũng như giải thích cặn kẽ các kiến thức toán học liên quan, rất đáng tham khảo nếu đi sâu vào tìm hiểu QR.

‎Một số kết luận tóm gọn

  • Cost càng ngày càng tăng nếu data càng dài (hiển nhiên luôn)
  • Encoding đã khó, decoding còn khó hơn nhiều :v
  • Rất nhiều kiến thức toán cao cấp của năm 1 2 đại học được áp dụng như Vành đa thức (univariate polynomials), tập hữu hạn và các phép toán trên tập hữu hạn (finite fields)

PS: trên ruby cũng có lib generate string sang QR code với format png, ansi… mà mình cũng đang sử dụng cho Anychat



Related Posts

Tìm hiểu bộ lọc Bloom (Bloom filter) và một số ứng dụng dưới con mắt đời thường

Bloom filter không phải là một cài đặt cụ thể, nó là một tư tưởng thoả mãn tính chất False positive.

Higher-Order Function (HOF) và Currying

HOF và Currying là hai kỹ thuật không khó, thậm chí bạn đang dùng nó hàng ngày mà không để ý. Cùng tìm hiểu chúng thông qua một số ví dụ.

Vài suy nghĩ về nghề Lập Trình Viên (LTV)

Nghề LTV dưới góc nhìn của người viết. Liệu nó có phải là nghề "đáng làm" hay không?

Xây dựng ứng dụng chat sử dụng websocket có khó không?

A-to-Z Xây dựng ứng dụng realtime chat sử dụng action cable rails 5

Tổ hợp, chỉnh hợp và bài toán đếm cơ bản

Một số bài toán về chỉnh hợp, tổ hợp cơ bản đã học hồi cấp 3 và áp dụng vào bài toán đếm

Pinterest đã thực hiện scaled MySQL của họ như thế nào

Bài viết lược dịch từ Sharding Pinterest How we scaled our MySQL fleet, một bài viết theo mình đánh giá là rất chất lượng, và có nhiều giá trị có thể tham khảo.

Thực hiện benchmark (BM) MySQL InnoDB Buffer Pool(BP) trước và sau khi được warmup

Mình thực hiện BM này cho chính [tool mình viết](https://github.com/manhdaovan/mysql_warmup), cũng là 1 tool đơn giản thôi, tiện thể đem kết quả lên khoe với mọi người luôn.

So sánh các câu lệnh warmup primary key vào buffer pool với engine InnoDB mysql

Buffer pool(BF) của mysql quả thực có nhiều lợi ích, và việc warm up BP luôn là việc nên làm đầu tiên mỗi khi start/reload/create new mysql. Tuy nhiên, "touch" thế nào cho tối ưu nhất? Trong quá trình thực hiện benchmark cho [tool này](https://github.com/manhdaovan/mysql_warmup), người viết thấy có 1 số điều thú vị như dưới đây.

Muốn đi Nhật - Cần làm gì?

Kinh nghiệm bản thân về việc chuẩn bị sang vùng kinh tế mới :v