絶対に取り除くpow()
。これの最適化の大部分は、使用方法によって異なります。非常に大きな N に対してこれを 1 回実行すると、時間がかかりすぎますか? それとも、タイトなループでこれを何度も行っている可能性が高いですか?
非常に大きな N (>1000 程度) を使用している場合、これを実行できる高度に最適化された数値ライブラリがあります。たとえば、BLAS にはユークリッド ノルム (データ型 [single、double、complex single、complex double] に応じて 、 、、)*nrm2
を計算する関数があります。GotoBLASは、特定のプロセッサ アーキテクチャではおそらく最速です。 MKLは Intel の手で調整された BLAS 実装を備えていますが、無料ではありません。最後に、ATLASは BLAS を実装するセルフチューニング ライブラリです。dnrm2
snrm2
cnrm2
znrm2
N が小さいか、それほど大きくないタイトなループがある場合は、高速化するために手動で調整する必要がある場合があります。-O3
または-ftree-vectorize
コンパイラ フラグを使用して自動ベクトル化を有効にすることができます。手でベクトル化することもできますが、これを行う方法を学ぶのは大変です。
ループ展開を行うことができます (つまり、N をたとえば 4 のチャンクに分割し、for ループ本体内の 4 つの連続する値の計算を明示的に書き出すことができます。これには、コンパイラーをだまして、即時の計算により多くのレジスターを使用させる効果があります。 ---そして、レジスターは、使用する必要がある最速のメモリー形式です. また、プリフェッチ (1 回のメモリーアクセス呼び出しで一連のデータを読み取る) を利用できる場合もあります。
この状況で行うべきもう 1 つのことは、入力の 1 つを上書きすることです。つまり、出力をp
orに書き込むことでうまくいくかもしれませんq
。p
これは、書き込みの準備ができたときに、計算した の位置がまだキャッシュにあるため、役立ちます。多くの場合、キャッシュは絶対に必要な場合を除き、データをメモリに書き込みません。理由の 1 つは、キャッシュ ラインが必要であり、最後のラインを追い出す必要があるためです。入力の 1 つに書き込むことで、使用するキャッシュ ラインが少なくなります。
他にも 50 万の試してみるものがありますが、ここでやめようと思います。幸運を!