2012-03-20 12 views
-1

私はこの式を実現するプログラムを書いた:プログラムを最適化するにはどうすればよいですか?

パイ= 1/N * SUMM(4 /(1 +((I-0.5)/ N)^ 2)

プログラムコード:

#include <iostream> 
#include <math.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/time.h> 
using namespace std; 

const long double PI = double(M_PI); 

int main(int argc, char* argv[]) 
{ 
    typedef struct timeval tm; 
    tm start, end; 
    int timer = 0; 
    int n; 

    if (argc == 2) n = atoi(argv[1]); 
    else n = 8000; 

    long double pi1 = 0; 
    gettimeofday (&start, NULL); 

    for(int i = 1; i <= n; i++) { 
     pi1 += 4/(1 + (i-0.5) * (i-0.5)/(n*n)); 
    } 

    pi1/=n; 
    gettimeofday (&end, NULL); 
    timer = (end.tv_usec - start.tv_usec); 
    long double delta = pi1 - PI; 
    printf("pi = %.12Lf\n",pi1); 
    printf("delta = %.12Lf\n", delta); 

    cout << "time = " << timer << endl; 
    return 0; 
} 
最適な方法でそれを提示する方法

この部分に以下の浮動小数点演算があるでしょう?

for(int i = 1; i <= n; i++) { 
      pi1 += 4/(1 + (i-0.5) * (i-0.5)/(n*n)); 
     } 

おかげ

+0

「少ない操作」 - 一度構築されたコードや命令の行? – Nim

+3

Sergey、あなたのスペースバーは機能しませんか? – jrok

+4

なぜ 'printf'と' cout'を組み合わせる – triclosan

答えて

3

私はあなたがこの素晴らしいドキュメント読むことをお勧め:

Software Optimization Guide for AMD64 Processors

あなたはAMDプロセッサを持っていないときにも最適です。

しかし、私があなただったら、私はおそらくあなたが実際にパイ計算の高速化アルゴリズムに興味がある場合は、見て...最速されるだけ

pi1 = M_PI; 

で全体の計算ループに取って代わるだろうウィキペディアの記事:Category:Pi algorithm

あなたのコードをマイクロオプティマイズするには、上記のソフトウェア最適化ガイドをお読みください。単純な最適化の

1
#include <iostream> 
#include <cmath> 
#include <chrono> 

#ifndef M_PI //M_PI is non standard make you sure catch this case 
    #define M_PI 3.14159265358979323846 
#endif 

typdef long double float_t; 
const float_t PI = double(M_PI); 

int main(int argc, char* argv[]) 
{ 
    int n = argc == 2 ? atoi(argv[1]) : 8000; 
    float_t pi1=0.0; 
    //if you can using auto here is a no brainer 
    std::chrono::time_point start 
      =std::chrono::system_clock::now(); 

    unsigned n2=n*n; 
    for(unsigned i = 1; i <= n; i++) 
    { 
     pi1 += 4.0/(1.0 + (i-0.5) * (i-0.5)/n2); 
    } 
    pi1/=n; 
    std::chrono::duration<double> time 
     =std::chrono::system_clock::now()-start; 

    float_t delta = pi1 - PI; 

    std::cout << "pi = " << std::setprecision(12) << pi1 
       << "delta = " << std::setprecision(12) << delta 
       << "\ntime = " << time.count() << std::endl; 
    return 0; 
} 
+0

@ Sergey:私はちょうど編集したので、もう一度見てください。 – 111111

+0

@Sergey:もう一度確認してください – 111111

+0

ああ...申し訳ありません)とてもありがとう! – Sergey

2

例:ループ pi1 += 4/(1 + j*j);

  • 内側各反復
  • 計算double j = (i-0.5) * one_per_nnで割るのコストを削減forループ外

    • 計算double one_per_n = 1/n;

      これは速くなければならず、さらに大きい値の場合はnの整数オーバーフローを避ける必要があります。さらに最適化されたコードでは、生成されたコードを見て、適切な変更を行うためにプロファイラを使用する必要があります。このように最適化されたコードは、CPUやキャッシュが異なるマシンでは動作が異なる可能性があります。ディビジョンを避けることは、計算時間を節約するために常に良いことです。

  • 3

    1の考えは次のようになります。

    double nn = n*n; 
    for(double i = 0.5; i < n; i += 1) { 
        pi1 += 4/(1 + i * i/nn); 
    } 
    

    ていますが、それは現在のコードとのいずれかの差があるかどうかをテストする必要があります。