2017-05-11 8 views
0

ガウス分布を使ってランダムに分布した数値の多次元行列を作成する必要があり、できるだけ最適化したプログラムを作成しようとしています。現在、Boost行列を使用していますが、手作業でループすることなくこれを実現するものは見つけられません。理想的には、Pythonのnumpy.random.randn()関数に似たものが欲しいですが、これはC++で行う必要があります。これを達成する別の方法は、手動でループするよりも速いのですか?ループなしでC++で乱数の行列を作成

+1

[これは 'std :: generate'の仕事のようですね!](http://en.cppreference.com/w/cpp/algorithm/generate)しかし、私はあなたが多くの改善を見ているかどうかは分かりません。 – user4581301

+4

なぜ手動ループが遅いですか? – Jarod42

+5

私は、ループのコストと行列の各要素の値を1つずつ設定することについて心配する必要はないと考えています。私はあなたのプログラムのボトルネックがどこかにあると思う。 –

答えて

0

ループを実行する必要がありますが、ループ内で配列の参照を取り除くことができます。真のN次元配列の索引付けは高価になるため、最適なオプションは、基礎となる線形データストアを提供するライブラリ(または自分で書かれたもの)です。

これで、n次元配列全体が線形であるかのようにループすることができます。その結果、次元によるインデックスの多数の乗算が回避されます。

もう一つの最適化は、完全にインデックスを取り除き、最初の要素へのポインタをとり、ポインタ自体を反復することです。これにより、CPU内の変数全体がなくなり、コンパイラに他のもの。例えばベクトル内に1000個の要素がある場合:

vector<int> data; 
data.resize(1000); 

int *intPtr = &data[0]; 
int *endPtr = &data[0] + 1000; 

while(intPtr != endPtr) 
{ 
    (*intPtr) == rand_function(); 
    ++intPtr; 
} 

ここで2つのトリックが発生しました。ループ自体の外側で終了条件を事前に計算します(vector :: size()などの関数の検索を1000回)しないで、インデックスではなくメモリ内のデータへのポインタを使って作業します。インデックスは、配列にアクセスするたびに内部的にポインタに変換されます。 「現在のポインタ」を記憶し、その都度1を加えることにより、インデックスからのポインタを1000回計算するコストが排除される。

このですが、実装によって異なります。コンパイラは同じハンド最適化を行うことができますが、それらのすべてを行うわけではありません。関数呼び出しのオーバーヘッドを避けるために、rand_functionもインラインでなければなりません。

しかし警告:std :: vectorをポインタtrickで使用するとスレッドセーフではなく、別のスレッドがループ中にベクトルの長さを変更すると、ベクトルがメモリ内の別の場所に再割り当てされる可能性があります。 自身のベクトル、配列、テーブルクラスを必要に応じて書くのが完全に快適でない限り、ポインタトリックはしないでください。

+0

説明をありがとう! – nlhenderson17

関連する問題