いくつかの小さな操作を高速化するために並列割り当てを理解しようとしています。次のスクリプトを実行すると (メモリが不足してロックアップされたと警告されています)、ベクトル内の行数が増えるにつれてスクリプトが急激に遅くなることがわかります。
for(i=1, i<=5, i++,
t = [59760, 71220, 79380, 83820, 3300, 11400, 27900, 39060, 43500, 51300,56220, 60];
t = repeat(t, 10^i);
n = nitems(t);
diff = t[2::n]-t[1::(n-1)];
day_v = diff < 0;
st = HPTime();
day_cum = cumulative Sum([0]|/day_v);
tot_cum = HPTIme() - st;
st= HPTime();
day_break = loc(day_v); // this will give you last row of the day
// make a matrix n x number of day breaks
m = J(n, nitems(day_break), -1);
parallel assign({db = day_break},
// make the item a 1 if it's row is higher than the corresponding row
m[a, b] = a > db[b];
);
m;
// now just sum the matrix
day = VSum(m`); // +1; // if you want the day to start at 1
tot_pa = HPTime() - st;
show(n, tot_pa, tot_cum);
);
並列代入を実行する方がcumulativesum()よりも高速であるとは期待していませんが、並列代入がどのように機能するかについて興味があります。
もう読んだこれそれはスレッドごとに非常に大きな行列のコピーを作成しているためだと思いますか?
これがどのように動作するかについて他に洞察を持っている人はいますか?
良い点です。私は、自分の例が同一対同一の比較ではないということを考えていませんでした。ありがとう@Craige_Hales 、これは本当に便利です。
Parallel Assign は素晴らしい仕事をしています。 実際の問題は配列 m のサイズだと思います。配列 m は反復ごとに飛躍的に、つまり 100 倍に増加しています。
| 私 | ナイトム(m) | Seconds_in_Parallel_Assign | ネストされたループの秒数 |
| 1 | 2,400 | NickSeconds() には小さすぎます | .18 |
| 2 | 240,000 | .033 | 19 |
| 3 | 24,000,000 | 3.3 | 1951年 |
| 4 | 24億 | 338 | 待つのを諦めた |
その脚本、
m[a, b] = a > db[b];
は 1 秒あたり約 700 万回実行されます (4 CPU 17.5G VirtualBox)。 メモリも足りなくなった、ということはページング。 ページングにより、おそらく i==5 で劇的な速度低下が発生します。
列 4 (ネストされたループの比較) は次のように行われました (画面キャプチャ...コンピューターは行 3 で 1900 秒に到達しようとしてビジー状態です)。

これは並列割り当てが設計された種類の問題。 速度の一部は JSL ループではなく C++ ループによるもので、一部はスレッドによるものです。