他の人が言ったことに加えて、速度最適化のいくつかのテクニックがあります:
プロフィール
コードのどこでほとんどの時間が費やされているかを調べます。モースのメリットを得るには、その領域のみを最適化してください。
ループを展開する
プロセッサは、実行パスの分岐やジャンプ、変更を好みません。一般に、プロセッサは命令パイプラインをリロードする必要があり、計算に費やすことができる時間を使い果たします。これには関数呼び出しが含まれます。
この手法は、ループ内により多くの「セット」の操作を配置し、反復回数を減らすことです。
変数をレジスタとして宣言する
頻繁に使用される変数は、として宣言する必要がありますregister
。SOの多くのメンバーは、コンパイラーがこの提案を無視すると述べていますが、私はそうではないことを知りました。最悪の場合、入力に時間を浪費しました。
集中的な計算を短くシンプルに保つ
多くのプロセッサには、小さなfor
ループを保持するのに十分なスペースが命令パイプラインにあります。これにより、命令パイプラインのリロードにかかる時間が短縮されます。
大きな計算ループを多くの小さなループに分散させます。
配列と行列の小さなセクションで作業を実行します
多くのプロセッサにはデータキャッシュがあり、これはプロセッサに非常に近い超高速メモリです。プロセッサは、オフプロセッサメモリからデータキャッシュを1回ロードするのが好きです。負荷が増えると、計算に費やすことができる時間が必要になります。Webで「データ指向のデザインキャッシュ」を検索します。
並列プロセッサの用語で考える
計算の設計を変更して、複数のプロセッサでの使用に簡単に適応できるようにします。多くのCPUには、命令を並行して実行できる複数のコアがあります。一部のプロセッサには、命令を複数のコアに自動的に委任するのに十分なインテリジェンスがあります。
一部のコンパイラは、並列処理用にコードを最適化できます(コンパイラのコンパイラオプションを検索してください)。並列処理用のコードを設計すると、コンパイラーにとってこの最適化が容易になります。
関数のアセンブリリストを分析する
関数のアセンブリ言語リストを印刷します。関数の設計をアセンブリ言語の設計と一致するように、またはコンパイラがより最適なアセンブリ言語を生成できるように変更します。
本当に効率を上げる必要がある場合は、アセンブリ言語を最適化し、インラインアセンブリコードまたは別のモジュールとして挿入します。私は一般的に後者を好みます。
例
あなたの状況では、テイラー展開の最初の10項を取り、それらを別々に計算して、個々の変数に配置します。
double term1, term2, term3, term4;
double n, n1, n2, n3, n4;
n = 1.0;
for (i = 0; i < 100; ++i)
{
n1 = n + 2;
n2 = n + 4;
n3 = n + 6;
n4 = n + 8;
term1 = 4.0/n;
term2 = 4.0/n1;
term3 = 4.0/n2;
term4 = 4.0/n3;
次に、すべての用語を要約します。
result = term1 - term2 + term3 - term4;
// Or try sorting by operation, if possible:
// result = term1 + term3;
// result -= term2 + term4;
n = n4 + 2;
}