Thuật toán kiểm tra mạnh mẽ và nhanh chóng?


23

Thuật toán kiểm tra nào bạn có thể đề xuất trong trường hợp sử dụng sau đây?

Tôi muốn tạo tổng kiểm tra các tệp JPEG nhỏ (~ 8 kB mỗi) để kiểm tra xem nội dung có thay đổi không. Tuy nhiên, việc sử dụng ngày của hệ thống tệp được sửa đổi không phải là một tùy chọn.
Số kiểm tra không cần phải là mạnh về mặt mã hóa nhưng phải chỉ rõ các thay đổi của bất kỳ kích thước nào.

Tiêu chí thứ hai là tốc độ vì nó phải có khả năng xử lý ít nhất hàng trăm hình ảnh mỗi giây (trên một CPU hiện đại).

Tính toán sẽ được thực hiện trên máy chủ có nhiều khách hàng. Khách hàng gửi hình ảnh qua Gigabit TCP tới máy chủ. Vì vậy, có không có đĩa I/O là nút cổ chai.

  0

1 Gigabit là 125 Megabyte (full duplex). Trong số 125MB/s đó, một tỷ lệ rất lớn sẽ là chi phí mạng (đặc biệt là khi bạn muốn gửi hàng trăm thứ gì đó nhỏ). Kể từ MD5 trên một lõi nhỏ có thể chạy ở gần 250MB/s, bạn nên thay đổi nó từ ** không có đĩa I/O như nút cổ chai ** thành một cái gì đó như ** hoàn toàn đĩa I/O như nút cổ chai **. Câu hỏi này đã được lên trong 7 năm và không ai có vẻ đã đề cập rằng nếu bạn đã chỉ thử một cái gì đó trước khi gửi bài lên StackOverflow, bạn đã thấy điều này cho chính mình. 01 mar. 162016-03-01 14:42:24

17

Nếu bạn có nhiều tệp nhỏ, nút cổ chai của bạn sẽ là tệp I/O và có thể không phải là thuật toán kiểm tra.

Danh sách hàm băm (có thể được coi là tổng kiểm tra) có thể được tìm thấy here.

Có lý do gì khiến bạn không thể sử dụng ngày của hệ thống tệp được sửa đổi để xác định xem tệp đã thay đổi chưa? Điều đó có lẽ sẽ nhanh hơn.

+2

Đồng ý. Hầu hết các thuật toán băm không mã hóa bảo mật đều đủ ngắn để có cơ hội đáng tin cậy về các từ âm sai, vì vậy tôi chỉ đơn giản sử dụng MD5 hoặc SHA1 và được thực hiện với nó. Tốc độ tính toán dường như không phải là một vấn đề. 24 sep. 082008-09-24 07:44:53

+3

@ luke Tôi cũng muốn kiểm tra sửa đổi tập tin và lần cuối cùng tôi xem lại lưu trữ của mình, tôi nhận thấy rằng một vài phần trăm tệp trong kho lưu trữ của tôi (một bản lưu trữ 100GB nhỏ trên hai đĩa khác nhau) bị hỏng! Dấu thời gian không được thay đổi, nhưng nội dung tệp bị hỏng âm thầm. Một số tập tin được hơn 10 năm, vì vậy tôi phải di chuyển chúng ít nhất hai lần từ máy này sang máy khác. Vì vậy, checksum là phải. 06 feb. 122012-02-06 15:44:59


5

CRC

  0

CRC không mã hóa mạnh mẽ 23 sep. 082008-09-23 19:01:39

+15

Làm cho nó phù hợp cho ứng dụng này. 23 sep. 082008-09-23 19:12:57

+7

OP không yêu cầu thuật toán băm mật mã mạnh :) 23 sep. 082008-09-23 19:13:36


5
  • CRC-32 đi vào tâm trí chủ yếu là bởi vì nó rẻ để tính toán

  • Bất kỳ loại I/O đi vào tâm trí chủ yếu là bởi vì đây sẽ là yếu tố hạn chế đối với một cam kết như vậy;)

  • Vấn đề không tính tổng kiểm tra, vấn đề là đưa hình ảnh vào bộ nhớ để tính tổng kiểm tra.

  • tôi sẽ đề nghị "stagged" giám sát:

    • giai đoạn 1: kiểm tra các thay đổi của timestamps tập tin và nếu bạn phát hiện một sự thay đổi có bàn giao cho ...
      (không cần thiết trong trường hợp của bạn như được mô tả trong các phiên bản chỉnh sửa)

    • giai đoạn 2: có được hình ảnh vào bộ nhớ và tính toán checksum

  • Để chắc chắn quan trọng: đa luồng: thiết lập đường ống cho phép xử lý nhiều ảnh song song nếu một số lõi CPU có sẵn.


7

Có rất nhiều thuật toán CRC nhanh mà nên làm các trick: http://www.google.com/search?hl=en&q=fast+crc&aq=f&oq=

Edit: Tại sao ghét? CRC là hoàn toàn thích hợp, được chứng minh bằng các câu trả lời khác.Tìm kiếm của Google cũng thích hợp, vì không có ngôn ngữ nào được chỉ định. Đây là một vấn đề cũ, cũ đã được giải quyết rất nhiều lần mà không có khả năng là một câu trả lời dứt khoát.


2

adler32, có sẵn trong tiêu đề zlib, được quảng cáo là nhanh hơn đáng kể so với crc32, trong khi chỉ kém chính xác hơn một chút.

+4

Kiểm tra Adler rất yếu đối với một lượng nhỏ dữ liệu, ít hơn vài trăm byte. Giao thức SCTP ban đầu đã sử dụng Adler-32 làm tổng kiểm tra của nó nhưng phải chuyển sang CRC-32 vì lý do này (trong RFC 3309). Mặc dù kích thước trung bình của người hỏi là 8K, nhưng đối với các tệp nhỏ nhất thì đó có thể là vấn đề. 23 sep. 082008-09-23 19:23:35

  0

Thật tuyệt khi biết, cảm ơn! 24 sep. 082008-09-24 01:35:07


3

CRC32 có lẽ là đủ tốt, mặc dù có một cơ hội nhỏ bạn có thể gặp phải xung đột, chẳng hạn như tệp đã bị sửa đổi có thể trông giống như vậy. Để tránh khả năng này, do đó tôi khuyên bạn nên sử dụng MD5, điều này sẽ dễ dàng đủ nhanh và khả năng xảy ra va chạm sẽ giảm xuống đến mức gần như vô hạn.

Như những người khác đã nói, với rất nhiều tệp nhỏ, nút cổ chai thực sự của bạn sẽ là I/O nên vấn đề là giải quyết vấn đề đó. Nếu bạn đăng thêm một vài chi tiết, ai đó cũng có thể gợi ý cách phân loại nó.


2

Yêu cầu quan trọng nhất của bạn là "kiểm tra xem nội dung có thay đổi không".

Nếu điều quan trọng nhất là BẤT K change thay đổi trong tệp được phát hiện, MD-5, SHA-1 hoặc thậm chí SHA-256 phải là lựa chọn của bạn.

Vì bạn đã chỉ ra rằng tổng kiểm tra KHÔNG được mã hóa tốt, tôi khuyên bạn nên sử dụng CRC-32 vì ba lý do. CRC-32 cung cấp khoảng cách hấp dẫn tốt trên một tệp 8K. CRC-32 sẽ có ít nhất một đơn đặt hàng có cường độ nhanh hơn MD-5 để tính toán (yêu cầu thứ hai của bạn). Đôi khi là quan trọng, CRC-32 chỉ yêu cầu 32 bit để lưu trữ giá trị được so sánh. MD-5 yêu cầu bộ nhớ 4 lần và SHA-1 yêu cầu bộ nhớ gấp 5 lần.

BTW, mọi kỹ thuật sẽ được tăng cường bằng cách thêm độ dài của tệp khi tính toán giá trị băm.


2

Theo Wiki page được chỉ ra bởi Luke, MD5 thực sự nhanh hơn CRC32!

Tôi đã tự mình thử bằng cách sử dụng Python 2.6 trên Windows Vista và nhận được kết quả tương tự.

Dưới đây là một số kết quả:

crc32: 162,481544276 MBps md5: 224,489791549 MBps

crc32: 168,332996575 MBps md5: 226,089336532 MBps

crc32: 155,851515828 MBps md5: 194,943289532 MBps

Tôi cũng đang nghĩ về cùng một câu hỏi và tôi bị cám dỗ khi sử dụng biến thể của Adlerync là Adler-32 để phát hiện tệp e khác biệt.

+2

Điều đó không bình thường. Là chất lượng của việc thực hiện CRC32 và MD5 tương đương, hoặc không sử dụng mỗi tối ưu hóa trình biên dịch và tìm kiếm bảng lừa có, trong khi một trong những khác không? 24 mar. 102010-03-24 23:59:30


1

Chỉ cần một bản ghi bài viết ở trên; jpegs sử dụng nén lossy và mức độ nén có thể phụ thuộc vào chương trình được sử dụng để tạo jpeg, bảng màu và/hoặc độ sâu bit trên hệ thống, hiển thị gamma, card đồ họa và mức độ nén/cài đặt màu do người dùng đặt. Do đó, việc so sánh các jpeg được xây dựng trên các máy tính/nền tảng khác nhau hoặc sử dụng phần mềm khác nhau sẽ rất khó ở cấp độ byte.

  0

cảm ơn nhận xét này. Tôi đã lấy thực tế này thành acount. 19 may. 092009-05-19 08:13:25


5

Nếu bạn đang nhận tệp qua mạng, bạn có thể tính tổng kiểm tra khi bạn nhận tệp. Điều này sẽ đảm bảo rằng bạn sẽ tính toán tổng kiểm tra trong khi dữ liệu nằm trong bộ nhớ. Do đó bạn sẽ không phải tải chúng vào bộ nhớ từ đĩa.

Tôi tin rằng nếu bạn áp dụng phương pháp này, bạn sẽ thấy chi phí gần như bằng không trên hệ thống của mình.

Đây là thói quen tôi đang sử dụng trên hệ thống nhúng kiểm tra kiểm soát phần mềm và các nội dung khác.

static const uint32_t crctab[] = { 
    0x0, 
    0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 
    0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 
    0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 
    0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 
    0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, 
    0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 
    0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 
    0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 
    0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 
    0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, 
    0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, 
    0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 
    0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, 
    0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 
    0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 
    0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 
    0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 
    0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 
    0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 
    0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 
    0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 
    0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 
    0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 
    0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, 
    0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 
    0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 
    0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 
    0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 
    0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, 
    0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 
    0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 
    0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 
    0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 
    0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 
    0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, 
    0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 
    0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, 
    0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 
    0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 
    0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 
    0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 
    0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, 
    0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 
    0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 
    0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 
    0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 
    0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 
    0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, 
    0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 
    0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 
    0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 
}; 

typedef struct crc32ctx 
{ 
    uint32_t crc; 
    uint32_t length; 
} CRC32Ctx; 


#define COMPUTE(var, ch) (var) = (var) << 8^crctab[(var) >> 24^(ch)] 

void crc32_stream_init(CRC32Ctx* ctx) 
{ 
    ctx->crc = 0; 
    ctx->length = 0; 
} 

void crc32_stream_compute_uint32(CRC32Ctx* ctx, uint32_t data) 
{ 
    COMPUTE(ctx->crc, data & 0xFF); 
    COMPUTE(ctx->crc, (data >> 8) & 0xFF); 
    COMPUTE(ctx->crc, (data >> 16) & 0xFF); 
    COMPUTE(ctx->crc, (data >> 24) & 0xFF); 
    ctx->length += 4; 
} 

void crc32_stream_compute_uint8(CRC32Ctx* ctx, uint8_t data) 
{ 
    COMPUTE(ctx->crc, data); 
    ctx->length++; 
} 

void crc32_stream_finilize(CRC32Ctx* ctx) 
{ 
    uint32_t len = ctx->length; 
    for(; len != 0; len >>= 8) 
    { 
     COMPUTE(ctx->crc, len & 0xFF); 
    } 
    ctx->crc = ~ctx->crc; 
} 

/*** pseudo code ***/ 
CRC32Ctx crc; 
crc32_stream_init(&crc); 

while((just_received_buffer_len = received_anything())) 
{ 
    for(int i = 0; i < just_received_buffer_len; i++) 
    { 
     crc32_stream_compute_uint8(&crc, buf[i]); // assuming buf is uint8_t* 
    } 
} 
crc32_stream_finilize(&crc); 
printf("%x", crc.crc); // ta daaa