C、C++の最適化について語るスレ 3

このエントリーをはてなブックマークに追加
477デフォルトの名無しさん
誘導されて来ました、
プログラムでこの部分がかなりの時間をとっているので改善したいと考えています。

#define M 300000
#define N 50000

int XY[M], b[N];
double x[N], y[N], z[N];

for(int i = 0; i < 40000; i++)
{
 for( int j = i+1; j < 40000; j++)
 {
  r = sqrt((x[i]-x[j])*(x[i]-x[j]) +
   (y[i]-y[j])*(y[i]-y[j]) +
   (z[i]-z[j])*(z[i]-z[j]))+0.5;
  XY[r] += b[i]*b[j];
 }
}

・x,y,zの有効数字は整数桁まで
・rの最大値は200000程度
・インラインアセンブラやMMXを使用せずに速度を上げたい

インデックスへのアクセスとsqrtの計算の部分がボトルネックのようです。
よろしくお願いします
478デフォルトの名無しさん:2011/09/17(土) 04:35:58.89
>>477
1秒かからないんだが、データが違うのかな?
http://ideone.com/bGwRs
479デフォルトの名無しさん:2011/09/17(土) 04:42:51.13
>>477,478
ちょっと修正。結果変わらず。
http://ideone.com/EpARv
480デフォルトの名無しさん:2011/09/17(土) 05:18:58.04
プロファイラだと、  XY[r] += b[i]*b[j];がボドルネック。
481デフォルトの名無しさん:2011/09/17(土) 05:26:58.28
>479
セグメンテーションフォルトになる可能性がある
(少なくとも僕の環境では起こった)
データ作っているところでM/3とかでいいかな
482デフォルトの名無しさん:2011/09/17(土) 05:30:59.24
95%以上は、XY[r]のアクセスと判明。
483デフォルトの名無しさん:2011/09/17(土) 05:32:49.23
>>481
配列の動的確保つかうといい。
484デフォルトの名無しさん:2011/09/17(土) 05:35:48.75
(x,y,z)のノルムの小さい順に並べるなどして、XYのランダムアクセスを減らせばいいかもしれない。
485デフォルトの名無しさん:2011/09/17(土) 05:43:00.01
具体的なデータを見ながら改良するほか無いと思う。
XY[r]のランダムアクセスをなくせれば良いが、元のをこれ以上改善できるところがない。
486デフォルトの名無しさん:2011/09/17(土) 05:43:42.51
>>477
固定小数点演算にすればいいんじゃないの?

u_long sqrt2(u_long f)
{
  u_long s = f,t;
  if(x == 0) return 0;
  do {
    t = s;
    s = (t + f / t) >> 1;
  }while(s < t);
  return t;
}

int XY[M], b[N];
int x[N], y[N], z[N];
int xi, yi, zi;

for(int i = 0; i < 40000; i++) {
  xi = x[i]; yi = y[i]; zi = z[i]:
  for( int j = i+1; j < 40000; j++) {
    r = sqrt2( (xi-x[j])<<1 +
          (yi-y[j])<<1 +
          (zi-z[j])<<1  ) + 0.5;
    XY[r] += b[i]*b[j];
  }
}

sqrt2()関数はここから持ってきた。
 ttp://www.geocities.co.jp/SiliconValley-PaloAlto/5438/sqrt.htm
487デフォルトの名無しさん:2011/09/17(土) 05:46:22.64
>>479
自分のPCとコンパイラだと25秒くらいかかります
1秒以下というのはコンパイラやPCの性能の違いかもしれないです
もしそこまで早くできるなら十分なのですが・・・

>>482
そこが大きいと思ってたけどそんなにですか・・・
ありがとうございます
488デフォルトの名無しさん:2011/09/17(土) 05:47:18.23
>>480>>482
そうなんだ。じゃぁ、>>486は意味無いのねorz
489デフォルトの名無しさん:2011/09/17(土) 05:52:15.81
>>484,485
ランダムアクセスがXY[r] += b[i]*b[j];におけるボトルネックということですか・・・
でも、データはかなりランダムに配置されていてrの最小値が10000、最大値が200000くらいなので
ノルムでソートしたらそれのほうが時間がかかりそうです・・・
490477:2011/09/17(土) 05:55:13.56
>>488
自分のプログラムではsqrtを省略する時rの値がMより大きくなるため、
XY[1000] += b[i]*b[j]みたいな感じプログラムを回していました

そのせいでランダムアクセスが起きず、
速度が上昇→sqrtがボトルネック
のように勘違いしていたみたいです。
お手数をおかけして申し訳ないです
491デフォルトの名無しさん:2011/09/17(土) 06:02:33.45
速いメモリを使うか、並列計算だな。
GPUは使ったことないけど、こういった単純な計算には向いていそう。とおもうだけど実測はしていない。
CPUのマルチスレッドでも速くなると思うけど実測はしていない。
492デフォルトの名無しさん:2011/09/17(土) 06:09:46.56
並列4スレッドだと例えばこうやるんです。
メモリ共有すると衝突で遅くなると思うので、実メモリが十分にあったら別々に確保。


スレッド1 : for(int i = 0; i < 40000; i+=4) { XY0[r]・・・ }
スレッド2 : for(int i = 1; i < 40000; i+=4) { XY1[r]・・・ }
スレッド3 : for(int i = 2; i < 40000; i+=4) { XY2[r]・・・ }
スレッド4 : for(int i = 3; i < 40000; i+=4) { XY3[r]・・・ }

for( r = 0; r < M; r++) { XY[r]=XY0[r]+XY1[r]+XY2[r]+XY3[r]; }
493477:2011/09/17(土) 06:15:16.82
>>493
ありがとうございます。

それならインテルコンパイラでコンパイルを行うと勝手にMMX最適化を
行ってくれるのではないか、という認識でいます。

ですので、現時点では並列計算は考えていません、
認識が間違っていたら申し訳ないです
494デフォルトの名無しさん:2011/09/17(土) 06:32:32.19
>>492は、マシン4台あったら良いけど。
一台でやるとランダムアクセスが一気に4つ来るだけで速度が速くならないか。


495デフォルトの名無しさん:2011/09/17(土) 07:54:40.93
i=39999の時、jのループは飛ばされるだけなのでi<39999にすれば数クロック節約出来るんじゃね
496デフォルトの名無しさん:2011/09/17(土) 09:40:51.94
>>478
> #define M 300000
> x[i] = rand() % M;

32bitのコンパイラなら、普通はRAND_MAXって32767程度だと思う。
だから、これだとx,y,zのサンプルデータが小さすぎるんでないかな?
497477:2011/09/17(土) 09:44:04.74
static int XY[M], b[N];
static double x[N], y[N], z[N];

こうしてたの忘れてました、すいません
498デフォルトの名無しさん:2011/09/17(土) 09:49:05.30
今時のcpuはmmxじゃなくてsseだな。
iccを使えるなら、OpenMPの指定がらくだから試してみるといい。
# そしてがっくりくる、とw
499477:2011/09/17(土) 10:04:57.95
>>498
どうせだし、ちょっと調べてみます
ありがとうございます
500デフォルトの名無しさん:2011/09/17(土) 10:14:16.90
iccのOpenMPて最適化に制限ないの?
VCだとPGOが使えなくなるぽいけど
501デフォルトの名無しさん:2011/09/17(土) 10:15:44.55
>>482
かなり大きなキャッシュが必要だな
502デフォルトの名無しさん:2011/09/17(土) 10:24:43.92
for (i = 0; i < 40000; i++) {
x[i] = rand() % M;
y[i] = rand() % M;
z[i] = rand() % M;
b[i] = rand() % 100;
}
memset(XY, 0, sizeof XY); //できるかぎりキャッシュに残るように分離した
503 ◆0uxK91AxII :2011/09/17(土) 14:33:42.51
テキトーに並列処理すると、余計に時間が掛かってしまった。
/(^o^)\

こういうのは、IntelよりAMDのCPUの方が有利かもね。
loopを微妙に解いてprefetchするとかで。
504デフォルトの名無しさん:2011/09/17(土) 14:39:47.12
メモリランダムアクセスがネックだから。
同一メモリにアクセスする限りは、並列化しても大して速くならないことは目に見えているな。
505デフォルトの名無しさん:2011/09/17(土) 14:42:05.73
XY[0]〜XY[M/2-1]、XY[M/2]〜XY[M-1]とアクセスを局所的になるようにCPUを
割り当てると速くなるかもしれない。
506デフォルトの名無しさん:2011/09/17(土) 15:11:18.87
CPUのキャッシュに残るように、メインメモリへアクセス減らすようにするといい。
なるべく同じXY[r]へのアクセスを増やすこと。
507デフォルトの名無しさん:2011/09/17(土) 15:12:25.12
r を近場の連続したとこに溜めといて、裏で書き込むとか
508デフォルトの名無しさん:2011/09/17(土) 16:57:20.03
>>505-507
それはちょっと無理じゃないかな。
>>477
> #define M 300000
> int XY[M], b[N];
> ・rの最大値は200000程度
必要なキャッシュは800kB。結構デカイ。
short intとかWORDとかの16bitに入れたほうが簡単かも。
509デフォルトの名無しさん:2011/09/17(土) 17:07:10.79
数キロのダブルバッファでも駄目かのう
組みたくないが
510デフォルトの名無しさん:2011/09/17(土) 17:20:53.96
jをインデックスにしたメモり参照が、XYをキャッシュから弾き出すんだろ
ループを工夫して対策するしかない
511デフォルトの名無しさん:2011/09/17(土) 17:57:33.20
int b[N]; double x[N], y[N], z[N];
を部分的にCPUキャッシュに乗せて
XY[M]と併せて全てがキャッシュに乗るようにする。
まずCPUキャッシュにのっている部分だけで計算をすすめて
終わったら次を読み込む。
512デフォルトの名無しさん:2011/09/17(土) 18:49:42.97
XYが10個でも、キャッシュから追い出されて速度低下する。他の配列が優先されてしまうんだな。強制でCPUキャッシュに配置する方法あるか?

#include <math.h>
#include <stdio.h>
#define M 10
#define N 50000
#define R 50000
unsigned int xor128();
void main() {
int i, j, r, *b = new int[N];
float *x, *y, *z;
x= new float[N]; y= new float[N]; z= new float[N];
unsigned int *XY = new unsigned int[M];
for(i = 0; i < M; i++) XY[i]=0;
r = (int)(M/sqrt(3.0));
for(i = 0; i < N; i++) {
b[i]=1 + i%32768; x[i]=xor128()%r; y[i]=xor128()%r; z[i]=xor128()%r; }
unsigned int sum=0;
for(i = 0; i < R; i++) {
for( j = i+1; j < R; j++) {
r = sqrt((x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]) + (z[i]-z[j])*(z[i]-z[j])) + 0.5;
sum+=b[i]*b[j];
//XY[r] += b[i]*b[j];
}}
printf("%d\n",sum);
}

unsigned int xor128() {
static unsigned int x=123456789UL,y=362436069UL,z=521288629UL,w=88675123UL;
unsigned int t=x^(x<<11); x=y; y=z; z=w; return w^=(w>>19)^t^(t>>8); }
513 ◆0uxK91AxII :2011/09/17(土) 19:14:48.13
>>512
他の配列をcache不可な場所に配置するのはどうだろうか。
514デフォルトの名無しさん:2011/09/17(土) 19:17:12.01
配列はshort intとfloatにするのはどう?
515デフォルトの名無しさん:2011/09/17(土) 19:18:18.11
レジスタ命令付けてもたいした効果無いし。無視されてる?
強制的にキャッシュに乗らせない命令もあるの?
516デフォルトの名無しさん:2011/09/17(土) 19:20:52.43
>>514
(x,y,z)のdoubleをfloatへ節約してみたがダメだった。CPUキャッシュサイズには依存するが。
517デフォルトの名無しさん:2011/09/17(土) 19:22:09.08
[j]で参照しているメモリが1M以上ある
これがXYをキャッシュから弾き出している
518デフォルトの名無しさん:2011/09/17(土) 19:23:37.36
ターゲットのキャッシュはどのくらいのサイズなのかな?
519デフォルトの名無しさん:2011/09/17(土) 19:34:03.93
なんか一個の構造体に整理とか、できないか
520デフォルトの名無しさん:2011/09/17(土) 19:50:48.03
単純にキャッシュの使い分けでいいんじゃね?
struct CACHE {
int r;
int b;
};
CACHE c[N];
を追加して

for(int i = 0; i<40000; i++) {
 for(int j=i+1; j<40000; j++) {
  // 読み込み:キャッシュをフルに使う
  // 書き込み:追い出されてもOK
  int r = static_cast<int>(sqrt(
   (x[i]-x[j])*(x[i]-x[j]) +
   (y[i]-y[j])*(y[i]-y[j]) +
   (z[i]-z[j])*(z[i]-z[j]))+0.5);
  c[j].r = r;
  c[j].b = b[i]*b[j];
 }

 for(int j=i+1; j<40000; j++) {
  // 読み込み:追い出されてもOK
  // 書き込み:キャッシュをフルに使う
  XY[c[j].r] += c[j].b;
 }
}

少しは速くなるはず
521 ◆0uxK91AxII :2011/09/17(土) 20:31:32.81
お手上げ。
522デフォルトの名無しさん:2011/09/17(土) 21:02:42.16
for(int k=0; k < 40000; k += 256)
{
for(int l = 0; l < 40000; l += 256)
{
for(int i = k; i < min(40000,k+256); i++)
{
 for( int j = max(k+1,l); j < min(40000,l+256); j++)
 {
  r = sqrt((x[i]-x[j])*(x[i]-x[j]) +
    (y[i]-y[j])*(y[i]-y[j]) +
   (z[i]-z[j])*(z[i]-z[j]))+0.5;
   XY[r] += b[i]*b[j];
}
}
}
}

256エントリーずつにした
523デフォルトの名無しさん:2011/09/17(土) 21:03:42.32
どのくらい速度上がったのか比較を乗せて。
524520:2011/09/17(土) 21:18:03.51
汚いプログラムで悪いけどやってみた
ttp://ideone.com/nkhXc

チョットだけ速くなったかな
525デフォルトの名無しさん:2011/09/17(土) 21:21:41.55
えらく手が込んでるな。いつもそういう感じなのか。
526520:2011/09/17(土) 21:36:55.08
あんまり適当なベンチだと何が悪いか分からなくなるので、いつもこんな感じです
ソースの骨組みは前からあるのでそれを改造して作ってます
527デフォルトの名無しさん:2011/09/18(日) 02:35:46.99
>>524
使うメモリを二分割とか、三分割にしたらもっと速くならない?
こんな感じで。
 for(int j=i+1; j<40000; j++) {
  if (c[j].r<(i+200000)/2)
   XY[c[j].r] += c[j].b;
 }
 for(int j=i+1; j<40000; j++) {
  if (c[j].r=>(i+200000)/2)
   XY[c[j].r] += c[j].b;
 }
528477:2011/09/18(日) 07:14:51.15
>>520
>>520を利用したら計算時間が25秒->20秒まで早くなりました!
構造体にこんな使い方があるなんて知りませんでした。

あと、今日誤差を許容して計算してみたら、Mのオーダを一つ落とせそうな事に気づきました。
これらを利用したら合計計算時間を半分近くまでできそうです。

他の方の意見も非常に参考になるので色々と試しています
様々な意見を出していただいてありがとうございます!
529477:2011/09/18(日) 07:15:34.06
>>520
>>520を利用したら計算時間が25秒->20秒まで早くなりました!
構造体にこんな使い方があるなんて知りませんでした。

あと、今日誤差を許容して計算してみたら、Mのオーダを一つ落とせそうな事に気づきました。
これらを利用したら合計計算時間を半分近くまでできそうです。

他の方の意見も非常に参考になるので色々と試しています
様々な意見を出していただいてありがとうございます!
530477:2011/09/18(日) 07:19:51.38
>>520の考えを利用したらかかっていた時間が25秒から20秒まで短縮されました!
ありがとうございます!!構造体のこういう使い方は始めて知りました。

あと、今日計算していて気づいたのですが、誤差を許容してMのオーダを1つ下げてもそれほど結果は変わらないみたいです
これらを利用したら全体の計算時間を半分くらいにできるかもしれません。


他の意見も参考にして色々試しています。
様々な意見をありがとうございます、非常に参考になります。
531デフォルトの名無しさん:2011/09/18(日) 07:22:06.40
反映されてないから連投してた、申し訳ないし恥ずかしい・・・
532デフォルトの名無しさん:2011/09/18(日) 08:44:07.73
rはiとjについて対象な値だから、i<jの時に計算したrを覚えておき、j>iのときは計算せずに覚えておいたrを使えば
計算時間半分になるんじゃん?
関係ないがiとjが出てくるコードは読みにくくてたまらん。xとyのほうがいい。
533デフォルトの名無しさん:2011/09/18(日) 09:34:47.35
>>532
i<jとj>iは同じだろう…ってのは置いといて

for(int i = 0; i < 40000; i++)
{
 for( int j = i+1; j < 40000; j++)

常に j>i だよ。
もともと半分しか計算してない。
534477:2011/09/18(日) 09:39:48.13
>>527
Mの大きさを1/10,1/100にそれぞれしたときかかる時間は
22.352->21.563->21.523
程度の短縮だったので、提示していただいた考えではあまりうまくいかなさそうです
やはりランダムアクセスにおいてキャッシュがうまく働いていないのかと・・・

知識不足で>>520の方法でなぜ短縮されるのかがよくわかりませんが・・・
535508:2011/09/18(日) 10:53:58.92
>>534
> やはりランダムアクセスにおいてキャッシュがうまく働いていないのかと・・・
だからランダムでもXY[M]がキャッシュに入る様、二分割三分割でやろうって話し。
536477:2011/09/18(日) 11:19:41.40
>>535
>>512で示していただいてますが、Mを10にしてもキャッシュをうまく使えないのならメモリを分割しても
うまくいかないと思います

>>534のレスでは>>527への応答になっていませんね、すいません。
537デフォルトの名無しさん:2011/09/18(日) 11:31:48.79
アクセスを局所的にして、キャッシュ溢れを防ぐという意味で>>522が一番有効な気がするが。
538デフォルトの名無しさん:2011/09/18(日) 11:33:36.10
>>536 atmwri?
539477:2011/09/18(日) 12:12:24.85
実際にやってみましたが>>527>>522の方法では逆に遅くなってしまいました。

XY[r]へのランダムアクセスがボトムネックで、
jが大きすぎるため、キャッシュがXYの方に割り当てられず、
Mのを小さくしてもXY[r]のアクセスにキャッシュを使うことができない
というのが現在の認識です。
540デフォルトの名無しさん:2011/09/18(日) 12:17:59.42
ランダムアクセスよりキャッシュから追い出される事が問題。
アクセスを局所に集中させるという方向は間違っていないはず。
541デフォルトの名無しさん:2011/09/18(日) 14:59:32.45
>>493
>それならインテルコンパイラでコンパイルを行うと勝手にMMX最適化を
>行ってくれるのではないか、という認識でいます

コレ見てSSEでもいいんじゃね?って思ってSSE2版を追加しました(一度に2個のsqrtを計算してるだけですが)
ttp://ideone.com/8ZS47
542デフォルトの名無しさん:2011/09/18(日) 15:15:36.44
i i+1 i+2 i+3を同時に計算したら、キャッシュの入れ替えが減ると思っていたが。もしかしたら無意味になるかも思って手を出していなかった。
速くなったか。
543デフォルトの名無しさん:2011/09/18(日) 15:20:33.06
自分の考えてたのとは違うか
544522:2011/09/18(日) 15:47:03.27
>>539

>>522は自分で書いて何だが、会社辞めて何年もプログラム書いていないし、
コンパイラも入れていないから駄目な気がする
すまぬ

>>520,>>541ってすげー
545デフォルトの名無しさん:2011/09/18(日) 16:38:13.95
iccなら、ループ内が不自然に複雑じゃなければsseを使ったベクタ化してくれると思う。
546デフォルトの名無しさん:2011/09/18(日) 16:54:15.41
x,y,zを近場に置けない?
547520=541:2011/09/18(日) 17:06:50.77
>>544
別に凄くは無いですよ。google先生が凄いんです

>>542
一番いい最適化の方法だと自分は思います。複雑な演算をしている間にプリフェッチが完了すればメモリアクセスを
隠蔽できるので
548デフォルトの名無しさん:2011/09/18(日) 18:17:02.88
double を float にしても、ちょい速くなるね。
bxyz を構造体にしても変わらなんだ。
549デフォルトの名無しさん:2011/09/18(日) 18:26:16.41
転送量が削減できるからな。
550520:2011/09/18(日) 23:13:29.10
全部SSE2でやってみたけど微妙すぎる
関数が大きいから命令キャッシュから溢れているかも
ttp://ideone.com/P8jIP
疲れたのでROMに戻ります
551デフォルトの名無しさん:2011/09/19(月) 01:43:14.36
>>496
遅レスだが、
gcc version 4.2.1 (Apple Inc. build 5664)
RAND_MAX = 2147483647
gcc a.c -O2 -Wall
552デフォルトの名無しさん:2011/09/19(月) 02:08:12.19
>>551
RAND_MAXでかくていいなぁ。
ちなみにsrandの引数の型ってどうなってる?
64bitになってるのかな?
553デフォルトの名無しさん:2011/09/19(月) 03:21:22.23
>>552
unsigned
554デフォルトの名無しさん:2011/09/19(月) 09:02:29.11
>>479の実行結果
1秒未満

>>550の実行結果
res:477 -> 32.4342
res:520 -> 31.6174
res:520s -> 34.1533
res:520s2 -> 31.2566

なんだが、議論を続ける理由は何だろう?
例えばデータ量が数桁大きくなった場合でも適用出来る方法を探る、とか?
555デフォルトの名無しさん:2011/09/19(月) 10:06:34.97
>>552
stdlib.h @ MSVC
#define RAND_MAX 0x7fff

>>554
イマイチ、状況が解らないんだよね。

intやdoubleの四則演算の300000, 50000 の配列なんて、
ベクタ化でガッツリ早くなるのに。
556477:2011/09/19(月) 10:20:29.02
>>520
色々なアイデアを出してくださって非常に参考になりました。
SSEに関しては、もう少しでインテルコンパイラが使えるようになるので、
それを導入してから参考にさせていただきます。本当にありがとうございます。

>>548
大きい配列を扱う場合はfloatの方が少し早いみたいですね、知りませんでした。
ですがこれも何故か遅くなってしまったので保留しておきます。

>>554
実際には時間を変えた複数のデータの比較になるので、一つ一つの計算が早ければ早いほど望ましいです。
あと>>479のままでは私のPCではコンパイルできないので、データを十分に計算していない可能性があるのではないかと・・・
557デフォルトの名無しさん:2011/09/19(月) 10:52:00.02
>>556
floatを使うときは、doubleとの変換が発生しないように注意。
具体的には、定数は必ずfをつけるかキャストするとか、標準関数もfloat版を使うとか。
手っ取り早い検証方法としては、アセンブリ出力をしてcvtなんちゃらのニモニックを探せばいい。
あ、勿論、gccの場合は-msse2 -mfpmath=sseを忘れずに。
558デフォルトの名無しさん:2011/09/19(月) 11:12:51.70
>>556
> 私のPCではコンパイルできない

どんな環境か知らないけど、配列を動的確保してないからじゃない?

ttp://ideone.com/Sicye
559477:2011/09/19(月) 11:34:38.50
>>558
すいません、コンパイルできないじゃなくてコンパイルしても動かないの間違いでした
動的確保の代わりにstatic int, static double を使ってプログラムを動かしているのですが
動的確保したほうがいいのでしょうか?

>>557
どこかで無駄な変換が起きてる可能性がありますね、
アセンブリはあまり理解していないですが、
そちらからも無駄がないか調べてみたいと思います。ありがとうございます。
ちなみにVisual C++2010でやってます。
560デフォルトの名無しさん:2011/09/19(月) 12:03:50.85
>>559
> コンパイルしても動かない

32bitバイナリで、スタックエラーでしょ?

スタック・ヒープってのがあって、mallocやnewすると、ヒープ領域が使われて
自動変数は、スタック領域が使われるんだよ。MSVCの既定では、1MBだから

int XY[300000], b[50000];  // int型 (4Bytes) * (300000 + 50000)
double x[50000], y[50000], z[50000]; // double型 (8Bytes) * (50000 + 50000 + 50000)

簡単に溢れるじゃんw Cellみたいにアーキテクチャによっては、
スタックが非常に高速なメモリーだったりするんだけど、スタック領域は大きくないんだよ。

コンパイラによっては、staticキーワード付けるとヒープ領域使うらしいけど
所詮環境依存だからね。
561477:2011/09/19(月) 12:18:54.86
>>560
環境依存ならstaticは使わないほうが良さそうですね、

だとすると、
>>554は全部スタック領域で演算できてるから早いのでしょうか
それとも、計算時に何らかのエラーが発生しているため早いのでしょうか
もし前者なら1秒未満というのは非常に魅力的です
562デフォルトの名無しさん:2011/09/19(月) 13:46:28.56
>>554

>>479の実行結果
1秒未満

>>550の実行結果
res:477 -> 32.4342


何でこうなるの
563デフォルトの名無しさん:2011/09/19(月) 14:07:02.74
精度が重要でない限りは、配列はfloatがいい。容量削減。
現代のパソコンは複数のソフトが動くから、他のソフトに迷惑掛けないのが高速化のコツ。
スワップアウトを何度もやると遅い。
564デフォルトの名無しさん:2011/09/19(月) 14:08:55.18
1秒未満って、異常終了してるだけだろ。
newやvectorで動的確保した方が良い。
staticは遅いのと、容量確保に限界がある。
動的確保も限界があるがそっちのほうが大きい。
565デフォルトの名無しさん:2011/09/19(月) 14:13:02.78
スタックもヒープも、物理的にはメインメモリで同じだから。
コンパイル時に確保が決定している固定領域がスタック。
コンパイル時に確保が決まっていない領域がヒープ。
自プログラム、他のソフトにとっても、使っていないメモリは解放した方が、空きが増えて速度が上がるので動的確保の方が良い。

566デフォルトの名無しさん:2011/09/19(月) 14:16:36.05
>>554
>>479は計算結果を表示していないから計算自体が最適化でなくなってるんじゃないの?
バグにしかみえないんだけれど…
567477:2011/09/19(月) 14:16:55.14
>>554
>>479をそのままコンパイルしてやってみましたが18秒かかりました
1秒未満というのはちょっと考えづらいです・・・

>>563
後の参考になります。ありがとうございます。
しかし今回時間がかかっている部分の計算は、ほとんどがintの配列に格納されることと、
sqrtの引数・戻り値がdoubleであることからfloatを使う旨みはあまりなさそうでした
568デフォルトの名無しさん:2011/09/19(月) 14:22:19.40
今回のケースは、CPUキャッシュから、よく参照される配列が追い出されないことが大事なわけで
sqrtの計算部分は無視できるよ。
全体の容量削減が追い出されない可能性をあげる。
569477:2011/09/19(月) 14:32:47.86
>>564-565
ありがとうございます。早くなりそうなら動的確保に変えてみます
その場合、calloc関数でも構わないのでしょうか?
C++は全然していないので・・・質問ばかりですいません

>>568
なるほど!
ということはメモリを動的確保して、例えばx,y,zをintで表現できれば
キャッシュ内に配列が収まる可能性があるということですね
これはちょっと光が見えてきた気がします!
570デフォルトの名無しさん:2011/09/19(月) 14:36:43.27
callocでも同じ。最終的には、WinAPIのメモリ確保関数を呼び出してるだけとおもう。C、C++でセイノウ差は無い。
571デフォルトの名無しさん:2011/09/19(月) 14:50:59.72
>>567

static int XY[M], b[N], r, i, j;
static double x[N], y[N], z[N];

一番簡単に修正するには静的領域に置くのがいいな
元のプログラムは多分スタックオーバーフローで異常終了している
572デフォルトの名無しさん:2011/09/19(月) 14:54:17.77
>>567
r,i,jは分けないと
573572:2011/09/19(月) 14:55:51.24
アンカミス
>>572で示す>>567>>571の間違いスマソ
574デフォルトの名無しさん:2011/09/19(月) 14:59:14.33
>>573
static int XY[M], b[N];
int r, i, j;
static double x[N], y[N], z[N];

こういう事だね了解
575デフォルトの名無しさん:2011/09/19(月) 15:04:55.84
UNIXやLinuxはスタック領域が不足すると自動的に拡げてくれるディストリビューションがあるからな
あれは正直羨ましい
576デフォルトの名無しさん:2011/09/19(月) 15:14:25.15
Intel C/C++ コンパイラでベクタ化すると、こんな感じ。
http://www.dotup.org/uploda/www.dotup.org2040834.zip.html

MSVCのデバッグビルドで、実行すると120秒。
ICCで最適化したら、12秒

そろそろ速いマシン欲しいわー。
577477:2011/09/19(月) 16:42:58.30
メモリの動的確保を行う前に、インデックスの数をできる限り減らして、
全ての変数をスタック領域内に入れて計算を行いましたが
結局は>>520のやり方の方が早かったです・・・
これだと動的確保の処理を入れると余計に時間がかかりそうです

今の考え方のままだとそろそろ頭打ちかもしれないです
578デフォルトの名無しさん:2011/09/19(月) 19:05:21.65
XY[r] += bi * b[j]; を別のループで回してみたら、3秒縮まった。
L2Cacheに収めると、劇的に早くなるだろうね。

http://www.dotup.org/uploda/www.dotup.org2041723.zip.html
579デフォルトの名無しさん:2011/09/19(月) 19:17:24.26
(x,y,z)をcharかshort int変換したら容量削れる。
580デフォルトの名無しさん:2011/09/19(月) 19:21:02.68
良い方法考えついた。
581デフォルトの名無しさん:2011/09/19(月) 20:11:45.92
>>580
大きいL2キャッシュマシンを用意するんですね
582デフォルトの名無しさん:2011/09/19(月) 21:12:40.02
L3キャッシュだろ?
583デフォルトの名無しさん:2011/09/19(月) 22:28:38.07
>>567
>557は言っている。sqrtf()を使えと。
584デフォルトの名無しさん:2011/09/20(火) 00:54:19.40
>>477
rは最大、sqrt(3)*Mに成り得るから、
X:int XY[M]
O:int XY[2 * M]
の方がいいと思う。
585デフォルトの名無しさん:2011/09/20(火) 01:05:37.13
>584
floor(sqrt(3)*(M-1) + 1/2)
ようやくこの話が出たか
>47ではなくて>479に言うべきだけどな
586デフォルトの名無しさん:2011/09/20(火) 01:26:15.90
>>585
アンカーは正しく使えよ。
専ブラならいいけど、そうでない人が困るだろ?
587デフォルトの名無しさん:2011/09/20(火) 01:45:58.61
>>585
>rは最大、sqrt(3)*Mに成り得るから
絶対になりませんよ。

>>477 には、"#define M 300000" "rの最大値は200000程度"
って書いてあるんだから。
588デフォルトの名無しさん:2011/09/20(火) 01:48:42.67
お、アンカ間違えたw 上は>>585じゃなくて>>584宛て
589477:2011/09/20(火) 06:06:00.22
>>578
そのやり方でやってみましたが、

>>520 -> 22.105sec
>>578 -> 27.413sec

という結果でした。

しかし、自分でTestCodeのcalc3の部分をコンパイルして計算したところ、
倍近く時間がかかったので、インテルコンパイラには期待が持てそうです。
ありがとうございます。
590477:2011/09/20(火) 06:23:20.91
>>520



for(int i = 0; i < max; i++){
 const int bi = b[i];
 const int xi = x[i];
 const int yi = y[i];
 const int zi = z[i];

 for( int j = i+1; j < max; j++){
  c[j].r = sqrt((xi-x[j])*(xi-x[j]) +
   (yi-y[j])*(yi-y[j]) +
   (zi-z[j])*(zi-z[j]))+0.5;
  c[j].b = bi*b[j];
 }

 for( int j = i+1; j < max; j++)
  XY[c[j].r] += c[j].b;
 
}

>>578を利用してこのように書き換えると
22.188sec, 22.328sec -> 20.645sec, 20.670sec
と、少し速度があがりました!
参照を減らすのはもっと早くやっておくべきでした。
591デフォルトの名無しさん:2011/09/20(火) 06:57:39.03
浮動小数の計算はコンパイラオプションに/fp:fastを指定すると余計な変換を省ける。
592デフォルトの名無しさん:2011/09/20(火) 08:26:10.40
bi * b[j] は下のループでもいいと思ったが
上のループの方が速いのかのう

コンパイル環境用意していない者の戯言です
593デフォルトの名無しさん:2011/09/20(火) 14:54:03.20
>>590
そのくらいの速度向上でいいなら、 float 化が一番楽じゃないかねえ。
sqrtf と +0.5f に気をつけるだけじゃん。
594デフォルトの名無しさん:2011/09/20(火) 18:07:24.70
一般に単にfloat化するとsqrtf使っても若干遅くなるはず。SSE2使っていいなら別だが。
595デフォルトの名無しさん:2011/09/20(火) 18:30:00.41
そんなところが遅いわけではないので関係なし。
596デフォルトの名無しさん:2011/09/20(火) 20:20:20.02
float化で数秒速くなったけどね。i7で。
597520:2011/09/20(火) 23:19:31.89
マルチスレッドに対応しました
メモリ動的確保に対応しました
>>477がC++をやってないのでC言語にも対応しました
ttp://ideone.com/F48Ay
適当に弄って遊んでくださいな
598477:2011/09/21(水) 10:17:24.18
>>597
本当に何から何までありがとうございます!
プログラムだけでなく、ベンチマークも非常に参考になります
これからコードを書くときも参考にさせていただきます
599477:2011/09/21(水) 10:29:13.39
>>520のコードでなぜ速くなるのかが、昨日やっと理解できて

double x[N], y[N], z[N];
int b[N], r[N], XY[M];

for(int i = 0; i < max; i++){
 const int bi = b[i];
 const int xi = x[i];
 const int yi = y[i];
 const int zi = z[i];

 for( int j = i+1; j < max; j++){
  r[j] = sqrt((xi-x[j])*(xi-x[j]) +
   (yi-y[j])*(yi-y[j]) +
   (zi-z[j])*(zi-z[j]))+0.5;
 }
 
 for( int j = i+1; j < max; j++)
  XY[r[j]] += bi*b[j];
}

このように書けば、書き込みの無駄が省ける事に気づきました
これで1%ほど速度が上がりました
600477:2011/09/21(水) 10:58:43.15
あと、>>505>>540で言われていた局所性ということもやっと分かりました
最初はb~z[i],b~z[j]を使っていたので、キャッシュが追い出されて十分に使えなかったんだと思います

しかし、試しに

for( int j = i+1; j < max; j++)
  XY[c[j].r] += c[j].b;

を消して計算したところ15秒ほどかかったので、
局所性を使ってもそれほど速度は変わらないかと思いました
>>482で95%がX[r]へのランダムアクセスと書かれていましたが
もしかしたら、どこか他にボトルネックがあるのかもしれません

また、試しに

int B = 0;
for( int i = 0; i < max; i++)
 for( int j = i+1; j < max; j++)
B++;

と、書いてみたところ、計測不可能なくらい時間がかかりました
b~z[N]を定義していないプログラムだと3秒程度で計算が終わったので
ヒープ領域が関係あるのかと思いましたが、もし原因がわかる方がいたら教えて下さい。
連投申し訳ありません。
520さんのコードでももう少し調べてみようと思います本当にありがとうございます。
601デフォルトの名無しさん:2011/09/21(水) 13:14:07.97
>>600
Windowsが動くようなマシンは、ヒープもスタックもメインメモリ。
つまり変数へのアクセス速度は、ほぼ変わらない。

ただCPUには、メインメモリのキャッシュ領域がある。
そこは、32KB程度の小さい領域。

アクセス先の配列が数十KBくらいなら、CPUのキャッシュが効いて
非常に高速になるはず。

このアルゴリズムでは、全ての配列が大きくて
キャッシュには非効率的になってるんだお。

アクセスする先を数十KB程度毎に区切れるように、
アルゴリズムの最適化するのが、一番。

って話だよ。
602477:2011/09/21(水) 13:32:18.16
すいません。

>また、試しに
以降は再度計算したら3秒程度で計算が終りました。

>>601
自分の付け焼刃的な考えでは、>>599

for( int j = i+1; j < max; j++)
 XY[r[j]] += bi*b[j];

の部分を消したらキャッシュに全て乗ってかなり速くなると思ったのですが、あまり速くなりませんでした
これはb[N],x[N],y[N],z[N]が大きすぎるため(それぞれ、200KB程度)、配列がキャッシュに乗り切らず、結局は何度もアクセスをしているため、
キャッシュの局所性を利用したぶんしか速くならなかったとういうことでしょうか。
603デフォルトの名無しさん:2011/09/21(水) 13:36:03.04
コンパイラの最適化で不要な計算を落とすのがある。
604デフォルトの名無しさん:2011/09/21(水) 22:02:31.16
>>477>>520はコンパイラのオプション次第で同じくらいの速度になるね
参考まで。

-O3
res:477 -> 19.3800
res:520 -> 11.8600
res:520s -> 7.1000

-O3 -funroll-loops
res:477 -> 11.4100
res:520 -> 11.0900
res:520s -> 6.7000
605デフォルトの名無しさん:2011/09/21(水) 22:38:16.56
>これはb[N],x[N],y[N],z[N]が大きすぎるため(それぞれ、200KB程度)

x,y,zがdoubleならそれぞれ400KB程度
606デフォルトの名無しさん:2011/09/21(水) 22:42:46.59
gccとVCは速いね
なんでBCCは遅いんだろ
607デフォルトの名無しさん:2011/09/21(水) 22:45:48.77
そりゃほぼ最適化ないし
608デフォルトの名無しさん:2011/09/21(水) 22:49:49.69
そっか
コンパイルが馬鹿っ速い代わりに最適化無しか
609デフォルトの名無しさん:2011/09/22(木) 00:30:15.57
http://codepad.org/Op0Jt0gx
スレッド2つにすると少しだけ速くなるみたい。
例のテンプレートは使ってないので悪しからず。
610デフォルトの名無しさん:2011/09/22(木) 00:35:17.69
ノーマルでもCPUキャッシュ次第で変わるんだ。
スレッドにするとメモリアクセスがよりランダムになってしまいキャッシュ溢れで遅くなる可能性。
全部CPUキャッシュに乗れば良いが。
環境によって変わる。
611デフォルトの名無しさん:2011/09/22(木) 00:37:01.92
最初からほとんど改良できる余地は無くて、速度は環境依存なのでもう改良しなくて良いと思う。
これが言いたかった。
612デフォルトの名無しさん:2011/09/22(木) 00:51:13.56
>>610
今の問題はL3/LLがあふれることではなくL2のことでしょ
ならば一般的な2コアCPUの場合は片方のL2が遊んでるから使おうと考えるのが自然
実際うちでは1スレッドで10秒、2スレッドで8秒くらいだしっていう
613609:2011/09/22(木) 01:09:24.22
やっぱり>>597のが速いなw
アセンブラつかうなという縛りで、intrin使用はずるいような気がしないでもないけれど。
614デフォルトの名無しさん:2011/09/22(木) 02:16:26.77
>>611
>>604が書いているように、ほぼ同等の速度となるものに対して、
>>477が、速くなりました!といっているということは、
少なくともロジック以外の面では改良の余地があったってことじゃないのかな。
615デフォルトの名無しさん:2011/09/22(木) 03:10:34.27
x,y,z 近くにおくのって今まででてきたっけ?
それともそもそもだめなん?
ttp://codepad.org/92NIdZeV

構造体変えると15秒くらいはやくなった。
環境は Linux のみなんで、ごめん。
616604:2011/09/22(木) 04:48:20.91
CentOS(VBox) corei7 860 gcc-4.1.2

% gcc 615.c -lm -O3 -funroll-loops
% ./a.out
original took 7.114642 sec
xyz_near took 7.254803 sec
% ./a.out
original took 7.169084 sec
xyz_near took 6.879905 sec
% ./a.out
original took 6.539106 sec
xyz_near took 7.331002 sec

>>520からの流れはC++だったのでオリジナルの速度に差が出ているようで
xyzを近くに配置することの有意差は認められなかったかなぁ。
617477:2011/09/24(土) 00:54:01.94
コンパイラによる最適化を考えると表面的なコードはこれ以上いじらない方が良い気がしてきました
色々と考えてみましたが、コーディング以外で速度を上げる方法として


1.r[j] がint型であるのでint型を受け取ってint型を返すsqrt関数を用いる
→アルゴリズムは幾つかあったが、sqrtの方が速い
→テーブルを作るにはrが大きすぎる

2.3点a,b,cがあったときa,b,cの座標と、ab,acの長さが既知であるとき、
  bcの長さを簡単な計算で求められないか
→ベクトルや、三角関数で考えると無理
→しかしsqrtを使用しないクロック数の少ないアルゴリズムあるかもしれない

3.b[i]最大値は100程度なので、b[N]をchar型にできる。
→キャッシュの大きいマシンがあれば二つ目のループを全てキャッシュに乗せられるかも
4.r[i]をr^2[i]のまま計算を行い、sqrtが40000^2回行われるのを防ぐ
→r^2[i]を入れるXY[M]のMが大きくなりすぎるため、r^2[i]を規格化しなければならないが、その時の誤差がどの程度か


というものを今のところ考えています。

実際に確認してもXY[r[i]]へのアクセスとsqrtの計算は同じくらい時間をとっている事がわかったので、どちらかの計算が省略できれば速度は上がるはずです。
また、並列化や、配列の位置を調整することは、人間の手で行うことが果たして良いことなのかわからないのでICCを使える様になってからにしておきます。
もし何か気づいたことがあれば教えて下さい。

このスレのおかげで、プログラムの速度が上がり知識も増えました。しかし、これ以上の高速化はデータを見ながらの作業だと思います。
ですので、一旦ここでこの話題は終了とさせていただきます。
520さんをはじめ、様々なアイデアをだしていただいた皆様、ありがとうございました。
618デフォルトの名無しさん:2011/09/24(土) 22:47:13.68
最適化に手を出すと不毛な消耗戦になるからね。
619デフォルトの名無しさん:2011/09/27(火) 17:09:25.86
熱い議論の後に素人丸出しの質問ですみませんが
上記やりとりも含めた最適化に関するスキルは
みなさんどうやって習得されたのでしょうか?

もちろん「(CPUなどの)仕様を確認」と「ひたすら実践あるのみ」
というのは前提だと思いますが、取っ掛かりや基礎的な知識の
習得などはどうされたのかな、と…

例えばC++の勉強をするのに膨大な仕様書をいきなり読む人と
いうのは中々いなくて、普通は入門書を読むことでスタート地点に
立ちますよね。最適化にはそういった定番の入門書のようなものは
あるのでしょうか?


自分なりに調べてみたところ

プログラマのための硬派なコンピュータ学
http://www.amazon.co.jp/dp/4798023027/

プロセッサを支える技術
http://www.amazon.co.jp/dp/4774145211/

マイクロプロセッサ・アーキテクチャ入門
http://www.amazon.co.jp/dp/4789833313/

この辺りの書籍は参考になるのではないかと思いましたが
これらはあくまでも理論的な背景であって実践的なスキルとは
また別の話になりますよね?

何か参考になる書籍なりサイトなりあれば是非教えてください。
620デフォルトの名無しさん:2011/09/27(火) 17:19:20.33
>C++の勉強をするのに膨大な仕様書をいきなり読む人

いるけど
621デフォルトの名無しさん:2011/09/27(火) 19:42:05.39
>>619
なんか、このスレとかで。。。
新しいキーワードを見たらそれしらべて、周辺に転がってる情報も集めて。。。
今回の話でいえばループ展開とCPUのキャッシュあたりがキーワードになってるよ。
本ならハッカーズデライトが有名かも。

>>620
なかなかいないって書いてるのに。
622619:2011/09/27(火) 23:07:30.83
なるほど、基本的には個別に調査するという感じでしょうか。
書籍についてもありがとうございました。

興味はあったのですが、いまいちどこから手をつけていいのか
わからず困っていたので助かります。
623デフォルトの名無しさん:2011/09/28(水) 17:04:03.44
ソースコードを書いて、標準環境でビルドする。

ここで、速度が気になったらWebを読み漁り、
三項条件演算子やi++を++iに書き換えたり
最適化オプションを色々試して、無駄な努力をする。

IntelC/C++コンパイラでビルドしても
大して変わらない事に失望する。

そのうちに、プロファイラを使い始めて
ボトルネックを発見、解消するw

ここまで来ると、コンパイラによる最適化を意識したソースコードを書くようになる。
気がする。
624デフォルトの名無しさん:2011/09/28(水) 17:04:45.96
>>619
ノイマン型のアーキテクチャなら、高速化というのは結局
1) 計算量を下げる
2) IPC = 1 サイクル当たりの実行命令数を上げる
ということに落ち着く。

で、CPU メーカーやコンパイラメーカーの文書に、IPC を向上させるために
自社の製品にどのような技術が使われているかが、自慢げに誇張気味に
書いてあるから片っ端から読むといい。

ところで君の書き込みは、「手抜きしたい」というように感じてしまう。
ほとんどの人は、効率よく勉強したいと考えて上達したわけじゃない。
片っ端から全部学ぶしかないから、図書館で片っ端から読むのがいい。
625デフォルトの名無しさん:2011/09/28(水) 18:17:43.04
どの段階でどの本を読めばいいのかってのはあるかもしれないけどね
でも、熟練度が足りなくて読めなかったら、他の本を読めばいいだけとも
626デフォルトの名無しさん:2011/09/29(木) 08:28:07.75
結局さ、自分で触ってtry&Errorを繰り替えさないと
何も解決しないし、何も身につかないよね。

Intel C/C++ コンパイラも VTuneも試用ライセンスを
無料で取得できるんだから、弄ってみれば良いんだよ。
627デフォルトの名無しさん:2011/09/29(木) 16:09:22.46
指定桁数で四捨五入する以下の関数の実行速度を上げたいの。
(valueは正、digitsは0〜5が保証される)
これ以上速くできる?

double NormalizeDouble(double value, int digits) {
  static double t0[] = { 1, 10, 100, 1000, 10000, 100000 };
  static double t1[] = { 1, 0.1, 0.01, 0.001, 0.0001, 0.00001 };
  return (int)(value * t0[digits] + 0.5) * t1[digits];
}
628デフォルトの名無しさん:2011/09/29(木) 19:48:27.50
韓国アイドルグループ「2PM」のテギョンが、韓国女優キム・テヒ主演の日本ドラマにキャスティングされ、フジテレビ「僕とスターの99日」に出演することがわかった。

 テギョンの所属事務所JYPエンターテインメントは29日、テギョンが「僕とスターの99日」で、キム・テヒに接近する謎の男テソン役にキャスティングされた、と明かした。
テギョンの日本ドラマ出演は、今回が初めてだ。

 来月23日より初放送される「僕とスターの99日」は、フジテレビが日本のゴールデンタイムである日曜夜9時に編成した「ドラマチック・サンデー」で放送されるロマンチックコメディー。

 韓国のトップスターハン・ユナ(キム・テヒ)と彼女の日本撮影で99日間の契約警護を務めるボディーガード(西島秀俊)の秘密のロマンスを描く。

 テギョンが演じるテソンは、やや暗い性格のベールに包まれたキャラクターだ。
彼には夢があるが、実現することができずに夢をあきらめてきた男。誰にも話せない大きな秘密を持っている。

 所属事務所は「テソンの秘密は、主人公2人はもちろん、パパラッチ役である要潤まで引き込み、彼らの人生に大きな影響を与える。
ドラマのストーリーを作っていく上で、重要な役柄になるだろう」と伝えた。

なお、テギョンは韓国でドラマ「シンデレラのお姉さん」や「ドリームハイ」を通じて演技に挑戦していた。

http://www.asahi.com/showbiz/korea/AUT201109290027.html
629デフォルトの名無しさん:2011/09/29(木) 23:30:12.27
>>627
ある様な無い様な。

10進数で小数点第二位を四捨五入する場合を考える。
この時、0.05以上なら切り上げ。未満なら切り捨てになる。
一方、double型の指数部を見れば仮数部の実際の小数点を特定出来る。
0.05は 0.0000_1100_1100_1100_1101…であるため、特定した小数点の下位ビットから「1100_1100_1100_1101…」に該当するビットと「1100_1100_1100_1101…」とを大小比較する。
小さければ該当ビットをクリア。
大きければ該当ビットをクリアの上、その小数点に0.1を加算する。

なんか間違えている気がする。
630 ◆0uxK91AxII :2011/09/30(金) 02:21:00.87
t0, t1をfloat型にして、計算部分でdouble型にcastしてみる。
631デフォルトの名無しさん:2011/09/30(金) 02:22:24.82
>>630
低レベルすぎなので結構です。
632デフォルトの名無しさん:2011/09/30(金) 02:55:56.63
>>630
遅くなる。
633デフォルトの名無しさん:2011/09/30(金) 07:09:21.64
>>629
例えば0,23は0,2と0.03に分けられるが、0.2を2進数表記すると…。
そう、単純にクリアしたらダメだねぇ〜

どうしても、x10,x100,x1000の処理は必要か。
634 ◆0uxK91AxII :2011/09/30(金) 07:53:13.44
>>632
CPU次第だけど、cacheの境界に合わせれば、floatだと一本に入りきる。
連続しない呼出なら、有効だと思ってみた。
635デフォルトの名無しさん:2011/09/30(金) 08:37:39.79
>>633
仮数部をlong型に取り出し、x10dを実行。
すると実小数点は3桁右に移動するので、そこに0.5dを加算。
加算後、実小数点以下はクリア。
/10dを実行すると小数点が元に戻るので、元のdouble型にそのままはめ込む。

こんなんでも同じ結果が得られる。
でも、doubleとlongの乗算時間は同じな気がするし、castが減ってもそんなに早くなるとは思えない orz
FPGAなら間違いなく速くなるんだけどね。
636デフォルトの名無しさん:2011/09/30(金) 12:28:48.04
VC++だと2008あたりからdouble→intのキャストが高速化されてるから
キャストは大して負荷にならないんだよね。

ところで>>627のコードだと、valueの最大値が21474になってしまうが
それは問題ないの?
637,, ・´ ∀ `・ ,,)っ-○○○:2011/09/30(金) 12:44:41.47
それってSSE2使ってるからじゃないの?> キャストが高速化
638デフォルトの名無しさん:2011/09/30(金) 13:38:23.57
だんごだったらどうするんだろ、とおもってたらだんごw
639デフォルトの名無しさん:2011/09/30(金) 13:46:49.17
>>634
よくそんな役立たずでコテつけれるな。寒心するわ。
640デフォルトの名無しさん:2011/09/30(金) 14:12:54.47
>>627
環境によっては int にキャストするより floor のインラインアセンブラや intrinsics を使った方が早いだろうね。
そして呼び出し側の設計しだいでは SIMD 版を作って呼び出すようにするとよりいいだろうね。
許されるなら double ではなく float にすると、SIMD の並列実行数が上がっていいだろうね。

ところで、それを高速化したところで、プログラム全体の処理が目に見えて早くなるとは思えない。
VTunes とかの CPU イベントをカウントできるプロファイラにかけてみた方がいいと思うよ。試用版もあるし。
641デフォルトの名無しさん:2011/09/30(金) 16:11:27.09
>>640
大量の座標を処理するようなもので、各座標の値を整数化したいのかもしれないじゃない
642デフォルトの名無しさん:2011/09/30(金) 18:03:00.81
>>635
2進じゃなくて10進で四捨五入したいからそれだとだめじゃない?
FPGAだとしても。
>>636
それは気づかんかったwでも大丈夫。値域もvalue*pow(10,digits)は
MAXINT以下が保障されるということで。
>>640
CygWinなんだけど、g++-4 の最強オプション教えて。ググっても出てこない...
-mcore=nativeとか使えなくなった?
floor()にしてみたけどインライン展開されなかった。
floorf()にしても展開されなかったけど速くはなった。
643デフォルトの名無しさん:2011/09/30(金) 18:25:58.87
>>642
> 2進じゃなくて10進で四捨五入したいからそれだとだめじゃない?
小数点第一位の四捨五入は簡単だよ。
そこが0なら0.5未満だから切り捨て。
そこが1なら0.5以上だから切り上げ。
1ビット見るだけで判断出来るんだ。
644デフォルトの名無しさん:2011/09/30(金) 18:32:22.83
>>643
なるほど。
でもx10はいいとして/10はどうすんの?
645デフォルトの名無しさん:2011/09/30(金) 18:46:53.18
浮動小数点だから気にしなくてよかったりしないの
646デフォルトの名無しさん:2011/09/30(金) 19:46:54.60
>>643
ちょっとunsigned long long f:52;とかしてゴニョゴニョやってみたけど
もちろん全然ダメだったw
>>645
いや、FPUがあるのに高速除算機分のセルを使ったりすることもないだろう
と思ってね。
647デフォルトの名無しさん:2011/09/30(金) 21:00:23.13
固定小数点演算って、案外知られてないんだな。
648デフォルトの名無しさん:2011/09/30(金) 21:08:28.39
いや、ほかの部分はdoubleが必要なんだよ。
649デフォルトの名無しさん:2011/09/30(金) 23:11:51.66
fortranには今も4倍長精度ってあるの?
メインフレームのFORTRAN77にはあった記憶があるが。
650デフォルトの名無しさん:2011/09/30(金) 23:13:08.60
とんでもなくスレ違い。
651デフォルトの名無しさん:2011/09/30(金) 23:17:15.14
switchにしたらちょっと早くならない?
652デフォルトの名無しさん:2011/09/30(金) 23:20:00.70
>>651
遅くなった。
653デフォルトの名無しさん:2011/10/01(土) 00:20:25.91
むしろ128ビット浮動小数点数はやっと標準化されたところだから、まだこれから
654デフォルトの名無しさん:2011/10/07(金) 18:27:10.28
なんかレベル低いんだな。
655デフォルトの名無しさん:2011/10/07(金) 18:36:55.30
おまえモナ〜
656デフォルトの名無しさん:2011/10/29(土) 16:32:36.27
Or演算って遅いのか?
And演算やXor演算の倍近くかかるんだけど。


やってる処理は10000×10000、32bit画像の全画素に固定の32bitの値をAnd演算、Or演算、Xor演算するだけ。

環境
Win7 64bit VS2008
計測結果※clock()を使用
&= 69
|= 140
^= 68

せめて80〜100くらいに押さえたい。
657デフォルトの名無しさん:2011/10/29(土) 17:13:22.26
>>656
ビット演算自体は高速化できるかよくわからんけど
配列アクセスなどの部分で高速化可能かも。
現ソースどうなってる?
658デフォルトの名無しさん:2011/10/29(土) 17:28:44.63
測定順序を変えたら結果が変わりそうだなw
659デフォルトの名無しさん:2011/10/29(土) 17:57:21.43
>>657

こんな感じ。
const unsigned int flag;//引数。

int wh=Image.Width()*Image.Height();
unsigned int* ptr=Image.Buffer();
while(wh--){
*ptr&=flag;//ここを|=等に変える。
ptr++;
}

Imageは自作クラスでunsigned intのポインタを持っていてBuffer関数はそのポインタを返すだけの物です。

計測した三つの関数の違いはWhileループの中のコメントがある行だけなんだ。
660デフォルトの名無しさん:2011/10/29(土) 18:08:12.52
>>658
試してみたら変わったw
最初が遅いんだ。
キャッシュとかされてるのか?
661デフォルトの名無しさん:2011/10/29(土) 18:18:57.91
今時されないCPUが有るのか?
662デフォルトの名無しさん:2011/10/29(土) 19:12:05.38
>>661
キャッシュって数Kバイトときいてたから10000×10000×4バイトもキャッシュするのかなとおもって。
663デフォルトの名無しさん:2011/10/29(土) 20:33:50.61
>>662
キャッシュラインサイズ分先読みする.
664デフォルトの名無しさん:2011/10/30(日) 01:05:52.45
こんな単純な処理、アセンブラ使えよ
665 ◆0uxK91AxII :2011/10/30(日) 09:09:45.30
>>663
ソレは微妙に違う。
666デフォルトの名無しさん:2011/10/30(日) 11:52:26.60
>>664
こんな単純なプログラムでもコンパイラの最適化よりアセンブラの方が速くなるのですか?

>>665
後学のためにも教えてもらえると助かります。
667デフォルトの名無しさん:2011/10/30(日) 16:03:14.78
キャッシュサイズはターゲットCPUの資料を開発元のサイトで見つければいい。
最近の Intel のなら L3 が 8MB くらいあるんじゃないの。
それでも
> 10000×10000×4バイト
なら入らないけど。
もっと大きくして試してみたら。
668デフォルトの名無しさん:2011/10/30(日) 16:19:06.02
キャッシュサイズについてまで言及するなら環境依存スレの話題になるんじゃね
まあここでもいいけど
669 ◆0uxK91AxII :2011/10/30(日) 20:49:54.21
>>666
一部を読むだけで1line読み込むから、『微妙に違う』と書いてみただけ。

RMMAだと、
mov eax, [esi-16] // read cache lines
mov eax, [esi-32]
mov eax, [esi-48]
とか書いているね。
670デフォルトの名無しさん:2012/05/16(水) 14:44:59.05
core i7だと、forループのアンロールはいくつ単位で行えば良いの?
671デフォルトの名無しさん:2012/05/16(水) 14:51:45.88
必要なだけ。
672デフォルトの名無しさん:2012/05/16(水) 20:22:54.83
>>656
http://pastebin.com/pkrh7E0L

x86だけど演算によって速度に差が出ている様子はないなあ
x64ならcompiler intrinsicsを使えばいいと思うけど
673デフォルトの名無しさん:2012/05/16(水) 20:23:27.13
キャッシュに関係があると思うならprefetch命令で配列を読みこめばいいと思うし
674デフォルトの名無しさん:2012/05/17(木) 00:35:27.76
しかしアセンブラって面白いな
OSのお陰で暴走しても大抵止められるしとにかく速い
ただ REALTIME_PRIORITY_CLASS には注意が必要だな
これが入っているとドライバにすら優先するのでこれで暴走すると事実上止められない→リセット

NORMAL_PRIORITY_CLASSにすると暴走は止められるが誤差が大きくなるので
確実に暴走しない事を確かめてから REALTIME_PRIORITY_CLASS にすると
正確な値が測定出来る
675デフォルトの名無しさん:2012/05/17(木) 17:39:10.50
2行目以降でアセンブラに関連する内容が見当たらないような。
> とにかく速い
これだろうか。
676デフォルトの名無しさん:2012/05/17(木) 18:15:54.21
>>675
いやそういう意味じゃない

>>672のSetPriorityClass()は一つ使い方を間違えると止まる物も止まらなくなってしまう
という話
しかし簡単に止まるようにすると測定誤差が大きくなるという諸刃の剣
677デフォルトの名無しさん:2012/05/17(木) 18:28:34.94
要するに1行目はいらないってことか
678デフォルトの名無しさん:2012/05/17(木) 18:30:15.50
読み流してくれればいいじゃん
なんでそんなに突っかかってくんの
679デフォルトの名無しさん:2012/05/17(木) 18:35:39.79
突っかかってないよw
ちなみにプロセス優先度はタスクマネージャからも変えられるから、使ってみるといいかもね
680デフォルトの名無しさん:2012/05/17(木) 18:42:56.60
>>679
悪い悪い
でもうっかりRealTimeProcessにして動かしちゃうと、タスクマネージャすら反応しなくなるよ
やってみればわかる

マウスも止まるし
681デフォルトの名無しさん:2012/05/17(木) 18:54:58.19
プロセス優先度について知ったばかりかと思って、コード書かなくても試すことは出来るよって伝えたかったんだ。
でも運用環境と似た状態で測定しないと気づかないことも多いと思うよ。
ある程度の指標にはなるだろうけど、その辺って難しいなぁといつも思う
682デフォルトの名無しさん:2012/05/17(木) 18:56:47.45
今時のOSで動かすようなアプリで、正確な計測って何の意味があるんだろう。
つーか、そんなに速さを追求したいならWindowsなんて使わなければいいのに。
683デフォルトの名無しさん:2012/05/17(木) 18:57:26.42
大発見だったんじゃないか?よくあること。
684デフォルトの名無しさん:2012/05/17(木) 19:57:53.31
スレの流れを見て
os内のプロセスの優先度と
cpuの特権レベルを一瞬混同したのは俺だけでいい
685デフォルトの名無しさん:2012/05/17(木) 20:08:11.11
>>682
演算の種類によって本当に差が出るのか調べてみたかったわけです

>>683
そんな事はない
このパフォーマンスカウンタは数年前から使っている
686デフォルトの名無しさん:2012/05/21(月) 22:56:10.46
>>660
>最初が遅いんだ。

ディスクキャッシュ関連かな
自分もプログラムの速度を検証するときは、最初は除外しているよ
687,, ・´ ∀ `・ ,,)っ-○○○:2012/07/06(金) 08:20:34.07
いまだにシングルコア使ってるのか?
688デフォルトの名無しさん:2012/07/06(金) 10:10:40.82
マルチコアでもプロセス優先度は全てのコアに掛かるから関係ない
むしろコア一つを優先度無視するように設計するのも手だね
689デフォルトの名無しさん:2012/07/27(金) 06:09:29.14
お前ら責任持ってここで暴れてる馬鹿たち引き取ってよ

http://toro.2ch.net/test/read.cgi/tech/1334374186/
690デフォルトの名無しさん:2012/07/27(金) 06:56:42.90
>>689
明らかにスルースキルの問題だ。
自分らのごみは自分らで始末しろ。

それにここに来たとして、
「インライン展開でコンパイル結果のコード量が減ることがあるよね」
「そうだね」
で終わり。
オーバーロードのあのケースに、ああいう難癖の付け方をするのが、無能か精神疾患だ。

例えば、
「ARM 向け gcc はベクトルレジスタにそこまでの最適化を施さないから、『俺は』演算子オーバーロードではなく3引数の関数で実装する」
ならいいんじゃないの。

演算子オーバーロードを使わない最適化の上での理由はいくつかあっても、あのスレの議論では全然出てきてない。
理解してない問題にかみつくから「彼」が調子に乗るのであって、まるでお前らの責任。
691デフォルトの名無しさん:2012/07/27(金) 06:58:30.15
まるで?
692デフォルトの名無しさん:2012/07/27(金) 07:43:24.57
他人事を装ってるが誤魔化せないもんだな
693デフォルトの名無しさん:2012/09/13(木) 15:28:36.68
シングルコアですら無かった。
694デフォルトの名無しさん:2012/09/25(火) 08:31:10.42
>>686
最低と最高のパフォーマンスを除外して、残りの平均値を取らないの?
695デフォルトの名無しさん:2012/09/28(金) 20:35:42.19
中央値と標準偏差とか、他の要約統計量も。
696デフォルトの名無しさん:2012/10/03(水) 04:33:47.23
>>694
異常値が両端の一件ずつまでで済むという保証はないのだから
平均値なんか使わずに中央値使え
697デフォルトの名無しさん:2012/10/04(木) 17:27:00.24
でもいきなり中央値やモードで比較すると、平均の結果が都合悪いんだろうなと思われてしまう。
外れ値の存在を強調してもいかにも言いわけっぽいんだよ。
まじで困っている
698デフォルトの名無しさん:2012/10/04(木) 17:38:25.69
平均値・・徒競争
中央値・・パン食い競争
最頻値・・デカパン競争
699デフォルトの名無しさん:2012/10/04(木) 20:28:39.40
>>697
被害妄想だな
つべこべ言わず中央値使え
700デフォルトの名無しさん:2012/10/08(月) 13:55:43.41
平均値や最小値・最大値を提示する必要が無いなら、中央値でも良いだろうがね。

時と場合によるわ。
701デフォルトの名無しさん:2012/10/08(月) 14:29:42.77
>>700
ベンチマーク測定で最大値なんてただのノイズ
そんなもの提示する必要あると言われる会社なら辞めてしまえ
702デフォルトの名無しさん:2012/10/08(月) 14:39:16.47
>>701
つ >時と場合によるわ。
703デフォルトの名無しさん:2012/10/08(月) 16:34:08.78
>>702
で、ベンチマークの場合は?
704デフォルトの名無しさん:2012/10/08(月) 17:13:03.09
たくさん繰り返されたベンチマーク測定の集計で、
その最大値も大事な情報だから提示する必要性ありなんて主張する奴がいたら
そいつをクビにするよう動くべきだし、それができないならそんな会社捨てろ。
705デフォルトの名無しさん:2012/10/08(月) 17:15:07.05
どれか一つ出すなら中央値だな。
もう一つ足すなら平均値。
さらにもう一つ足すなら分散値。
さらにさらにもう一つ足すなら歪度。
706デフォルトの名無しさん:2012/10/09(火) 02:01:02.44
最小値と最大値の一件ずつだけを除外する、つまり2件目に異常値を含むことはないと決めつけて、最小値と最大値だけを極端に価値がないものとする>>694みたいな奴もいる。
逆に最小値と最大値を異常値と見なさず提示する必要まで考慮している、つまり場合によっては報告する必要があるだろうと考えるほど最小値と最大値に価値があるものとする>>700みたいな奴もいる。

この両者の両極端は互いに意見が大きく食い違っているが、同じ穴の狢。
算術平均を使うべきではないところで無理矢理使おうとするからそんな発狂を引き起こす。
なぜ無理に算術平均を使いたがる?
707デフォルトの名無しさん:2012/10/09(火) 02:21:49.76
GCのベンチマークで最大停止時間も知りたいのに
「中央値取ってきました!最大値?捨てましたよ?」
とか言ってきた馬鹿が居たら首切るよ
708デフォルトの名無しさん:2012/10/09(火) 02:23:49.07
>>707
お前はGC書いたことあるの?
最大停止時間を求めるのに実測の最大値を使うとか馬鹿じゃね?
709デフォルトの名無しさん:2012/10/09(火) 02:24:44.29
実測値も使いますよ?論文読んだ事無いの?
710デフォルトの名無しさん:2012/10/09(火) 02:28:42.13
そもそもベンチマークで期待値が存在しない前提なのが頭おかしい
数学知らんアホだから意味分からんと中央値を妄信してるんだろうな
711デフォルトの名無しさん:2012/10/09(火) 03:26:22.04
数学知らん奴は何かと平均値を使いたがるよな
712デフォルトの名無しさん:2012/10/09(火) 07:36:10.53
代表値で語るのは分布見てからにせえよ。
713デフォルトの名無しさん:2012/10/09(火) 14:37:00.25
分布を把握する手段として代表値を明らかにするんだよ
714デフォルトの名無しさん:2012/10/09(火) 19:37:33.69
>>713
平均値や中央値で分布がわかるわけないだろ。中学からやりなおせ。
715デフォルトの名無しさん:2012/10/09(火) 20:00:34.89
>>714
誰もそんなこと言ってないのでは?
716デフォルトの名無しさん:2012/10/09(火) 20:02:02.95
平均値や中央値だけが代表値だと思ってるのでは
717デフォルトの名無しさん:2012/10/09(火) 20:03:44.92
>>715
はあ?713を読めよ
718デフォルトの名無しさん:2012/10/09(火) 20:29:11.38
>>716
代表値と呼ばれるものは平均値、中央値、最頻値など。
この他に基本統計量として最大最小値、標準偏差、四分位、尖度歪度などがある。
しかし歪度まで見ても二山分布とかはわからないから、統計を始めたばかりの者は
まず分布を見ろと口うるさく言われたりする。
719デフォルトの名無しさん:2012/10/09(火) 20:36:28.34
さて、ベンチマーク結果の話から逸脱してるのは何番の人でしょうか?(10点)
720デフォルトの名無しさん:2012/10/09(火) 20:38:18.01
そもそも、分布を見るとは代表値を見ることに等しいのだが
721デフォルトの名無しさん:2012/10/09(火) 20:41:08.94
16分位とか32分位を見てりゃだいたいのことが分かる
722デフォルトの名無しさん:2012/10/09(火) 20:43:36.41
>>712
代表値を無視して分布を見るのは不可能じゃないか?
グラフで表示したものを見るにしても、それは代表値の表現方法を変えてるだけで、そこで見えてるのも絵にされた代表値だろ?
723デフォルトの名無しさん:2012/10/09(火) 20:46:35.68
>>722
標本と代表値を混同してる?
724デフォルトの名無しさん:2012/10/09(火) 21:13:13.09
>>723
標本が100万件あった場合
標本をそのままプロットして100万件の点を描画するのではなく
代表値に変換してそれを折れ線グラフで描画するのが普通では?
725デフォルトの名無しさん:2012/10/09(火) 21:15:12.54
http://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:Normal_distribution_pdf.png

こういうグラフのことか?
こういうグラフならたしかに標本ではなくて代表値を使ってるな
726デフォルトの名無しさん:2012/10/09(火) 21:19:33.26
>>694
なんでそこで平均値使いたがるの?
上と下を破棄する考えがあるならその延長線上に中央値があると思うんだけど
727デフォルトの名無しさん:2012/10/09(火) 21:24:24.85
>>724
それは統計で言う「代表値」じゃないな。
728デフォルトの名無しさん:2012/10/09(火) 21:59:39.50
>>726
素朴な疑問なんだが…。
1秒/2秒/3秒/4秒/10秒の計測値があった場合に「中央値」って、3秒となるの?
729デフォルトの名無しさん:2012/10/09(火) 22:24:29.71
>>728
もちろんそうですよ。
明らかに 10 や 1 は異常値でしょう?
730デフォルトの名無しさん:2012/10/09(火) 22:25:20.69
メジアンとモードは違うしな
731デフォルトの名無しさん:2012/10/09(火) 22:50:06.30
>>727
何言ってんの。
四分位数や十分位数や百分位数など分位数はみんな統計上の代表値。
732デフォルトの名無しさん:2012/10/09(火) 22:51:11.20
>>723
普通、グラフで現すのは生の標本そのものじゃなくて集計したデータじゃない?
733デフォルトの名無しさん:2012/10/09(火) 23:30:56.20
>>731
集団の傾向を少数(普通は1つ)で代表する値だからこそ「代表値」というタームで
呼ばれているわけで。
百分位が代表値だなんて書いている本どこかにあるのか?
おまえさんの脳内定義じゃなくて。
734デフォルトの名無しさん:2012/10/09(火) 23:39:39.94
>>733
四分位や十分位は代表値として良く出てくるけど、
あれは代表値ではないと?
735デフォルトの名無しさん:2012/10/09(火) 23:40:54.19
分位数は代表値でそ
どの本にも書いてます
736デフォルトの名無しさん:2012/10/09(火) 23:42:37.08
四分位数が代表値ではないなんていう脳内統計学を語る奴には何も教えてやるな。絶対に相手をするな。ここは小学校じゃねえぞ。
737デフォルトの名無しさん:2012/10/09(火) 23:47:32.35
分位数は代表値にあらず説が出た時点で退場でしょ
738デフォルトの名無しさん:2012/10/10(水) 00:01:12.74
もう元データそのままでいいよ。
N個あれば、N分位数だ。
739デフォルトの名無しさん:2012/10/10(水) 00:10:19.79
>>734
>>735
四分位のようなよく使われる統計量を代表値の範疇に含める考え方は
あるかもしれんが、十分位や百分位まで代表値と呼んでいるのは見たこと
ないねぇ。
どの本でもというが、その本では要約統計量ならばすべて代表値としているのか?
740デフォルトの名無しさん:2012/10/10(水) 00:11:28.79
>>738
元データが { 1, 2, 5 } の3個の場合、
せめて
0.5 .. 1.5 : 1個
1.5 .. 2.5 : 1個
2.5 .. 3.5 : 0個
3.5 .. 4.5 : 0個
4.5 .. 5.5 : 1個
の5つに分けないと全体の形を正確に知れないのだから、
元が3個でも五分位は必要だ。
741デフォルトの名無しさん:2012/10/10(水) 00:13:00.12
>>739
N分位数のうち、四分位数は代表値になれて、十分位数は代表値になれないという意見なんですね。
Nがいくつ以下なら代表値になれるんですか?
そんな話はどこにも見たことがないので詳しく教えてください。
742デフォルトの名無しさん:2012/10/10(水) 00:13:57.61
七分位数くらいまでは代表値なの?
743デフォルトの名無しさん:2012/10/10(水) 00:15:02.72
統計の本を見てみりゃほとんどの本で「代表値」のところの例に「分位数」が書かれてるはずだがな
744デフォルトの名無しさん:2012/10/10(水) 00:28:13.93
>>740
それは分位数を誤解していると思う
745デフォルトの名無しさん:2012/10/10(水) 00:30:53.41
くそー、俺が間違ってた。
746デフォルトの名無しさん:2012/10/10(水) 00:33:55.76
偉そうな物言いしてごめんな。酒飲んで寝る。
747デフォルトの名無しさん:2012/10/10(水) 01:03:15.51
百分位数は代表値として有名だと思ってたが、ひょっとして違う?
748デフォルトの名無しさん:2012/10/10(水) 01:11:10.44
ある値が分布のどの辺りにいるかをパーセンタイルで表すのはよく見るけど、
分布そのものを百分位で表すのはそんなにあるかな?
749デフォルトの名無しさん:2012/10/10(水) 01:12:50.24
数学知らんプログラマの特徴

1 何かと平均値を使いたがる(極力中央値を使わない)
2 最小と最大の一件ずつを異常値として棄却したがる
3 平均値・最小値・最大値を重視
4 代表値を見ずにグラフを見て分布を把握したがる
5 代表値軽視・標本値重視(代表値を使わず標本値を使ってグラフを描こうとする)
6 分位数に馴染みがない
7 分位数は代表値にあらず説を主張する
750デフォルトの名無しさん:2012/10/10(水) 01:15:29.40
>>748
分布形状を人間を介さずコンピュータに判断させるときは百分位数が活躍
ネットゲーの負荷解析で何かの閾値を越えたら異常事態としてアラートを発生させるシステムで重要
751デフォルトの名無しさん:2012/10/10(水) 07:11:25.57
>>749
> 4 代表値を見ずにグラフを見て分布を把握したがる

これは無いわー。
アホの中央値信者くんだけじゃね?こんなこと言ってんの。
まあ馬鹿だから中央値しか知らんのだろうけど。

ていうか、平均値とりたがるアホも大概だけど、
アホのお前は平均値が意味をなさない条件すら知らなそう。
752デフォルトの名無しさん:2012/10/10(水) 07:33:42.47
>>729
たった5個のサンプルで「明らかに異常値」ですかwwwwww
アホはすごいなー
753デフォルトの名無しさん:2012/10/10(水) 07:43:36.05
>5 代表値軽視・標本値重視(代表値を使わず標本値を使ってグラフを描こうとする)

これ何が悪いのか意味わからんわ。
754デフォルトの名無しさん:2012/10/10(水) 14:00:09.02
>>753
分布のグラフは、分位数という代表値をグラフ化したものじゃね?
755デフォルトの名無しさん:2012/10/10(水) 23:30:30.31
連続値を適当な精度で離散化するのと
分位数の区別が付かないアホが居る事に
驚きを禁じ得ない
756デフォルトの名無しさん:2012/10/10(水) 23:52:07.50
目視は重要なんだけどな。
正規性検定が受かってもqqプロットは載せるべきとされてる。
人間の直観はやっぱすごい
757デフォルトの名無しさん:2012/10/11(木) 00:33:03.57
>>756
結局は人間の目視を必要とするという考えで作られたシステムとは

例:
全国に大量に配置された地震計のデータを集計し、統計的な処理をした挙げ句、プロットされた絵を担当者が見て「これは地震が発生したな。規模はおそらくマグニチュード△だろう」と判断して、緊急地震速報を発信する
758デフォルトの名無しさん:2012/10/11(木) 00:34:00.28
>>756
人間の直観?
人間の直感?
759デフォルトの名無しさん:2012/10/11(木) 00:38:37.89
>>757
必要と言うか確認。
逆に、どんな検定でも駄目だったが
ヒストグラムやqqプロットでそれっぽいのでオケとはならない。
760デフォルトの名無しさん:2012/10/11(木) 01:32:50.99
人の目が必須デバイスというのは
プログラマっぽいくない考えのような
761デフォルトの名無しさん:2012/10/11(木) 07:18:05.67
>>758
今は、辞書的に「直感」と「直観」が同じ意味らしいな。
昔は使い分けろと注意されたものだが。
762デフォルトの名無しさん:2012/11/15(木) 09:22:46.30
合計を求めるコード

double sum=0;
for (int i=0;i<N;i++)sum+=a[i];

はNが非常に大きい時、最後の方で大きな数+小さな数となり、
計算精度が落ちてしまうと思うのですが、これを回避するアルゴリズムを教えてください。
763片山博文MZボット ◆0lBZNi.Q7evd :2012/11/15(木) 09:27:14.98
>>762 ソートして小さい方から足していく
764デフォルトの名無しさん:2012/11/15(木) 10:46:44.57
sum=0;
d=0;
t=0;
for (int i=0;i<N;i++){
t=(a[i]+d)+sum;
d=(a[i]+d)-(t-sum);
sum=t;


for (i = 0; i < N; i++) {
t = s + (f[i] + r);
r = (f[i] + r) - (t - s);
s = t;
}
765 ◆0uxK91AxII :2012/11/15(木) 11:20:24.34
多倍長整数を使う。
766デフォルトの名無しさん:2012/11/15(木) 12:51:00.40
もう、一文字とか文字列とか
そんな概念ある言語なんて終わってる
終わりすぎてるってことにいい加減気づけよ
極左かお前らwwwwwwwwwwwwww
767デフォルトの名無しさん:2012/11/15(木) 13:26:02.38
>>762
そこまで分かってるんなら、配列分割して、それぞれの合計を足し合わせれば良いじゃない
768デフォルトの名無しさん:2012/11/15(木) 17:47:34.93
浮動小数点数を理解してない奴はレスしない方がいいと思う
769デフォルトの名無しさん:2012/11/15(木) 20:48:17.46
>>762
a[]をソートして小さい方から足せば桁落ちは最小限に出来る
770デフォルトの名無しさん:2012/11/16(金) 06:11:59.14
絶対値の大きい方から足していって、絶対値が充分小さくなったら打ち切る。
精度は落ちるが高速だぜw
つーか、単に「ソートして小さい方から」だと拙い。
771デフォルトの名無しさん:2012/11/16(金) 14:21:28.89
>>770
お前は科学技術計算プログラムは作れないな
772デフォルトの名無しさん:2012/11/16(金) 15:36:21.73
単純に小さい方から足すだけだと、Nが大きすぎるとダメだね。
doubleの精度で問題になるほどNが大きかったら全部足すのは
無駄だとは思うがw
773デフォルトの名無しさん:2012/11/16(金) 20:08:56.95
ソートして小さいほうからがつたないってのは、
絶対値の大きな負数のことを考慮していないって言いたいんだと思う。
精度は落ちるが高速って書いてるからちゃんと分かってる人なんじゃないかな。

引き換え、Nが大きすぎると小さいほうから足すだけじゃだめだという意見はよくわからない。
774デフォルトの名無しさん:2012/11/17(土) 10:48:08.79
ソートされた100件ほどの数値の配列があり、与えられた値をランク分けするために
この配列のどの位置に該当するかを求める処理があります(std::lower_bound()のような)。
これまではバイナリサーチをしていたのですが、SSEを使って高速化できないかと考えています。
SIMDに適したサーチアルゴリズムなどはないでしょうか?
なお、テーブルは変化しませんので構造を変えてもかまいませんが、入力の方は事前に
ソートなどを行うことは難しいです。
775デフォルトの名無しさん:2012/11/17(土) 11:02:24.32
>>774
100件ぐらいしか無いんだから確実で簡単なハッシュ関数作るとかは?
「数値」たって範囲も何も分からんが、バイナリサーチで困るほどなのか……
776デフォルトの名無しさん:2012/11/17(土) 11:39:33.59
配列はランクの境界値で、間隔も一定ではありませんので、一致比較ではなく
どうしても大小比較する必要があります。
バイナリサーチよりさらに高速化したいというのは、単に入力が多いためです。
777デフォルトの名無しさん:2012/11/17(土) 13:02:21.35
もうちょっと詳細知りたい……
入力のサイズとか型とか(整数か実数か、とか)範囲とか
ビット演算とかバケットソートとか、どんな手段が使えそうか分からないとヒント出しようがない
778デフォルトの名無しさん:2012/11/17(土) 13:43:16.40
ボトルネックが違う悪寒。
779デフォルトの名無しさん:2012/11/17(土) 14:48:55.88
>>777
扱う数値はshortあるいはfloatで、入力は数百万件あります。
スレッドを分割したりしてはいますが、どうしても1秒を超えるくらいの時間が
かかってしまうので、SSEを使ってあと4倍かせめて2倍くらい速くできないかと
考えています。
質問したかったのは、SIMDに適したサーチアルゴリズムがないかということです。
780デフォルトの名無しさん:2012/11/17(土) 17:39:40.54
数百us単位のスループットが要求される処理のソフト化を試みています。
その過程で分かったことを以下にまとめます。
間違っていないでしょうか?

■WindowsAPIやDirectXなどのAPIは、カーネルモードへの遷移が必要なため、
大きなオーバーヘッド(数千クロックオーダー)が生じる。
DirectXではドライバへのコマンドをある程度キューに蓄積しておき、
まとめて送ることでオーバーヘッドを低減している

■マルチタスクOSでは、単一のプロセッサでプロセスを切り替えて実行
(コンテキストスイッチング)させている。
これはマルチスレッドプログラムにおけるスレッドの切り替えでも発生する。
現代x86CPUはハードウェアによるコンテキストスイッチングを搭載しているにもかかわらず、
Windowsでは技術的な事情からソフトウェアによるコンテキストスイッチングを行っているため、
オーバーヘッドが大きい。
CPUに搭載されている物理コア数に応じたスレッド数を立ち上げて処理させる場合、
コンテキストスイッチングは(他プロセス(ここでは相対的に低負荷とする)との切り替えを除いて)
必要ないはずであるが、実際はコア数に比例したパフォーマンス向上が見られないことから、
なぜか不要なコンテキストスイッチングが働いている。

ちなみに、何千、何万というスレッドを扱うGPUではハードウェアによる1クロック切り替えを行っているので
オーバーヘッドはない。

■SIMD演算もマルチスレッドと同様に(粒度は異なるものの)並列演算手法の一つであるが、
コンテキストスイッチングが発生しないため、並列化数に比例した(場合によってはそれ以上)の
パフォーマンス向上が得られるため効率が良い。
781デフォルトの名無しさん:2012/11/17(土) 18:33:19.25
>>780
色々微妙。一番の問題点だけ指摘。
不要なコンテキストスイッチングが発生していないとしても、
コア数に比例したパフォーマンス向上が得られると期待できるケースは稀。
782780:2012/11/17(土) 18:38:22.67
>>781
ループ間でのリソース競合がない完全に独立した並列処理(例えば配列要素同士の演算)でもでしょうか?
そのような処理を試しても、並列数(物理コア数)に比例した性能は得られませんでした。
783 ◆0uxK91AxII :2012/11/17(土) 20:23:36.85
>>780
>数百us単位のスループットが要求される処理のソフト化を試みています。
どう見ても主目的は別。
うせろ。
784デフォルトの名無しさん:2012/11/17(土) 20:34:42.58
Windowsと一口に言ってもバージョンによって違うしな。
Windows7(64bit)だとcore数に対してほぼリニアに性能が出た。10%くらい誤差は
あるだろうけど。
逆にSIMDはコンテキストスイッチのオーバーヘッドがないと言っても、処理内容に
よってはそれ以上にプログラミング上のオーバーヘッドが大きかったりして、
演算器の並列数だけきっちり性能が出せる条件は限られる。
785780:2012/11/17(土) 21:00:39.58
>>784
自分が試した環境はWindowsXPでした。
Windows7では改善されているんですね。
SIMD化に関するご意見は承知です。
SIMD演算に持っていくためのデータ構造の変換等が避けられないケースがありますし。

ハイパフォーマンスなプログラムを目指す上で、
本質とは関係ない処理をいかに避けるかが課題となるので、
プロファイラを導入するなどして問題個所を潰していきたいと思っています。
786デフォルトの名無しさん:2012/11/17(土) 21:22:00.02
>>779
ソートされてて数百万件あったらバイナリサーチが速いに決まってる。
ただ、事前に(例えば)千件ごとに抽出したテーブルを作っておいて、そこから探すというなら、SIMD最適化の余地もあるかもしれない。
最適化であって、サーチアルゴリズムと言うわけじゃないけど。
そしてそれでも、キャッシュメモリの効率を考えると、バイナリサーチより速くなるかは疑問だ。
最適化ってのは例えば 32 回とかのループアンロールして、それを SIMD 並列化ね。

あとは、最近検索された結果を覚えておいて、それをソートしておいて、バイナリサーチすることで、事前に範囲を絞り込める。
検索される値に偏りがあるなら平均時間が改善されるだろう。

最後に、データベースがメインメモリになければ SIMD で最適化する余地はほとんどない。
そして本当にメインメモリにあってバイナリサーチしてるのに1秒もかかるなら検索の問題じゃない。プロファイラなどを試すべきだ。
試しに 1GB の float 配列を全探索するとウチの PC で0.5秒位。バイナリサーチなら数マイクロ秒。
787774:2012/11/17(土) 21:46:45.55
>>786
いえ、そうではなくて、100件ほどの配列のサーチを数百万回行うということです。
最初はバイナリサーチをそのまま並列化しようとも考えましたが、配列を参照する
部分が並列化できないので他に良いアルゴリズムがないか探しているところです。
見つからないようであれば、最初の考え通り比較のみの並列化でやろうと思いますが。
788デフォルトの名無しさん:2012/11/17(土) 21:54:09.57
キャッシュ化とかできないの?
789デフォルトの名無しさん:2012/11/18(日) 16:55:08.89
その変化しないテーブルが本当に不変なら、
if ( x < 100 ) {
&nbsp;if ( x < 50 )
&nbsp&nbsp&nbsp...
else {
&nbsp&nbsp&nbsp...
というように全部展開してコンパイルしたら多分速くなるし、並列化の効率も上がるだろう。
short なら結構期待できるし、float でも正の数しかないなら浮動小数点数表現を int で比較できて結構いけるかも。
SIMD 最適化は、SSE だとレジスタ少な過ぎて速くならないのではなかろうか。
GPGPU は案外いけるかも?
いろんなアイデアがあるが、他のことが分からんと、これ以上はなんとも。
790デフォルトの名無しさん:2012/11/18(日) 18:16:19.25
バイナリサーチを即値でやるだけに見えるけど、SIMDでどう並列化できるんだろう?
791デフォルトの名無しさん:2012/11/20(火) 14:51:20.28
値とインデックスをひっくり返したハッシュとか作ればよかったのではないの?
792デフォルトの名無しさん:2012/11/21(水) 02:51:13.42
SIMDは基本ベクトル演算なわけで、定型的な単純な処理を多数行うのが得意なだけ
一回の計算あたりのクロック数は減らせても
アルゴリズムの計算量(オーダー)自体を少なくするわけではないから向かないよ

SIMD以外なら
・入力に偏りがあればバイナリサーチの分割点を調整することで速くなりそう
・値範囲がそれほど大きくないなら全範囲を展開したランクテーブルを表引き
 例えば0-7の値範囲に対し[0,3,5,6]というランクテーブルを[0,0,0,1,1,2,3,3]と展開
>>786 が言うようにループアンロール
・バイナリサーチの範囲をMSB等で最初に絞る方法
 例えばMSB4bitに対する上下範囲を16通り作っておいて、バイナリサーチの初期値にする。
793デフォルトの名無しさん:2012/11/21(水) 08:06:28.61
さすがにSIMDでオーダーが変わると考えるプログラマはいないだろう。
794デフォルトの名無しさん:2012/11/21(水) 08:28:36.54
ヒープソートみたいなアクセス方法の4分木や16分木使えばいいんじゃない?
ソートされた木なら比較結果をhaddでまとめて子世代のインデックスを計算すればいいと思うよ。
末端の無効な要素は最大値でも入れときゃなんとかなりそかな。

>>792
昔マンデルブロ集合計算するプログラムで、計算の終わった要素だけ順次差し替えてく方式を試したことがあるよ。
入れ替え処理は重いけど、普通SIMD化する場合は全要素の計算が終わるまでループするからトータルでは速くなった。
単純な処理でなくてもコストに見合う効果が得られる可能性があるから考える価値はあるよ。
実際は難しいケースが多いだろうけど。
795デフォルトの名無しさん:2012/11/21(水) 19:21:28.04
数百万件の入力を最初に16分割するのにならSIMD最適化の余地があるのでは。
その分割されたレコードがある範囲について数千件程度たまるたびに、その範囲内での正確な位置を検索するスレッドに投げる。
まあ、単に今のをスレッド分割するのに比べて、労力に見合うほどの効果があるかは疑問だけど。
796デフォルトの名無しさん:2012/11/21(水) 20:00:57.67
100分割の範囲特定なら7回アンロールして途中の条件分岐排除したほうが速いんでない?とは思う。

今時のマルチコアCPUで数百万件の処理に1秒かかるのかなぁ。
4GHz1コアで4百万件のデータでも1処理あたり4.0e9/4.0e6/7=140クロックも必要ないと思うんだよね。
ひょっとしたら再帰使ってたりだとか、分割するところでcmovみたいな計算型の命令使わずにブランチ使うコード吐いてて
大量の予測ミスが発生してたりとか・・
797デフォルトの名無しさん:2012/11/22(木) 17:19:19.03
三年前の i7 950 3GHz で、128要素の float 配列に対して 400万回の std::lower_bound() を行って0.25 秒位。
VC++2008 /O2。最適化なしだと 0.7 秒程度。
ちなみに単純に8000ループごとにスレッド分割するだけで倍速以上になった。
798デフォルトの名無しさん:2012/11/22(木) 20:21:42.17
さらにSIMDで4要素まとめて処理できそうだな
799デフォルトの名無しさん:2012/11/22(木) 21:21:24.05
できそうなんだけど、それをどういうアルゴリズムでやればいいかわからん、
てのが元の質問だろ。
俺もわからんが。
800,, ・´ ∀ `・ ,,)っ-○○○:2012/11/22(木) 21:30:38.53
アルゴリズムもなにも4要素丸ごとcmpgtpsでマスク生成してptestやるだけですがな
何番目の要素がヒットしたかは、pmovmskbで汎用レジスタに転送してbitscanすればわかる
801デフォルトの名無しさん:2012/11/22(木) 21:39:44.25
こんばんわ。
802デフォルトの名無しさん:2012/11/22(木) 22:17:54.16
>>800
それって比較だけだよな。
次のインデックスを計算して比較対象をセットする部分はシリアルにやらざるを
得ないんじゃないの?
803デフォルトの名無しさん:2012/11/22(木) 22:35:07.40
そういうのはHaswell以降(vgather系の命令)にならないとだめなんじゃないの?
804デフォルトの名無しさん:2012/11/22(木) 23:18:40.25
Haswellの新命令一覧ってどっかにない?
805 ◆0uxK91AxII :2012/11/23(金) 00:37:06.98
1ノード4要素の木?
806,, ・´ ∀ `・ ,,)っ-○○○:2012/11/23(金) 04:26:03.38
そもそも目的はなんだ?
ソートって本当に必要?

合計値の誤差を減らしたいだけのためにソートなんて必要無いぞ。
単精度なら倍精度、倍精度なら多倍精度に変換してから加算すればいいだけだろ?

ああもちろんソフトウェア多倍精度は遅いかもしれないが、たいがいDRAM帯域のほうがネックになるからw
807,, ・´ ∀ `・ ,,)っ-○○○:2012/11/23(金) 04:59:40.87
簡易的には指数オーダーごとにグループをわけて加算するのが低コストかもね

もちろんこれもSSE*がつかえる。
値をブロードキャストしてcmpXXps/pdでビットマスクして論理和とってから加算すればいい。
808デフォルトの名無しさん:2012/11/23(金) 05:59:38.95
>>806
数百万個の値を、100程度の区間に分類したいんだと。
分類してどうしたいのかは知らん。
数百万個のレコードを個別に何かするのかもしれないし、個数が必要なだけかもしれない。
809,, ・´ ∀ `・ ,,)っ-○○○:2012/11/23(金) 06:20:34.09
正直何がやりたいのかハッキリ言わなきゃわからんな

とりあえずいまどきのマシンはSIMD化よりもまず先にメモリ読み書きを最小限にしたほうが性能出ると思う。
810デフォルトの名無しさん:2012/11/23(金) 09:28:02.90
いきなり合計とか誤差とか出てきて何かと思ったら、>>774のソートの質問と
それ前の合計を求める話を混同してるんだな。
811デフォルトの名無しさん:2012/11/23(金) 09:55:09.64
最適化しすぎてうっかり必要な命令を削っちまったんだろうな
812デフォルトの名無しさん:2012/11/23(金) 16:25:50.38
>>809
質問者は>>774,776,779,787かな。
813デフォルトの名無しさん:2012/11/23(金) 16:41:36.63
以下のコードをVC++2012でコンパイルすると一回の検索が30クロックちょとだったから、
>>797の人のstd::lower_bound()より約6倍高速。
ただし、データ数が2のべき乗の制限があるから余ったところはFLT_MAXでも詰めとく必要があるのと、
VC++2008や2010のfloatでは分岐のあるコードになって半分の速度になって、
逆に整数だと2008や2010の方がこれより5倍近く速くかった。
2012はflotat・intどちらもcmov使ってるけど、最近のCPUはcmov遅いからその影響みたい。

float&nbsp;*top&nbsp;=&nbsp;array;
float&nbsp;key,&nbsp;cmp;
int&nbsp;nelm&nbsp;=&nbsp;128;
int&nbsp;half;

half&nbsp;=&nbsp;nelm&nbsp;>>&nbsp;1;

/*&nbsp;ここからコピペで7個ならべる&nbsp;*/
cmp&nbsp;=&nbsp;*(top&nbsp;+&nbsp;half);
top&nbsp;+=&nbsp;(cmp&nbsp;<=&nbsp;key)&nbsp;?&nbsp;half&nbsp;:&nbsp;0;
half&nbsp;>>=&nbsp;1;
/*&nbsp;ここまで&nbsp;*/
814デフォルトの名無しさん:2012/11/23(金) 16:43:56.27
特殊文字変換で変になっちゃた。

float *top = array;
float key, cmp;
int nelm = 128;
int half;

half = nelm >> 1;

/* ここからコピペで7個ならべる */
cmp = *(top + half);
top += (cmp <= key) ? half : 0;
half >>= 1;
/* ここまで */
815,, ・´ ∀ `・ ,,)っ-○○○:2012/11/23(金) 19:18:14.69
> 2012はflotat・intどちらもcmov使ってるけど、最近のCPUはcmov遅いからその影響みたい。

それ毎回ランダムな値で検索してる?
float配列の値に対して比較値の分布は均等になってる?
もし偏りがある状態で反復してみて分岐したほうが速いといってるのなら計測方法見直す必要がある。

ところでcomiss + jcc ってMacro OPs fusion対応してたっけ?
816デフォルトの名無しさん:2012/11/23(金) 21:19:23.94
>>815
2010の整数はsetとdec使うのに対して2012はcmovなので遅いということで
float・intとも分岐の方が遅くなってます。

>>799,802
SIMD化するとしたら木を浅くするのが効果的だから、_mm_sad_epi8(comp_result, zero)とかが使えるだろう。
817,, ・´ ∀ `・ ,,)っ-○○○:2012/11/23(金) 22:50:33.17
comiss + cmovかな?
cmovを使わない方法があるとすれば、cmpssでall 1 or 0のビットマスク作って
汎用レジスタに転送(extractps or movd)してandとって加算かな。
何となく遅そうだ。
818デフォルトの名無しさん:2012/11/24(土) 14:29:08.96
>>817
2012はその組み合わせになってた。
普段のマシンはcore 2だからデコーダの制限でcmovが遅くなってるのかも。
昔は1クロックで実行できてたんだよね。
2012でcmov使うようになったのは/arch:SSE2が標準になったのとネハ以降が主流になったからかもね。
819デフォルトの名無しさん:2012/11/25(日) 13:29:02.57
ルンゲクッタをSIMD化する良い方法があったら教えてください。
820片山博文MZボット ◆0lBZNi.Q7evd :2012/12/01(土) 15:07:18.40
数独ギバー&ソルバー
http://katahiromz.web.fc2.com/sudoku/
これを高速化する方法を教えて下さい。お願いします。
821,, ・´ ∀ `・ ,,)っ-○○○:2012/12/01(土) 19:13:40.54
それ、ビットボード使えないかなあと思った事がある。
81ビット×9でボードを用意して、それぞれのマスの1〜9の可能性をビットで表現する。

これならビット演算だけで可能性をマスクする事ができる。
822デフォルトの名無しさん:2012/12/01(土) 20:00:46.74
bsrとかbsfで検索すると数独とか将棋の
AI関連のページがやたらと引っかかっていた古き良きSSE2時代
823デフォルトの名無しさん:2012/12/01(土) 22:17:30.24
誰か知ってたら教えてください。
コードの質問に関係する部分は

unsigned __int64 point;
unsigned __int32 bit;
〜中略〜
//point = 1ull << bit;
point = 0;
_bittestandset64(&amp;point,bit);
でこれをコンパイルして
xor ecx, ecx
bts rcx, rax
の様になるようにはどうすればいい。
当然bitは0〜63の範囲内に入ってます。
__assumeは既に試してみてます。
コンパイラはVS2010、2012で試してみました。

iccなら最適化うまくいくのかな?
824デフォルトの名無しさん:2012/12/04(火) 03:01:40.53
825823:2012/12/04(火) 20:01:58.87
>>824

情報ありがとう。でも2010のそれに相当するページを見ていた。
問題はbtsのdestにメモリを使ってしまうことが問題。
826デフォルトの名無しさん:2012/12/04(火) 20:06:04.65
thats shitty japanese
827デフォルトの名無しさん:2012/12/04(火) 22:45:18.64
unsigned __int64 point;
unsigned __int32 bit;
〜中略〜
point = 1ull << bit;
if (!(amp & point))
point = 0;
828823:2012/12/05(水) 18:30:22.79
例示したコードにごみが入ってた!

正しくは
unsigned __int64 point;
unsigned __int32 bit;
〜中略〜
//point = 1ull << bit;
point = 0;
_bittestandset64(&amp;point,bit);

やりたいことはもともとあった
unsigned __int64 point;
unsigned __int32 bit;
〜中略〜
point = 1ull << bit;
を高速化したい。
ターゲットCPUはSandy Bridge以降。

お願いします。
829823:2012/12/05(水) 18:33:13.01
またごみが入ってる!amp;は無視してください
830デフォルトの名無しさん:2012/12/05(水) 20:51:13.55
2ちゃんねる用ブラウザ「ギコナビ」 Part64
ttp://anago.2ch.net/test/read.cgi/software/1350168418/64

64 名前:名無しさん@お腹いっぱい。 [sage]: 2012/11/08(木) 18:52:58.35 ID:fox14i8S0 (3)
>>63
レスエディタのメニューから特殊文字変換の下の「Space/Tab→&amp;nbsp;」のチェックを外してください
831デフォルトの名無しさん:2012/12/05(水) 21:59:48.05
inline
iint64_t
hoge(int bit)
{
static unsigned int64_t _hage[64]=
{
1,2,4,8,16,32,64,128,以下略
};

return _hage[bit];
}
832823:2012/12/17(月) 01:21:53.89
>>831
ありがとうございます。
試してみたところ状況によって速くなったり遅くなったりでした。
他の箇所の最適化をしてみてからまた試してみたいと思います
833片山博文MZパンク ◆0lBZNi.Q7evd :2013/01/16(水) 23:31:45.44
>>831 const使えよ
834デフォルトの名無しさん:2013/01/17(木) 00:38:20.09
constつけたら、早くなるのけ?
835,, ・´ ∀ `・ ,,)っ-○○○:2013/01/17(木) 01:03:46.59
constをつけないstatic変数はwritableなグローバル変数と解釈されるよね。
スコープは閉じててもポインタかなんかでアクセスしようがあるから勝手に定数化できない。

constをつければ定数領域からアクセスするだけのコードになる。
x64のバヤイこれだけですむ。_hageはRIP相対の32ビット値。

hoge:
  mov rax, [_hage + rcx*8]
  ret

んでもってconstになってないと、C/C++ランタイムのスタートアップルーチン(main関数より前の)で
_hageの値を定数領域からwritableな領域にコピーやったりするかもしれない。
これが無駄。
もし逆アセンブルやる機会があったら調べてみて。

ワンチップマイコンだと高速化のためにテーブルを多用するケースがあるんだけど
constならROM化できるというメリットがあるんだわ。
ROMはある程度余裕あるけどRAMリソースは限られてるから書き換える必要のない値は
なるべく固定にしてしまったほうがいい。
836デフォルトの名無しさん:2013/01/17(木) 01:11:28.51
チンピラに煽られるとは思わんかった、それも、即興で書いたもんに
837デフォルトの名無しさん:2013/01/17(木) 13:22:20.63
ROMとRAMのアクセス速度の違いを無視してROMから
読むだけだから速いってのは…
838,, ・´ ∀ `・ ,,)っ-○○○:2013/01/17(木) 18:58:16.82
内蔵ROMよりRAMのほうが速い実装なんてあるの?
CUDAでも定数メモリ(デバイス側から見れば一種のROM)はシェアードメモリ(RAM)より高速で
容量も大きいからパラメータは極力定数化したほうがいい。

しかしstaticでメモリを確保すると、プログラムが動いている間ずっとwritable領域に全てのデータを
配置しておかないといけない。

ランダムテーブル参照に使う配列はともかく、x86は単一の64ビット固定値程度なら
イミディエイト値として命令ストリームに埋め込むことができる。
839デフォルトの名無しさん:2013/01/17(木) 20:25:30.47
EEPROMって、書き込みが遅いのはともかく、読み出しも遅くなかった?
840,, ・´ ∀ `・ ,,)っ-○○○:2013/01/17(木) 22:23:12.16
マスクROMのつもりで書いたんだが・・・
どっちかというと速度云々よりRAMの容量の制約という観点で考えて欲しい。

const修飾がついていようがいまいが、どのみち配列はメモリに展開するかもしれない。
別にRAMのほうが速いならそれでもいいんだけど、必要なときに読み出せばいいでしょ
ただのstatic修飾だとプロセスが動いている間【常に】メモリに配置されてるということが無駄なわけよ。

SRAMでも書き換える必要ないものならCPUコア側からみてRead Onlyで使われる。
(CUDAの定数メモリがそうだしL1Iキャッシュもそう)
841デフォルトの名無しさん:2013/01/17(木) 22:51:50.47
CUDAのコンスタントメモリってFermiでなくなってなかったっけ??
842デフォルトの名無しさん:2013/01/17(木) 23:21:12.15
そんなに切迫しているのか。
組み込みのRAMってどのくらいのサイズなの?
SoCで512バイトって聞いたことあるけど…。

Cでいうローカル変数なんか注意しないといけないし、
関数コールのネストも計算しないとならないですね。
メモリはローカル変数無しのグローバル変数のワークエリア
使いまわしかな。
動きはROMのテーブルか処理(コード)で実装しなければならなさそう。

ああ、512バイトとか、ここまで来たらスレ違いかな。
mallocなんかとても使えなさそう。。
843デフォルトの名無しさん:2013/01/17(木) 23:42:55.18
AVRでメモリ0バイトでレジスタが32個だけてのもあったぞ
Cコンパイラの対象外だったけどな、128バイトのモデルからは使える
844842:2013/01/17(木) 23:51:29.89
>>842このスレ、
main以外★mallocの後にfree不要と言うバカいるの?
http://toro.2ch.net/test/read.cgi/tech/1352812333/
と勘違いしてた。。(恥ずかしい)

>>843
レジスタ32個ですか。
8ビットだとすると32バイトのRAMと考えられなくも
ないですが…、すごい世界ですね。
ありがとう
845デフォルトの名無しさん:2013/01/18(金) 02:40:26.60
自分もRAM128バイトのRISC CPUで仕事したことある
846デフォルトの名無しさん:2013/01/18(金) 05:54:52.99
> 内蔵ROMよりRAMのほうが速い実装なんてあるの?
90年台のパソコンはBIOSのROMをメインRAMにコピーして、アクセススピード稼いでたの知らんのけ?
847デフォルトの名無しさん:2013/01/18(金) 07:34:09.45
先日、組み込みの仕事を受けたら、対象機はItaniumだったでござる
VMSは癖があるなぁ
848デフォルトの名無しさん:2013/01/18(金) 15:02:20.09
CUDAの定数メモリを持ち出してるくせにマスクROMのつもりとか…
専用のキャッシュを持った定数メモリを持ち出して速いとか…
しかも速度の話からRAMの容量の話にすり替えちゃってるし…
849,, ・´ ∀ `・ ,,)っ-○○○:2013/01/18(金) 15:38:26.39
アフォが沸いてるなぁ

> CUDAの定数メモリを持ち出してるくせにマスクROMのつもりとか…

CUDAの定数メモリの実体はSRAMだが、CUDAコア側からの書き戻しがされないことが
保障されているから速い。
Writeに割かない分Readに帯域を割いているからね。

コア側からは読み出さないことで一種のROMとして使ってる。
EEPROMだって書き換えを頻繁にやらないからROMだと言ってるだけで実際は不揮発性のRAMだろ?w

普通のPCのアプリの話をするなら、いったんRAM上に展開されて実行される。
でも全部がアプリケーション側で書き換えできるわけではない。
.rodataや.textは読み出し専用のセクションだ。

> しかも速度の話からRAMの容量の話にすり替えちゃってるし…

容量については最初の最初っから言及してましたが?↓

> ワンチップマイコンだと高速化のためにテーブルを多用するケースがあるんだけど
> constならROM化できるというメリットがあるんだわ。
> ROMはある程度余裕あるけどRAMリソースは限られてるから書き換える必要のない値は
> なるべく固定にしてしまったほうがいい。

別に組み込みに限らずconst指定をサボるのは良くないよ。
定数が重複する場合、コードサイズの最適化で1箇所にまとめてしまうようリンカに指示することができるが、
書き換え可能な静的データとして配置されている場合、いくらデータが重複していても纏めることができない。
プログラムサイズが肥大化することになり、結果的にキャッシュのヒット率など速度面にも悪影響を
及ぼす可能性がある。

とはいってもx86の場合は定数データが重複していてもコードのディスプレースメントフィールドが
8ビットに収まるなら結果コードがコンパクトというケースもあるので一概に重複を排除しろとも言えないが
850デフォルトの名無しさん:2013/01/18(金) 16:04:58.78
>>849
無能自慢してるのがまだわかってないの?
851デフォルトの名無しさん:2013/01/18(金) 16:27:19.27
>>850 おまえがな
852デフォルトの名無しさん:2013/01/18(金) 16:32:17.49
組み込みのマイコンが逝ってる系だけとでも思ってるんかね
853デフォルトの名無しさん:2013/01/18(金) 16:42:31.73
単語知ってる自慢をもっとやってよ
854,, ・´ ∀ `・ ,,)っ-○○○:2013/01/18(金) 16:43:21.29
書き換えないテーブルにconst修飾子を使うべき理由を一例として述べてるだけであって
別にそれが全てではないのも事実ですな
ROMよりRAMのほうが速い環境があるからといってconst指定が不利になる理由はないはずですが
(というかRAMにプログラムを読み出してくるのはどのみちROMなりストレージなんですけどね)

つまらない揚げ足とりに終始して自分のミスを誤魔化そうとするのはみっともないです。


逆に、ROMよりRAMのほうが速いと、定数配列をstatic constではなくmutableなstatic変数として
用いたほうが有利なんですか?
855デフォルトの名無しさん:2013/01/18(金) 17:16:32.93
パソコンならconstあるなしで速度はあんま変わらんのと違うか?
constあるなしで実行コードの最適化した汗比較してみたけど、変わらんかった、gccは
パソコンなら変数は実行前に配置されてるでしょ
関数内で宣言してるから、外から書き換えられることはない
タンゴはグローバル変数が好きなの?
856デフォルトの名無しさん:2013/01/18(金) 17:38:45.84
const が駄目なんて一言も言ってないぞ
const 付けた方が速いから付けろって言ってるから突っ込んだだけ
const 付けた方が速くなる環境もあるかもしれないが、それが const を
付ける本来の理由か?
const 付けたら絶対速くなるのか?
857,, ・´ ∀ `・ ,,)っ-○○○:2013/01/18(金) 17:40:26.61
> 関数内で宣言してるから、外から書き換えられることはない

とはいってもポインタでアドレス取ってくればアクセス可能なので、constにする以外で
外部から書き換えできないことが言語仕様上保障できないのがC/C++の制約ですよ。

ある程度共通で使ってる定数配列なら必要に応じてグローバル化するけどね。
たとえば別の関数で全く同じ定数テーブルを使ってる場合はテーブルを共通化したほうが
キャッシュの効率が上がるはずだ。
858,, ・´ ∀ `・ ,,)っ-○○○:2013/01/18(金) 17:42:42.69
constにしたほうが「速い」なんて一言も言ってないのですが
constにしない理由はないし、しないことで不利なケースのほうが多いだけで。
859デフォルトの名無しさん:2013/01/18(金) 17:44:13.44
自分で暴走するもん作ってますって逝ってないかい?
860デフォルトの名無しさん:2013/01/18(金) 17:53:19.96
外部から書き換えられないことが保障できないというのは
同じプログラム内の別の場所に同じようなデータがあっても
書き換えによって別々の値を持つ可能性があるということ。
初期値が同じだからといってテーブルを1つに纏めるような最適化を
コンパイラ・リンカ側でやってくれない。


LUTを使った最適化でのパフォーマンス低下の最大の原因はキャッシュミスだ
十分なプロファイリングをしたうえで本当に全体性能に影響があるかどうかを検討したうえで使う
1割未満の使用率の関数で安易にLUTを使うのは感心しない。
861デフォルトの名無しさん:2013/01/18(金) 17:54:38.95
タンゴ自慢もっとやって
862デフォルトの名無しさん:2013/01/18(金) 18:12:10.49
>>858
>>834 に対して >>835 は何?
速度に対する話でしょ

お前の言ってることは
const にすれば ROM化出来る
ROMの方がRAMより速い(アクセスするコードの話も含めて)
だから const 付けろ
これをグダグダ言ってるだけじゃん

速度の話じゃないとしたら
>>838 の「内蔵ROMよりRAMのほうが速い実装なんてあるの?」は
どこから出てきたの?

>>854 の 「つまらない揚げ足とりに終始して自分のミスを誤魔化そうとするのはみっともないです。 」を
そっくりそのまま返してやるよ
863デフォルトの名無しさん:2013/01/18(金) 18:15:07.44
片山がconstを使えと言ってるからそれに対してその理由をフォローしただけだけど?
「早くなるのけ?」(速くではなくて?)の回答は環境に依存するが、
少なくともconstを付けたら遅くなるハードウェアなんてものは知らない。
864デフォルトの名無しさん:2013/01/18(金) 18:33:46.29
> んでもってconstになってないと、C/C++ランタイムのスタートアップルーチン(main関数より前の)で
> _hageの値を定数領域からwritableな領域にコピーやったりするかもしれない。
> これが無駄。
> もし逆アセンブルやる機会があったら調べてみて。
>
> ワンチップマイコンだと高速化のためにテーブルを多用するケースがあるんだけど
> constならROM化できるというメリットがあるんだわ。
これが速度の話じゃ無いとは思わなかったわ
865,, ・´ ∀ `・ ,,)っ-○○○:2013/01/18(金) 18:36:00.79
最初っからメモリサイズの問題に言及してるだろ
866デフォルトの名無しさん:2013/01/18(金) 18:36:02.66
まぁ、つけられるconstはつけておけってこった。
867デフォルトの名無しさん:2013/01/18(金) 18:40:58.81
> メモリサイズの問題
?
868,, ・´ ∀ `・ ,,)っ-○○○:2013/01/18(金) 19:01:45.83
constをつけるべき理由を勉強しなおしてからおいでください
869デフォルトの名無しさん:2013/01/18(金) 19:03:57.15
知ってるタンゴがつきてきた?
870,, ・´ ∀ `・ ,,)っ-○○○:2013/01/18(金) 19:08:35.37
言ってることを理解しようとしないやつに何を言っても無駄です。
871デフォルトの名無しさん:2013/01/18(金) 19:17:30.02
書き込み禁止の意味
link時の配置が通常の初期化付き変数と違う場所になる

関数内でstatic宣言した変数を書き換えられる腕をお持ちの方には参りました。
872デフォルトの名無しさん:2013/01/18(金) 19:43:26.92
// 普通にできるだろ。
int * func()
{
static int static_var;
printf("%d\n", static_var);
return & static_var;
}
`
int * tmp = func();
* tmp = 1;
873デフォルトの名無しさん:2013/01/18(金) 20:00:15.85
そういう関数じゃないんだけど、話題になってるのは
874デフォルトの名無しさん:2013/01/18(金) 20:45:44.05
>>872
お前のせいで台無しだ
875,, ・´ ∀ `・ ,,)っ-○○○:2013/01/19(土) 01:55:13.69
>>871
> link時の配置が通常の初期化付き変数と違う場所になる

とは限らないが、.dataと.rodataで配置を分けるから結果的にそうなることが多いかもな
よーするに理屈を全然理解してないのね

>>872みたいに関数内で定義したstatic変数を外部から書き換えできるような関数なんていくらでも作れるし
実際にあるんだよね(C文字列を返せみたいなのは特に多い)
外部参照を意図したものかそうでないかをコードの流れを読んでコンパイラが判断するのは難しい。

>>873
そういう関数と>>831の関数でのstatic変数の使われ方の意味を処理系が容易に判断してくれるとでも?


というか俺的には>>831の一番の突っ込みどころは、CPU組み込みのビットシフト命令は0-63以外の値が
与えられても通常安全だが、そのテーブル参照に置き換えるとページ違反になるかもしれないことね。
俺なら最初に bit &= 0x3f; とでもやっておくわ。

あと容量の問題についてもう少し言及しておくと、inline関数は通常ヘッダに書くものだが
そのヘッダをincludeしたソースごとに_hage[64]の実体が定義されることになるかもしれない。
これが大きな配列だと結構問題になる。




で、肝心のが速いかどうかについてもう少し。
命令のレイテンシを考えればshl rax, clよりmov rax, [mem]が速いわけがないんだが
Sandy Bridge以降ではロードユニット2本あるからシフト(ユニット1本)よりスループットが
稼げるケースも存在しなくはない。
その辺の理屈まで説明できないと片手落ちだわね。
876デフォルトの名無しさん:2013/01/19(土) 02:03:15.16
超単語、乙
877823:2013/01/19(土) 14:47:47.17
あれここで教えられたコードってconstついてなかったのね。
一目見てルックアップテーブルと認識したから
テストしたコードではconst付きで試しています。
ちなみに前提条件としてbitは0〜63に限定してるので
(デバッグビルドではそれ以外の値が来た時点でassertしてる)
テーブル参照でも問題ありません。
878,, ・´ ∀ `・ ,,)っ-○○○:2013/01/19(土) 17:26:07.87
むしろ_bittestandsetで何か問題あったのか問いたいね。
VCの組み込み関数って値を2個以上返す命令は一方の値をポインタで受け取るようにはなってるけど
最適化でレジスタ渡しになるのでストア命令が生成されることはないと把握してる。
オプションは /Ogty になってる?

IACAとかでプロファイルとってみて、btsを発行してるポートがボトルネックになってて
Loadユニットに空きがあるようなら部分的にテーブル参照に置き換えてみるのもいいと思う
→えいちてぃーてぃーぴー://software.intel.com/en-us/articles/intel-architecture-code-analyzer
879823:2013/01/19(土) 22:06:05.32
問題はストア命令が生成されること。
オプションは /O2を指定してるから問題ないと考えてる。
msdnによると等価オプションに/Og,/Ot,/Oyが含まれてるし……

bittest系の命令はsrcに64以上の値が来た場合、
destで指定されたアドレスからsrcビット目のデータを見るから
うまくコンパイラにsrcが0〜63であることを伝えないと
レジスタ渡しになってくれないみたい。
880デフォルトの名無しさん:2013/01/19(土) 23:20:56.46
今日、constを付けたり外したりして試してたら、
基本的にはconst付けたほうが速かった。
割と分かりやすいレベルで変わったな。

__m128に付けたら遅くなったりした。
881デフォルトの名無しさん:2013/01/20(日) 13:09:43.88
>>879
>destで指定されたアドレスからsrcビット目のデータを見るから
>うまくコンパイラにsrcが0〜63であることを伝えないと
メモリオペランドでもオペランドのサイズ自体は変わらないから関係ないでしょ。
__assume(bit >= 0 && bit <= 63);とか入れてみても影響ないね。
レジスタだと不都合があるとも思えんし……
コード生成のバグ?なのかね。
882デフォルトの名無しさん:2013/01/20(日) 14:33:37.91
> __m128に付けたら遅くなったりした。
これ興味深いな。何故だろう?
883823:2013/01/20(日) 15:09:50.32
>>881
Intelのマニュアルを見れば分かるけどメモリオペランドと
レジスタオペランドで動作が違う。
レジスタオペランドだと剰余を求めてみるビットを決めるが
メモリオペランドだと、例えば6400あたりが渡されたとすると
800バイト先あたりの値を見る。
884デフォルトの名無しさん:2013/01/20(日) 17:07:50.08
>>883
おぉ、マニュアル見たら確かにそんな挙動になってるね。
__assmumもダメならVCでは無理なんじゃないの?
_bittestandset64を3つ並べたらleaまで3回出力されてたよ。
885880:2013/01/20(日) 19:47:03.48
もう少し詳しく書くと、
クラスのメンバ関数内でローカル変数でconstで指定してたある変数を、他のメンバ関数と共有したくなったので、
クラスのメンバ変数(constなしでコンストラクタで初期化)にしたら遅くなった、ということ。
同じ場所でconst外すのも試しとくべきだったな・・・。
886デフォルトの名無しさん:2013/01/20(日) 20:01:44.90
スタックからヒープに移ったって話じゃないかよう
887880:2013/01/20(日) 20:35:12.95
ヒープって遅いんすね・・・
888,, ・´ ∀ `・ ,,)っ-○○○:2013/01/21(月) 03:29:42.38
m |= 1 >> n;

みたいな式で勝手にbtsに展開してくれるのが理想なんですけどね。
ちなみに x << n | x >> (64-n) なら大体のコンパイラでrotlに展開してくれたけど
889,, ・´ ∀ `・ ,,)っ-○○○:2013/01/21(月) 03:34:57.45
1 << nですた
890デフォルトの名無しさん:2013/01/21(月) 04:37:34.71
rotにならない助けて
891デフォルトの名無しさん:2013/02/02(土) 20:05:03.11
単純にスタックだとcallされた時点で参照される→キャッシュラインに乗る率が高くなるからな
892デフォルトの名無しさん:2013/02/10(日) 09:56:29.53
gcc 使えよ。
vector_size とか便利すぎる。
893デフォルトの名無しさん:2013/02/18(月) 19:50:58.26
突然ですみません。
VC2010ExpressとIntel Composer XE 2013(体験版)とで実行時間を比較していたのですが、
前者で/O2のみ付けて生成した実行ファイルだけ異常に遅いという現象が発生したのです……。

プログラムは、ヒッチコック・ベアストウ法に従ってn次方程式を解く時間を計測する、といったものです。
計算量のオーダーはO(n^2)になるはずなので、条件を変えつつ平均計算時間を測定していました。

実行バイナリは、
VCの方で「/Od」「/O2」「/O2 /arch:AVX」、
ICXEの方で「(引数無し)」「/QxAVX」の
5パターンを試しました。

「/Od」>>「/O2 /arch:AVX」までは予想通りだったのですが、どうも「/O2」のタイムが振るいません。
具体的には、2000次方程式を100回解いて平均時間(ミリ秒)を出した際に、
それぞれ「312.78」「478.93」「10.24」「11.39」「11.32」となりました。
いくらなんでも「/Od」より遅いとか異常です。

ソースコードと各実行ファイル、測定条件・時間や自環境を記したテキストを以下に配布しますので、
どなたか速度低下の原因を考えてくださいませんか……?

ファイルURL:http://www1.axfc.net/uploader/so/2798834.zip
894デフォルトの名無しさん:2013/02/18(月) 22:25:09.69
>>893
まずは結果が一致しているのか確認してみては
895デフォルトの名無しさん:2013/02/18(月) 22:30:15.36
>>894
確認しようにも、乱数を元にした初期化を使っているので、単純な比較ができないんですよね‥…
外部ファイルを読み込めるように修正してから再度チェックするべきでしょうか>
896デフォルトの名無しさん:2013/02/18(月) 22:34:47.86
乱数の種、同じにしたら毎回同じなのでは?
897デフォルトの名無しさん:2013/02/18(月) 22:35:26.88
>>896
あ、その手がありましたか。早速試してみます。
898デフォルトの名無しさん:2013/02/18(月) 22:36:04.77
コンパイラが違うと同じとは限らんな
899デフォルトの名無しさん:2013/02/18(月) 22:36:42.01
毎回同じ乱数を生成する my_rand(); を作るべし
900デフォルトの名無しさん:2013/02/18(月) 22:56:41.78
コード中、「srand((unsigned)time(NULL));」となっていたところを
「srand(765);」と書き換えて、再度計測しました。結果、
size   Od   O2 O2AVX   icl   iclAVX
500.    4.54 . 12.98 1.51   1.63   1.69
707   13.63 . 43.47 1.99   2.22   2.24
1000.  34.67 121.20 3.16   3.48   3.44
1414 113.17 245.40 5.57   6.22   6.26
2000 303.54 432.40 9.79 . 11.03 . 11.02
(100回平均。単位はミリ秒)
また/O2だけ遅いです……。
901デフォルトの名無しさん:2013/02/18(月) 23:02:24.59
最適化と相性が悪いんだろうかね

/O2 = /Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy
らしいので、どれが悪さしてるか調べてみたら?
902デフォルトの名無しさん:2013/02/18(月) 23:03:46.28
こんなことあるんだなぁ・・・。
903デフォルトの名無しさん:2013/02/18(月) 23:10:55.87
まず確認する必要があるのは、
最適化による数値誤差で
ループ数に変化がないかだな
904デフォルトの名無しさん:2013/02/18(月) 23:16:59.90
テキトーに
インライン展開されないコードがあるから、遅くなってるとか
905デフォルトの名無しさん:2013/02/19(火) 06:48:56.88
アセンブリ出力してみればいいじゃん。
後は、プロファイラでホットスポットを割り出したり。
906デフォルトの名無しさん:2013/02/19(火) 18:53:01.52
多分、x87命令が使われていて遅くなってる
/arch:SSE2を追加してみたら?
907 ◆0uxK91AxII :2013/02/19(火) 21:13:09.97
/Odでも使っとるがな。

/Ogを外すと幾分マシになる。
#pragma optimize("g", off)
908 ◆0uxK91AxII :2013/02/19(火) 21:41:27.36
/fp:preciseからstrictに変更しても良くなるね。
fastは遅い。
909デフォルトの名無しさん:2013/02/19(火) 22:49:17.25
VC11じゃ別に遅くなったりしないんだけどな
910デフォルトの名無しさん:2013/02/19(火) 23:20:37.82
>>893
BCC 6.4.4でCodeGuardを掛けてみた。

Error 00001. 0x400000 (Thread 0x0124):
Exception 0xC0000091:
| dai2.cpp line 141:
| printf("n = %d ", n);
| lambda = c[n-2] * c[n-2] - c[n-3] * (c[n-1] - b[n-1]);
|>dp = (b[n-1] * c[n-2] - b[n] * c[n-3]) / lambda;
| dq = (b[n] * c[n-2] - b[n-1] * (c[n-1] - b[n-1])) / lambda;
| /* Δp,Δqをp,qに反映 */
Call Tree:
0x004017C4(=dai2.exe:0x01:0007C4) dai2.cpp#141
0x32C9C8CA(=CC32120MT.DLL:0x01:09B8CA)

Exception 0xC0000091とはfloat overflowなので、大きすぎる値が入って実行不能な
状態です。ちなみにn=430〜470位の範囲で(乱数を初期値にしているからか)出ます。
911片山博文MZパンク ◆0lBZNi.Q7evd :2013/02/23(土) 00:46:59.38
COBOLがC/C++より処理が早いというのは本当ですか?早いならなぜですか?
912デフォルトの名無しさん:2013/02/28(木) 21:16:59.08
>>911
時と場合に寄る。
配列を対象に演算したりすんのは、得意だよね。
913片山博文MZパンク ◆0lBZNi.Q7evd :2013/02/28(木) 22:49:03.85
>>912 d
914827:2013/03/01(金) 01:50:42.59
COBOLが走る環境では大抵CPUが10進演算サポートしてるから、キャラクタ10進数や2進化10進数の演算はベラ速いね
915デフォルトの名無しさん:2013/03/08(金) 04:15:29.66
>>914
いまどき速いと言われるCPUで10進演算をサポートするものなんか無いだろ
916デフォルトの名無しさん:2013/03/08(金) 04:45:05.27
最近だとIBMのPOWER6/7でハードウェアサポートが付いてる
一般人には触る機会がほとんど無いが……
917デフォルトの名無しさん:2013/03/08(金) 13:02:46.16
「SPARC64 X」では、10進演算、暗号処理、コピーなどのソフトウェア処理の一部を
プロセッサで実行するソフトウェア・オン・チップを採用し、最適化されたソフトウェア
との組み合わせで、さらなる飛躍的な性能向上を実現します。
918デフォルトの名無しさん:2013/03/08(金) 13:20:15.54
>>917
Javaのシェアをx86からごっそり奪うつもりだろう
それにJavaの超越関数はIEEE754の64bit精度なので、内部で80bit精度で
演算しているx86は結果が異なって来るとしてソフトウェアエミュレーションしてるもんなあ
919デフォルトの名無しさん:2013/03/08(金) 13:50:30.72
strictfpじゃない場合は結果が異なることを容認してるんじゃないの?
920デフォルトの名無しさん:2013/03/08(金) 13:55:28.72
SSE2も使えないJVMなんか使うから
921デフォルトの名無しさん:2013/04/11(木) 02:18:29.34
お薦めのC++のルンゲクッタクラスはありませんか?
922デフォルトの名無しさん:2013/04/13(土) 08:45:59.77
>>915
そもそもCOBOLはPCでは使われないからなぁ
923デフォルトの名無しさん:2013/04/13(土) 09:02:39.83
924デフォルトの名無しさん:2013/04/13(土) 09:44:15.09
>>923
中間言語or機能拡張前提では言語の種類は問わないってのが今のトレンドなんだな
925デフォルトの名無しさん:2013/04/13(土) 13:54:21.35
そもそもCOBOLはPCでは使われないからなぁ
926デフォルトの名無しさん:2013/05/04(土) 14:30:59.21
[Mac/NUC] AGK / DarkBASIC / Basic4GL / 99BASIC 2013 Part.1
http://jbbs.livedoor.jp/bbs/read.cgi/computer/43761/1367197701/l100
927デフォルトの名無しさん:2013/07/05(金) NY:AN:NY.AN
ここまでllvmなし
928デフォルトの名無しさん:2013/07/07(日) NY:AN:NY.AN
テンプレートの最適化って技術的にはどうなん?
929片山博文MZパンク ◆0lBZNi.Q7evd :2013/07/21(日) NY:AN:NY.AN
「クロスワード ギバー」
http://katahiromz.web.fc2.com/xword/

これを高速化する方法を教えて下さい。お願いします。
930デフォルトの名無しさん:2013/07/21(日) NY:AN:NY.AN
自分で考えろアホ
931デフォルトの名無しさん:2013/07/21(日) NY:AN:NY.AN
アルゴリズムの最適化はスレ違いだ。自分で考えろ。
932デフォルトの名無しさん:2013/07/22(月) NY:AN:NY.AN
>>929
1マス1Byteにしてみれば?
0=空白,1=黒,2=ア みたいに
933デフォルトの名無しさん:2013/07/23(火) NY:AN:NY.AN
934デフォルトの名無しさん:2014/02/26(水) 21:55:57.42
コーディングレベルでの最適化は玄人しかやらないほうがいい
初心者〜中級者がやってもほとんど変わらないか、かえって遅くなる
935デフォルトの名無しさん:2014/02/27(木) 13:09:47.73
std::string やコンテナ周りの記述は、最適化でも消えない無駄な書き方をするのは多い
記述方法を変えるだけで 30% も高速化して、個人的な報酬の面ではうはうはだったけど、
会社としてはまずいんじゃなかろうか、と思った
936デフォルトの名無しさん:2014/02/27(木) 13:46:48.10
200行もかけた関数のデバッグ頼まれて、sprintf()一回呼ぶだけに書き換えたら詐欺呼ばわりされたのを思い出した。
寧ろ、もとの関数を書いた奴にこそ文句を言うべきだろうに。
937デフォルトの名無しさん:2014/03/01(土) 08:00:17.88
>>936
内容が分からんから何とも
938片山博文MZ無能 ◆T6xkBnTXz7B0 :2014/03/01(土) 23:34:24.85
諸君はgprof使ってるか? 色々捗るぞ
939デフォルトの名無しさん:2014/03/02(日) 02:26:24.26
自分が書いたコードではあまり使わないけど、他人が書いたコードの初動調査には重宝するね。
940デフォルトの名無しさん:2014/03/02(日) 17:57:29.70
GCCって最適化が何種類かあるみたいだけど
どのオプションが最強?
941デフォルトの名無しさん:2014/03/02(日) 19:07:36.25
-O9じゃねーの?
942デフォルトの名無しさん:2014/03/02(日) 19:07:42.07
自分で調べられないようならとりあえず -O2 使っとけ。
-O3 だと、たまに妙なバグを踏んだりする危険がちょっと高いから。
943デフォルトの名無しさん:2014/03/03(月) 08:49:42.49
そのレベルなら-Oでいいだろ。今だと普通に-O2相当だ。
944デフォルトの名無しさん:2014/03/04(火) 21:14:57.50
最適化厨
945デフォルトの名無しさん:2014/03/04(火) 23:37:05.98
最適化中
946デフォルトの名無しさん:2014/03/04(火) 23:47:49.61
メモリに余裕があるアプリならもうshortとかは使わない方がいいのかな
947,,・´∀`・,,)っ-○○○:2014/03/04(火) 23:52:31.82
使えよ。
movzx/movsxなんて通常のmov命令と比べてもゼロコスト同然なんだし
948デフォルトの名無しさん:2014/03/05(水) 06:22:14.30
今はキャッシュの利用効率とかで速度が決まる時代だから、メモリ節約する意義は昔より大きいくらいだよ。
949デフォルトの名無しさん:2014/03/05(水) 11:31:55.19
そのマシンのワードサイズより小さい転送はむしろペナルティがある
950,,・´∀`・,,)っ-○○○:2014/03/05(水) 19:44:06.06
なぜ、そしてどこにペナルティがあるのか説明できたらOK
そうでなければ理解してないので却下
951デフォルトの名無しさん:2014/03/06(木) 12:57:05.16
組み込み経験者だと、1ビットの信号を8ビットのポートに出す話を譬えに出すだけでわかってくれる問題だな。
952デフォルトの名無しさん:2014/03/06(木) 14:07:48.84
レジスタの部分アップデートが、なんでパイプラインの邪魔になるのか、まで説明できるかな組込み屋さんはw
(できる人も一定割合でいるとは思うけどね)
953,,・´∀`・,,)っ-○○○:2014/03/07(金) 09:06:44.19
上位ビットのゼロクリアあるいは符号拡張する命令を備えてないプロセッサが
どれだけあるのかと。
x86でもQuarkあたりでもmovsx/movzxは使える
954デフォルトの名無しさん:2014/03/08(土) 00:20:43.40
パーシャルレジスタストール??
955デフォルトの名無しさん:2014/03/08(土) 05:11:04.71
956デフォルトの名無しさん:2014/03/09(日) 01:51:13.04
>>952
レジスタリネーム機構は毎回新しいレジスタを確保して演算結果を格納するから
部分的な更新があると一回の参照で処理できないからね
movzxとかvzeroupperで依存関係の問題を解決できるのは更新されなかった部分をゼロとみなすことが可能になるから
957デフォルトの名無しさん:2014/03/09(日) 13:30:34.92
アセンブラレベルの最適化を勉強したいけど、本とか一冊もないのな
958デフォルトの名無しさん:2014/03/09(日) 13:37:53.94
最近はインテルの出してるドキュメント嫁とか、そういう感じ?
959,,・´∀`・,,)っ-○○○:2014/03/09(日) 14:07:41.72
古い本だけどHacker's Delightは現代でも通用する部分はある
960デフォルトの名無しさん:2014/03/10(月) 11:54:06.95
やっぱりソースコードこそ最良の教科書
gccのソース読め
961デフォルトの名無しさん:2014/03/10(月) 12:42:32.81
COINSもよろしく
962デフォルトの名無しさん:2014/03/13(木) 10:27:06.99 ID:lmSU7iga
>>940
-O2がいいよ
-O3でGCCビルドするとバグって通らない
963デフォルトの名無しさん:2014/03/13(木) 16:29:25.91 ID:ehk1j1eU
「最適化がバグってる」とか主張する奴の何割が
規格違反のコードを書いてるんだろうな
964デフォルトの名無しさん:2014/03/13(木) 17:17:38.61 ID:wI+RMMKp
うむ。
strict aliasing ruleについて完璧に理解している奴だけに許された台詞だよなw
965,,・´∀`・,,)っ-○○○:2014/03/13(木) 19:49:00.09 ID:0x0bjcUd
gccの最適化で落ちるってのは最近どっかで見たような
↓これもいい例だが

http://homepage1.nifty.com/herumi/diary/1401.html#8
966デフォルトの名無しさん:2014/03/13(木) 20:20:11.94 ID:dyPbFnv9
その例だとコンパイルは通っているんだな。
>962の言う「通らない」は何のことなんだろ。
967,,・´∀`・,,)っ-○○○:2014/03/13(木) 20:28:48.44 ID:0x0bjcUd
バリデーションじゃね?

>>965の例のASM出力見る限りでは一応intの境界にあわせてやれば
通るコードにはなってるようだ。
16バイト境界に合ってないからというよりint境界にあってないのが直接の原因。

アラインメント制約が緩いx86だから最適化してない状態ではたまたま動くだけで
RISCだとアラインメント例外吐くかアドレス下位2〜3ビットを無視してロードだろうな。
968デフォルトの名無しさん:2014/03/13(木) 21:33:51.73 ID:nZXH4hR1
最適化すると内部エラーでコンパイルできないってのは時々出くわすような。
リンク時の最適化オプション使うと処理が複雑になるからバグやエラーになりやすいのでは?

前に別スレに書いたVC2012の_mm256_extracti128_si256のバグは最適化すると
処理対象のレジスタがおかしくなるってやつだったな。
あれは結局2013で直ってるからそれで解決という返事だったよ…
これね
>VC2012 x64コンパイラの_mm256_extracti128_si256バグにハマってしまった。
>当面は_mm256_extractf128_si256使って回避した方がいいよ。
969,,・´∀`・,,)っ-○○○:2014/03/13(木) 21:40:51.76 ID:0x0bjcUd
http://www.beta.microsoft.com/VisualStudio/feedback/details/812347/visual-c-17-18-sse-avx-bugs

こんなのあったんだな。
Intrinsicsってキャストがすごいめんどくさいわ無駄なvmov*を吐くわで
自動ベクトル化やりつつ細かいところをNASM/YASMでいいやと
思ってしまった。
ところでcmovに対応する組み込み関数ってないよね?
970デフォルトの名無しさん:2014/03/14(金) 00:12:42.17 ID:YndCz6Us
VC2013で__vectorcallが追加されたけど、旧バージョンやICCでは使えないから
あまり細かいとオーバーヘッドが気になることもありそうな。
intrinsicはインラインで展開されるメリットがあるけど、インラインアセンブラだって
最適化に支障があってもインラインで展開されるんだよなぁ。
VCのx64はそこらが不便だね。

ところで、_mmのSSEコードを_mm256に変換した程度でやたら遅くなる原因ってあるかな?
VEX128のSSEにした時は速くなってるし、インテルのアナライザでもスループットの問題はないから
原因がよく分からなくて。
やたら遅くなるといえばデノーマル数の処理速度には注意って話があったんだけど、
もしかしてAVXのデノーマル数の処理ってSSEの倍くらい掛かる?
971,,・´∀`・,,)っ-○○○:2014/03/14(金) 00:56:26.52 ID:KVEDcQD1
ICCには汎用レジスタも含めて極力レジスタ渡しするコール規約として__regcallがある。
小さい関数ならASM化してしまうのも手ですね。

> やたら遅くなるといえばデノーマル数の処理速度には注意って話があったんだけど、

普通にデノーマル数自体が遅い
http://www2.kobe-u.ac.jp/~lerl2/l_cc_p_10.1.008/doc/main_cls/mergedProjects/fpops_cls/common/fpops_denormal_num.htm

ソフト処理だから当然ベクトル幅に比例した時間がかかかる。

0に切り捨てるモード使おうか。
http://www2.kobe-u.ac.jp/~lerl2/l_cc_p_10.1.008/doc/main_cls/mergedProjects/fpops_cls/common/fpops_reduce_denorm.htm





ところで、なんでどこそこにIntelコンパイラのドキュメントのミラーがあるんだろうな
972デフォルトの名無しさん:2014/03/14(金) 01:39:40.20 ID:YndCz6Us
>>971
>ソフト処理だから当然ベクトル幅に比例した時間がかかかる。
あぁ、やはりベクトル幅が関係しますか。
CPU内部で例外が発生してマイクロコードで実行してるのかな?
973デフォルトの名無しさん:2014/03/16(日) 21:54:49.99 ID:G/OYWqJl
>>965の問題はICCだとこんな方法が使える?

http://www.isus.jp/article/compileroptimization/avx_part3/
>__assume() を使うことによりコンパイラーの最適化に有用な情報を伝えることが可能です。
>以下の例では変数 num1 が 8 の倍数である(具体的な値は問わない)と指示することで、
>b[0], b[0+num1], b[0-num1] が同じ 32 バイト境界のアドレスにあることがコンパイラーに伝わります。
>void foo(float *restrict a, float *b, int n, int num1){
> int i;
> __assume_aligned(a, 32);
> __assume_aligned(b, 32);
> __assume(num1%8==0);
> for (i=0; i<n; i++){
> a[i] += b[i]+b[i+num1]+b[i-num1];
> }
>}
974973:2014/03/16(日) 21:59:05.60 ID:G/OYWqJl
何言ってるんだか。
コンパイラへの指示で、使い方の制約じゃないから関係ないや。
975デフォルトの名無しさん:2014/05/25(日) 16:39:38.96 ID:i4MNOuY/
埋め
976デフォルトの名無しさん:2014/05/26(月) 21:48:01.23 ID:P1pAx+kR
976
977デフォルトの名無しさん:2014/05/27(火) 22:40:04.85 ID:Ic9XwEQT
977
978デフォルトの名無しさん:2014/05/28(水) 21:10:58.82 ID:St2mZNey
978
979デフォルトの名無しさん:2014/05/28(水) 21:33:03.47 ID:r6RWITw2
あと一つ
980デフォルトの名無しさん:2014/05/28(水) 21:33:46.46 ID:St2mZNey
980
981デフォルトの名無しさん:2014/05/28(水) 21:36:40.59 ID:r6RWITw2
実に6年越しでやっと消費出来たのかー。
感無量だね。
次スレどうするのかしら?
982デフォルトの名無しさん:2014/05/28(水) 21:40:18.54 ID:poDq1Uss
究極の最適化は「何もしないこと」である。



というわけで次スレも最適化してしまおう。
983デフォルトの名無しさん:2014/05/28(水) 22:54:36.10 ID:St2mZNey
次スレいらないでしょ
984デフォルトの名無しさん:2014/05/29(木) 12:11:51.76 ID:BzM20fyM
最適化すると、別スレならずに他のスレにインライン展開されるな
985デフォルトの名無しさん:2014/05/29(木) 12:55:32.37 ID:ld2lb9I8
最適化を定義しよう
986,,・´∀`・,,)っ-○○○:2014/05/29(木) 20:02:12.91 ID:lUpNZIqd
必要なら立てればいいじゃん。
俺には「高速化手法」スレと何が違うのかわからない
987デフォルトの名無しさん:2014/05/29(木) 22:09:57.83 ID:3vKJnOmW
必要な人いる?
988デフォルトの名無しさん:2014/05/29(木) 22:32:09.40 ID:guk1iO+w
SIMD or マルチスレッド

以上。


って感じだしなぁ・・・w
989デフォルトの名無しさん:2014/05/29(木) 22:55:11.20 ID:3vKJnOmW
てすぽ
990,,・´∀`・,,)っ-○○○:2014/05/29(木) 23:02:30.51 ID:lUpNZIqd
あとは
・省メモリ化やストリーム制御命令によるキャッシュ効率の向上
・アルゴリズム自体の見直し

大体にC/C++の単発ネタスレ多すぎる気がするんだが
とりあえず俺的に移行先スレはこんなところで。


【C++】高速化手法【SSE】
http://peace.2ch.net/test/read.cgi/tech/1130349336/

アセンブラ 13
http://peace.2ch.net/test/read.cgi/tech/1314512680/

OpenMPプログラミング
http://peace.2ch.net/test/read.cgi/tech/1102483474/

GPGPU#5
http://peace.2ch.net/test/read.cgi/tech/1281876470/

【O(n)】計算量の評価方法について【O(log n)】
http://peace.2ch.net/test/read.cgi/tech/1363854937/
991デフォルトの名無しさん:2014/05/29(木) 23:19:55.49 ID:3vKJnOmW
まあ、高速化手法が一番良さそうだね
992デフォルトの名無しさん:2014/05/30(金) 07:02:24.06 ID:iM2/XKtt
うん、このスレはお役御免。
ご苦労様でした ∠(`・ω・´)
993デフォルトの名無しさん:2014/05/30(金) 07:48:13.45 ID:t9L11UzZ
6年間お疲れ様でした
994デフォルトの名無しさん:2014/05/30(金) 15:51:44.56 ID:tQtZpcuA
うんこの、スレは、お役御免
995デフォルトの名無しさん:2014/05/30(金) 22:56:45.34 ID:t9L11UzZ
995
996デフォルトの名無しさん:2014/05/30(金) 23:00:00.51 ID:uSMUGQ91
カウントダウンー
997デフォルトの名無しさん:2014/05/30(金) 23:07:41.63 ID:t9L11UzZ
996
998デフォルトの名無しさん:2014/05/30(金) 23:12:48.41 ID:uSMUGQ91
へいへいへーい
999デフォルトの名無しさん:2014/05/30(金) 23:19:35.96 ID:IDMDYieI
999
1000デフォルトの名無しさん:2014/05/30(金) 23:20:07.50 ID:IDMDYieI
1000
10011001
このスレッドは1000を超えました。
もう書けないので、新しいスレッドを立ててくださいです。。。