2016-03-25 10 views
1

私はGoを学習しています。math/bigパッケージを使用して任意の長さの整数を処理し始めました。GoでGMPスタイルのパフォーマンスで大きな数字を扱う

Iはn番目のフィボナッチ数を計算し、このプログラムを書いた:(import秒削除):

int main(int argc, char** argv) 
{ 
    int imax = atoi(argv[1]); 

    mpz_t a, b, c; 
    mpz_inits(a, b, c, NULL); 
    mpz_set_ui(a, 0); 
    mpz_set_ui(b, 1); 

    int i = 0; 
    for (i = 0; i < imax; i++) { 
     mpz_swap(a, b); 
     mpz_add(b, a, b); 
    } 

    char* astr = NULL; 
    astr = mpz_get_str(NULL, 10, a); 
    printf("%s\n", astr); 

    return EXIT_SUCCESS; 
} 

囲碁プログラムを計算:

func main() { 
    imax, _ := strconv.Atoi(os.Args[1]) 
    var a, b, c big.Int 
    a.SetUint64(0) 
    b.SetUint64(1) 
    for i := 0; i < imax; i++ { 
     c.Set(&b) 
     b.Add(&b, &a) 
     a.Set(&c) 
    } 
    fmt.Println(a.String()) 
} 

ここでCプログラムのためのコードですGMP libを使用した場合のCの等価物は0.04秒でのみ実行されます。それは2倍遅いです。

私のGoプログラムで同じパフォーマンスを得る方法はありますか?

+0

これはコードレビューのリクエストであるため、このトピックをオフトピックとして閉じることにしました。 – Olaf

+1

コードレビューのリクエストはどうですか?私はこのプログラムを特に最適化するのではなく、2つの言語で同じperfsを得る方法を学ぶことを望んでいます。私は、偏っていないベンチマークを得るために、2つのプログラムを可能な限り似ているようにしようとしました。答えは、例えば、他の任意精度の算術Goライブラリであってもよい。 – Arno

+1

操作を比較する場合は、再現可能なベンチマークを設定する必要があります。コードのコンパイル方法と実行方法はわかりません。私のシステムでは、goコードは〜55msで10000を計算します。 – JimB

答えて

2

stdoutに印刷しないでください。遅いです。このコードの結果はどうなりますか?

package main 

import (
    "math/big" 
    "os" 
    "strconv" 
) 

func main() { 
    max, err := strconv.Atoi(os.Args[1]) 
    if err != nil { 
     panic(err) 
    } 
    a, b := big.NewInt(0), big.NewInt(1) 
    for i := 0; i < max; i++ { 
     a.Add(a, b) 
     a, b = b, a 
    } 
} 

手作りのアセンブラコードではありません。

100,000という値は、信頼性の高いベンチマークには小さすぎます。少なくとも10秒間実行される1,000,000または別の値を使用します。

+0

私はimax = 1,000,000を試して、出力を/ dev/nullにリダイレクトしました.Goでは9秒、Cでは3.6秒かかりました。利点はかなり明確です。私はあなたのコードを後で試してみます。 – Arno

+0

あなたのコードの結果は面白いです。これは、4.5秒で1,000,000番目の項を計算しますが、Cコード(印刷なし)は3.5秒かかります。パフォーマンスはライブラリに依存し、Go GMPバインディングを使用すると似ています。ありがとう! – Arno

+0

出力を '/ dev/null'にリダイレクトしても助けにならない:プログラムは何かが出力されるたびにsyscallを実行しなければならない。標準パッケージ 'testing'のベンチマーク機能を使用することを検討してください。また、ベンチマーク対象のコードには何も印刷しないでください。少なくとも、特にI/Oのベンチマークを行わない場合は – kostix

1

一般に、GMPはパフォーマンスの面で優れているため、高速です。このフードの下では、関数の呼び出しのオーバーヘッドを減らし、ADXのようなCPU命令を利用することができるアセンブリで部分的に書かれていることがわかります。

パフォーマンスが気になる場合は、mpz_fib_uiルーティンを使用することができます。これは、数学的なトリッキーから得られるので、さらに高速になります。

あなたの質問への直接の答えはおそらくGMPのためのいくつかのGoのバインディングを使用することです。

関連する問題