4

ubuntuのbashスクリプトで、300万個程度の文字列のMD5合計が必要です。300 万の文字列 -> 300 万の MD5 ハッシュ。簡単な実装では、文字列あたり約 0.005 秒かかります。それは4時間以上です。より高速な代替手段は何ですか? 文字列のグループを md5sum に送り込む方法はありますか?

#time md5sum running 100 times on short strings
#each iteration is ~0.494s/100 = 0.005s
time (for i in {0..99}; do md5sum <(echo $i); done) > /dev/null

real    0m0.494s
user    0m0.120s
sys     0m0.356s

適切なソリューションには、stdin から文字列のリストを取得し、MD5 ハッシュのリストを出力する bash/Perl スクリプトが含まれます。

4

5 に答える 5

7

多くの md5 実装のいずれかを使用して、C (または Perl または Python) で実行することは難しくありません。md5 の中心は、文字ベクトルから文字ベクトルに変換するハッシュ関数です。

したがって、300 万の文字列を読み取る外部プログラムを作成し、選択した md5 実装に 1 つずつフィードするだけです。そうすれば、300 万回ではなく 1 回のプログラム起動で済み、それだけで時間を節約できます。

FWIW のあるプロジェクトでは、Christophe Devine による md5 実装 (C) を使用しました。OpenSSL もあり、CPAN には Perl 用にも多数の実装があると確信しています。

編集:わかりました、抵抗できませんでした。私が言及した md5 の実装は、たとえば、この小さな tarball内にあります。ファイルを取得し、下部md5.cの (#ifdef'ed out) をこれに置き換えますmain()

int main( int argc, char *argv[] ) {
    FILE *f;
    int j;
    md5_context ctx;
    unsigned char buf[1000];
    unsigned char md5sum[16];

    if( ! ( f = fopen( argv[1], "rb" ) ) ) {
        perror( "fopen" );
        return( 1 );
    }

    while( fscanf(f, "%s", buf) == 1 ) {
        md5_starts( &ctx );
        md5_update( &ctx, buf, (uint32) strlen((char*)buf) );
        md5_finish( &ctx, md5sum );

        for( j = 0; j < 16; j++ ) {
            printf( "%02x", md5sum[j] );
        }
        printf( " <- %s\n", buf );
    }
    return( 0 );
}

たとえば、単純なスタンドアロン プログラムをビルドします。

/tmp$ gcc -Wall -O3 -o simple_md5 simple_md5.c

そして、あなたはこれを得る:

# first, generate 300,000 numbers in a file (using 'little r', an R variant)
/tmp$ r -e'for (i in 1:300000) cat(i,"\n")' > foo.txt

# illustrate the output
/tmp$ ./simple_md5 foo.txt | head
c4ca4238a0b923820dcc509a6f75849b <- 1
c81e728d9d4c2f636f067f89cc14862c <- 2
eccbc87e4b5ce2fe28308fd9f2a7baf3 <- 3
a87ff679a2f3e71d9181a67b7542122c <- 4
e4da3b7fbbce2345d7772b0674a318d5 <- 5
1679091c5a880faf6fb5e6087eb1b2dc <- 6
8f14e45fceea167a5a36dedd4bea2543 <- 7
c9f0f895fb98ab9159f51fd0297e236d <- 8
45c48cce2e2d7fbdea1afc51c7c6ad26 <- 9
d3d9446802a44259755d38e6d163e820 <- 10

# let the program rip over it, suppressing stdout
/tmp$ time (./simple_md5 foo.txt > /dev/null)

real    0m1.023s
user    0m1.008s
sys     0m0.012s
/tmp$

つまり、300,000 (短い) 文字列では約 1 秒です。

于 2009-12-25T19:28:55.410 に答える
5
#~/sw/md5$ time (for i in {0..99}; do md5sum <(echo $i); done) > /dev/null

real    0m0.220s
user    0m0.084s
sys 0m0.160s
#~/sw/md5$ time (python test.py `for i in {0..99}; do echo $i; done`) > /dev/null

real    0m0.041s
user    0m0.024s
sys 0m0.012s

Python コードは、この小さなサンプルでは 5 倍高速ですが、大きなサンプルでは、​​spawn が欠落しているため、違いははるかに大きくなります。1k サンプルは 0.033 秒から 2.3 秒です :) スクリプトは次のとおりです。

#!/usr/bin/env python
import hashlib, sys

for arg in sys.argv[1:]:
  print hashlib.md5(arg).hexdigest()
于 2009-12-25T20:02:04.570 に答える
4
perl -MDigest::MD5=md5_hex -lpe '$_ = md5_hex $_'
于 2009-12-25T19:42:51.247 に答える
3

私は今それをテストするためのマシンを持っていmd5sum <<< "$i"ませんが、より速いですmd5sum <(echo $i)か? この<<<構文は、のサブプロセスを fork するオーバーヘッドを回避し、標準入力に直接echo渡します。$imd5sum

于 2009-12-25T19:28:13.210 に答える
1

パフォーマンスを向上させるには、おそらく別のプログラムを使用するか、公開されている md5 ハッシュ API のいずれかを呼び出す C プログラムを作成する必要があります。

もう 1 つのオプションは、複数の md5 呼び出しを一度に生成して、複数のコアを利用することです。ループごとに 8 つの呼び出しが生成される可能性があり、最初の 7 つは最後に & を使用します (非同期であることを示すため)。4 ~ 8 個のコアが利用可能な場合、これにより 8 倍高速化される可能性があります。

于 2009-12-25T19:29:50.267 に答える