1 名前:デフォルトの名無しさん [2008/01/04(金) 14:25:44 ] 主にx86系で浮動小数点を扱う話題
448 名前:デフォルトの名無しさん mailto:sage [2010/06/26(土) 01:54:08 ] >>445 レスサンクス。 使っているのはC++とIntrinsic。最初はインラインアセンブリで書いていたんだけど、 WindowsのVCCも考えて、Intrinsicに変更した。 コードをさらしたいのだけど、さすがにそれは出来ないので、 ちょっとシンプルなコードを書いて比較してみるよ。 何かわかったら書き込んでみる。 なんとなく思っているのは単精度だとシャッフルやらシフトを多用しているんだけど、 倍精度ではデータ幅の関係でそんなにやらなくていいので、Opteronはシャッフルとかシフトに弱いのかなあ? とか思っている。 >>446 64bitで使っているんで、もはやコンパイラがx87のコードを吐いてくれません。 ちょっと表現が悪かったけど、SSEと言っているのはベクトル化したSIMDコードという意味。
449 名前:デフォルトの名無しさん mailto:sage [2010/06/26(土) 04:22:39 ] >>448 シャッフルのレイテンシ AMD Family 10h: 3 cycle Intel Penryn以降: 1 cycle
450 名前:デフォルトの名無しさん mailto:sage [2010/06/26(土) 10:40:33 ] 「OpteronとIntel(Core2?)とで挙動が違う」のが問題であるなら、 キャッシュ構成を疑ってみるのはいかが。 Opteronの一次キャッシュって今も2-wayなの?
451 名前:443 mailto:sage [2010/06/29(火) 01:29:17 ] ちょこっと調べてみたら、クリティカルな部分は ループの中に for(;;) { //A,B,Cその他諸々のデータを取ってきて下記を実施 SSEの計算群1 -> 結果をxmm0に最終的に放り込む SSEの計算群2 -> 結果をxmm5に最終的に放り込む SSEの計算群3 -> 結果をxmm10に最終的に放り込む // メモリへの書き込み A[i] = xmm0; B[i] = xmm5; C[i] = xmm10; } と言うような感じなんだけど、メモリへの書き込みの段階で偉く遅くなっていた。 >>450 が言うようにキャッシュの問題なんだろうけど、解決方法は無いのかな? Opteronはライトスルーなのかな? A、B、Cの結果は再利用されることはないので_mm_stream_ps()でやってみたけど、そっちはもっと遅くなった。
452 名前:デフォルトの名無しさん mailto:sage [2010/06/29(火) 03:11:14 ] 配列A,B,Cのサイズを 32kBの倍数+64*n(n=1,2,...,511) に変える
453 名前:デフォルトの名無しさん mailto:sage [2010/06/29(火) 19:57:17 ] >>451 A,B,Cのサイズは? SSEの計算群1 -> 結果をxmm0に最終的に放り込む A[i] = xmm0; SSEの計算群2 -> 結果をxmm5に最終的に放り込む B[i] = xmm5; SSEの計算群3 -> 結果をxmm10に最終的に放り込む C[i] = xmm10; とやってみるとか。 Cだけ_mm_stream_psにしてみるとか。
454 名前:デフォルトの名無しさん mailto:sage [2010/06/29(火) 22:57:53 ] キャッシュスラッシングが原因だとすると スカラーコードではA,B,Cは独立した ループで処理してるのかな?
455 名前:443 mailto:sage [2010/06/30(水) 02:18:30 ] >>453 レスありがとう。 実はすでにやってみたけど変わらなかった。 ひょっとしてレジスタが足りなくなって、xmm0とかが、メモリに待避させられているのでは? と思ったんだけど。 A,B,Cのサイズ自体多次元配列で、すごく大きいけど、ループの中では4K以下になるように処理している。 たとえば AAA[i][j][k]の3次元配列があった場合、 A = AAA[i][j] と1次元は配列として扱っている。そしてA[max]が4KB以下になるようにしている。 >>454 スカラーのコードもA,B,Cでループ内で処理している。 やっぱり、スラッシングが原因なのかなあ?
456 名前: ◆0uxK91AxII mailto:sage [2010/06/30(水) 18:03:29 ] とりあえず、境界を合わせて128[bit]ずつnon temporalな書込みをする。
457 名前:デフォルトの名無しさん mailto:sage [2010/06/30(水) 19:03:04 ] Cだけ_mm_stream_psにしても変わらないならA,B,Cだけが原因じゃなさそうだ。 計算群1,2,3で参照しているメモリがA,B,Cとスラッシングしてるんじゃないかな。 なので、こうしたらどうだろう? for () {SSEの計算群1-> 結果をA[i]} for () {SSEの計算群2-> 結果をB[i]} for () {SSEの計算群3-> 結果をC[i]} これでも計算群1で参照しているメモリがA[i]とスラッシングしてたらお手上げなんだけど。
458 名前:443 mailto:sage [2010/07/01(木) 01:21:40 ] >>456 >>457 いろいろと調べてみたら、キャッシュの問題ではなくて、 NUMAノードの設定が問題だったようだ。 メモリの確保をmalloc()ではなく、numa_alloc_onnode()でダイレクトにNUMAノードを指定してあげたら、 ほぼスカラーの倍の速度が得られたよ。 numactlをつかって、--preferred=nodes --localallocとかいろいろといろいろとオプションを つけてやってみたけど、うまく指定したノードでのメモリ割り当てが出来ていなかったみたい。 いずれにしてもSSEの問題ではなかったので、変な質問をして申し訳ない。 レスしてくれた人ありがとう。 ただ、プリフェッチの指定をしていた部分でNehalemではかなり効果があったのが、 Opteronでは全く効果が無いので、プリフェッチの距離とかはOpteron用に考えないといけない様だ。
459 名前:デフォルトの名無しさん mailto:sage [2010/07/01(木) 08:56:52 ] OpteronのNUMAは諸刃の剣だな。ハマればメモリの許す限りスケールするしな。 ていうかSMP Opteron由来の問題とは俺も気付かなかった。
460 名前:デフォルトの名無しさん [2010/07/23(金) 11:32:54 ] (000、000)10 ー10、835 とかいう問題
461 名前:デフォルトの名無しさん mailto:sage [2010/07/27(火) 16:59:37 ] >>458 First touch 問題だね