2010-11-01 26 views
10

Tôi đã có một nhu cầu đặc biệt và những mối quan tâm quan trọng nhất là:thuật toán: số khổng lồ của mảng chút rất thưa thớt, mà mã hóa để sử dụng

  • trong bộ nhớ
  • nhớ rất thấp chân
  • speed

Đây là "vấn đề" của tôi: Tôi cần lưu trữ, trong bộ nhớ, một số lượng lớn các mảng bit rất thưa thớt. Những bitets đó chỉ là "nối thêm" và được sử dụng chủ yếu cho các giao lộ. Bởi lớn, tôi có nghĩa là cao như 200 000 bit mảng.

Dải ô phải nằm trong khoảng từ [0 ... 16 000 000] cho mỗi bitet.

Tôi chạy một số pre-test với "chỉ" 10 673 mảng chút có chứa một số dữ liệu thực tế tôi đã có và nhận được kết quả như sau:

1% of the bit arrays ( 106 bit arrays) Hamming weight: at most  1 bit set 
    5% of the bit arrays ( 534 bit arrays) Hamming weight: at most  4 bits set 
10% of the bit arrays (1068 bit arrays) Hamming weight: at most  8 bits set 
15% of the bit arrays (1603 bit arrays) Hamming weight: at most 12 bits set 
20% of the bit arrays (2137 bit arrays) Hamming weight: at most 17 bits set 
25% of the bit arrays (2671 bit arrays) Hamming weight: at most 22 bits set 
30% of the bit arrays (3206 bit arrays) Hamming weight: at most 28 bits set 
35% of the bit arrays (3740 bit arrays) Hamming weight: at most 35 bits set 
40% of the bit arrays (4274 bit arrays) Hamming weight: at most 44 bits set 
45% of the bit arrays (4809 bit arrays) Hamming weight: at most 55 bits set 
50% of the bit arrays (5343 bit arrays) Hamming weight: at most 67 bits set 
55% of the bit arrays (5877 bit arrays) Hamming weight: at most 83 bits set 
60% of the bit arrays (6412 bit arrays) Hamming weight: at most 103 bits set 
65% of the bit arrays (6946 bit arrays) Hamming weight: at most 128 bits set 
70% of the bit arrays (7480 bit arrays) Hamming weight: at most 161 bits set 
75% of the bit arrays (8015 bit arrays) Hamming weight: at most 206 bits set 
80% of the bit arrays (8549 bit arrays) Hamming weight: at most 275 bits set 
85% of the bit arrays (9083 bit arrays) Hamming weight: at most 395 bits set 
90% of the bit arrays (9618 bit arrays) Hamming weight: at most 640 bits set 
95% of the bit arrays (10152 bit arrays) Hamming weight: at most 1453 bits set 
96% of the bit arrays (10259 bit arrays) Hamming weight: at most 1843 bits set 
97% of the bit arrays (10366 bit arrays) Hamming weight: at most 2601 bits set 
98% of the bit arrays (10473 bit arrays) Hamming weight: at most 3544 bits set 
99% of the bit arrays (10580 bit arrays) Hamming weight: at most 4992 bits set 
100% of the bit arrays (10687 bit arrays) Hamming weight: at most 53153 bits set 

Nhìn những con số liên quan, tôi rõ ràng là cần phải sử dụng nén mảng bit và đó không phải là một vấn đề: nó sẽ ở lại dễ dàng để đối phó với thấy rằng các mảng bit là "nối thêm chỉ".

Các bit mảng bit được bật là nhóm được nhóm, nhưng không hoàn toàn. Vì vậy, bạn sẽ có xu hướng có một vài bit trên trong cùng một khu vực (nhưng thường không phải cái khác, làm cho RLE kinda không tuyệt vời cho các bit được bật).

Câu hỏi của tôi là loại nén nào sẽ sử dụng?

Bây giờ tôi không biết liệu tôi có nên đặt cách tiếp cận đầu tiên của mình ở đây hay trong câu trả lời cho câu hỏi của riêng mình hay không.

Về cơ bản tôi tưởng tượng một "trường hợp xấu nhất" kịch bản sử dụng một mã hóa rất ngớ ngẩn:

  • 1 chút: nếu trên, 5 bit sau xác định bao nhiêu bit là cần thiết để tính toán 'bỏ qua', nếu tắt, tối ưu hóa: 5 bit sau xác định có bao nhiêu bit cũng được thực hiện theo nghĩa đen (nghĩa là 'bật' hoặc 'tắt', không bỏ qua) [điều này sẽ chỉ được chuyển sang khi được xác định là hiệu quả hơn so với các biểu diễn khác, vì vậy khi nó khởi động, nó sẽ luôn là một tối ưu hóa (kích thước khôn ngoan)]

  • 5 bit: số lượng bit chúng ta có thể bỏ qua trước bước tiếp theo t trên

  • x bit: skip

Dưới đây là một ví dụ: một mảng bit có 3 set bit, các bit đầu tiên là vào lúc 3 098 137, thứ hai lúc 3 098 141 và thứ ba tại 3 098 143.

       +-- now we won't skip 
           | 
           |  +-- 3 because we need 3 bits to store "6" (from 3 098 138 to 3 098 143) 
           |  | +--- 3 098 141 is on 
    22 3 098 137    |  3 | +- 3 098 143 is on 
1 10110 1011110100011000011001 0 00011 000101 etc. 

bit đầu tiên cho biết chúng ta sẽ bỏ qua bit. 5 bit tiếp theo (luôn luôn 5) cho biết có bao nhiêu bit chúng ta cần biết số bit chúng ta sẽ bỏ qua 22 bit yêu cầu bỏ qua đến 3 098 137 một chút cho biết bây giờ chúng ta không bỏ qua các bit 5 bit tiếp theo (luôn luôn 5) cho biết có bao nhiêu bit chúng ta sẽ đọc "như là" 6 bit: tắt, tắt, tắt, bật, tắt, có nghĩa là 3 098 141 và 3 098 143 là trên , v.v.

Thấy điều tuyệt vời sparsity của các mảng bit, điều này có vẻ khá kích thước hiệu quả.Vì vậy, bằng cách sử dụng mã hóa đó, tôi lấy dữ liệu mẫu của mình và tính toán trường hợp "trường hợp xấu nhất" (tôi chưa viết bản ngã nào, trước tiên tôi muốn có một vài đầu vào ở đây): về cơ bản tôi đã xem là không chỉ có "tối ưu hóa kích thước" sẽ không bao giờ đá vào và, cũng, rằng 5 bit sẽ luôn luôn được thiết lập giá trị tối đa của họ (24 bit), mà tất nhiên không thể xảy ra.

Tôi đã làm nó chỉ để có một xấp xỉ rất thô của những gì "tồi tệ nhất của trường hợp xấu nhất" có thể được.

Tôi đã rất ngạc nhiên:

Worst case scenario: 

108 913 290 bits needed for the 10 687 very sparse bit arrays 
12.9 MB (13 295 KB) 

Các dữ liệu là dữ liệu thực tế và tất cả các dữ liệu là tương tự, tôi biết rằng, nếu xấu đến tồi tệ hơn, tôi có thể lưu trữ 200 000 mảng chút tôi trong khoảng 240 MB, được rồi.

Tôi khá chắc chắn mã hóa thực tế sẽ ít hơn nhưng tôi chưa thực sự viết nó, tôi chỉ có thể (rất dễ) tính toán "trường hợp xấu nhất", đó là lý do tại sao tôi chỉ hiển thị một.

Bất kỳ gợi ý/ý tưởng nào về cách làm cho kích thước này hiệu quả hơn (ghi nhớ đây là mảng bit siêu thưa thớt, sẽ có hàng trăm nghìn, chúng phải nằm trong bộ nhớ và chúng sẽ là " chỉ nối thêm ")?

Về trường hợp 'append-only' của tôi

Về cơ bản tôi đã có một phát triển "rộng" (phạm vi, nhưng "rộng" là một thuật ngữ thực tế như tôi hiểu nó) và rất nhiều mảng bit có một vài bộ. Khi phạm vi đi từ, ví dụ, từ 0 đến 1 000 000, tất cả các mảng bit đều từ 0 đến 1 000 000 đến. Khi phạm vi tăng lên 1 000 001, thì tất cả các mảng bit cũng đang phát triển, tất cả chỉ bằng một bit. Nhưng hầu hết các mảng bit sẽ có một '0' nối vào cuối của chúng, trong khi khoảng 4-8 của mảng bit sẽ có một '1' nối vào cuối của chúng. Tuy nhiên tôi không thể tiên đoán trước mảng bit nào sẽ có 0 hoặc 1 được nối thêm.

Vì vậy, tôi có rất nhiều mảng bit có cùng kích thước, tất cả đều rất thưa thớt (< 0,5% số bit được đặt) và tất cả đều "tăng trưởng" khi tăng trưởng phạm vi (vì vậy chúng ' tất cả luôn phát triển với cùng tốc độ).


Judy arrays thật tuyệt. Nhưng tôi đã đọc về chúng cách đây vài năm và những thứ đó là "trên đầu của tôi". Các mảng Judy là một lib 20KLOC chỉ C và tôi chắc chắn không thực hiện lại điều đó. Nhưng chúng thật tuyệt vời. Vì vậy, tôi đoán tôi cần phải thêm tôi muốn tất cả điều này để ở lại tương đối đơn giản, mà không phải là xa vời thấy đặc biệt "phụ thêm duy nhất" tài sản của mảng bit rất thưa thớt của tôi. Tôi có thể làm như vậy.

+0

Lưu ý rằng các ý kiến ​​về việc phát minh lại bánh xe có thể được gửi tới */dev/null *: nếu chỉ tính toán/thách thức phía sau nó Tôi muốn tự mình thực hiện điều này. Và dù sao tôi cũng sẽ rất ngạc nhiên khi tìm thấy một bánh xe có thể xử lý 200 000 mảng bit "nối thêm" trong bộ nhớ :) Nhưng nếu bạn có một, thì cơ chế đằng sau nó sẽ khiến tôi quan tâm nhiều :) – SyntaxT3rr0r

+1

Có lý thuyết giới hạn về mật độ mã hóa: với mảng các phần tử N, n trong số đó được thiết lập, số bit tối thiểu để mã hóa sẽ là -n * log2 (n/N) - (Nn) * log (1-n/N). Đối với mảng của bạn trong đó 53153 của 16M được thiết lập này sẽ là 514kBits và cho 4992 bit thiết lập - 65 kBits. Và gần gũi hơn với bộ nhớ của bạn với giới hạn này, mã hóa phức tạp hơn bạn phải chọn. – Vovanium

+1

@Vovanium, tôi nghĩ bạn đã bỏ qua một số bối cảnh cần thiết cho giới hạn lý thuyết của bạn (như, một số giả thiết thống kê về phân phối bit được thiết lập?) – comingstorm

Trả lời

2

Thậm chí nếu chúng không chính xác những gì bạn đang tìm kiếm, bạn nên kiểm tra số Judy trees. Judy là một thư viện được tối ưu hóa rất nhiều cho các bản đồ có thứ tự, và một cấu hình được thiết kế đặc biệt như một bitet chứ không phải là một bản đồ. Tôi không nghĩ giao lộ là một trong những hoạt động được tối ưu hóa nguyên bản, mặc dù ...

Ý tưởng chung là sử dụng một cây có số bit địa chỉ cố định cho mỗi cấp và tận dụng lợi thế của độ thưa thớt ở mỗi cấp . Điều này dẫn đến việc nén khá tốt ngay cả trong trường hợp xấu nhất và hiệu suất truy vấn nhanh. Tôi tin rằng một hoạt động giao lộ sẽ tương đối đơn giản và có khả năng rất nhanh.

Dù sao đi chăng nữa, bạn luôn nên ăn cắp tốt nhất!

+0

yup mảng Judy là tuyệt vời nhưng thành thật mà toán đằng sau nó hơi phức tạp đối với tôi :) Và AFAICT nó chỉ có sẵn dưới dạng 20KLOC C-lib : -/Tôi chắc chắn tái phát minh * rằng * bánh xe :) – SyntaxT3rr0r

+0

Chết tiệt, tôi có nghĩa là, tôi chắc chắn * không * tái phát minh * rằng * bánh xe :) Rõ ràng :) – SyntaxT3rr0r

+0

Không cần phải tái tạo lại bánh xe của họ, nhưng nguyên tắc cơ bản có vẻ giống như loại thứ bạn đang tìm kiếm: rất thưa thớt và dễ thích nghi để viết một hàm giao cắt nhanh. – comingstorm

1

Xem xét bạn sẽ thực hiện một loạt các kiểm tra giao lộ, có thể bạn nên thử lưu trữ tất cả các bitvector song song. Một danh sách mục nhập 16M thưa thớt. Mỗi mục trong danh sách đó chứa danh sách các bitvector đầu vào 200k có dấu '1' tại vị trí đó. Có vẻ như bạn mong đợi chỉ có khoảng 5 bit được đặt cho mỗi vé vào, hoặc tổng số 1 triệu mục nhập? Lấy danh sách liên kết danh sách liên kết rơm-man cho toplevel và bucket, và trường hợp xấu nhất không có nút giao nào (vì vậy 1M thùng với 1 phần tử) bạn có thể lưu trữ tất cả trong 32MB.

+0

không không, danh sách tôi đăng cho thấy nó, ví dụ: * "50% bitvectors sẽ có [giữa 55 và] 67 bit "*.Sẽ có nhiều hơn 1 triệu tổng số mục nhập. Với bitkectors 200K tôi muốn nói rằng có, rất thô lỗ, tổng cộng 100 triệu bit được thiết lập. – SyntaxT3rr0r

+0

Tôi đã không nhìn vào nó theo cách này, nhưng bây giờ mà bạn đề cập đến làm nó "một cách khác", đó là một đảm bảo rằng tất cả các đơn * "mở rộng" * (phạm vi 16 triệu) sẽ được sử dụng một vài lần. Cách bạn phrased nó, mỗi mục trong danh sách 16M sẽ có khoảng 4 đến 8 bit thiết lập. – SyntaxT3rr0r

+0

Aha, tôi nghĩ đó là tổng số, do đó 55k/10k = 5, sai lầm của tôi. Vì vậy, không có lý do để làm cho mảng 16M thưa thớt, mỗi mục cần khoảng trống cho khoảng 8 18 bit (2^18> mảng 200k) số nhận dạng, vì vậy 288MB. Tương tự như ước tính của bạn. –

3

Bạn có thể sử dụng cây nhị phân cho mảng bit. Giả sử, bạn có mảng với phạm vi [M..N]. Lưu trữ theo cách như vậy:

Chọn mã hóa số cho [0 ... kích thước ram], như Fibonacci, Golomb hoặc Rice code (bạn có thể chọn đại diện phù hợp nhất sau khi lập hồ sơ chương trình của bạn với dữ liệu thực tế).

  1. Nếu mảng rỗng (không có bit thiết lập), lưu trữ nó như là số 0.
  2. Nếu mảng có đầy đủ (tất cả đều bit thiết lập), lưu trữ nó như là số 1.
  3. khác chia nó trong hai phần: A trong [M .. (M + N)/2-1] và B trong [(M + N) /2..N]
  4. Tạo biểu diễn của P0 và P1 bằng thuật toán này đệ quy.
  5. Độ dài P0 (tính bằng bit hoặc đơn vị độ dài khác có thể là số nguyên) và lưu trữ dưới dạng số (bạn có thể cần phải thêm 1 nếu chiều dài có thể là 1, ví dụ: bạn lưu 0 là bit đơn 0).
  6. Lưu trữ P0 rồi P1.

Trong trường hợp này, nếu giới hạn là phổ biến, hoạt động giao nhau một đoàn là recursions tầm thường:

Intersection:

  1. Nếu mảng A là trống rỗng, cửa hàng 0.
  2. Nếu mảng A đầy, lưu trữ bản sao của B
  3. Các mảng phân tách khác, tạo các giao điểm của cả hai nửa, chiều dài lưu trữ của nửa đầu, sau đó cả hai nửa.

Thuật toán này có thể xử lý các bit (nếu bạn cần chúng nhỏ gọn nhất) và byte/từ (nếu hoạt động bit chậm). Ngoài ra, bạn có thể thêm mã hóa specical cho mảng với bộ bit đơn, tất cả các mảng có kích thước nhỏ hơn một số giới hạn (ví dụ 8 phần tử) để giảm mức đệ quy.

Hạn chế là không có một số hacks thêm/loại bỏ phần tử vào/từ mảng là hoạt động phức tạp (phức tạp như giao lộ/nghiệp đoàn).

Ví dụ: mảng có bộ bit 0xAB đơn phải được lưu trong mảng 0 ..0xFF như (giả cho):

0 1  2 3 4  5 6 7  8 9 10  11 12  13 14  15  16 
1, EMPTY, 13, 1, EMPTY, 9, 1, EMPTY, 5, 1, EMPTY, 1, EMPTY, FULL, EMPTY, EMPTY, EMPTY 
                | AA | AB | 
             |A8..A9| AA .. AB | 
             | A8   ..  AB |AC..AF| 
          |A0..A7| A8    ..    AF | 
         | A0     ..     AF |B0..BF| 
       |80..9F| A0      ..      BF | 
      | 80         ..      BF |C0..FF| 
| 0..7F| 80           ..       FF |  

EMPTY và ĐẦY ĐỦ là dành cho mảng trống rỗng và đầy đủ, con số này được độ dài trong các yếu tố (nên được thay thế bằng lengthts thực tế tính theo byte, bit hoặc lâu hơn)

FF bạn không cần nhanh chóng kiểm tra bit đơn, bạn có thể sử dụng cách tiếp cận đơn giản nhất: Chỉ cần lưu trữ khoảng cách giữa các bit thiết lập bằng cách sử dụng mã: fibonacci, gạo, golomb, levenshtein, elias vv hoặc phát minh một số khác. Lưu ý, để có độ dài mã tối thiểu, bạn nên sử dụng mã có độ dài mã càng gần càng tốt để -log p/log 2, trong đó p là xác suất của mã đó. Bạn có thể sử dụng mã huffman cho điều đó.

Ví dụ, sử dụng elias đang gamma, vì vậy mảng như thế này:

0 1 0000 1 1 000 1 0 1 000000000000000000 1 000000000000000000 
2  5 1 4 2   19     18   (distance) 

nên được mã hóa như:

010 00101 1 00100 010 000010011 000010010 
2 5 1 4 2  19  18  (distance code explained) 

Và chủ yếu là nhỏ gọn cho mảng với phân phối bit thống nhất sẽ là số học mã hóa, nhưng nó rất counsumpting CPU thời gian. Becaouse bạn sẽ phải đọc và viết các mảng như vậy từng chút một mà không bỏ qua nhanh.

+0

+1, câu trả lời tuyệt vời nữa. Tôi không biết con đường nào tôi sẽ đi nhưng điều này chắc chắn mang lại thức ăn cho những suy nghĩ :) – SyntaxT3rr0r

+0

Cảm ơn. Ngoài ra tôi có thể khuyên bạn nên xem cách thực hiện các thuật toán nén âm thanh khác nhau (MP2, AAC, vv). Chúng xử lý các mảng thưa thớt (như 0, 0, 0, 1, 0, -1, 1, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0) khi nén phổ tần số cao. – Vovanium

4

Bạn không nói ngôn ngữ lập trình nào bạn muốn sử dụng. Có vẻ như bạn không muốn Judy vì đó là "C-only" ... nếu bạn đang sử dụng C# thì bạn có thể sử dụng số Compact Patricia Trie thay thế. Là gần như 4500 LOC (nhận xét) và sử dụng những ý tưởng tương tự như Judy, nhưng kích thước và tốc độ của mỗi trie không phải là lý tưởng do hạn chế của .NET. Nó không được tối ưu hóa cho các giao lộ tính toán, nhưng có thể thêm một thuật toán như vậy. Bài viết về CP Tries không nhấn mạnh điểm này, nhưng nó có thể lưu trữ các bộ (mảng bit thưa thớt) nhỏ gọn hơn nhiều so với từ điển (các đồ thị trong bài viết hiển thị kích thước và tốc độ của từ điển, chứ không phải bộ).

Trường hợp tốt nhất là một cụm bit dày đặc. Với 50% công suất (mỗi bit khác được đặt), nó yêu cầu ít hơn 8 bit cho mỗi khóa (ít hơn 4 bit cho mỗi số nguyên). (chỉnh sửa: ít hơn 8 bit, không nhiều hơn.)

Nếu bạn chỉ cần đại diện gần đúng của dữ liệu, hãy sử dụng Bloom filter.

Nhân tiện, bạn có ý nghĩa gì khi chỉ "nối thêm"? Điều đó có nghĩa là bạn chỉ thêm khóa hoặc mỗi khóa bạn thêm lớn hơn các khóa bạn đã thêm trước đó?

Cập nhật: Vì bạn chỉ thêm các khóa lớn hơn, có lẽ bạn nên thiết kế một thuật toán đặc biệt chỉ dành cho trường hợp của bạn. IMO, khi thiết kế một thuật toán tùy chỉnh, bạn nên làm cho nó càng đơn giản càng tốt. Vì vậy, đây là ý tưởng của tôi, giả sử các khóa của các bit khác nhau không tương quan (do đó không có lợi ích khi cố nén dữ liệu giữa các bit khác nhau):

Bitet được biểu diễn bằng một mảng sắp xếp các khe 32 bit. Bởi vì nó được sắp xếp, bạn có thể sử dụng tìm kiếm nhị phân để tìm khóa. Mỗi khe chứa một tiền tố 24 bit và 8 bit của "cờ". Mỗi khe đại diện cho một vùng gồm 8 phím. Các "lá cờ" cho bạn biết 8 phím trong khu vực có mặt trong bitet và "tiền tố" cho bạn biết vùng nào chúng ta đang nói đến, bằng cách chỉ định các bit từ 3 đến 26 của khóa. Ví dụ: nếu các bit sau là "1" trong bitet:

1, 3, 4, 1094, 8001, 8002, 8007, 8009 

...thì bitset được biểu diễn bởi một mảng của 4 khe cắm (16 byte):

Prefix:  0, 136, 1000, 1001 
Flags: 0x15, 0x40, 0x86, 0x02 

Khe đầu tiên đại diện cho 1, 3, 4 (lưu ý rằng bit 1, 3 và 4 được thiết lập trong 0x15 số); khe thứ hai đại diện cho 1094 (136 * 8 + 6); khe thứ ba đại diện cho 8001, 8002 và 8007; khe thứ tư đại diện cho 8009. Điều này có hợp lý không?

Tôi không biết điều này nhỏ gọn như ý tưởng của bạn hay không. Nhưng tôi nghĩ bạn sẽ nhận được các truy vấn nhanh hơn và sửa đổi nhanh hơn, và nó sẽ khá dễ thực hiện.

+0

+1, câu trả lời hay. Không biết nhiều về Patricia Trie (ngoài tên tôi đã nghe), sẽ đọc. Yup, bởi * "nối thêm chỉ" * Tôi có nghĩa là khi "mở rộng" (phạm vi) phát triển, một số mảng bit (thường là 4 đến 8) sẽ có một bit đặt ở cuối mảng bit. Vì vậy, tôi không bao giờ "chèn" bất kỳ bit ở giữa của một mảng bit. Vì vậy, nó thực sự là một trường hợp đặc biệt mà, tôi nghĩ, làm cho mọi thứ dễ dàng hơn nhiều. – SyntaxT3rr0r

+0

Tôi đoán rằng bằng cách "nối thêm chỉ", tôi có nghĩa là cả hai tôi chỉ thêm các khóa và khóa đó cũng luôn luôn lớn hơn khóa tôi đã thêm trước đó. – SyntaxT3rr0r

+0

Tôi ước tôi có thể cung cấp nhiều hơn 1, bài viết của bạn trông tuyệt vời, do đó, thực hiện C# của bạn về "CPT". Trên thực tế ngôn ngữ tôi đang sau là * có lẽ * Java nhưng tôi có thể cần phải có một cách dễ dàng để cổng này cho cả C# và Objective-C ... Vì vậy, tôi muốn có một cái gì đó tương đối dễ dàng. Nhưng Compact Patricia Trie của bạn trông thật tuyệt vời. Một lần nữa trường hợp của tôi là rất đặc biệt: hầu hết các mảng bit của tôi thậm chí không có 0,5% của mỗi bit thiết lập, do đó, nó thực sự là * siêu thưa thớt *. – SyntaxT3rr0r

1

Bạn có thể quan tâm đến Binary Decision Diagrams (BDD), và chính xác hơn là Binary Decision Diagram Diagram (ZBDD).

Chúng được sử dụng để biểu diễn các bộ theo cách nén. Không giống như các biểu mẫu nén khác, các hoạt động (chẳng hạn như các nút giao nhau thiết lập hoặc chèn các phần tử - điều "chỉ nối thêm" của bạn?) Hoạt động trực tiếp trên biểu mẫu nén.

+0

Tôi đã chỉnh sửa một chút câu hỏi của mình để làm rõ "điều bổ sung duy nhất". Về cơ bản, các mảng bit ngày càng tăng (tối đa 16 000 000 bit) và tôi luôn chỉ thay đổi phần cuối của nó, vì vậy rất dễ dàng để làm việc trực tiếp trên biểu mẫu nén. – SyntaxT3rr0r

Các vấn đề liên quan