【C++】高速化手法【SSE】 (884)
TOP カテ一覧 スレ一覧 2ch元 削除依頼 ▼
【漏れは】猫でもわかる質問スレ【猫以下です】 (496)
C++相談室 part105 (888)
【普通のやつらの】 Arc Language 0 【上を行け】 (260)
Perlについての質問箱 61箱目 (102)
静的型付け言語の潜在開発生産性は今の100倍 ×3 (561)
ふらっとVisual C#,C♯,C#(初心者用) Part107 (667)
【C++】高速化手法【SSE】
1 :2005/10/27 〜 最終レス :2013/09/26 C++やインラインアセンブラ、SSEなどによる高速化の手法 について語りましょう。
2 : まずはi++は++iにしろよ。
3 : それで速度があがるならな
4 : Intelのコンパイラ買って開発したほうがいいんじゃね? ヘタに素人が最適化なんてやるより
5 : アルゴリズムよりメモリアクセスが最大のボトルネックだったりする。 結局レジスタやキャッシュを意識するのが重要になってくる。
6 : >>4 コンパイラを変えるんじゃなくてパフォーマンスの解析ツールを 買わないとダメじゃないかな。 コンパイラ自体はVC7も用途によっては悪くないし。
7 : >>6 VC++はプロファイラがついてると思うが
8 : 今月のCマガ買って読め。
9 : STL使うなら自分で同じような物を作ったほうが高速。
10 : その心は?
11 : なんでいきなりSTLが・・・
12 : 主要部分をasmで書き直せばOK
13 : >>7 VC++のプロファイラは、普通に一通りの機能を備えているのに、使われないんだよね。 VC.NET用だと、Compuware(Numega)がプロファイラを無償で提供してくれてるよ。 VC++6.0まで、TrueTimeは売り物だったのにねぇ。
14 : >1 >>12 インラインアセンブラよりも、組込み関数を使ったほうがいいことが多い。 ・コンパイラが最適化をしてくれる ・プログラムの記述が楽で、修正しやすい。 という2つの大きなメリットがあるよ。
15 : なおVC系の場合、 組込み関数をインライン展開する というオプションを有効にしてしまうと、 インライン展開されてしまい、最適化されない という直感的ではない結果になるので、確認しながらやりましょう。
16 : VCにプロファイラがあるなんて気づかなかった というか2chで聞いたら無いっていわれてずっと信じてた
17 : VC7でなくなったんだっけか
18 : >>13 >使われないんだよね。 GUIに罠が仕掛けてあるからじゃまいか?
19 : SSE2が付いてるマシンではインラインアセンブラで書かれた処理を実行したいけど、 それ以外のマシンでは普通のC++で書かれた処理を実行したいと言うような場合、 どうすればいい?
20 : 開始時に判別して関数ポインタで入れ替え
21 : やっぱそれしかないか。 関数のインライン化されにくいなぁとか、 C++のメンバ関数だと面倒だなぁとか思ったんで。
22 : >>21 インスタンスをやたら作る必要が無いならファクトリーパターンで作り分けしてもらうという逃げ方もある。
23 : んなややこしいことしなくても、マクロ使って1つのソースから2つのオブジェクトを吐かせればいい。 関数ポインタだってコストかかるので、1つずつの関数を切り替えるのではなく、 2通りのプログラムを1つのプログラムに押し込むくらいの気持ちで、 もっとmain関数に近いところから切り替えてしまおう。
24 : インテルコンパイラってプリフェッチ命令を挿入するとか言ってるけど プリフェッチって入れても効果ほとんど無いよね? あとこれからPen3コアをベースにしたCPUになっていくからPen4用に 最適化はしないほうがいい?
25 : >>24 場合によるだろ。prefetch命令はL2へのロードのアルゴリズムを 変更するので、場合によってはメモリのレイテンシを劇的に減らす 事が出来る。というかintelのpdf嫁。
26 : prefetch命令を使って具体的に速度改善を説明する本とかないのかな。 サンプルコードとか載せてるのがあったら欲しい。 Webでも以外と情報無いし。
27 : STL like Template based coding with MMX/SSE extension http://www.codeproject.com/useritems/STL_like_coding_with_MMX.asp Intel IPP Iten OpenCV そのまま使えば高速じゃん
28 : >>27 なんだこれ。 マトリクスとかImageとか扱えるものなのか。 結構みんな使ってるんだろーか。
29 : クイックソート以外の例えばマージソートやバルブソートなどはどのようなときに使うのでしょうか?
30 : >>29 クイックソートは万能ではない。 特にソートする要素数が少ないときには他の方法が早い。 また、安定でないという欠点もある。(マージソートは安定)
31 : >>29 じやないんだが >また、安定でないという欠点もある。(マージソートは安定) これどーゆー意味なんよ? 高速化のスレだから速度の事を言ってるのか?
32 : >>31 ソートで不安定といったら 比較関数の評価で重みが重複した場合に順序関係が保存されない ことだと思うが…(;´Д`)
33 : >>31 >>31 >>31
34 : 出席番号順にソート済みの身体測定データを身長順にソートしたいとする。 ただし、同身長の人間がいる場合は出席番号の若い順に並んだままになっていて欲しい。 そういうときは「安定したソート」の出番よ。 クイックソートだと出席番号はバラバラになるからな。 まあ「安定した速度」って点でもマージソートはなかなかのもんだと思うけど それにしても
35 : それは、キーの指定が悪い。
36 : >>31 基本情報の資格でも取ったほうがいいお 言葉が通じないと頭良くても吸収できないでしょ
37 : >>35 ソートで大小の評価を、 身長だけではなく、出席番号も加味してやればいい と言いたいのだろう。 でもね、出席番号がついてなかったら、どーするの?
38 : 一般的にソート前のインデックス順序を比較で使えばいい 二次キーとして出席番号があるならそれを使えばいいし
39 : インデックスがついていなかったら?
40 : アドレスで比較すればいいだろ馬鹿か?
41 : アドレスで比較? なに馬鹿いってるの?
42 : IntelのライブラリはAMDでワザと遅くなるようにしてそうなんで 一般向けには使ってません
43 : 高速なメモリコピーするにはmemcpy? それともキャシュ無視するためにSSEとか利用するのか?
44 : memcpyの実装はたくさんあるから一概には言えないぞ。 最もシンプルなのは1バイトずつコピーしているし、 コンパイラによってはインライン展開どころか組込み関数として処理しちゃうぞ。
45 : へぇー、組み込み関数(SSE?)で処理しちゃうのか。 ネットで調べてたらSSEのレジスタ4つにまず読んで、それを また4つ書き出すとレイテンシとやらを隠蔽できるとかなんとか あったけどそんな感じかな。 とりあえずmemcpy使っておきます。
46 : 組込み関数の意味がわかってない希ガス。
47 : 関係ないけど __divdi3 は組み込み関数なんだろうか。
48 : 直にCPUの命令またはその組み合わせに展開してしまえる関数だね。 組み込み関数の利用は#pragma intrinsic で明示できるよ。 逆に出来ない場合は組み込み関数として用意されてないといえる。」 ぶっちゃけIntel C++のオートベクトライズなんてあんま役に立たない。 処理を並列化できるところは明示的にMMX/SSEの組み込み関数 使って最適化したほうがいい。 CPUの動きを知り尽くしてレジスタカラーリングしてくれるから へたなアセンブリコード書くより速い。 あとIntel C++なんかは、インライン関数を基本的に展開しない。 STL使ったら重いってことは結構ある。 ただし __forceinliceは受け付ける。 VC2005はcpuidとかローテート命令まで組み込み関数として使える ようになったから、アセンブラ嫌いにはかなりフレンドリーになった希ガス。
49 : ローテートはVC6の頃から組み込み関数であった希ガス。
50 : 2005は8bit版や16bit版も用意されてる http://msdn2.microsoft.com/library/hd9bdb82(en-US,VS.80).aspx
51 : U \ | \ 人 / メ´ ヾ _,−' −―< , -、 て_ C++とSSE! ) / / (´ / / ⌒ 、 (⌒V ,'´`ヽ ト、 ,ヘ ヽ ! :〉 ト、ヽ / /! / 、゙ーァ' |,ノ ´ ̄` ヾ! / /`~´ ,' > < ゙, / / l 、ー―:ァ i/ / ゙、 Y⌒/ ,/ / `''ァ‐`ー' / / i /
52 : だんごって何の仕事してんの?
53 : .NEETでFA
54 : 倍精度実数、うらやましいなー
55 : constで最適化が促進させられる理由ってなんでそ?
56 : 書き込むスレ間違えました。失礼しました。
57 : [1] 授業単元: 数値計算法 [2] 問題文(含コード&リンク): @f (x) = cos (x) - x2 = 0 の根のうち、0 < x < 1 を満たすものを2分法で求める 初期値 a, b が入力でき、 6桁推定された解と関数 f (x) を呼びだした回数を出力するようにしなさい。 [3] 環境 [3.1] OS: WindowsXP [3.2] コンパイラ名とバージョン: VC 6.0 [3.3] 言語: C [4] 期限: (2006年06月08日まで よろしくお願いします
58 : やべっ 二分法って何だっけ 忘れちゃったよ
59 : >>58 カップラーメンを従来の1.5倍の速度で完成させる最適化技法
60 : 調理時間の短いラーメンほど短時間で伸びる
61 : グルテンを加えるといい
62 : 麩になっちまう
63 : 即値で掛け算する場所を書き直してみたら?
64 : PenMのSSE2って遅くね?
65 : デコーダがネック。複合デコーダパスだからね。 汎用&MMレジスタベース命令と交互に配置するとデコーダネックを隠蔽できる。 Yonahでは解消されてる。てかめちゃくちゃスループットいい
66 : じゃあPenMだったら無条件でSSE2不使用、ってコーディングはもうしちゃ駄目だね。
67 : そもそもYonahな時点でPenMじゃないし。 つかPenMって3年前から更新されてない一昔前のチップだろ。
68 : ド忘れされてるDothanとi915萌え YonahもBanias、Dothanと同様Pentium-Mですよ。 ただ発表後にPentiumブランド消失と絡んでIntel Coreとも名付けられちゃったが。 ブランド展開がまだよく分からんのでこの先どうなるか知らんが
69 : 面白い話題なんでもっと調べたいんですが、 いい本ないでしょうか? やっぱりパターソン&ヘネシーですか?
70 : メーカのドキュメント
71 : SSEはコンパイラが自動的に使ってくれるのですか?
72 : コンパイラによる。VCだとスカラ演算のみ。 自動ベクトル化が可能なコンパイラはgcc4.0系とかiccとかPGIとか。
73 : SSEで最適化してもメモリアクセスのほうがボトルネックになんね? キャッシュとかよく分かんねけどメモリよりキャッシュを意識せな いかんのだろうけど。
74 : 処理の内容によるんじゃない? 動画の画像処理みたいにプリフェッチの予測が当たりやすい処理だと メモリ帯域の方がボトルネックになってる感じはしない。 他の分野についてはわかりません。
75 : >>73 同じデータを色々な組み合わせで何度も使う場合 キャッシュをうまく効かせるのが腕の見せ所。
76 : 誰かSSEのプリフェッチをどう使えばいいのかまとめてくれ。
77 : めちゃくちゃ大雑把に話せば、 メモリを使う100クロック前くらいで 64byteごとに1回プリフェッチ命令を置く。 どの命令がいいかは、全部試して速いのを採用。 詳しくは、たくさんコードを書いてから キャッシュについて勉強してくれ。 俺も勉強せねば・・・。
78 : GPUと組み合わせ使うて場合って GPUができる計算はみんななげちゃうって方針でいいの? 低次元行列計算はDirextXでできるみたいだから、 DirextXになげちゃおかと思ってるのだけど
79 : >>78 DirectXは誰が動かしていると思っているの? ユーザプロセスは? OSカーネルは?
80 : インテルのペンティアムプロセッサのマシン語で 高速化を勉強できる良い入門書みたいなのあったら教えてください ホント、よろしくお願いします。 このとおり!m(_ _;)m m(-.-;)m m(_ _;)m
81 : >>4
82 : そうおっしゃらず。。 なにとぞ、お願いします〜m(_ _;;)m
83 : >>83 いやマジで、下手な本買うよりiccのアセンブラ出力眺めた方がよっぽど勉強になるって。
84 : なるほど、そういう意味でしたか。
85 : >>80 MMXテクノロジ最適化テクニック(ISBN4-7561-0797-4)の5章
86 : >>85 さん、ありがとうございます。 早速書店で探してみます。m(_ _)mペコリ
87 : SSEでどこか参考になるサイトはありませんか?
88 : つ[google]
89 : 最近のコンパイラはSSEなどは指定しなくても自動的に使ってくれるのでしょうか?
90 : ではまず最近のコンパイラの定義から(ry
91 : >>89 そういうコンパイラもあります。
92 : インテルコンパイラです
93 : 自動的に使うようになってると、SSEがないCPUでは動作しないのでは。
94 : O3を指定した場合、自動的に検出され使われる
95 : _ ∩ ( ゚∀゚)彡 オッサン!オッサン! ⊂彡
96 : ここってこんなに人居たんだ
97 : >>95 オマイの駄洒落のほうが・・
98 : /Qx*とか/Qax*なしで使うことってあったっけ? とりあえずboost:mt19937はICCのオートベクトライズでやたら速くなるが
99 : Auto-vectorization in GCC ttp://gcc.gnu.org/projects/tree-ssa/vectorization.html
100 : AMD64向けだと強制的に使ってくれる。 自動ベクトル化は知らん。
101 : 次スレまできた。飽きっぽい俺が良く続くもんだ。Σ(´∀`;) どうぞよろしくお願いします。
102 : http://www.intel.co.jp/jp/developer/download/index.htm ここにあるインストラクションセット表って、 SSE3以降のものも載ってます?
103 : SSE3は載ってたと思う。SSSE3は知らん
104 : gcc 4.1.1をMinGW gcc 3.4でコンパイルして使っています。 自分の使っているCPU向けに最適化をしようと、 -O2 -march=pentium-m -msse2 -mfpmath=sse 上のオプションを付けてLame 3.97をコンパイルしたところ、最後の -mfpmath=sse を外した方が速いという結果になってしまいました。 CPUはCeleron Mを使っています。 Cerelon Mでは、実数演算ではSSEではなく80387を使った方が速いのでしょうか。 SSE命令を使った方が一見速そうに見えるのですが・・・。
105 : BaniasかDothanかYonahかにもよるけど、SSEはあんまり得意じゃないよMは
106 : >>105 Dothanコアです。 MはSSEが得意ではないのですね。参考になりました。 参考までに、姫野ベンチでも実験したところ、こちらは-mfpmath=sseありの方が速かったので、 コードに依るかも知れません。
107 : Pentium M系アーキテクチャでSSE*が遅いのはデコーダがネックになってるらしい。 Complex Decoderのみでデコードされるから、倍精度は浮動小数が速くても不思議じゃない Pentium MのFPUは加減算・乗算毎に倍精度×1、単精度×2だけど x87とSSEスカラ演算だと単精度はクロックあたり1、SSEのパックド演算だと2つは 発行できるから、単精度ならまだ使う価値があるね。
108 : 演算ユニットの構成は Port 0: x87ADD x87&SSE-MUL Port 1: SSE-ADD(SP Only) よってクロック毎に実行できる最大値は x87-SP: 1 SSE-SP: 4 SSE-DP: 1
109 : んでもSSE使うように最適化オプションつけた方が 遅くなるってのは不思議だよなぁ。 早くならないってことはあっても遅くなるってのはなぁ・・・ タスクスイッチのときにXMMレジスタも全部退避するようになるから? そういやXMMレジスタまで対比するか否かってOSはどうやって知ってるの?
110 : >>109 そもそも初期状態でFPUセットになっているのなら、SSEを使うだけで切り替えコストが発生する。
111 : まあ、Complexデコーダパス命令だから、の一言なんだが 待避のオーバーヘッドなんてたかがしれてる MXCSRレジスタってあるじゃん
112 : >>110 それXMMレジスタじゃなくてMMレジスタの話では
113 : でもSISDならデコードも速い。 単純にコンパイラが最適化しきれてないだけじゃないのか。 そもそも104氏が何の処理をさせてたのか書いてないから イマイチ議論のしようがない気もする。 おそらく人間が書けばDothanでもSSEの方が速いとは思う。
114 : >>109 >XMMレジスタまで対比するか否か http://hira.main.jp/wiki/pukiwiki.php?__save_init_fpu()%2Flinux2.6
115 : Core 2 (Merom)ベースのCeleron Mももう出たし
116 : 二つの符号付及び符号無し 64bit 整数の乗算、 さらには 128bit 整数同士の乗算などは SSE/SSE2/SSE3 命令群を使うことで高速化できるのでしょうか? そもそもこれらの命令は SIMD 目的であって ビット幅の長い演算が目的ではないので、 見当違いでしょうか?
117 : 64ビット同士の整数乗算は素直にx64命令セット使えと思うが。。。 16×16の積算・積和演算があるから組み合わせればいくらでも可能だ罠
118 : 海外旅行での現地のATMでのキャッシングって、 キャッシング枠ですか?それともショッピング枠ですか? 以前現金主義の友人がどうしても両替商見つからなくて 現地のATMでキャッシングしたら、日本に帰ってきて ショッピングとして明細に出てたって聞いたんですが。
119 : >>118 ATMによる。スレ違い。
120 : 誤爆じゃないのか
121 : 浮動小数点モデルを /fp:fast にする 精度は落ちるが
122 : マルチタスク/マルチスレッドで、セマフォを長時間握ったまま返さない奴とか見つける、とかは やっぱプロファイラとかで動的解析しないと分らんよね。 そんなの静的解析でどうにかなるもんじゃないか・・・。
123 : doubleは2つ同時にしか実行できないのか?
124 : >>123 日本語よろ!
125 : だぶる先生らいふのことだろ。 常識的に考えて。
126 : ダブル先(の)生ライフ?
127 : >>123 C++でおk
128 : >>123 一つのみも可。 ex) addsd
129 : 下がり過ぎ
130 : SSEで大部分が記述された 正規表現エンジンって知りませんか?
131 : 闇雲にSSEを使えば速くなるってもんじゃないし、そんな阿呆な代物ないでしょ。 # 速度に寄与する肝腎な箇所に使っているってことなら話は別だが。
132 : sseで正規表現・・・どこで使ったものやら
133 : SSEって並列処理や積和なんかが1命令化で速くなる。 端からデータを舐めていくような処理はあまり効果ないよ。 特に検索には向かない。
134 : bit列のマッチングはどう? 1bitずつずらしたのをxorしてall 0になったかどうか調べるとか
135 : strlenをSSE2でやる人がいるくらいだし、その応用でstrchr/strstrのような単純な検索はできると思う。 ただ、正規表現となるとうまく使うのは難しいと思う。
136 : sse4.2じゃないのか
137 : 固定文字列部分を抽出してBoyer-Moore法とかで検索するのが良く使われる方法。 strstrなんかはSIMDを使った力技検索に置き換えることができる。 >>136 確かにあれは速いようだ
138 : 固定文字列部分ならともかく「大部分」をSIMDに置き換えることに意味はない。 文字クラス程度ならSSE4.2で一括判定みたいなのも可能になるかと思うけど
139 : つうかそんなのAltiVecでとうの昔にやられてる事だしな。 Intelは必要な命令(シャッフル、MIN/MAXなど)が揃うまでにどれだけかかるんだ。 ルーチンごとにSSE1があるか、2があるかと判定しなくちゃいけなくて面倒くさい。
140 : Macのこと言ってるのか? SSE3以上使える前提できめうちで組めるからかえって楽だろw 大体にAltiVecに文字列比較命令なんてねーよ。 汎用レジスタ−SIMDレジスタ間のダイレクト転送命令ないし レジスタ値を比較してbranchフラグを更新する命令もない。 そもそも更新が停まってるだけだろ。
141 : SSE2の16バイト単位の文字列同時比較なんてこれだけだぞ (MMX(SSE)での8バイト同時比較でもこいつの64bit版を使えばいい) pcmpeqb → pmovmskb → test → branch SSE4.1だと pcmpeqb→ptest→branchでおk AltiVecだとpmovmskb相当のことをMSBの縮約いちいちマスク&シフトを繰り返した上 いったんメモリにストアしてから汎用レジスタで読み直さないといけない。 pmovmskbなんてIntelプロセッサでは1サイクルでこなせる処理だがAltiVecなんて ここだけで何十サイクルもかかる。 なにかと俺がコケにしてるCell SPEのほうがまだ使えるよ。 SPUにはMSBじゃなくてLSBのビット縮約命令がある。 要するに AltiVec=保守されてない時代遅れの命令セット 俺も使ってたからよくわかるよ。
142 : 俺の経験上文字列サーチでAltiVec使うと遅くなるケースのほうが多い。 だからMacOSでもstrcpy/memcpyみたいな分岐の必要ない操作に限ってだけAltiVecが内部的に使われてる。
143 : 同時比較でいいならロードして比較してvec_all_eq()するだけじゃね? ストアと読み出しはいらん。
144 : >vec_all_eq() あのさー、それ複合関数だから。 ではマスク生成+縮約+ストア+汎用レジスタにロードって操作を1つの組込関数に纏めただけ。 1インストラクションで済んでるわけではない。 アセンブリコード読んだことある?無いだろうけど。 CPUネイティブのベクトル比較命令であるvcmpequb自体は、SIMDレジスタ上にマスクを生成するのみ。 マッチしたのか、マッチしてないのか、マッチした場合、どこの位置でマッチしたのかっていう判定は 汎用レジスタ側でやるしかないんだよ。
145 : お前こそvcmpequbの仕様を読んだ事あるのかと。 > The CR6 is set according to whether all, some, or none of the elements compare equal.
146 : 最近論調がおとなしくなってきて改心したのかと思えば、 内心人を見下してるのは変わってないんだよな。
147 : あ、なんでアセンブリコードとか的外れな事言ってるのかようやく分かった。 最適化オプションを全く指定しないと確かに複合になるね。 ていうかさあ、デバッグ用とはいえ確かにこのアセンブリは変態だけど つまりはお前は大口たたいておきながら その実>>143 を言われて顔真っ赤にして焦ってアセンブリ出力を確認したんだろ。 恥ずかしいなあ。
148 : 「.」付き版はcr6を更新するからptest相当のことだけはできるよ。それは正しい。 どこでマッチしたかを求めるには汎用レジスタ側でやんないといけない。 pmovmskb相当の命令がないから遅いんだって。 Cell SPEだと7ビットシフトしてギャザリングし、ビットスキャンすれば位置が求まるけど
149 : >>147 で、pmovmskbの代用命令はどこにあるの?
150 : っヒント:もうL1に乗ってる
151 : >>149 無いよ。 そこを叩きたいなら叩いてくれ。
152 : そんなことは聞いてない。 SSE*にはSIMDレジスタ上のベクトルデータのMSBを縮約してダイレクトに汎用レジスタに転送する命令がある。 bsfと組み合わせればマッチ位置まで簡単に求めることができる。 AltiVecには、そういう命令は、ない。
153 : >>151 なら結局遅いじゃん。
154 : 支離滅裂だな。 それが初めから分かってるなら慌ててアセンブリ確認なんてしてないだろ。 百歩譲って今お前が力説したい事にスポットを当てるなら all_xx()が複合であるかどうかなんてどうでもいいんだからな。 ていうかstrchなのかstrstrなのかハッキリしろよ。 反論するのに都合の良い方を選択してるだけじゃねーか。
155 : 慌ても確認もしてないよ
156 : じゃあall_xxが複合だと言ったのはどこのだれですか? 結局gather出来ないんだから、そこはどうでもいいんだけどね。
157 : >>154 どっちもSSEより遅いよ。 PPCからの移植にSSE1まで使えるか2まで使えるかとか気にしなきゃいけないと思う方が馬鹿だよ。 Win32でもSSE2が使えないCPUなんてどのみちSIMDユニットの実装もショボイから最適化対象としては無視して良いくらいだよ。 非SIMDのパスに飛ばしておけばいい。
158 : まあそれも論点ずれてるんだが、建設的な話をしたいからお前に合わせよう。 確かにSSE2が使えないCPUは大抵しょぼいから無視しても良いんじゃないかな。 強いて言うならAMD(笑)が例外だが。 でもx86陣営がそういう路線を歩んでいるのは間違いなくて SSE3, SSSE3, SSE4.1, SSE4.2, AVX, LNIといちいちチェックしなくてはいけない日々が続く事には変わりない。
159 : Core2 Duoと比較して、Athlon X2がそれほど酷いとは思えないんだけど。
160 : 整数演算はひどいな
161 : 一晩考えて、何故団子がgatherに必死なのかが分かった。 団子はトリップ検索が主だから検索対象が極端に小さくて、 詳細な位置の特定の方がボトルネックになっているんだな。
162 : tawake
163 : 続きをどうぞ
164 : >>161 誰が笑いを取れとw
165 : 変な事言った?
166 : 一晩考えることじゃないだろ。俺のブログ一通り読んだら30分以内に否定される。
167 : で?
168 : 笑いしかとれなかったね
169 : そうだね。俺もだけど団子も痛い子だね。
170 : 痛いのはお前だけですからwww
171 : だから何故? 煽ってるんじゃなくて純粋に。
172 : 無知のまま過ごすのは恥だし勿体ないので団子でも名無しでも回答くれないかな。 名無しが答えられるかどうかは疑問だけど。
173 : ∩___∩ . \ | ノ ヽ \ / ● ● | \| ( _●_) ミ そんなエサでおれが釣られるかクマー! 彡、 |∪| ,/.. ヽ ヽ丿/ /⌒| / \__ノ゙_/ / ===== 〈 _ノ ==== \ \_ \ \___) \ ====== (´⌒ \ ___ \__ (´⌒;;(´⌒;; \___)___)(´;;⌒ (´⌒;; ズザザザ
174 : 都合が悪くなるとすぐ逃げるか話そらすからな。 結局161が図星だったのか。
175 : 名無しが寂しそうにしてるから構ってやれよw
176 : ビット演算の代数的な性質、それを導き出す公理が知りたい 算術演算から式変形だけでアセンブリ言語のコードを導き出せるようになりたい
177 : コンパイラでも作りたいの?
178 : メモリアクセスとかを考慮すると構造体より配列のほうが高速?
179 : >>178 同じ。
180 : SSE2でnビット左rolってどうやって記述すればいいのですか?
181 : Intelのマニュアル読みなさい
182 : 好きなの使え ;;【16bit×4並列】 movdqa xmm1, xmm0 psllw xmm0, N psrlw xmm1, 16-N pand xmm0, xmm1 ;;【32bit×4並列】 movdqa xmm1, xmm0 pslld xmm0, N psrld xmm1, 32-N pand xmm0, xmm1 ;;【64bit×2並列】 movdqa xmm1, xmm0 pslld xmm0, N psrld xmm1, 64-N pand xmm0, xmm1 【↓こっからまだ存在してないCPU向け】 protb xmm0, xmm0, N ;; 8bit×16用 AMD SSE5 protw xmm0, xmm0, N ;; 16bit×8用 AMD SSE5 protd xmm0, xmm0, N ;; 32bit×4用 AMD SSE5 protq xmm0, xmm0, N ;; 64bit×2用 AMD SSE5 あと要素毎に変量が変えられる命令もサポートされてる。 俺は実用性を思いつかないが何かしら使える用途があるんだろう。 ちなみに128ビットフルは、場合によるので省略する。 4バイト単位ならpshufdとかのシャッフル命令使った方がいい。
183 : 俺の質問には答えずに人の質問には答えるんだな。 要素ごとのは、例えば最上位に立っているビットからNビット欲しいとか色々使い道はあるよ。 floorみたいのを自力で実装しようとすれば分かる。
184 : サーセンwwwpandじゃなくてporだwww
185 : >>179 うほ? >>178 の意味がいまいち分からんが、 char array[0x100]; と struct{char value;} array[0x100]; だったらレジスタサイズにパディングされる分、構造体の方が早くね? ちなみに、同じ事だが容量気にして構造体のなかでshortとか使うと パデイング入るんでメモリに無駄が発生する。 まぁ、パディングを知っていれば無駄を防ぐこともできるけど。
186 : 構造体にすればパディングされると決まっているわけではない。 だからその例だけだとどちらとも言えない訳だが。 構造体のメンバを一部だけshortにするのは意味が殆どない(寧ろ遅くなる)という点については同意。
187 : >>185 short array[3]; と struct{short value1;short value2;short value3;} array; でどっちが高速かという意味です。
188 : 配列のindexが定数なら変わらんだろ アセンブラ見ろ
189 : >>185 > struct{char value;} array[0x100]; > だったらレジスタサイズにパディングされる分、構造体の方が早くね? pragmaやattributeでパックしない限りpaddingは入らないだろ。
190 : 16とか32になるのはいいけどメモリアドレッシングで使えるscaleが8倍までなんだよな。 添字によるアクセスは思わぬ性能低下を起こすことがある
191 : >>189 構造体やその配列の場合、パディングが入る。 デフォルトが4バイト単位だったかな?
192 : おまえほんとにだんごか? デフォルトなんて決まってるわけ無いだろ
193 : まあデフォルト値は処理系依存だな。 >>189 の言ってることが嘘ってことで。 少なくともパディングが入らない保障はない。
194 : コンパイラ依存だよな。 歴史的な理由で当時の最長のレジスタがdoubleだからCPUのアライメントが8byte推奨で、コンパイラも8byteに詰めてた気が。 もしかしたらx86じゃなくてPowerPCかも知れん。
195 : VCやGCC辺りはパディングが入る。 Bitmapヘッダをそのまま構造体で読み取ろうとして引っかかった やつも少なくない筈。(VCならpragmaを使えばパディングを消すことができる) 一応32bitCPUならVC、GCC共にcharもshortも32bitで確保される。 64bitなら64bitで確保されるとか聞いたことがあるが真偽は不明。 蛇足だが、VCでchar array[5];などと確保すると確保した容量+3 の領域が確保される。
196 : http://kikyou.info/diary/?200812#i24_1 > つまり最大でポインタ二つ分のデータを保持しています。LP64の場合は128bitとなります。ILP32の場合は64bitとはならず、パディングの関係でLP64と同じく128bitとなります。 8byte?
197 : 将来AVXの1024bit SIMDが使えるようになった際に、128byteにパディングされるとかなるとイヤだな。 その頃にはメモリは数十GBで128byteなんてゴミみたいなもんだろうけど。
198 : その頃までにSIB.scaleのビット拡張してほしいね。1ビット増やせばx16, x32, x64, x128になるのに。
199 : \ \\ ____ // / / < _-=≡:: ;; ヾ\ > < / ヾ:::\ > < | |::::::| > < ミ|-=≡、 ミ≡==- 、 |;;;;;/ > < || <・>| ̄| <・> |── /\ > < |ヽ_/ \_/ > / > < / /( )\ |_/ > < | | ` ´ ) | > < | \/ヽ/\_/ / | > < \ \ ̄ ̄ /ヽ / / > < \  ̄ ̄ / / \ > / /  ̄ ̄ ̄ ̄ ̄ ̄ ̄ \\ \ \ ___ / ―\ ナンミョウホウレンゲッキョウナンミョウホウレンゲッキョウナンミョウホウレンゲッキョウ /ノ (@)\ ナンミョウホウレンゲッキョウナンミョウホウレンゲッキョウナンミョウホウレンゲッキ .| (@) ⌒)\ ナンミョウホウレンゲッキョウナンミョウホウレンゲッキョウナンミョウホウレンゲッ .| (__ノ ̄| | ///;ト, ナンミョウホウレンゲッキョウナンミョウホウレンゲッキョウナンミョ \ |_/ / ////゙l゙l; ナンミョウホウレンゲッキョウナンミョウホウレンゲッキョウナンミョ \ _ノ l .i .! | ナンミョウホウレンゲッキョウナンミョウホウレンゲッキョウナンミョ /´ `\ │ | .| ナンミョウホウレンゲッキョウナンミョウホウレンゲッキョウナンミョ | | { .ノ.ノ ナンミョウホウレンゲッキョウナンミョウホウレンゲッキョウナンミョ | |../ / . ナンミョウホウレンゲッキョウ
200 : パディングってむやみに入れるとキャッシュヒット率悪くなってかえって効率落ちたりしないんだろか
201 : 逆にキャッシュラインを跨ぐと効率悪くなるんだよ
202 : >>200-201 どっちも一般論だー 場合によるでしょ
203 : 実測すれば済む話
204 : >>191 cygwin上のgccで試してみたけど、padding入らないよ
205 : >>204 CPUによるが struct foo { char a; double b; }; でパディングが入らなかったら例外起きるだろうが。
206 : 起こんねーよ、CPUによるが。
207 : struct {char a, b, c;}だったらパディングなくても例外起きないよ。 コンパイラがまともなら。
208 : アラインメント制約の厳しいプロセッサなら、例外が起きないようにコンパイラが勝手にパディングするんじゃないかな。 しかしミスアラインメントのデータに対するロード・ストアの扱いは各CPUアーキ毎に方針が違ってて面白いな x86のSSE以降は、ミスアラインメントを許すが遅い命令と、許さないが高速な命令の2通りを用意。 対して、POWER/CellのSIMDは下位ビットを無視してロードし、プログラマが勝手にPermuteしてくれっていう扱い。
209 : 下位ビットを無視してくれるのはわざわざAND取ってアライメントする必要がないから楽でいいよな。
210 : 中を作る側もデコーダが軽くなるからウマー
211 : >>205 > >>204 > CPUによるが > struct foo { > char a; > double b; > }; > でパディングが入らなかったら例外起きるだろうが。 なぜ勝手にdoubleが入ってるんだww 誰もそんな場合の話はしていない。 団子にこんな基本的なことで嘘つき呼ばわりされたが嘘じゃないってことで >>185 > struct{char value;} array[0x100];
212 : ところでパディングの入らない環境ってどんな環境だろ? PC用で32bitプロセッサじゃ大抵入ると思うが。 sizeof(struct{char value;})==4 見たいにね。
213 : struct{char value;} array[0x100]; printf("%d\n", sizeof(array)); => 256 gcc-4.3.2ではこうなったけど、パディングってそもそも何だ?無効領域?
214 : >>212 Crayだとchar=short=int=32bitとかが普通らしい。 PC用じゃないけど。
215 : >>213 ゴメン sizeof(struct{char value;})じゃ1だね。 sizeof(struct{char v1;short v2})じゃ4になったから試さずに 書いちゃった。メンバーが同じサイズなら配列化されるっぽいね。
216 : 1つの構造体中でサイズ違いのアクセスが発生するかどうかによって変わるのじゃない。 連続の同一単位アクセスだけなら必要ないし、むしろ最適化にも邪魔だと思うんだよね? struct{char a;} arrayo[10]; struct{char a; char b;} arrayp[10]; struct{char a; char b; char c;} arrayq[10]; struct{char a; int b;} arrayr[10]; /* inserted */ struct{int a; char b;} arrays[10]; /* interted */
217 : 俺的に配列は__declspec(align(32))がデフォです
218 : 32? 16じゃないのか?
219 : AVX化を視野に入れてるから
220 : Alphaには16bitレジスタなかったよん
221 : MacでIntel PPC両対応のコードを書いています。 SSEでは、16ビット整数や8ビット整数をVectorに一括セットする命令が 見つけられません。 SSEで、以下のAltivecと同等の記述をするには通常どのような手順を使えば よいのでしょうか? 例:Altive用コード vUInt8 multiL, multiS; vUInt16 shift; switch (mode) { case 2: multiL = vec_splat_u8(5); multiS = vec_splat_u8(3); shift = vec_splat_u16(3); break; case 1: multiL = vec_splat_u8(3); multiS = vec_splat_u8(1); shift = vec_splat_u16(2); :
222 : っ _mm_set1_pi16
223 : >>222 __mm_set1_pi16とか_mm_set1_pi8とかですと、MMXレジスタが対象と ありました。 SSEレジスタにセットする場合、もしかして次のような手順になるのですか? CPUでメモリ上にパターンを作成 SSEレジスタにロード それとも、そもそもsseレジスタを使うのが遠回りで、MMXレジスタで2回 まわすのが普通なのでしょうか?
224 : 「e」pi16だな。
225 : >>224 なるほど! __m128i _mm_set1_epi8(char b) 見落としていました。ありがとうございました。
226 : xrgbxrgb の8[Byte]を、vuyyの4[Byte]に変換する場合、 途中で、 mm0: 左右平均r, 左右平均r, 左r, 右r mm1: 左右平均g, 左右平均g, 左g, 右g mm2: 左右平均b, 左右平均b, 左b, 右b っていう感じに並べ換えるのに、えらく時間が掛かる。 32[bit]なOS上で、Athlon 64の2[GHz]、SSEは2までを使用、 メモリは、DDR 400を、dualchannel、 連続した1024*768[dot]の処理に、6[ms]弱を要する。 極力、同じレジスタに連続して触れないように書こうとしても、 何かとやりづらい。 他に適当な方法があれば、教えて欲しいとか、書いてみる。
227 : pmaddwd 2個で済むように書けるよな?
228 : thx pmaddwd - packssdw - pmaddwdで、vuかyyの二要素出せるのかー。 /(^o^)\
229 : 5[ms]弱に短縮。 適当に並び換えれば、もう少し行けるかも。
230 : バイト列の入れ替えをしたいのですが、普通はどのように行うのでしょうか。 単に偶数、奇数バイトをスワップさせたいだけなのです。 00 11 22 33 00 11 22 33 00 11 22 33 00 11 22 33 11 00 33 22 11 00 33 22 11 00 33 22 11 00 33 22 上マスク、下マスクで二つの値を出し、それぞれシフトして、ANDを取る という方法しか思いつきません。もっと賢い方法がありそうな気がします・・・
231 : 4バイトならbswapで一発なんだが
232 : 言葉足らずですみません。xmmでの処理途中なんです。
233 : psrlw psllw por または pshufb あたりじゃね? >>231 エンディアン変換命令使ってどうするw
234 : >>233 なるほど、前者はSSE2までのマスク+シフト+orですね。 後者はSSSE3ってことはCore2Duo以降ですか・・・ CoreDuo以前を切り捨てれば楽だけど・・・ん〜。
235 : 2通りの関数書いてCPUIDで振り分けるのはどう? SSSE3でも128ビット版は65nm版Core2やAtomは速くないよ。 ちなみにSSE5なら protw xmm0,xmm0,8 で1命令ですな
236 : >>235 >2通りの関数書いてCPUIDで振り分けるのはどう? これでやってみます。サンクスでした。
237 : お前ら、ちょっと頼みがあるんだが。 SSEでどの程度高速化できるか、ちょっくら試しにコードを書いてみたんだが全然速くねぇ。 コードの書き方が悪いのか、俺のPCのCPUがAthlonなのが悪いのか、アドバイスおくれ。 ソースはコレ↓ http://uproda11.2ch-library.com/11172112.zip.shtml 題材はビットカウントで、コンパイラは GNU C++。 よろしくおながいします。
238 : あ、言い忘れたけどDLキーはデフォルトの1です。
239 : ちなみに家のPCでの実行結果はこんな感じ init data func = reference : test=OK : clock = 15063 : sum = 504854834 func = bit32 : test=OK : clock = 6812 : sum = 504854834 func = bit64 : test=OK : clock = 5219 : sum = 504854834 func = sse : test=OK : clock = 5109 : sum = 504854834
240 : すまん、データの初期化でバグがあった。 直したんで、こっち↓を見てくれ。 http://uproda11.2ch-library.com/11172113.zip.shtml
241 : 生のアセンブラで書けよ!インラインってw 実行せずとも分かる事を述べよう。 ソースを16バイトアライメントに合わせている? ソフトウェアパイプライン化が行われていない。(これをやっていないとSSEの意味がない。) そもそも速度計測しているコードが小さい。 SSE4.2だと1命令でなかった?
242 : >>235 CPUIDで振り分けてもSSE5じゃ使えるCPUが現状ないジャマイカw SSEPlusでエミュレーションするとSSE2の実装で9.3サイクルかかるな。 これ分岐いらんだろjk ttp://sseplus.sourceforge.net/group__emulated___s_s_e2.html#g80be0eae1c514715a253654cdc4280db
243 : 勉強し始めです。 リトルエンディアンとxmmで混乱してしまったので教えてください。 実アドレス上、以下の順で並んでいたアドレス上のデータは、 0 1 2 ... D E F xmmレジスタにロードすると F E D ... 2 1 0 の順で取り込まれるのですよね? _mm_srli_si128()で1バイト右シフト(256で割る)するとレジスタ上は 0 F E ... 3 2 1 となり、これをメモリにストアすると 1 2 3 ... E F 0 という順でストアされる ということは、 xmmで右シフトした状態というのは、 メモリ上では(上記表現では)左シフトした状態に相当 これ、認識あっていますでしょうか。
244 : デバッガで見えるレジスタの状態は右が下位だよっと 糞長い128bit変数だと思えばいいよ
245 : >>240 inline __m128i population_count_sse_iter(__m128i *v) { __m128i tmp0,tmp1,tmp2,mask; tmp0=_mm_load_si128(v); mask=_mm_set1_epi32(0x55555555); tmp1=_mm_and_si128(tmp0,mask); tmp2=_mm_srai_epi32(tmp0,1); tmp2=_mm_and_si128(tmp2,mask); tmp0=_mm_add_epi32(tmp1,tmp2); mask=_mm_set1_epi32(0x33333333); tmp1=_mm_and_si128(tmp0,mask); tmp2=_mm_srai_epi32(tmp0,2); tmp2=_mm_and_si128(tmp2,mask); tmp0=_mm_add_epi32(tmp1,tmp2); mask=_mm_set1_epi32(0x0f0f0f0f); tmp1=_mm_and_si128(tmp0,mask); tmp2=_mm_srai_epi32(tmp0,4); tmp2=_mm_and_si128(tmp2,mask); tmp0=_mm_add_epi32(tmp1,tmp2); mask = _mm_setzero_si128(); tmp0 = _mm_sad_epu8(tmp0, mask); return tmp0; }
246 : 【続き】 virtual int population_count(unsigned int data[4]) { __m128i sum = population_count_sse_iter((__m128i *)data); return _mm_extract_epi16(sum, 4) + _mm_cvtsi128_si32(sum); } virtual int population_count_array(unsigned int data[][4],int size) { __m128i sum = _mm_setzero_si128(); for(int i=0;i<size;i++) { sum = _mm_add_epi32(sum, population_count_sse_iter((__m128i*)data[i])); } return _mm_cvtsi128_si32(sum) + _mm_cvtsi128_si32(_mm_srli_si128(sum, 4)); } んで、うちの環境ではこんな感じになった(Core 2 Duo E8500, Cygwin) func = reference : test=OK : clock = 8890 : sum = 504854834 func = bit32 : test=OK : clock = 4859 : sum = 504854834 func = bit64 : test=OK : clock = 12829 : sum = 504854834 func = sse : test=OK : clock = 2156 : sum = 504854834 func = dango-sse : test=OK : clock = 1281 : sum = 504854834 func = dango-ssse3 : test=OK : clock = 1093 : sum = 504854834 64bitが遅いのは32ビットとしてビルドしてるからだと思うが、それはさておき SSSE3を使う方法は、Penryn/Nehalemでは速いけど AtomとかCore 2 65nm系は使えてもSSE2のより遅い。
247 : virtual int population_count_array(unsigned int data[][4],int size) { __m128i sum = _mm_setzero_si128(); for(int i=0;i<size;i++) { sum = _mm_add_epi32(sum, population_count_sse_iter((__m128i*)data[i])); } return _mm_cvtsi128_si32(sum) + _mm_cvtsi128_si32(_mm_srli_si128(sum, 4)); } 訂正してくだしあ><
248 : 【これが正解】 virtual int population_count_array(unsigned int data[][4],int size) { __m128i sum = _mm_setzero_si128(); for(int i=0;i<size;i++) { sum = _mm_add_epi32(sum, population_count_sse_iter((__m128i*)data[i])); } return _mm_cvtsi128_si32(sum) + _mm_cvtsi128_si32(_mm_srli_si128(sum, 8)); }
249 : >>,,・´∀`・,,)っ-○○○ うちのAthlonの環境でも>>246 のdango-sseの結果と大体同じくらいの性能うpが確認できました。 しかし、こんなに差がつくとはSSE侮りがたし。 団子さん、多謝です!
250 : VC++ と gcc (言語は C++)のインラインアセンブラで SSE の16バイトアラインメントされていることを仮定した命令を使いたいのですが、 float の配列変数全体を16バイト境界にアラインさせることって可能ですか?
251 : >>250 __declspec(align(16))と__attribute__((aligned(16))) マクロなりなんなりで切り替えればいい
252 : >>251 即レスありがとうございます!
253 : __m128(あるいはその配列)との共用体にすれば勝手に合うけどね。
254 : gcc で使えるの?
255 : gcc で使えるの?
256 : 大事な事なので2回聞きました
257 : #include <xmmintrin.h>
258 : あとコンパイルオプションにフラグつけとけ -msse とか
259 : そしてautotools地獄へ…
260 : ああ、あのへんマジで何とかして欲しい。 Win32ではASMで書いた関数の頭にアンスコ付けないと認識しなかったりとか
261 : 頭に…アンスコ…?
262 : アンダースコート被るんだよ
263 : underscore、呼出規約云々のアレ。
264 : こやつらには5Fhって言った方がわかりやすいかもしれんな
265 : プログラマのくせに、「あんすこ」が通じないのはおかしい。
266 : 職業プログラマだけじゃないだろ 趣味でやるやつもいる
267 : 趣味グラマだけど理解してるよ
268 : アンダーバーとか言う奴は素人
269 : ひゃっひゃっひゃっひゃっ
270 : なさけなや
271 : アンダーバー。
272 : 今のVCのコンパイラは、インラインアセンブラを書くと、そのインラインアセンブラを含む関数が最適化がされないらしいけど、 xmmintrin.hなどは、使うと最適化されなくなる?
273 : うん
274 : インラインアセンブラだけインライン関数で分離すればいいじゃまいか
275 : インライン展開されたら最適化抑制も伝播したりして。
276 : >>273 いやいや、組込関数ならインラインアセンブラと違って最適化できるという触れ込みではなかったっけ?
277 : sse使って、まだコンパイラが入り込むある余地があるのか?
278 : xmmintrin.hなどの場合はxmmレジスタへの割付が最適化まかせなので、 最適化をしないと、1命令ごとにメモリとデータをやり取りするので非常に遅くなる。
279 : __m128iってクラスはレジスタ的なもので局所変数にしか使えないかと思ってたんだが、 実はvector<__m128i> みたいな使い方もありなの?
280 : typedef union __declspec(intrin_type) _CRT_ALIGN(16) __m128 { float m128_f32[4]; unsigned __int64 m128_u64[2]; __int8 m128_i8[16]; : 略 } __m128; てな感じで普通にメモリ上にとられるよ。最適化でレジスタに置きっぱなしになる。
281 : そうなのか。ありがとう。
282 : 組み込み関数の最適化は lstファイルでも出力して見てみるといいよ。 一応されるようだよ。
283 : GCCはpshufb周りのコード生成が酷い。
284 : まあgccはコードジェネレーター部がx86決め打ちじゃなくて汎用だからな
285 : _mm_set1_epi8()相当のことやろうとしたんだけどさ _mm_shuffle_epi8(_mm_cvtsi32_si128((int)c), _mm_setzero_si128()); ってやるじゃん。Intel先生は当然のごとくこういう風に生成するだろ。 pxor xmm0, xmm0 movd xmm1, DWORD PTR [esp+4] pshufb xmm1, xmm0 3行で済むことを6行もかける馬鹿コンパイラ pxor xmm0, xmm0 movd xmm1, DWORD PTR [esp+4] movss xmm0, xmm1 pxor xmm1, xmm1 pshufb xmm0, xmm1 movdqa xmm1, xmm0 飽くまでカンだけど、pshufbの引数の順番間違えてて、応急処置的に直したんじゃないかと思うんだ
286 : そういうときはgccのソース読むのが基本だろ。
287 : insn-attrtab.cが酷いな。SSSE3以降の命令の扱いがテキトーすぐる。
288 : >>279 処理系によっては自作アロケータで128ビットアラインされた領域に確保するようにしないと酷いことになるかもしれません。
289 : GCCはGPLなんだから文句ばっかり行ってないでお前らも プロジェクトに参加して改良しろよ
290 : それは本末転倒。アセンブラよりも作業効率を期待してCコンパイラで生成できないか試みてるのに いっそう手間かけてどうすんだと。別にGCCである必要ないんだよ。 っていうかオープンソース界隈は今頃AMD SSE5がキャンセルで大荒れだと思う。
291 : まあ、正論だな
292 : ダンゴさんの正論でスレがピリッと引き締まったな。
293 : キャンセルって何の事って調べたら・・・ 俺的にはAVX一本のほうが楽でいいな。AMDは正しい判断をしたと思う。 当初の予定はSSSE3もSSE4もサポートせずに、SSE5追加だけだったよね?
294 : いや、元々SSSE3はSSE5と一緒に追加、SSE4.1/4.2は順次対応する予定だったと思う
295 : Intel様、3Dゲームとか画像とか動画エンコとか特殊な用途向けよりもっと一般人が 恩恵をうけれるような命令を追加して下さい。といいつつ、マイナーな事言いますが、 IEEE754Rで改訂された10進浮動小数点の命令を追加して下さい。
296 : 一般用途とかけ離れてるだろ10進浮動小数なんて 金融演算でもやるのか?
297 : >>296 そうです、金融がらみとかです。
298 : >>290-292 一度実装すれば以後恩恵を受けられるわけだし、そもそもサポート契約してないなら、正論とは言えないだろう。
299 : 本来そういうのはハードベンダーが技術協力名目でやるものだろう
300 : インテル様はインテル・コンパイラを買えと仰っているからなぁ。 gccのauthorに-○○○@2ch.netとでも付け加えた方が トータルで安く上がるだろ。
301 : Intelコンパイラもたいがいだよ。 _mm_set1_epi8()はCore 2以降でなら>>285 の実装のほうが速いのに -QxSSE4.1とか加えても使ってくれないのはどうしたものかね _mm_set1_epi1(0)を pxor (_mm_setzero_si128()相当)に置き換えるのはさすがにやってくる
302 : メディアンフィルタの高速なアルゴリズムを教えてください。 複数のピクセルから中央値を選べばいいだけなのですが、 ifステートメントを避けて並列化する方法はないでしょうか?
303 : それを考えるのが面白いところなのに・・・
304 : http://www.j-tokkyo.com/2003/G06F/JP2003-177912.shtml 特許申請されてるお
305 : ちなみに言うと8要素のソートして真ん中の値をとればいいだけ。 pmaxub/pminubを使うことで大小入れ替えができる ちょっと考えてみたが愚直な並列バブルソートでpmaxub/pminubを合計40回程度かな? それでも1要素あたりにすると2.5回の比較で済む。 まあ、ベクトルのセットアップがちょっとばかし大変だが。
306 : 8?
307 : 自身含めて9か。 すまん素で間違えた 3.5命令・・・うーん
308 : ダンゴさん何者なんだw CPUに詳しいな。
309 : ダンゴさんへの賞賛でスレがヒートアップしたな
310 : AGIストールとかパイプリングストールとか意味がわかりまセンチ
311 : だんごー だんごー
312 : だんごー だんごー だんごー大家z(ry だんごさんって鳥の方の人かしら。 もしそうだとすると、数年前に某荒板でCPUのこととかお話した元コテですがお久しぶりです(´・ω・`)ノ 人違いだったらごみんなさい。
313 : 島は鳥の左側です。
314 : レフトシフト
315 : おまえらだんごさんがいるうちにいっぱいためになる話聞いておけよ。
316 : いっぱいだめになる話?
317 : itoaを高速に書く場合 どうやってかけばいいのですか? val % 10なんかで基数割してると 遅くてダメポなんですが.......
318 : 除算が遅いなら0.1を乗算すりゃいいじゃない
319 : 100でやれば除算回数が半分になる
320 : テーブル引け
321 : ,,・´∀`・,,)っ-○○○先生 おられませんかー?
322 : >>317 一体何桁の数字を変換したいんだ? 速くしたけりゃベクトル化すればいいだろ。
323 : >>322 10桁っす
324 : fbstpとか 10桁は遅いか
325 : いっそ数値の方をBCDにしちまえ ついでにCPUを6502にだな
326 : 10桁の数字を何回処理してどの程度時間がかかり、 どれだけ高速化したいのか位は言えよ。
327 : fildしてfbstpするのが速そうではあるね
328 : 基数は可変...っと。 ふつーitoaの高速化は無意味。
329 : > 基数は可変...っと。 それitoaじゃねー。
330 : x86のAAMとかAADの基数って変えられたよな? Opcodeがないからマシンコード直打ちになるけど
331 : if (a>=b) a = 0; これから条件分岐を取り除くにはどうすれば良いですか
332 : (void)(a >= b) && (a = 0));
333 : 余計な括弧がついていた (void)(a >= b && (a = 0));
334 : それってアセンブラレベルでは分岐してないか?
335 : アセンブラ以前に分岐しとるがな if構文を使ってないだけでしかない
336 : なぜ条件分岐を取り除きたいの? 倍精度・スカラだとこんな感じ movsd xmm1, dword ptr [b] movsd xmm0, dword ptr [a] cmpgtsd xmm1, xmm0 andpd xmm0, xmm1 movsd dword ptr [a] xmm0 で、もっとも移植性の高く速いコードを生成する可能性の高い俺の回答はこれ。 a = (a >= b)? 0 : a; っていうかConditional MOVEとかプレディケートの仕組みをハード的にサポートしてるCPUでないと 根本的に高速化にならないと思うんだ。 なんのために分岐を除去するのか、本末転倒な解決策でもいいなら、他にいくらでも方法はある。
337 : つーか三項演算子ってもともとハードがサポートしてるから、それを利用する為に作られたってどこかで読んだような。 x86がサポートし始めたのがC言語の登場に比べれば割と最近だからまるで最新技術のような錯覚を覚えるけどな。
338 : Pentium Proが出た時期を最近とか言っちゃうか? それを最近って言っちゃうならRISCでプレディケートをサポートするCPUはかなり新しい部類だよだよ。 分岐のオーバーヘッドを軽減するための機構が必要になったのはパイプラインが深いCPUが出だした頃の話だからな。 分岐(条件ジャンプ)が相対的にボトルネックになったのが動機。 つーか、Pentium Proの更に10年前、386の頃からCコンパイラはあったろ? あと、こんなブログ見つけた http://keisanki.at.webry.info/200908/article_8.html これARMそのまんまだな
339 : Conditional MOVEで思い出したけど、cmovcなどのフラグレジスタを見るものは、前の演算結果が出るまでストールするから、普通に条件分岐するより遅くなることが多いって本当?
340 : >>339 大嘘 >前の演算結果が出るまでストールする これは大いなるミスリード。 CMOV命令の結果に依存しない命令は先行実行出来るだろ? パイプラインの充填率を高める努力を怠ってはならない >普通に条件分岐するより遅くなることが多いって本当? 分岐予測の精度と頻度によってはそうなる「こともある」程度 一般的には単純な3項演算に展開出来る程度の条件分岐ならCMOVのほうが速い
341 : そうだったのか サンクス
342 : if - else のブロック中の演算式がいくつもあるようなのをcmovに展開して速くなるかって話なら 流石に無理。そういうイチャモン付ける奴は単に使い分けを見誤ってるだけ。
343 : a &= - (a >= b);
344 : あ、条件が逆だた
345 : >>343 どういう命令に展開されるか意識して書いてる? cond?0:1が表記上省略されてるだけで、大概のCPUでは演算回数は増えてしまうと思われ 条件フラグ値を汎用レジスタに転送する命令があればそれを使うんだろうが、 それなら既にConditional-MOVEより条件は悪い フラグ確定までフラグに依存関係のある命令は(投機)実行できないのは同じだからな
346 : だったら、最初のままでCMOVに展開されるから、何もしないでよい で終了するだけじゃん。 コンパイラ次第だけど。
347 : あ、比較とandの場合は (cmp xx,xx)の後、 sbb edx, edx and eax, edx の2命令。 cmov の場合も 即値が使えないから、メモリアクセスをしないよう 比較の前にレジスタクリアをしなきゃいけないし xor edx, edx (cmp xx,xx) cmovxx eax, edx の2命令。
348 : cmp->sbb->andで依存関係が生じる。 cmovはというと、P6以降のアーキではxorによるゼロクリアはALUを消費せず リザベーションにゼロを入れるだけの操作にデコードされるから 実質cmp+cmovの2命令分のコストだけだな
349 : そう言えばcmovを吐くコンパイラって見た事ないな 大抵前者のコードを吐く
350 : 単純にターゲットCPUがi386になってるからだろ。
351 : cmp+cmovにもマクロフュージョン効けばいいのに
352 : setccは普通に見るな
353 : げっごめんageになってた
354 : setccとcmovの違いが分からない
355 : >>348 ただ、その分レジスタを消費するけどな。 内部的なレジスタリネーミングという話でなく、 アクセス可能なレジスタが足りずに内容を退避する必要が出て来るケースもある。 また、単純な比較命令ではなくサブルーチンコール等をまたぐ場合 フラグ保持のためにxor等でのクリアは使えない。 比較の後にmovで0を入れる等だと、「ゼロクリア時の特別扱い」の利点が弱くなる。 あと、当然だがcmovはP6以降。 まあこれは現在は問題にならないかもしれないけどね。
356 : >>354 Intelが配布してるPDF見ればいいじゃん cmovは条件が一致した時にソースをディスティネーションに転送する setccは条件が一致した時にレジスタを1に設定、それ以外は0に設定する C言語の場合条件は0か1で判定できるのでsetccで十分な場合が多い 但しcmov使った方がより短縮できる事もある
357 : >>355 どんだけカツカツなんだよ XMMレジスタにでも退避しろやwww
358 : ダンゴさんって何者なんだw
359 : このダンゴって本物のダンゴなの? i5ってどうなのーって聞いてみたいんだけど。
360 : だんごじゃないけどi5はi5だよ。それ以上でもそれ以下でもない。
361 : >>360 おめーみたいなカスには聞いとらん失せろゴミが ダンゴさんマダー?
362 : i7にしろや
363 : >>361 ちょwだれww ほれ、なんかcore2の時とかこれはいいぜーとかなんか詳しく言ってたような気がしたから i7なりi5なりのアーキテクチャ面からの意見を聞いてみたかったんだ
364 : Phenom 2も悪くないCPUだから好きなの選べ。
365 : >>363 i7ー900はメモリ周りが速い。(トリプルチャネル) i5/i7(デュアルチャネル)で少し遅い。でもCore2よりは速い。 さあ選べ。
366 : でもこれから6コアとか8コアとか12コアとか出てくるんだろ 少しでもFSBが速くないともっさりしてくるのは確実
367 : >>365 Core2とi7を比較すると、とりあえずメモリが速いのと、デュアルコア*2からクアッドコアになったという利点が あるのはわかる i5はコア間でのやりとりがずいぶん遅いらしいので、場面によっては結構な影響を与えそう iシリーズになって各命令が要するクロックとかパイプライン周りは変わってないの?
368 : >>367 >iシリーズになって各命令が要するクロックとかパイプライン周りは変わってないの? そのあたりは余り変わっていないと思われるが、大きく変わっているのはSSE4.2?(4.3だったか?)になっている。 メモリ周りと、キャッシュ周りが大きく変わっているので、iシリーズ用に最適化すると早くなるかもしれない。 iシリーズはQPIが速いので、Core2シリーズよりマルチプロセッサになったとき速い。 いずれにしてもメモリ帯域がボトルネックになりそうなプログラムを書くなら、 iシリーズを使った方がパフォーマンスが出る。 キャッシュに収まるレベルで、SSEの新機能を使わなければあまり変わらない。 今からならCore2Quadよりもi5の方がいいと思う。
369 : i7って64bit時のパフォーマンスはどうなの?Core2より良いという話を聞くけど。
370 : 良いと言われる理由は、Core 2と違ってMacro-Op Fusionが64ビットでも使えることだったと思う。
371 : 2のx乗(xはfloat、絶対値が100未満)を、テーブル参照やFPUなしで、SSEで4並列処理できませんか? 精度は6bit程度で十分なんですが
372 : 無理ぽ
373 : http://jrfonseca.blogspot.com/2008/09/fast-sse2-pow-tables-or-polynomials.html
374 : 整数乗なら簡単 指数部に加算するだけですむからな
375 : お前ら文盲か? 可能なら方法を書け。 できないならできないと書く。 わからないなら黙って首吊ってR。
376 : で、それは4並列可能なの?
377 : 整数+小数点以下にわけて 整数部は指数部直接操作 あと小数点以下はpshufbで勝つる
378 : 釣りにすらならねえ。。。
379 : >>373 これ凄いですね VS2005では_mm_castがないようなので、*(__m128i*)&に直してコンパイルを通しました 自前で用意した64kBのテーブルがばっさり不要になりました log10を求める処理もあるので、log2のソースと底の変換を使うことでこのテーブルもなくなりました 書き忘れでSSE2までという条件がありましたが、これも満たしていました 完璧です。ありがとうございました
380 : あれ。Debugだと上手くいきますが、Releaseだと0とか負の無限大になってしまいますね 直接アセンブラに落として使います
381 : 連カキ失礼します Releaseだと、__m128への代入の時点でスタックが何バイトがずれるようです この後でカウンタを1加算する処理がありますが、0に1を足して1になるはずが-2になっていてびっくりしました _m128をグローバル変数に置いたら直ったので、とりあえずこれで誤魔化します
382 : おい!テーブル使わん言ったじゃねえかよ。Rカス。
383 : >>382 >>373 > Polynomial
384 : >>382 は本当にカスだな
385 : >>382 テーブルと多項式の比較だから、下の方を見てみよう。
386 : 頻繁に整数を6で割った余りを使うプログラムなんですが、 除算が1回40クロック以上もかかると聞いて以下のようなロジック組んでみました。 試してみると若干早くなってるような気もしますが、 これは効率的って言えますかね?
387 : unsigned int mod6(unsigned int m){ unsigned int a = 0; static unsigned int x[] = {0,2,4,0,2,4,0,2,4,0,2,4,0,2,4,0,2,4,0,2,4,0,2,4}; __asm{ mov eax, m test eax, 1 jz Mod3 inc a Mod3: shr eax, 1 lea ebx, x mov edx, eax and eax, 0000ffffh shr edx, 16 add eax, edx mov edx, eax and eax, 0000003fh mov ecx, edx and edx, 00000fffh shr ecx, 12 shr edx, 6 add eax, ecx add eax, edx mov edx, eax and eax, 0000000fh shr edx, 4 add eax, edx mov edx, x[eax*4] add a, edx } return a; }
388 : 条件分岐入れるくらいなら素直に割れ。
389 : 考え方としては、偶数ビットシフトしても3で割った余りは変わらない (ただしシフトして消える部分に立ってるビットがない場合のみ)のを利用します。 まず2の剰余を取った後、値を半分にして6の剰余から3の剰余の問題に変えます。 上位16ビットと下位16ビットを加算して17ビットに落とし、 6ビット/6ビット/5ビットに分割して加算して8ビットに落とし、 上位4ビットと下位4ビットに分割して加算して5ビットに落とし、 最後にテーブル参照して、その時点の3の剰余の2倍の値に変換して 最初の2で割った余りを足します。
390 : >>388 条件分岐ダメですか? もう一個レジスタ使って mov edi, eax and edi, 00000001h … add edx, edi mov a, edx ってやり方にもできますが。
391 : x[]を読みに行く方が遅い説
392 : ・6割り算は本当にボトルネックか。 他にどうしようもなく遅い処理があるなら6割り算は無視していいはず。 6割り算だけする関数を作ってそれを呼ぶようにし、インライン展開を抑制してプロファイルを取るくらいはすべき。 ・6割り算の代わりに6掛け算は使えないか。 つまり、データの持ち方を工夫して高速化したい処理全体で6で割った商と余りを利用するようにすれば割り算は無視できるはず。 余りも要らないなら、メモリコストも増えないだろう。 ・値域はどのくらいか。配列参照で代用できないか。 値域が16ビット程度なら高高数十キロのメモリしか使わないで実現できる。巧くキャッシュに乗れば、速いかもしれない。
393 : 実に適切なレスだな、感動した
394 : 結論 人間よりコンパイラの方が賢い
395 : コンパイラを作ってる人たちより賢いユーザは極少数
396 : とも限らない
397 : ゆとりはRDTSCの使い方も知らんのか
398 : ちょっと面倒
399 : 逆数乗算で商を求めて元の値から引いたほうが速い 今のCore MAでは整数乗算は浮動小数除算機と兼用してて 非除数 − (除数×小数点以下切り捨てた商) まあベンチ取ってみればわかるがコンパイラの吐くコードにも勝てんと思う
400 : 整数 ×乗算は ○乗算は 浮動小数除算機と兼用してて
401 : static const int rcp6 = 1.0 / 6.0 * std::pow(2.0,16.0); int x = 255 - ((255 * rcp6) >> 16) * 6; 確かにこれで十分な気がするし、>>387 より速そうだ。
402 : 結果を使う40clk程度過去に除算を投げておくとか:b
403 : 申し訳ないけど俺のレベルが低すぎてまったく理解できん。 >>399 その「小数点以下切り捨てた商」はどうやって出したらいいの? >>401 … 考え方だけでも教えて欲しい。
404 : ここはアホしかいないからビット演算スレで適当に質問した方がいいよ
405 : >>403 x / 6 = x * 1 / 6 これで、除算がなくなる。 ただ、1/6は小数点数になるから、整数演算じゃ表現出来ない。 >>399 は、整数演算も少数演算もコストは同じだから少数でやれと。 >>401 は、一時的に2^16倍してるだけ。 >その「小数点以下切り捨てた商」はどうやって出したらいいの? std::floor(x * 1.0 / 6.0)
406 : 手持ちのコンパイラで int hoge(int a) { return a % 6; } をコンパイルしてasm吐かせてみてよ div使われてないと思うよ
407 : VC9だとこうなった。 // const int x = argc%6; mov ecx, DWORD PTR _argc$[esp-4] mov eax, 715827883 ; 2aaaaaabH imul ecx mov eax, edx shr eax, 31 ; 0000001fH add eax, edx lea eax, DWORD PTR [eax+eax*2] add eax, eax mov edx, ecx sub edx, eax ↓このブロックでargc/6を計算しているようだが、意味不明w mov eax, 715827883 ; 2aaaaaabH imul ecx mov eax, edx shr eax, 31 ; 0000001fH add eax, edx つーか、eax * 3を計算するのに、LEAを使うのか。すげーなオイ。
408 : VC6だと確かにDIV使ってたんですが… 今VS2008インストールしてみたら確かに>>407 みたいな感じでした。 符号なしの場合で、一部整理すると(popとかも省略) __asm{ mov ecx, DWORD PTR [m] mov eax, 0aaaaaaabH mul ecx mov eax, ecx shr edx, 2 lea ecx, [edx+edx*2] add ecx, ecx sub eax, ecx ret 0 } ぐはっ、まったく意味がわかりません!
409 : VC5あたりで整数定数除算は掛け算になってたはず 剰余は確かめたことないな・・・ 意味だけど、64bit固定小数点数で、小数点が32bit位置にあると考えると (0x1_0000_0000 / 6) を掛けることは 6 で割ることになるでしょ んでもって6掛けて元の数から引けば剰余になる leaの計算は3倍してて、その後自身とのaddで2倍、都合6倍 >コンパイラを作ってる人たちより賢いユーザは極少数 ときどきasm吐かせてみたりしないと浦島太郎になるね。
410 : mingw32 gcc 4.4.0 _hoge: pushl %ebp movl %esp, %ebp movl 8(%ebp), %eax movl $6, %edx movl %edx, %ecx cltd idivl %ecx movl %edx, %eax leave ret あれ?
411 : マヌケなコンパイラだと大変ですね(^^)
412 : 64ビット整数の3の剰余を分岐も乗算使わずにハイパー高速に求めるアルゴリズム n ^= n >> 32; n ^= n >> 16; n ^= n >> 8; n ^= n >> 4; n ^= n >> 2; n &= 3; n ^= ((n&1) << 1) | (n >> 1); 後半はLUT使ったほうが速いかもな
413 : んで6の剰余ってこれでいいよな? mod3(n >> 1) * 2 + (n & 1)
414 : >>387 inline unsigned int mod6(unsigned int a){ unsinged int b = (a >> 3) + (a >> 5); // /6 unsinged int c = (b << 1) + (b << 2); // *6 return a - c; }
415 : >>414 mod6 : 65536 % 6 = 4096 C : 65536 % 6 = 4 mod6の/6が0.15625と、精度が悪いせいか?
416 : その通り
417 : でもまあショートカットとしては十分優秀だよ SSEを用いた3の剰余のショートカット方法 movq xmm0, rcx pxor xmm1, xmm1 psadbw xmm0, xmm1 movd ecx, xmm0 これで64ビットが11ビットくらいに縮まる
418 : >>415 //もうすこし高精度版 inline unsigned int mod6(unsigned int a){ unsigned int b = a >> 1; unsigned int c = b + (b >> 2); unsigned int d = c + (c >> 4); unsigned int e = d + (d >> 8); unsigned int a_div6 = e + (e >> 16) - b; unsigned int a_div6_mul6 = (a_div6 << 1)+(a_div6 << 2); return a - a_div6_mul6; }
419 : あんたらよくやるよ templateで、任意除数版を作ってくれたら 俺様のライブラリに加えてやってもよいぞよ
420 : >>419 コードが膨らんでキャッシュの効きが悪くなりそう
421 : >>417 GCC4.4で-O3 -march=core2でコンパイルして なぞの某パイプラインシミュレータ通したらトータルレイテンシ20サイクル, スループット10サイクルって出た 俺の>>412-413 使った方法だとレイテンシ18と6 後半テーブル化すればもう少し減りそう 0, 1, 2, 3になったときに3だけを0に丸めるためだけにあほなビット演算やってるが なんとかならんかな
422 : >>412 は嘘ですたorz シフト+加算ならいけるんだが
423 : 団子かわいいよ団子
424 : signedだが 妙に凝ったことやるよりこれが一番速いだろ inline int mod6(int n) { return n - (_mm_cvttsd_si32(_mm_mul_sd(_mm_set_sd(n), _mm_set_sd(1.0/6))) * 6); }
425 : mm...mmmとか読みにくくてかなわん DirectXみたいなセンスが欲しい
426 : ……?
427 : これがエスパー戦争の始まりである
428 : 結論 inline int mod6(unsigned int n) { return n%6; } でおk
429 : unsignedだとLSB保存して1ビット右シフトすればsignedで扱える あとは>>424 の方法でmod3を求めて2倍してLSB足せばOK 整数ベースでやるにはレイテンシ1の命令だけでなんとか工夫しないと ちなみにpsadbwはレイテンシ3だからイマイチ 解説してなかったけどpsadbwが使える理由は mod3(A * 2^24 + B * 2^16 + C * 2^8 + D) = mod3(A + B + C + D) だから。 A * 256 + B = (A * 255) + A + B
430 : まあしかし、6の剰余程度だといずれの方法も大した意味は無いな http://www.wikihouse.com/x86clocker/index.php?div%CC%BF%CE%E1%A4%CE%A5%EC%A5%A4%A5%C6%A5%F3%A5%B7
431 : CedarMillの88クロックってひどいな。
432 : AMDがいきなりパなしてきたが・・・ ttp://developer.amd.com/CPU/LIBRARIES/LIBM/Pages/default.aspx
433 : この手のはIntelコンパイラに標準で付いてきてるんだがな。まあ有償だが。 どのみちプロプライエタリならGPL/LGPLには組み込めん。
434 : >>432 こういうのはコンパイラがチート使ってくれなきゃ 威力半減な気がするんだが、どうなのかね?
435 : それをするのがコンパイラの仕事だろ
436 : AMDは自社コンパイラを持ってないからな(あのお粗末なAMD Stream SDK以外)
437 : スカラなんかどうでもいいよ。 SIMDをどうにかしろバカIntel。
438 : SIMDでどうにかしろ
439 : SIMDとか用語が嫌になる しむど! かっこわるー
440 : ネイティブはシムディーって言ってるぞ
441 : MMX むむっくす! かっこわるー ネイティブでは?
442 : えめめくす
443 : かっこわるー
444 : はいはい無限再帰無限再帰 66 e8 fc ff
445 : かっこいいと思った用語 XMS EMS VMS なんと!最後にMSが付く・・・・
446 : あっちがっ・モビルスーツ!だからね! まい・・・・じゃないんだからね! 誤解しないでよね! ↓Rよガンオタしないでよね!!
447 : >>445 腹筋運動マシン?
448 : XMS EMS VMS IMS OMS UMS SMS
449 : Large Middle Small
450 : Long, Middle, Short corn.
451 : CMS忘れるなよ Chinko Manko, Sexだけどな
452 : 久しぶりにスレをのぞいてみたら、昔の自分のスレを発見。 そういや、こんなことしてたな。 団子さん、その節はお世話になりました。 あれからマシンもcore i7に代えたのでせっかくだからSSE4.2をためしてみた。 当たり前だけどやっぱり専用命令は速いね。 ところで_mm_popcnt_u32は使えたのに_mm_popcnt_u64はnot declared in this scopeって言われちゃった。 OSとかgccが32bitなのがいけないのかしら?
453 : 64bit専用です
454 : func = reference :clock = 14540000 func = bit32 :clock = 1710000 func = bit64 :clock = 4620000 func = sse :clock = 680000 func = dango-sse :clock = 430000 func = sse42:clock = 270000 文字数制限うぜぇ。削るのに手間取っちまった。しかも微妙にずれてるし。
455 : >>453 どもです。 世間がwindows 7 で64bitへ本格的に移行してくれることを期待してまつ。
456 : C/C++でメモリプール(int, doubleなど様々な型が共存)を作り、 メモリプール内部でメモリの詰め直しを行って最適化しようと試みています。 入門書+α(boostがわかるぐらい)なので、 キャッシュやメモリに関する特殊なことは全然わかりません。 何か気をつけなければならないことや忠告があれば教えてください。
457 : >>456 メモリのことを知らずにどうやって最適化する気なのかね?
458 : 高速化が必要というわけではなくて、ガベージコレクションの宣伝文を見て 興味本位に詰め直しをやってみようと思いました。 空き領域を整えるだけでなく、アドレス配置を上手くソートすれば キャッシュヒット率の向上ができると思いますが、それは難しいので 今回はプール内の空き領域を整えることだけに目的を留めて置きます。 プールはchar型の配列で確保し、memmove()でclassやプリミティブを 移動させる予定です。何か規則に反することなどがあれば教えてください。
459 : そんな無駄な事をする意味がわからない
460 : メモリコンパクションを実装するということは、 生ポインタから、ハンドル経由のアクセスに切り替えることになると思うけど
461 : >>460 自作のスマートポインタを利用してアクセスを管理する予定になっています。 スマートポインタとコンパクションが同一のスレッドになければ危険ですが。
462 : やってみりゃいいんじゃないの
463 : 下手の考え休むに似たり。
464 : バウンダリに気を付けろよ
465 : アライメント(構造体のサイズをバイトorワード境界に調整)はsizeof(...)使えば済むと思う。 でも開始アドレスもバイトorワード境界に調整する(これがバウンダリ?)のは知らなかった。
466 : いや、アライメントを制御することをバウンダリと呼ぶという記事を見つけた。 だとすれば開始アドレスは特に気をつけることはないはず……。
467 : 他人に伝わらず、自分もよくわからない言葉を使うのは、とりあえずやめよう
468 : 何のためにアドレス調整するのか分かってんのか?
469 : >>467 失礼しました。どうやら混乱してしまったようです。 とりあえず今日把握できた点について整理するために簡潔に書いてみます。 1.はじめに 32bitOSでは、4byte境界というものがある。 クラス・構造体であろうと、int,char,doubleなどのプリミティブ型であろうと、 インスタンスのサイズと開始アドレスは、4byte境界のルールに従うことになっている。。 2.サイズ 構造体やクラスは、4byte単位の大きさに整えられる場合がある。 以下のhogeクラスは5byteだが、4byte単位の大きさに整えられて8byteになる。 従って、sizeof(hoge)の返り値は8byteである。 ただしhelloクラスは4byte単位にされることはなく、 そのまま5byteなので注意が必要である。 class hoge { int i; char c; }; class hello { char c[5]; };
470 : 続き 3.開始アドレス インスタンスが4byte境界を踏み越えないように、注意しなければならない。 具体的には、以下のように分類してインスタンスを配置すれば良い。 (※以下は正しいのか非常に不安) ・4byte以上の大きさを持つインスタンスの場合 開始アドレスが、4の倍数となる番号になるように配置する。 ・3byteの大きさを持つインスタンスの場合 開始アドレスが、4byteで割り切れる番号になるように配置する。 ・2byteの大きさを持つインスタンスの場合 開始アドレスが、2の倍数となる番号になるように配置する。 ・1byteの大きさを持つインスタンスの場合 どこでもよい 参考URL http://park21.wakwak.com/~yuiti/program/c/08_boundary_c.htm
471 : OSつーか、ハードの制約では
472 : double(IEEE754)を4バイト境界なんかに配置しねーよ。 4byteだと、キャッシュラインをまたぐ位置に置かれる可能性が出てくるからな。 だから32bitOSだから4byteなんて話にはならない。
473 : >>471 >>472 ありがとう。わかった気がする。 アドレスの配置の仕方を訂正〜。 ・8byte以上の大きさを持つインスタンスの場合 開始アドレスが、8の倍数となる番号になるように配置する。 (double=8バイトプリミティブを含む可能性があるため) ・4〜7byteの大きさを持つインスタンスの場合 開始アドレスが、4の倍数となる番号になるように配置する。 (int,float,longなど4バイトプリミティブを含む可能性があるため) ・3byteの大きさを持つインスタンスの場合 開始アドレスが、4の倍数となる番号になるように配置する。 (4バイト境界を越えないため) ・2byteの大きさを持つインスタンスの場合 開始アドレスが、2の倍数となる番号になるように配置する。 ・1byteの大きさを持つインスタンスの場合 どこでもよい (x86CPU環境限定)
474 : そろそろ愚行に気付けばいいのに・・・
475 : 「32bitOSの境界は8byte」と認識するだけで十分ですね。
476 : 真性のアフォだ
477 : javaもコンパクション捨てたよな D言語は知らんが
478 : >参考URL >http://park21.wakwak.com/~yuiti/program/c/08_boundary_c.htm 見てみたが、酷い内容だなw
479 : 情報系の学校でも最近はいきなりJavaとかから入る所もあるらしいしなぁ。
480 : >>475 OSは全く関係ない。 関係あるのはCPUがメモリにアクセスする粒度。 同じハードウェアなら、16bitOSだろうか32bitOSだろうが64bitOSだろうが一緒。
481 : OS が関係あるとしたらミスアラインメント例外を捕捉して(処理速度以外は) 何も無かったかのように振舞う実装をしていた場合だな。 マニュアルとかには良く書いてあるけど、実際に実装されてる OS ってあるのかね? 境界跨ぎじゃなかったかもしれんけど、IRIX では何かやってたようななかったような。
482 : >>479 むしろ聞きかじり未満量産所
483 : >>481 Linux/ARM(規定で有効) Windows/IA-64(規定で無効)
484 : Linux/ARMは規定有効じゃなかったわ 規定例外だけ無視だわ
485 : >>480 それ嘘だから
486 : 456のベンチまだー?
487 : 配列の合計値を求めたいのですが、コンパイラがSSEを使いやすいようなコードはどのように書けばよいのでしょうか?
488 : for (i = 0; i < N; i+=4) { sum1 += A[i]; sum2 += A[i+1]; sum3 += A[i+2]; sum4 += A[i+3]; } sum = sum1 + sum2 + sum3 + sum4; っていうか組み込み関数使えよ
489 : ありがとう。 SSEに最適化された組み込み関数なんてあるんですか?
490 : _mm_add_ps _mm_add_pd
491 : >>487 インテルコンパイラを使って、普通に書けばなんとかしてくれる。 # つーか、そのアセンブリ出力を読むのが先ず一歩目だと思う。
492 : xmmintrin.h
493 : そこを高速化して意味があるのかどうか検証するのが先だな。
494 : モノによっては、配列に入れる際に和を求めるっていう手もあるワケで。
495 : まぁまずはどこがクリティカルなのかを割り出すのが一番大事だよな。
496 : >>490 って>>488 の処理の代替になる?
497 : >>488 これってNがわかっていないと、だめだよね? ICCだと出来るのかな? GCCでは無理だった。
498 : >>488 これってNがわかっていないとコンパイラはやってくれないよね? ICCだと出来るのかな? GCCではベクトル化してくれなかった。
499 : >>497 >>498 連投すまそ。書き込みが出来なかったと思った。 スレ汚し申し訳ない。
500 : >>498 Nが既知でなくてもベクタ化するよ。例えば4で割った余りの分は、ベクタ化しない処理になるだけ。 擬似的には>488にこれが追加されるだけ。 for (; i < N; ++i) { sum += A[i]; }
501 : >>500 そうなんだ。 以前やってみたときはaddssしか出さなくて、 addpsは使ってくれなかった。 ループが深すぎたからかなあ。
502 : Visual C++は何やってもベクトル化しないぞ
503 : >>502 GCCでもやってみたが、 #define N 4 __m128 vA[N],vB[N],vC[N]; float *A,*B,*C; A = (float *)&vA; B = (float *)&vB; C = (float *)&vC; for(i = 0; i < N*4; i+=4) { A[i+0] = B[i+0] + C[i+0]; A[i+1] = B[i+1] + C[i+1]; A[i+2] = B[i+2] + C[i+2]; A[i+3] = B[i+3] + C[i+3]; } は出来なくて、 for(i = 0; i < N; i++) { vA[i] = vB[i] + vC[i]; } これはやってくれたよ。 ICCならやってくれるのか?
504 : for (i = 0; i < N; i+=4) { sum1 += A[i]; sum2 += A[i+1]; sum3 += A[i+2]; sum4 += A[i+3]; } sum = sum1 + sum2 + sum3 + sum4; ちなみに>>488 は手動でSIMD組み込み関数に置き換えやすい形に展開しただけ コンパイラの自動最適化使うならここまでやる必要ない
505 : ↑前文引用してどうする俺
506 : hello
507 : Meow
508 : 高速道路無料化に関係ありそうだな( ・ω・)y─┛〜〜
509 : (__m128)num.m128_f32[0]=0;みたいな操作すると error: request for member 'm128_f32' in 'num', which is of non-class type 'float __vector__'って 怒られるんだが原因わかる?そんなクラスタイプねーよと怒られてる気がするのでインクルード足りない気がするんだが。。。 環境はXcode 3.2にGCC 4.2です。
510 : (__m128)num->m128_f32[0]=0; とかやらにゃならんとかいうオチではなかろうな?
511 : >>510 レスthx。試してみたがやっぱダメ。 根本的に__ml128構造体のメンバとしてm128_f32が無いんじゃないかとおもてきた。。。
512 : >>511 そうかもしれない。 自分とこのMinGW TDM gcc 4.4.1のxmmintrin.hを見たら次のように定義されていた。 typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__));
513 : HTTPヘッダを高速に 解析する方法を教えてください
514 : ggrks
515 : http://pc12.2ch.net/test/read.cgi/tech/1264774545/904 なんかわからんけどこんな結論がでているっぽいんで助けてください
516 : >>515 該当スレは落ちている希ガス。
517 : 保守
518 : for(i=0;i<16;i++) a[i]^=(d[i]+c[i])%16; このプログラムをSSE2で書きたいのですがわかりません。 教えてください。よろしくお願いします。 C言語からインラインアセンブラで呼び出したいと思うのですが、 うまくいきません。 moveq d,%xmm0 moveq c,%xmm1 paddb %xmm1,%xmm0 moveq a,%xmm1 pxor %xmm1,%xmm0 配列のデータをレジスタにセットするところもわかりません。
519 : ハッシュ計算で見たような式だな MASMなら答えれたが残念だ
520 : 95 :デフォルトの名無しさん:2010/09/19(日) 13:38:02 for(i=0;i<16;i++) a[i]^=(d[i]+c[i])%16; このプログラムをSSE2で書きたいのですがわかりません。 教えてください。よろしくお願いします。
521 : マルチポストか
522 : sse 4.2で大々的に文字列検索の命令追加されてたけど あれ大文字小文字の変換とかサポートしてくれんの?
523 : 無理じゃね? 単純一致だけだろ
524 : >>522-523 Equal Anyモードでいけるでしょ。 http://journal.mycom.co.jp/photo/articles/2008/04/10/idf09/images/Photo46l.jpg たとえば"hoge"を大文字小文字区別なしで検索するには、 まず [Hh] [Oo] [Gg] [Ee]の4つのベクトルに分け、ソース2として用いる。 ソース1には検索対象の文字列をロードし、まず[Hh]とのマッチ位置を検索する。 更にpalignrで1文字ずらして[Oo]とのマッチ判定、次は[Gg]とのマッチ判定。 以降、ecxのビットパターンのマスクをとっていって0になる、あるいは[Ee]に達するまで繰り返し。 マッチに失敗すれば次の16バイトをソース1に読み直してまた同じことをやる。 これ文字クラスとか簡単に表現できるよね。 正規表現のJITコンパイラとか作ったら爆速になりそうだから誰か試してみない? もっとも、SSDでも積まないと大した効果なさそうだけど。
525 : SSEに関する参考書とかってあるんですか?
526 : >>525 団子と寝るか5万払って買ってる
527 : 『MMXテクノロジ最適化テクニック』で基本的なことを覚えて SSE以降はIntelのマニュアルで独学した
528 : ナカーマ
529 : 俺はノンケじゃwwww
530 : 女子中学生かもしれんやん。
531 : みんなプロファイラは何使ってるの? VTune と AQTime の評価版を落としてきて試したんだけど、結果が結構違う。 手法とかが違うのかな。 AQTime は計測対象のプログラムの動作が遅くなるから侵入型なんだろうか。 これは Windows での話ね。
532 : AMDのプロファイラが世界で一番正確 研究者はAMDのプロファイラしか使わない 正真正銘プロのツールだよね
533 : >>532 ヤな言い方だな。何か AMD に恨みでもあるの?
534 : タダのネタでしょ 反応するほうが信者臭がしてキモイ
535 : 自演乙
536 : for(int i=0; i<N; i++){ sum += a[i]; } これってベクトル化効きませんかねぇ・・・
537 : それも分からんようなら諦めな
538 : というか*aとsumが浮動小数点数ならgccでもiccでも自動ベクトル化してくれるが。 問題は、メモリがボトルネックだからそんなの意味ないという事だ。
539 : x86は浮動小数点が弱くて仕方がないからなあ 8087のコプロセッサの頃からの負の遺産を引きずっている でもL1/大容量L2キャッシュを媒介にする事によって相当克服して来てはいるんだけどな PowerPCなどにどうしても勝てない
540 : 釣れますか?
541 : お前が釣れた
542 : >>539 インテルは不動整数点が抜群に早い
543 : 糞環境でちまちま最適化した後に インテルチップでてきとーにビルドしたプログラム走らせると絶望できる
544 : >>539 前世紀からタイムスリップしてきた人乙 理論値こんなもん Core i7 2600(3.4GHz) 54.4GFLOPS/27.2GFLOPS(DP) POWER7(4.1GHz) 32.3GFLOPS(SP/DP)
545 : >>542 整数に点はない。 よって、浮動も固定も不動もない。
546 : 不動少数点演算を整数演算でってなかったっけ?
547 : 「不動少数」なんて言葉はない。 そもそも、「動かない、少ない数」とは何なのだ。 こじつければ「不動小数点数」ならあるかもしれないが、 これは「固定小数点数」と同義と解釈すべきだろう。
548 : >>544 これって1コアあたりの性能?
549 : http://www.geocities.jp/jagam00z/index.html これつかえば楽に慣れるさ
550 : http://www.geocities.jp/jagam00z/index.html ffftpのID jaga00z パスワード **********
551 : へっへーくやしかったらハッキングしてみろーいバカども!!ww http://www.geocities.jp/jagam00z/index.html
552 : http://www.geocities.jp/jagam00z/index.html おっとヒントはここまでだ。まあきさまらなんざにサイトハックなんざ1000年はやいだろうがなあwwwぶけけけけ
553 : >>548 そうだね
554 : 10年かかってやっとCellに追いつけたのか。
555 : sse
556 : いや俺も「不動点演算子」に、はぁ?と思ったよ。
557 : 山の浮動が居るスレはここですか?
558 : いや不動点演算子は別に良いだろ スレチだけどさ
559 : >>554 またタイムスリップしてきたあたまのおかしい人か。 2001年にCellがあったんですか?パネエwww てかCellのスカラ整数演算性能はクロック半分のAtomにも負けてるよ
560 : 俺もCellは肝心なところで使えないと思っていたクチだが、 これ系のスレで毎回スカラを持ち出すお前の頭が分からない。 スレタイ読め。
561 : スレタイ読んだかスカラ演算がなぜ駄目なのかお前の頭が理解できない。 CellのSPEはC++ライブラリほとんど使えないしましてSSEなんて対応してないぞ。 スカラ整数演算が強い=(SIMDのデータ読み書きを含めた)メモリアドレッシングに強い
562 : SPUはCのライブラリを使えるし(標準?んなもんは知らない。)C++コンパイラもある。 SIMD演算に特化したSPUは比較対象としては適切と言えなくもない。 だが、Atomのスカラ整数演算能力なんざ完全に場違いもいいとこ。 団子さ、年取って耄碌してきたんじゃない?
563 : 良い訳に必死だこと ここのテーマは「高速化」であって並列化ではない。 スカラ演算の重要性を理解できないお前の存在自体が場違い。
564 : 具体的にはCellの整数加減論理演算のレイテンシは2〜6サイクル程度で クロック半分のAtomはdual issueで1〜3サイクル程度だから実質同程度なんだよ。 CISCのコード密度の優位性と16バイトアライン縛りの問題の分だけAtomのほうがむしろ有利なんだよ。 いくらあがいても速度勝負ではクロック半分のAtomに勝てない。 モバイルデバイスの市場は拡大してるし、Atom向けの最適化技術の重要性は増すと思ってるけど Cell(SPU ISA)はIBMも東芝も後継プロセッサの開発を事実上放棄してるし 誰もここでCellの話題なんて出さないだろ?
565 : 必死なのはどうみても連投までして言い訳を続けてる団子だろ。 みっともないから少し黙ってろよ。
566 : まあ、日々進歩しているプロセッサと設計がおそらく6,7年前で止まっているプロセッサを比較してもなんだかなあ。 Pentium4とCellはどっちが速い?と言われれば浮動小数演算であれば後者だからな。 Cellがインテル並に進化していたら、整数演算も改善されていたんでは?と思えなくもない。 それはそれで面白いんだろうが。
567 : うん、まあ取り敢えずお前らまとめてゲハ板にでも行け
568 : http://gmplib.org/~tege/x86-timing.pdf これのIntel NHMってやっぱネハレムの事?
569 : 16バイトにアラインメントされた構造体の配列を部分的にコピーしたいんですが、hogeが64bit型だとして _mm_stream_si128(&dest->hoge[0], _mm_stream_load_si128(&src-hoge[0])); _mm_stream_si128(&dest->hoge[2], _mm_stream_load_si128(&src-hoge[2])); _mm_stream_si128(&dest->hoge[4], _mm_stream_load_si128(&src-hoge[4])); … のようにすれば速いかと思ったのですがそれほどでもありませんでした 良いアイデアありませんか?
570 : データ設計をやりなおして、部分的にコピーする必要がないように並べる事をオススメする。
571 : 行列の演算ですが、高速化する方法はありますか? for(j=0;j<16;j++){ o=FG[a[j]]^FG[u1.m[j]]; p=FG[b[j]]^FG[u.m[j]]; for(i=0;i<16;i++){ d1[j]^=t[o][h1[p][i]]; d2[j]^=t[o][h2[p][i]]; } buf[j]=d1[j]; buf[j+16]=d2[j]; }
572 : >>571 それぞれの配列の構成が判らんとなんとも。 h1みたいな二次元配列っぽいのが配列の配列なのか、ポインタ配列なのか、演算子オーバーロードなのか全く判らん。 兎に角、動く形で提示してくれ。
573 : この手のものは式テンプレートというものを使うと早いんだそうだが あまりに複雑でいまだに自分のものにできん^^
574 : unsigned char FG[256],d1[16],d2[16],a[16],b[16],t[256][256],h1[256][16],h2[256][16],buf[32]l\; これで解りますか? コードパッドだとエラーが出て動きませんでした・
575 : http://codepad.org/Dc6LY5cV
576 : マルチしすぎ C/C++の宿題片付けます 146代目 http://hibari.2ch.net/test/read.cgi/tech/1296387672/571 質問にやさしく親切に答えてくれるスレ 4 http://hibari.2ch.net/test/read.cgi/tech/1222224721/789 【C++】高速化手法【SSE】 http://hibari.2ch.net/test/read.cgi/tech/1130349336/575
577 : まぁ高速化の基本だからな。 【マルチコア】並列化について語る【使いこなせ】 http://hibari.2ch.net/test/read.cgi/tech/1137540671/971-972
578 : movdqu命令はレイテンシ6のスループット1だとあります。 movdquを使った1クロック後に、それと依存関係の無い別の命令を実行でき、 movdquと依存関係のある命令は6クロック後まで待つ必要があるってのは分かるんですが movdquのロード命令と依存関係の無い、別のロード命令を使いたい場合は何クロック待ちになるんですか?
579 : メモリに依る、という回答では駄目だろうか。
580 : 素人から見ると団子のレスは読んでて面白いけどな。 批判するほうもちゃんとデータとか出してくれるとより面白いんだけど、俺を楽しませるスレじゃないしな。。。 Cellくそはええ!みたいなのは結局そうでもなかったってことなのかな。 BOINCあたりで活躍してたけど、結局i7とかのがはやいの
581 : >>578 > movdqu命令はレイテンシ6のスループット1だとあります。 それってネトバのmovdqu xmm,xmm命令の事? もしそうなら、それはxmmレジスタ間コピーのレイテンシ・スループット であって、ロード命令のレイテンシ・スループットではない。
582 : 理解しました 測ってみることにします。
583 : SIMDとは関係ないけど他に見当たらないんで、ここで聞くことにしたけど、 誘導してくれれば幸い。 ビット・オンの最上位のみ残したい場合、 ビットスキャンリバースを使わずに、いい方法ないかな。 ビット・オンの最下位のみ残す場合は、例えば対象の値を80としたとき、 mov eax,80 mov ebx,eax neg eax and eax,ebx こんな感じよね。 これを最上位ビットでやりたいんだが、何かいい方法ないかな。 最下位フラグを消していく方法を繰り返すくらいなら、素直にビットスキャンしちまうんだが。 なければ、ない、と言ってくれ。
584 : 【関数化】ビット演算 0x03 http://hibari.2ch.net/test/read.cgi/tech/1226143920/
585 : >>584 サンクス。感謝。 行ってきます。
586 : 撃墜100超えたんでやめよっと
587 : すれ違い誘導職人の晩年である
588 : ,.ィ'" ` 、 / ,.--、 :.:.\ r、 |:.:.:.:.〈;;;;;;;ノ :.:.:.:.ヽ _/△ハ,,__ / ハ !:.:.:.:.:.:.::.:.:.:.:.:.:... :.:.:.:.ヘ /: : : : : :/ ||:.:i/'ーリ―- 、_:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:. :.:.:.:.:.:.ハ //: : /: :.:.ト=': : : : :/: : : : : : :. ̄`''ー- 、:.:.:.:.:.:.:.:.:... . .:.:.:.:.:.:! / /: : /:.:.:.:.:/: :./: : : /: : : :./: : :/:/: /!: :.i::::``.、:.:.:.:.:.:.:.:.:.:.:.:.:.:! . /: :./:.:.:.:.:.:! : /: : : / : : : /: : :/:/!:./ |:.:.l|: : :.:.::::\:.:.:.:.:.:.:.:.:.:.| /Vlハ|/!/!|: : !: : : :! : : :.,'!: :.:/:/ |,' |: :|!: :! : i:.:.::::ヽ.:.:.:.:.:.:.:.:l ,イ /|: :.|: : : :|: : : :.!|: :/:/ |! .|:.リ|: :|:.:.:|: : : : :ハ:.:.:.:.:.:.! . / / ! ,r|: : : :|: :.'"丁/ ̄` |! !,'十ァ!、:.|: : : :.|: !:`! _,/ |:.! |: : : :| ,rfj ̄ヾ、 ! / |ム」_:リ!: : :.,':.:|:::「 | ト.|: : : :K {| ::::::リ l / ,イ}:::::::ハ,!: :.:/:.:.,'::::| V:.ハ: : :.| ゛ー '' K.__,/ }:.:.:/:.::/::::リ V: |: : :ト . xxxx ,. `"''" //}:::/: :.,' ただちに逃げてください... V:ハ : |:::\ __ "'''''' /イ:::::/: :./ リハハヽ-t`/ \ _,. イ//l/!/|/! ,..、 / /~\ ヽ‐、 / / / リ /: : :\ _ __,.ィ| イ ,.へ `< ヽr‐ァ―=‐、 くr! : : : : : }フ´ \ ̄ハ:.:.:.:ハ イ ,、〆``ー /:.:/::/ ハ . |ト、: : : : :/ ヘ::|: !.:.:.:ハ ∨ ̄ / .:/::/ / i! ただちににげろのガイドライン http://www.geocities.jp/ust7800870/index.html
589 : 沖縄は良いところです。
590 : ただし原住民にとってのみだが。
591 : 暑い所は嫌だなあ。PCが熱暴走しやすくなるし。
592 : >>591 昨日は暑かったけど、ビデオカードが膨張したのか接触不良を起こして 画面がいろとりどりの模様になって停まっていました。 夏場はエアコンがないと人もPCも死にそうになりますね。
593 : アライメントを逐一管理するのがめんどいんですけど、 コンパイラーなりリンカーオプションで、スタックからヒープまで 一括して指定することはできんとですか。 環境:GCC と CL。
594 : マクロ書いて、めんどくさくならない程度に短くして対処するんじゃだめじゃろか。
595 : 質問です。 画像処理で画素同士の加算や減算をSSEで高速化したいのですが, 速くなりません。 処理は, int型で, for(i = 0; i < width*height; i++) dst[i] = src1[i] + src2[i]; といった簡単なものです。 これに対して, ポインタを__m128iに変え, ループ回数を4分の1にし, 加算を_mm_add_epi32に変更しました。 しかし, 速度はint型とほとんど変化はありません。 平均化フィルタをSSEで実装したところ, 2倍近く高速化できたので, こちらもうまくいくと思ったのですが・・・。 もしどなたか原因がわかる方がいましたら, ご教授お願いします。
596 : 結論から言うとメモリの転送がボトルネックです。 書き出しのアライメントを揃える事とstreamを使う事で何割かは改善出来ますが、基本的に速く出来ません。 最適化とは遅い部分を探し出す事に他なりません。 安直にSSEとかマルチプロセッサにしようと思わず、真にボトルネックを見つけられるようになりましょう。 真に遅い部分が分かったなら、平均化フィルタと何が違うのか、どうしてもう速く出来ないのかが理解出来るようになります。
597 : つまり, メモリがボトルネックになっている以上, いくら演算速度をあげても効果は薄いということですね。 高速化に対するアプローチも教えていただき, 大変勉強になりました。 速度に影響する要因をまだ一部しかわかっていない私には難しいかもしれませんが、これから知識を得ていきたいと思います。 御回答ありがとうございました。
598 : >>596 メモリの転送がボトルネックなのか、演算部分がボトルネックなのかは どうやって判断すればいいのですか?つまりどこを見たらよいのか。 あるいはあなたはどうやってますか? ツールとか使うのでしょうか?
599 : メモリに対する操作や演算の大半は、ツールを使って調べるまでもなく、単純で十分に短い。 なので、ソースコードを眺めれば、そこがSIMDを使う事で高速化すべきか否かは、すぐに見分けが付く。 演算そのものが単純で短い場合は、複数種の演算を1命令にまとめることが出来るかどうかで判断していい。
600 : >>598 理論値と実際の処理時間の差で見積もる。 また、CPU メーカのプロファイラを使えば、命令のリタイア数とか、キャッシュミスなどのイベントの数を計測できる。
601 : Cのソース眺めるだけじゃわからんだろうに、汗で判断できるぐらいにならんと
602 : 最適化もしない状態のことだったりして
603 : CPUのつもりになってメモリアクセスパターンを想像したら見えてくるかもしれんね
604 : >>600 理論値ってアセンブラニーモニックを命令毎にスループットやレイテンシの累計計算して 全体で何クロックかかるかを算出した値という意味ですか? それで実際にどれだけクロックかかるかとの比較をする、と。
605 : メモリ参照をいかに少なくするかでしょ、今時の高速化は
606 : >>598 すまんレス遅れた。 メモリのアクセス回数と演算回数は見積もれるな? c[i] += d[i] * e だったらeはレジスタに乗っているものとして無視して、 読み込み2回(c, d)、書き込み1回(d)、加算1回(+=)、積算1回だ。 回数を見積もったら、加減積算はそのまま、メモリアクセスと除算とsqrtは10倍、その他sin/pow/log/expとかは100倍するんだ。 比率はいい加減なので、数倍しか違わないなら全体的に最適化。 その中で、演算が効いてそうならSIMD化だ。 あとは、何よりも実測が重要。
607 : >>606 ありがとうございます ソースの式から各演算毎にウエイトを用いてかかるコストを見積もるって意味だったんですね。 それでメモリアクセスより演算のコストの方が高そうであればSIMD化すると。 例の c[i]+=d[i]*eの場合 メモリアクセスコスト 3*10=30 演算コスト 1+(1*10)=11 なのでメモリアクセスのほうがコストが高いから、SIMD化しても早くならないだろうと考えるわけですね。 >書き込み1回(d) 揚げ足とるつもりではないのですが これは(c)への書き込みの間違いですよね?
608 : SSEで例えると、メモリの読み書きはSSEでやったほうが断然高速だから そんなコストとか馬鹿な計算する以前に速くなることは確定している。
609 : そんな前時代的などんぶり計算しても意味ないよ プロファイラにかけな
610 : キャッシュが考慮されてないよね
611 : > 間違いですよね? その通り。 >>608 総和とか本当にメモリがボトルネックだとスカラでやっても大して変わらない。 >>609 そう、机上は本当に大ざっぱな見積もりだけで基本的には実測が重要。 でもVTuneなんかは他にも項目が多過ぎて目星付けるのも勘がいるんだよ。
612 : SSE使わんと絶対にプリフェッチされない、とかだったら正しかった。
613 : >>610 畳み込みとの違いのヒントを示し忘れてた。 同じアドレスを複数回読むなら、最初の1回を見積もりに入れておけばいい。 勿論キャッシュに入らないサイズだと全てカウントする必要がある。
614 : メモリ周りがボトルネックなら、prefetch*とmovnt*。 とりあえず、CPUによっては32[bit]のmovntiは遅いから使わない方向で。 実行環境が単一でない場合、大雑把な見積もりで十分だと思ってみる。
615 : VCの__declspec(align(16))や#pragma pack(push, 16)って 一時オブジェクトには効かないんでしょーか? std::map、std::pair周りをソースひっぱってきて、__m128を含んだクラスを 受け取れるようにしたんですが、 aligned_stl::pair<int, hoge> pairArg = aligned_stl::make_pair(1, Hoge); mapFuga.insert(pairArg); とやるといけるけど mapFuga.insert(aligned_stl::make_pair(1, Hoge)); とすると、一時オブジェクトがアラインされてなくてこけます・・・・ 何か抜け道ないですかね(´・ω:;.:...
616 : 間違えたorz ”make_pairの返す一時オブジェクトが”アウトですた。 make_pair(1, Hoge); ←×(落ちる。) aligned_stl::pairArg(1, Hoge); ←○(落ちない。) なのでコンストラクタで直接渡せばいけるけども。 Hogeにもpairにもアライン指定つけてるんだけどなぁ・・・
617 : また間違えた・・・・連投すみませんorz 誤:aligned_stl::pairArg(1, Hoge); ←○(落ちない。) 正:aligned_stl::pair<int, hoge>(1, Hoge); ←○(落ちない。)
618 : mapの方がアライメントされてないんじゃない?
619 : std::pair<int, hoge>からaligned_stl::pair<int, hoge>へのコードがバグってるんじゃないの
620 : 適当な事書いたと思ったけど、std::mapにカスタムアロケータでいけるっぽい ttp://ideone.com/sOWl6
621 : >>618 mapの方は、__declspec(align(16))みたいなことはしてませんが カスタムアロケータを渡しており、カスタムのpair(aligned_stl::pair)を使うように指定してます。 >>619 わかりづらくてすみませんorz std::pairは一切使っておらず、aligned_stl::pairのみです。 make_pairもaligned_stl::pairを返します。 >>620 ありがとうございます、Win7 64bitのVC2008Expressで動かしてみましたが カスタムアロケータのc.insertで、Hoge()の引数なしのコンストラクタで落ちます(x_ = static_x) Hoge hoge; c.insert( ::std::make_pair<int,Hoge>(i, hoge) ); とやると、make_pairのところのコピーコンストラクタで落ちます( x_ = src.x_)。 なので、前回書いたのと同様に Hoge hoge; std::pair<int, Hoge> pairArg(i, hoge); とやってからpairArgを渡すと落ちませんでした(c.insertのみ。d.insertは落ちる)。 どうもpairに関してはアラインメント指定しなくても、中のメンバが アラインメント指定されていれば問題ないようですね(アロケータだけでよい?)。 もうちょっと試してまた報告します。 ただ、2008だとアラインメント指定が一時オブジェクトに対して効かないと考えたほうが いいのかもしれませんね(´・ω:;.:... (インライン展開された場合は除く) ありがとうございました。
622 : あと、x64をターゲットにすれば落ちませんでした(デフォルトのアラインメントが16バイトだから?) ついでに質問なのですが、>>620 のchar unused1__とunused2__はどういう意味でしょうか?
623 : それって構造体のメンバのアライメント指定であって、アドレスのアライメント指定する機能って基本的になくね。 x64だと関数の始まりのスタックは16バイトアライメントになるようになってるから、問題発生しにくいとか。 というか、落ちる落ちない以前にデバッガで逆アセ見れば、どういうコードが生成されているかすぐわかると思うんだが。
624 : >構造体のメンバのアライメント指定であって あああ、なるほど・・・x64なら安全、と考えるのは危険ですね。 >逆アセ見れば 見てます、きっちりmovaps使ってますw で、ウォッチ窓で見ると一時オブジェクト側のアドレス下位1バイトが0でないので 明らかにアラインされてないのが問題です。 __m128を使うだけなら、構造体の代入演算子やコピーコンストラクタで _mm_loadu_psとか使えばいいんでしょうけど。 誤解されるような書き方だったかもしれません、決して手詰まりというわけではないです。 どうにかしてアラインメント保ったままmapに突っ込めないかなー、というだけでした。
625 : ダメ、だったか・・・ (Initial D 星野好造風に) 2010だからこっちでは本来の動作確認はできないけど、コレならどうだろう ttp://ideone.com/h4QFh
626 : >星野好造風に 渋すぎるwww ありがとうございます、試して無事動きました(#if 1でも0でも) 予測しておられた?通り、char unused1__が含まれていようと問題ないんですね。 構造体の型自体は(__m128のような16byte境界を要求するものが含まれていれば) 先頭アドレスが16byte境界でさえあればいいような配置になっているけど、 2008は関数の返す一時オブジェクトのアドレス調整が抜けている、ということかな・・・ 大変参考になりました、ありがとうございました。
627 : int i = 10; int * p = &i;//int型ポインタpにiのアドレスを代入する 簡単。 char str1[] = "abcde"; char * str2 = "abcde"; 上と下は同じでどっちを使ってもいい。
628 : sizeof(str1) != sizeof(str2)
629 : str1++;
630 : sizeof とか return とかにかならずカッコをつける人がいるけど何で?
631 : sizeofとdefinedは関数として意味が通ってるから括弧付けちゃうな。 (a || b) && (c || d) も括弧いらないけど、あった方が読みやすいのと似てる。 returnに括弧付ける人の気持ちは聞いた事が無いから分からない。
632 : 間違えた(a && b) || (c && d)だ。
633 : >>630 sizeofの中身によって括弧つけたりはずしたりしてるのかい? おれはそんなとこ気を使っても意味ないと思うので常につけてる。 sizeofの括弧省略してるコードってほとんど見たこと無いしな。
634 : >>630 struct s{int i;}; sizeof struct s; :b
635 : 20年以上C書いてるけど、sizeof のカッコが省略可能なんて知らなかった…実際そんな記述を見たことがなかった。 return にはカッコつけない。
636 : return (0); とかは見たことあるけど、sizeof int は見たことないからなぁ。
637 : それは違反です
638 : 余分なカッコが多すぎるコードってみにくくて嫌いだ。 if (a == 0 && b == 0 || c == 0 && d == 0) if ((((a == 0) && (b == 0)) || ((c == 0) && (d == 0)))) この二つだと上の方がはるかに見やすいと個人的には思うが、 見やすさを優先してカッコをつけるとか言って下のように書く人がいる。
639 : LISPに慣れているせいか、かっこをつけておくと 式の構造が立体的に(ネストが深いほど浮き上がって)見えるんだ
640 : 確かに人間が見ると見やすいかも知らないが、 人間以外(コードアナライザの類とか)には 見やすくないと判断されるんで仕方がなくつけてる。
641 : >>638 if ( ((a == 0) and (b == 0)) or ((c == 0) and (d == 0))) って書く。論理演算はキーワード使う方がビット演算との取り違えも防げる。
642 : AndAlsoですね、わかります
643 : >>638 何処からが"余分"なのかを巡って紛糾する事も多し。
644 : #define EQUAL(a, b) (a==b) #define OR(a, b) (a||b) #define AND(a, b) (a&&b) if (OR(AND(EQUAL(a, 0), EQUAL(b, 0)), AND(EQUAL(c, 0), EQUAL(d, 0)))) 見づらいって言うか、吐き気がするほど読みづらい。
645 : こんな手法でちまちま高速化したところで、もっと簡単なGPGPUの並列処理に 圧倒されるだけ。
646 : GPGPUが簡単? OpenCLの厄介さを身を以て知って濃い。
647 : if ((!a && !b) || (!c && !d))
648 : 括弧が
649 : 指定桁数で四捨五入する以下の関数の実行速度を上げたいの。 (valueは0〜9999、digitsは0〜5が保証される) SSE使って高速化頼む。 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]; }
650 : ベクトル化は不要よ。
651 : あら、なんかデジャブ
652 : >>649 最適化スレで終了宣言してからにしろよ
653 : でもベクトル化で少しは早くなるわよ
654 : >>652 あっちはCでだから。 >>653 使う方がスカラーなのよ。
655 : >>2 これっていまでのそうなの?
656 : >>655 お前はQuickCでも使ってろよ
657 : なんで PSLLB だけないんだろう?
658 : x64の組み込み命令で、xmmレジスタに定数を代入したいんですが __m128i xmm0; xmm0.m128i_u64[0] = 0x1212121212121212; xmm0.m128i_u64[1] = 0x1212121212121212; これより速い方法はありますか? 各バイトが必ず同じ数字になるとして
659 : >>658 定数はループの外で置きっぱなしにするし、x64だとレジスタが多いから、そのままで良いと思ってみる。 mov eax, 12121212H movd xmm0, eax pshufd xmm0, xmm0, 000H
660 : VC++だと __m128i xmm0 = {0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12}; でmovdqaを使うようになる
661 : VC++だとそれでいいけどGCCだとコンパイル通らなかったりするんだよね。 最適化ルーチンが腐ってなければ大体これでいけるけど。 __m128i xmm0 = _mm_set1_epi8(0x12); というかアセンブリ出力読むと良いよ。
662 : >>654 お前はスクルトでもツカッテロ
663 : スクカジャの方が良いよ
664 : signed shortの配列に floatもしくはdouble型の乗算をして クリップ処理をほどこし signed shortの配列に戻すのを SSEにしたいのでやってください これ signed short s[100]; float f init a; for (a=0;a<100;a++) s = s[a] * f;
665 : それ、どう考えても実数型⇔整数型のコストがでかすぎる。 たった100件でいいなら実数で持てないの?
666 : >>665 100は例で実際はは数千万程度 waveファイルPCMの加工で
667 : >>664 自分で学習しないと答えを聞いても使えんよ。 そもそも意味不明なコード書かれても誰も答えられない。
668 : >>667 ワカンネーならクチダスな
669 : #1:すぐに話の風呂敷を広げる #2:よく理解しないまま突っ走る #3:嫌われていると勝手に思い込んでいる #4:キレて他人に八つ当たりする #5:やたらと自分の正当性を主張する #6:何も自分で決めない #7:何かにつけて理屈をこねる #8:やたら褒めてほしがる #9:他人の話を聞かない #10:何が言いたいのかわからない http://japan.zdnet.com/sp/feature/07tenthings/story/0,3800082984,20421237-2,00.htm
670 : 自分語り 乙w
671 : s = s[a] * f; って何がしたいんだw
672 : 話の内容を察するに、s[a] *= f; ってことだとおもうけれど
673 : それじゃ飽和処理してないし
674 : つーか、コンパイル通るの?
675 : 何も書いて無いけどどうせ色々特殊処理もあるんだろうから、予め 0x0000-0xffffに対する結果を128K byteのテーブルに計算しておき、 後はテーブルルックアップすれば良いだろw
676 : いっそ0x0000-0xffffffffに対する結果を16GByteのテーブルに(ry
677 : >>666 音を大きくしたり小さくしたりしたいだけなら、0.0〜1.0を、0〜255 とか 0〜65535 とかにして、 整数演算に帰結させてMMXのほうが速いんじゃ…
678 : お前らやさしいな
679 : 初めてSSEに触れるので、まずは簡単なコードを作成してみたのですが、 SSEを使わないほうが40倍も速いという驚愕の結果が出ました。 何が間違っているんでしょうか?? コンパイラ:VC++2005(Releaseモード、浮動小数点モデル:FAST) float* f4pakAdd( float* pfA, float* pfB ) { _declspec( align( 16 ) ) static float fC[ 4 ]; _asm { mov ebx, pfA movaps xmm0, oword ptr [ebx] mov ebx, pfB movaps xmm1, oword ptr [ebx] addps xmm0, xmm1 movaps fC, xmm0 } return fC; } 呼び出し側 for( int i = 0; i < 10000000; i++ ) { pfC = f4pakAdd( fA, fB ); }
680 : _asmのスコープをコメントアウトして、以下のようにスカラの加算を並べたほうが40倍速くなりました。 fC[ 0 ] = pfA[ 0 ] + pfB[ 0 ]; fC[ 1 ] = pfA[ 1 ] + pfB[ 1 ]; fC[ 2 ] = pfA[ 2 ] + pfB[ 2 ]; fC[ 3 ] = pfA[ 3 ] + pfB[ 3 ];
681 : fA、fBは以下のように宣言しています。 _declspec( align( 16 ) ) float fA[ 4 ] = { 1.0f, 2.0f, 3.0f, 4.0f }; _declspec( align( 16 ) ) float fB[ 4 ] = { 5.0f, 6.0f, 7.0f, 8.0f };
682 : パイプライン化したコードでもないし、スタックチェックが行われている気がするが。 逆アセ確認したかい?
683 : 40倍も遅いというのはインライン展開されずに普通に関数呼び出しされちゃってるんじゃないの
684 : インラインアセンブリは関数のインライン展開を阻害するから どうしてもASMを使いたいとか宗教的な理由が無い限りintrinsicsを使うべき 強いて関数呼び出しにするなら__fastcallにするかな。
685 : >>682 逆アセしてみました。 ■SSE使用 mov ebx, pfA 004115DE mov ebx,dword ptr [pfA] movaps xmm0, oword ptr [ebx] 004115E1 movaps xmm0,xmmword ptr [ebx] mov ebx, pfB 004115E4 mov ebx,dword ptr [pfB] movaps xmm1, oword ptr [ebx] 004115E7 movaps xmm1,xmmword ptr [ebx] addps xmm0, xmm1 004115EA addps xmm0,xmm1 movaps fC, xmm0 004115ED movaps xmmword ptr [fC (417540h)],xmm0 ■SSE未使用 fC[ 0 ] = pfA[ 0 ] + pfB[ 0 ]; 004115DE mov eax,dword ptr [pfA] 004115E1 fld dword ptr [eax] 004115E3 mov ecx,dword ptr [pfB] 004115E6 fadd dword ptr [ecx] 004115E8 fstp dword ptr [fC (417540h)] 配列インデックス1以降も同じ感じです。 どちらもまじめに演算しているだけのようですね・・・
686 : すみません、>>685 はDebugモードでの逆アセで、Releaseモードでは以下のように インライン展開されていました。 先ほどのはどちらも関数呼び出しを行っていました。(お決まりのpushやret) ■SSE使用 for( int i = 0; i < 10000000; i++ ) { pfC = f4pakAdd( fA, fB ); 004011A6 lea ecx,[esp+10h] 004011AA lea edx,[esp+30h] 004011AE mov dword ptr [esp+28h],ecx 004011B2 mov dword ptr [esp+2Ch],edx 004011B6 mov eax,989680h 004011BB jmp WinMain+190h (4011C0h) 004011BD lea ecx,[ecx] 004011C0 mov ebx,dword ptr [esp+2Ch] 004011C4 movaps xmm0,xmmword ptr [ebx] 004011C7 mov ebx,dword ptr [esp+28h] 004011CB movaps xmm1,xmmword ptr [ebx] 004011CE addps xmm0,xmm1 004011D1 movaps xmmword ptr [__fmode+10h (403380h)],xmm0 004011D8 sub eax,1 004011DB jne WinMain+190h (4011C0h) }
687 : ■SSE未使用 for( int i = 0; i < 10000000; i++ ) { pfC = f4pakAdd( fA, fB ); 0040114A fld dword ptr [__real@40c00000 (40213Ch)] } これって、定数演算だから、事前に計算した結果をメモリに置いておいて、 ロードするだけってオチでしょうか・・・(汗ンブラ)
688 : SSEなんてたいして効果無いんだろ。 コンパイラまかせでいい。 小手先のテクより、アルゴリズムやGPU使用など劇的変化が見込める所を研究すべき。 SSEは最高が20%とかだろ。
689 : >>683 Debugモードではいずれも関数呼び出しありで、 Releaseモードではいずれもインライン展開されていました。 両モードでこういった差があることは意識していなかったので勉強になりました。 >>684 団子さん、ありがとうございます。 今回は勉強の一環としてアセンブラを使いましたが、 できるだけ組み込み関数を使うことにします。 (__fastcallにしたら速度が半分に低下してしまいました・・・)
690 : 実用上はインライン展開で速くなることは稀。 関数にするからには一カ所より多くの所からコールされる可能性が高く、 インラインにしなければCPUキャッシュに乗っている場合に関数を使い回しができて高速化される。
691 : 変数をスタックに積むのって結構無駄だろ? 呼び出し元の関数が小さい場合は特にね。 VC++の32ビット版の場合、__fastcall規約だとxmmレジスタで3つまで渡せるよ。
692 : 失礼 VC++だと__m128{,i,d}は呼び出し規約にかかわらずレジスタ渡しになるね てかレジスタ渡し以外不可能。 ちなみにgcc(Linuxなど)とかだといったんストアしてポインタ渡しになる。
693 : >>692 なんか昔より太ってね?
694 : なりすましとか勘弁してください
695 : >>690 今の時代のインライン展開って、call命令減らすというより、コンパイラの最適化効きやすくするためというほうが大きいんじゃない? うまくいけば数命令ぐらい減るし。
696 : ステップ数の少ない小さい関数限定だな
697 : C++の話なら、たんなる要求に過ぎないので、 ステップ数が大きければコンパイラがinline指定を無視するような気もするな。
698 : gettimeofday()してusecを返すだけの関数はインライン展開したけれど、 (sec%1000)*1000*1000を足したら関数呼び出しになった(gcc4)。
699 : >>698 1関数呼び出しのみの関数はエイリアスとみなしてるんじゃね? 後者は引数渡しのオーバヘッドが無いし、インライン展開のメリットがあるか微妙な線だな。
700 : おいらC++の場合だとそれほど大きくないクラスならヘッダ内に関数実装も含めて書いちゃうし 最適化時にどれがどう展開されるかはコンパイラ任せという罠。
701 : インラインやマクロは最初から使わない方が良い。 EXEでかくなり、メモリ使用量も増える。 自分はオプションでインライン展開しない設定にしてる。 それで実測してみて、関数コールが実際に負荷になっていれば書き換えれば良い。 しかしそんなことが有ったことがない。 速いという思い込みでインライン指定してるだけとおもう。
702 : templateなんか駆使すると インライン展開されないと 桁違いに遅くなるけど
703 : maxとかabsとかSSE一命令でいけるのにわざわざレジスタ退避してcallしてたら コードサイズもでかくなるしいいことないだろ 関数のサイズをちょっとずつ大きくしてくとわかるけど インライン展開の閾値を超えた瞬間にインラインで展開されてた数命令規模の関数が 一気にcallに置き換えられてサイズが爆発するから
704 : mapとか、コンテナにvoid *を突っ込む癖が付いてしまう。
705 : C++は面罵関数がインライン展開されなかったら話にならないからな。 自分はオプションでインライン展開を積極的に行なう設定にしている。 それで実測してみて、EXEの大きさやメモリ使用量が実際に問題になっていれば書き換えればいい。 しかしそんなことがあったことがない。 増えると言う思い込みでインライン設定を毛嫌いしているだけだと思う。 実際、ベクタ化の方がよっぽどコードサイズが増えるよ。
706 : あと、SSEの場合アラインメントの推論が切れるのがかなり問題で 関数単位でコンパイラが見てしまうと ポインタにはアラインメントの情報が乗っていないから iccなんかは気を利かせて一旦アラインメントされたスタック上にコピーする コードを挿入してしまったりする アラインメントされてないとペナルティが大きいからね インライン展開されると アラインメントされているスタック上の変数や 明示的な_mm_load_psなんかから 変数やポインタのアラインメントを推論するので アラインメント前提のコードを生成させることができる
707 : どんな変数も問答無用でアライメント16にするようにコンパイルする設定があれば 面倒な記述を減らせると思うんですが、何かデメリットあるんでしょうか? メモリの隙間ができて勿体無いとかあるかもしれませんが、メモリ量の多い昨今、 それほど問題にならないのでは?と思います。 むしろアライメントすることでメモリアクセスの冗長さを減らせて帯域を節約する効果も あって一石二鳥ではと思うんです。
708 : gccだと-mpreferred-stack-boundary=4がデフォルトだから既に16バイトアライメントだよ 構造体の詰め物は互換性もあるし難しいじゃないか
709 : >>707 互換性
710 : >>707 なにそれ君いまだにPS3向けのゲームとか組まされてるわけ?
711 : >>708 glibcのmallocは8バイトだよ >>710 SandyBridgeでもアラインメント取れてないと遅いでしょ
712 : 構造体はCの規格だと順番を入れ替えられないだけで詰め物はし放題だよ 実際4バイトアラインメントのアーキテクチャだとコンパイラが詰め物するでしょ
713 : >>711 Nehalem以降はmovups/dquもペナルティ無く使えるでしょ まあ結局Core2以前も考慮するとコード振り分けるから労力は変わらないのだけれど...
714 : すみません、自分は日曜プログラマレベルで、対象CPUはx86、環境はVC++です。 VC++の設定を見ていると、「構造体メンバのアライメント」というのがあって16バイトアライメントを選べるようになってました。 同様に通常の変数もアライメントできる設定があるかと思い探しましたが見付かりませんでした。
715 : どう考えてもこれ以上削れないってくらいの手書きインラインアセンブリコードに対し、 C記述版をVC++のReleaseモード(最適化O2)でコンパイルしたもののほうが1.3倍速かったです。 生成されたアセンブリを覗いてみたところ、 変数 * 3 というコードを lea edx, DWORD PTR [eax+eax*2] としていてびっくりしました。 これって、アドレス演算を行うローダ(専用の演算器?)を使うことで、 通常のALUと並行して演算(スーパースカラって言うんでしたっけ?)し 高速化しているということなんでしょうか??
716 : >>714 __declspec(align(N))
717 : >>716 ありがとうございます。 それは知っているんですが、>>707 でも書いた通り、 そういった記述をわざわざせずとも、自動で全てアライメントしてくれるような設定があればイイのでは? と思った次第です。 しかし、上でも仰られたように、互換性の問題があったりで難しいのでしょうね・・・ でも二重インクルード防止の「#pragma once」のように、互換性を考慮しない機能があったりするくらいですから、 自分のようにずっとVC++しか使わない人間を対象にそういうオプションが用意されていても良いのではと思いました。
718 : >>715 ついでにPartial flags stallも回避できるな
719 : >>717 キャッシュミスが多くなったら速くならない。 だから隙間が多すぎるのは良くない。 まだそのレベルの高速化を気にするレベルじゃないと思うが、気になるなら続きは↓とかで。 http://toro.2ch.net/test/read.cgi/tech/1322981274/ http://toro.2ch.net/test/read.cgi/tech/1302223650/
720 : >>713 Nehalemでmovupsのペナルティがなくなったのはアラインメントされている場合だけ Penrynまではアラインメントされていてもmovapsより遅かった ハードウェアがどういう実装になっているのかをよく考えてほしい さらにSandyBridgeでは非アラインメントの場合 2つあるロードユニットが生かされないばかりか追加ペナルティもあるので アラインメントされている場合に比べて非常に性能が落ちる movaps/movups使い分けの時代はSegmentation Faultの温床だったので movupsオンリーで書ける様になったのはうれしいよね Haswellで32Byteアラインメントが出てくるかと思うと頭が痛いが
721 : >>716 VCの__declspec(align(N)) や gccの__attribute__ ((aligned(N)))は スタックやベースポインタからのアラインメントは保証されるけど ヒープにどう確保されるかは保証されないよ ランタイムライブラリ依存だからね そのクラスのnew/deleteをオーバーロードするか 大雑把にグローバルでオーバーロードするかしないといけないが どちらも一長一短ある
722 : >>717 ぶっちゃけそれやってどれだけの速度向上が望めるの?って事情もあるんじゃねーの たかだか1MBに満たないスタックに、って 最近のCPUだとunalignedアクセスの性能低下も軽減されて古いCPUだと速くなるって言われてもなーって気持ちもあると思う
723 : SandyBridgeもL1D$は1R1Wの4bank構成で うまくバンクコンフリクトを避けないとペナルティがある 非アラインメントのmovupsは2bank使ってしまう
724 : >>715 手書きでもふつーにやる。
725 : >>718 おお、そんなメリットもあるんですね。 >>724 覚えておきます。 コンパイラの吐くアセンブラを見てると眩暈がしてきましたw SIMDやプリフェッチ等のキャッシュ制御を除けば、 手書きでアセンブリ書くのはほとんど効果的でないような気がしてきました。
726 : >>719 なるほど、バイト境界を跨いでしまってアクセス回数が増えることより、 キャッシュに収まって低レイテンシでアクセスし易くなる効能のほうが上回るわけですね。 いかに外部DRAMへのアクセスがコストになっているかがよく分かります。 あと、スレ誘導もありがとうございます。 >>722 >最近のCPUだとunalignedアクセスの性能低下も軽減されて そうだったんですか。 それだったらmovupsでいいですね。 でも>>723 さんの御意見も気になりますので、パフォーマンス測りながら追い込むようにします。
727 : >>720 64ビットだと、当初MMXが使えなくなるとか言ってた関係で VCはMMX用の組み込み関数が使えないんだよなぁ でもって、MMXをSSE2に書き換えるとメモリオペランドのアライメントで 例外が発生したりするんだorz
728 : もう最初から全部、256バイト境界にアライメント揃えて実行ファイル作っとくかw
729 : グローバルのnewをオーバーロードしたくなる時は結構ある
730 : 32bitOSを切り捨てたい時もよくある
731 : intやポインタが64bitになっても面倒なだけだと思うけどな。
732 : お前がそう思うんならそうなんだろう お前ん中ではな
733 : unsigned int maxpos(unsigned int src[256]) { unsigned int i, m = 0; for(i = 1; i < 256; i++)if(src[m] < src[i])m = i; return m; } これをSSEで高速化する方法があれば教えて下さい
734 : byte配列ならPHMINPOSUWで速くなりそうだけど、そのコード基本的に検索だからSSE向きではないな。 最大値求めて、それを検索して位置返すのもありだが、速いかは知らんw
735 : >>733 src[m]をキャッシュした方が速いと思う。 要は、SSE以前にやることやってからにしろ。
736 : unsigned intだとSSE4使わないと素で書いたより無駄に遅くなりそうなのしか思いつかないわ
737 : SSE使った方が遅くなるのは何故でつか?
738 : 日本の道路をF1で走るようなもんだから
739 : >>733 画像とか統計の基礎だな。疑似コードで書くとこんな感じだ maxpos(src[256]) { pos = {0, 1, 2, 3}; for(i=0; i<256; i+=4) { s=load(&src[i]); isGT=maxVal<s; maxVal=isGT&s | ~isGT&maxVal; maxPos=isGT&pos | ~isGT&maxPos; pos += 4; } return max_position( maxVal[0], maxPos[0], maxVal[1], maxPos[1], maxVal[2], maxPos[2], maxVal[3], maxPos[3]); }
740 : >>739 SSEは max命令とunpackv命令があるんだから 32bitのsrc[i]値を64bitのsrc[i]<<32|iに変換して最大値を求める方が速いと思うね
741 : 740だが、64bitのmax命令はないんだな それなら >>739 でいいと思う スカラーコードより速く すまん
742 : >>739 signedの比較命令しかないからダメじゃない?
743 : なんか知らんが、そんなのずらせば済む事だろ
744 : 実際にコード書いて検証しようぜ。 思い込みと現実は違う場合が結構あるしさ。
745 : 古いPCを使ってるからかもしれんが>>733 を単純にアンロールしたのが一番速いな
746 : スレチではあるが、このコードを高速化する必要がある処理を見てみたい気がした。
747 : >>742 0x80000000を引く。 足してもいいしXORでもいいけど。
748 : 横レスだけどおおすげー。 そもそも正数同士・負数同士の比較ならsigned/unsignedで結果は変わらないので 問題は正数と負数の比較のみ。確かに最上位ビットを反転させれば万事うまくいくね。
749 : 256個ぐらいだと、最大値を見つけて最大値と同じのを見つけるのだと遅いかな
750 : signedとunsignedの変換が凄いのか。 この手のテクをまとめようと思ったらどのレベルから書いていいか分からんな。
751 : >>749 俺は実装が面倒という理由でそれでやってるが やっぱメモリに2週アクセスするから遅いのでは
752 : pxor x2+pcmpgtbとpblendvbで最大値のインデックスを保存 インデックスは0x01010101でインクリメント 最後に4要素を比較 4要素あたり2サイクルで回るかな signed intだったら4要素あたり1サイクルでいけるかも? unsignedでもcharだとpsub+pblendvbだけでいけるからよいんだけどね
753 : あpmaxudも必要か
754 : __m128i pos = _mm_setzero_si128(); __m128i maxpos = _mm_setzero_si128(); __m128i maxsrc = _mm_set1_epi32( 0x80000000 ); #pragma unroll(16) for( int i = 0; i < 256; i+=4 ) { __m128i signed_src = _mm_xor_si128( _mm_load_si128( (__m128i*)&src[i] ), _mm_set1_epi32( 0x80000000 ) ); __m128i mask = _mm_cmpgt_epi32( signed_src, maxsrc ); maxpos = _mm_blendv_epi8( pos, maxpos, mask ); maxsrc = _mm_max_epi32( maxsrc, signed_src ); pos = _mm_add_epi32( pos, _mm_set1_epi32( 1 ) ); } 以下略 実行してないのであってるかは知らん
755 : > unsignedでもcharだとpsub+pblendvbだけでいけるからよいんだけどね その程度ならpacked floatにキャストしてblendvpsでもいけるけどね。 SSE4対応以前ならpmovmskb/maskmovps+test+jccでもいけるか (メディアンならともかく最大値ならcmovより分岐のほうが速いはず)
756 : >>755 pbledvbは7+8nのビットしか読まないから符号の判定に使える SSE4以前だとmaskにはand+andnot+orが使われてたね
757 : Penrynだと下手にblendv系使うより速い場合もあったりした
758 : ごめんblendvpsも31+32nビットしか読まないのか 勘違いしてた 符号の判定に使えるね
759 : >>757 PenrynのPBLENDVBはレイテンシ1、スループット2で SandyBridgeはレイテンシ2、スループット1か… Penrynはデコーダの制限もありそうだし、and,orでもよさげ
760 : HTが使えるCPUならblendの方がいいかな?
761 : どうせ全検索するんだしレイテンシの長さ分だけインタリーブすればレイテンシ隠せるよ
762 : packed unsigned intの比較(マスク生成)だけど、両項のMSBを反転してからpcmpgtdするより psubd + psradのほうが速いかもしれない
763 : >>762 どっちも2命令でXORの方が実行出来るポートが多い分有利そうに感じるのだが
764 : pdangod
765 : >>762 blendvps用のマスクならpsubdだけでよい blendvpsは最上位ビットしか見ないから
766 : 話の流れぶった切るけど団子さんよ〜。 今の静的分岐予想って相変わらずifよりelseの方が速いの? ifとelseのどっちが速いか正確に計測するにはどういうコード書いたらいい?
767 : あれ?ifの方が速いんじゃなかったか
768 : P6,P2,P3,P4はforwardならnot taken backwardならtakenがデフォルト P4はPrefixでヒントを出せる PM,Core2はランダム ソースはAgner
769 : 分岐予測履歴がない場合あるいは予測そのものがない場合、条件付ジャンプは前のアドレスに 飛ぶ場合(多くの場合ループ)は原則ジャンプ、後ろならスルーが多くのCPUの実装ですね。 大体のコンパイラってforやwhile文はこんな感じに展開するでしょ? if (cond) { do { ... } while(cond); }
770 : >>769 モダンなCPUはどんな感じなのよ >>768 はランダムだと言ってるけど モダンなCPUでも静的予想だとifはスキップ whileはループ確定なのけ。
771 : 分岐履歴が無いのに前方への分岐を予測したら命令フェッチをやり直さなきゃならないじゃん 後方への分岐はループの場合が多いから特別扱いなんだと思う
772 : 大概returnやthrowが行われるからifをすっ飛ばせば速いのは解る。 反復も反復する事を優先した方が早いのは解る。 それはいいとして、今のCPUは分岐ヒントとか投棄とかあって単純じゃないんだろ。 そこを知りたいんだがね。
773 : >今のCPUは分岐ヒントとか投棄とかあって単純じゃないんだろ。 パイプラインが深いだけでしょ
774 : わかってないのにわかったつもりになって 単語だけ並べているように見えるのは何故だろう
775 : そう思ってくれるのはいいが、間違いの指摘と 実際はどうなってんのか答えてくれ 批難だけの回答はいらん。
776 : >>773 分岐予測の話はパイプラインが深いこと前提で話してるわけで・・・
777 : >分岐予測 って、言い方してるだけなの?
778 : >>775 じゃあ間違いを指摘してやる。 >大概returnやthrowが行われるからifをすっ飛ばせば速いのは解る。 前方への条件分岐は、「分岐しない」と予測される、とオマエ以外の全員が言っている。 if (xx) return で「すっ飛ばせば云々」なんて、理解していないまま「わかったつもりになってるだけ」の証拠。 >今のCPUは分岐ヒントとか投棄とかあって単純じゃないんだろ ヒントはともかく、投機はまさに「投機実行するために分岐予測をする」のであって 「投機実行もあるから分岐予測が複雑になる」はナンセンス。 もちろん、エンプラ系/VLIW系では「分岐の有無の両経路を実行する」なんてのもある(らしい)が 一般的とは言いがたい。
779 : >>778 内容じゃなく国語的に誤解されてるな。 >前方への条件分岐は、「分岐しない」と予測される、とオマエ以外の全員が言っている。 if( xx ) throw xxx; throwなんて実行するケース殆ど無いんだから基本if実行しないってのは同じ話。 矛盾してないでしょ。 まず分岐予測が複雑になってるって話はしてないよ。 投棄実行については投棄実行を考慮した上での静的予測方法があるでしょという話。
780 : >>779 だから、ifの内部は「実行すると予測される」んだよ、バーカ
781 : 尤も、わかりやすいからifと書いたけど、 実際はコンパイラの最適化でif、elseは反転するから この言い方は正しくは無いんだけどね。
782 : せめて正しい漢字使えよ。 一度なら単なる変換ミスとして納得できるけど 繰り返しているってことは、別の意味に捉えているとしか思えない。
783 : >>780 お前バカだろ みんなアセンブリ前提で言ってんだよ jze label if() { ・・・処理・・・ labeli }
784 : >>782 ん?尤も(もっとも)か?無い(ない)か?
785 : >投棄実行については投棄実行を考慮した上での静的予測方法があるでしょ 理解できる日本語で書いてくれないかな。 分岐予測というのは、投機的に(結果が判明する前に)実行する前提でのもの。 (無条件分岐や間接分岐もあるから、厳密には正しくないけど) 予想して(投機的に)実行するのでなければ、単に結果が判明するのを待って、それから実行すればよい。 つまり、投機実行するからこそ分岐予測が必要なのであって 投機実行しないのであれば、分岐予測など元々必要ない。 そのことをちゃんと理解していれば、 そもそも「投機実行を考慮しない分岐予測」などというものが存在しないから >投棄実行を考慮した上での静的予測方法 が意味不明に感じられる気がするんだけどな。 >>783 わかってるよ、そんなこと。
786 : >>780 ifが優先されると思ってたのは>>767 とお前ぐらいだよ
787 : >>785 ごめん。もう今更何を言おうが>>780 のせいで信用ないわ。
788 : >>782 ああ投棄実行ね投機の変換ミスそのままにしてたわ
789 : 投棄実行については誤解してたわ。 2つの分岐を両方実行して実際実行対象にならなかった方の結果を破棄するものだと思ってた。
790 : >大概returnやthrowが行われるからifをすっ飛ばせば速いのは解る。 もう一度考えてみたけど、この意味が全然理解できない。 ぱっと見で、何故returnや、 増してthrowなどという言葉が出るのかわからない。 (GP等の例外の割り込みは全く別物) で、次の行の >反復も反復する事を優先した方が早いのは解る。 の意味は、「ループであることが推測されるから分岐すると予測する」だよね? それとの対比で、「ifをすっとばせば」の意味が 「ifの内部は実行されないと予測」と捉えれば 「ifの部分での分岐は分岐すると予測すれば if内部のreturnやthrowに制御が来ないので別の分岐の予測を避けられる」という意味にもとれる。 それならようやく意味が通じるような気がして、そういう意味だと思ったんだけど。 つまり、ifの部分(=前方分岐)を「分岐すると予測する」という意味だと。 でもそれ(前方へ分岐すると予測する)は実際のプロセッサの動作とは違うわけで ならばどういう意味なのか、さっぱりわからなくなってしまってね。
791 : お前の文章が解らんわ
792 : 一応。 突然returnやthrowが出てくるのが if (xx) return という意味じゃないか、というのも勝手に俺が頭の中で補って想像しただけで 実際には何の説明も無く(ifの多くがreturnやthrowというのにも同意しにくい) 唐突な「rerturnやthrow」「すっ飛ばす」を必死に理解しようとしたのがそもそもの間違いかもね。
793 : 実行時の分岐予測って、どうなってるのかわかってないと、グダグダでしょ
794 : >>792 >>779 で補足だしてるだろしつこいわ
795 : >>790 >>792 ウゼェ・・・
796 : >>794 >>779 だとしたら>>780 だっての。 「前方分岐は分岐しないと予測する」のが実際のプロセッサの動作なわけ。 >>779 の「throwなんか滅多に起こらないから実行しない(と予測する)」は 「前方分岐は分岐すると予測する」ことになるから実際の動作と矛盾するという話。 それを、「わかってないくせに」の根拠の一つにしたんだよ。 実際、「分岐予測とはどういうものか」も「なぜ分岐予測するのか」もわかってなかったわけでしょ(>>789 )。
797 : 口汚い言葉で罵倒せずには居られない奴って下品・・・。 団子さんの紳士っぷりを少しは見習ったらどうだろうか。
798 : もう>>780 はいいから団子さんこないかな
799 : え?指摘するの780だけ? 露骨だなぁ。恥ずかしくないんだろうか。
800 : お前がなwww
801 : 頭が悪すぎて理解できなかったらしいから仕方ないな。
802 : >>796 投機実行という言葉については誤解してました。 分岐予測については、分岐ミスでパイプラインに読み込んだ 命令を破棄が発生するという認識です。 そもそも、それが気にならないのであれば分岐予測なんて 気にする必要はないでしょう。
803 : インテルの最適化マニュアルだと >インテルPentiumM プロセッサー、インテルCoreSolo プロセッサー、インテルCoreDuoプロセッサーは、 >ジャンプの向きに従った条件分岐を静的には予測しない。これらのプロセッサーでは、 >すべての条件分岐は、最初に発生したときでも動的に予測される。 と書いてあって、wikiで調べたらPenM以降は広域分岐予測を取り入れた関係で静的予測はしなくなったみたいだね ttp://ja.wikipedia.org/wiki/%E5%88%86%E5%B2%90%E4%BA%88%E6%B8%AC >>768 の >PM,Core2はランダム というよりも、「前に実行した別の分岐命令の結果も影響する」とした方が適切みたいだ 分岐予測に関して ttp://news.mynavi.jp/column/architecture/index.html の第167回からの解説が参考になるよ
804 : >>803 なるほど。いい話が聞けました。ありがとうございます。
805 : >>803 >と書いてあって、wikiで調べたらPenM以降は広域分岐予測を取り入れた関係で静的予測はしなくなったみたいだね P4もグローバル履歴を使ってるよ おそらくだけど ある分岐命令を最初に実行したかどうかはBTBのエントリが割り当てられているかで判断するので 分岐先予測より分岐予測のヒット率が十分に高い場合は動的分岐予測が当たる条件で誤って静的予測してしまう確率が高いから 1回目の分岐予測を諦めても静的予測をやめたほうがヒット率が上がるということなんじゃないだろうか
806 : ×分岐先予測より分岐予測のヒット率が十分に高い場合 ○BTBのヒット率より分岐予測のヒット率が高い場合
807 : これからSSEを使ってみようと思うんですけど、Cから使う場合の SSE Intrinsicの解説書でおすすめのものはありますか? Amazonで探したんですけど、SSEの解説書はアセンブラのものしか 見つけられませんでした。
808 : >>807 基本的な使い方はアセンブラで覚えて、組み込み関数への変換は http://software.intel.com/en-us/avx/ のIntrinsic Guidを使って対応する関数を探すようにすればそのうち慣れてくると思うよ。
809 : http://www.sofken.com/Documentation/compiler_c/main_cls/index.htm
810 : >>808 これ、日本語が用意されてないあたり、もう日本は完全に商売の相手としてみなされてないんだろうな・・・。 中国語はあるのに。
811 : 米中の長期的戦略では日韓は中国に併合される おまいらも今のうちから中国語勉強しておいた方が良いぞ
812 : 中国に併合?なら大丈夫だ。 中国語の一方言として日本語は残る。 やつら、言葉が通じなくても全然気にしないし。
813 : すぐ暴力に訴えるからな
814 : >>808 >>809 まとまった書籍があればと思いましたが、そういうのはないですか。ありがとうございました。
815 : >>810 スタッフに日本人はいないが中国人はいるだけの話。 あと、日本人で必要な人は英語を読んでしまうので、いらないと言えばいらないからじゃないか?
816 : それもあるだろうが、日本人は押しが弱くて文句言わない(言えない)とか 中国人なら「読めない!何とかしろ!」とIntelに怒鳴むに違いない
817 : 中国語のサイト見るとあっちのプログラマはかなりがんがってる 理系離れ技術者軽視でバカマスゴミに蹂躙されてる日本はもうだめだ
818 : Intelの日本法人が人手不足っていうだけかと
819 : 現実見ろや 中国語圏の人口は日本語圏の10倍以上いる
820 : つーかどう考えても世界最大勢力w
821 : コンピューターの世界では英語が最大勢力ではないか
822 : いまのEmacsのコミッタって中国人なんやね
823 : あっちはgeekの受け皿も多いからなあ 英語もできないくせにコミュニケーション能力とか言って オタを弾き出してる日本人が食っていける仕事じゃなくなったね
824 : 中国人は日本以上に英語ができないからな。
825 : んなこたーない。
826 : ピンキリのスパンが大きくて ネラー級の教養で大陸ならピン側寄りで キリの人数が日本の人口超えてるのは事実
827 : ループ内不変のクラスメンバ変数の参照を自動変数に代入して置き換えると 結構違いが出るね。
828 : 自動変数は可能ならレジスタに配置するからね
829 : >>828 だけじゃなくて、メンバ関数の呼び出しが あれば、少なからず実際に呼び出す 必要があるからじゃね。 うかつにキャッシュできるもんでも ないしね。
830 : じゃあこれも結局そうなの? http://qarc.info/qa/show-11205-871.html
831 : クラスオブジェクトはポインタで管理されてるから エイリアシングの最適化と似たような問題があるんだと思う。
832 : エイリアシングってあれか ポインタの値をレジスタに持ったままに出来ずその都度ロードするあれか だからFORTRANよりも速く出来なくて restrict って予約語がC99に作られたんだな VCなら__restrictを付ければ同じなんで少しはクラスは速くなるかな あ、だめか thisをrestrict化出来ないや
833 : http://www.ertl.jp/~takayuki/readings/info/no06.html ここがよく分かるな Cをコンパイルした時にポインタ変数がレジスタ割り当てされたら ハードウェア的にコヒーレンシを保証してくれる仕組みでもないものだろうか
834 : constつければいいだけだろ。
835 : constは安全だけどrestrictは相当注意して使わないと危険。
836 : 「ポインタは基本的にどこでも指し示せる」という性質が問題なんだよ これがFORTRANにもアセンブラにもない(厳密にはアセンブラにもあるけどそんな馬鹿な事はしない) 厄介事を引き起こして最適化の妨げになっている
837 : カプセル化をうっかりブチ壊せちゃうOOP気取りのクソ言語
838 : だからC++の哲学は「うっかりミスを防ぐ」だけであって、故意にOOPのバリアを ぶち破ろうとする悪意には抵抗力はない
839 : Cはむしろエイリアスの問題を無視すればよかったのに どうせバッファーオーバーフローだって無視されてる アセンブラと同じくエイリアスが問題が原因のバグはプログラマのせいにするとか
840 : Win32でいうCreateThreadのパラメータにthisポインタを渡して・・・みたいな厨テクってやってる人いるけど やっぱ害悪なんだろうな。 SSEとか駆使するときは極力クラス使わずベターCで使ってるわ。
841 : VC++の場合、thisポインタはecxレジスタに渡され、メンバ変数や仮想関数テーブルは ptr[ecx + offset]みたいな形でアクセスされると思うんだけど、 パラメータにecxをとる命令って結構多い(シフト・ローテートなど) 当然、ecxの中身を都度入れ替えるよね ローカル変数にコピーしたら速くなるってそういうことなのかも メンバ関数は特に必要がなければstaticにしてthisポインタを渡さないようにしてみると いいかもしれない
842 : >特に必要がなければstaticにして ベターCどころか記述が面倒な糞言語 それがC++
843 : そりゃC++を積極的に使う理由がないですわ。 templateを使ったメタプログラミングは便利だけどね
844 : そんなレベルで最適化が必要なら、最初からアセンブラ使えとおもうのは俺だけ?
845 : intrinsicを使うと、32bit, 64bit両方を一発で書けるのがいい。
846 : >>844 だけじゃないけど少数派だろう。 動くものを作ってから置き換えないと、どこのバグなのかわかりにくい。
847 : _mm_slli_si128のシフト量は即値だけど、可変にしたい場合は替わりに何を使えばいいのかな? switchで切り替えるかshuffleのmaskを配列で用意しておくというのは思いついたけど。
848 : SSSE3が使えるならpshufb+配列がいいだろうね そうじゃないなら分岐するか自己書き換えするか シフト量4以下限定なら movdqa dst, src psrldq dst, 4 psllq src, shamt psllq dst, shamt pslldq dst, 4 por dst, src 5以下限定なら movdqa dst, src movdqa tmp, src psrldq dst, 3 psrldq tmp, 5 psllq src, shamt psllq dst, shamt psllq tmp, shamt pslldq dst, 3 pslldq tmp, 5 por dst, src por dst, tmp ...とか煩わしいができなくもない(shamtはシフト量*8としてxmmに入れておく)
849 : zeroとpalignrするというのを思いついた。
850 : palignrも即値だけ
851 : 妙なことやるよりstoreしてlddquが一番シンプルな解決策だったりするかもな。
852 : くそー64bitモードでCompiler Instinctsじゃなくてasm復活させろよ 何のためにC++にわざわざasmキーワードが予約されてんだよ
853 : 解決策: gccかclangを使う
854 : gccは-masm=intelでintelシンタックスでもasm使えるけど、 ダブルクォートはどうにもならないよねぇ。 ただでさえSSEのバージョンに応じたコード用意するのが面倒なのに 64bitとgcc向けで組み合わせが膨れ上がるよ。 intrinsicsでいいや、って思うようになったよ。
855 : 64bitと32bitは工夫すれば共通化できるよ 確かにダブルクォートはどうにもならんけどね あれのせいでメンテナンス性が落ちてるのは確かだ
856 : >>855 >64bitと32bitは工夫すれば共通化できるよ intrinsicsなら同じソースで簡単に64bitに出来るけど、gccのインラインアセンブラで 共通にするには制約無い?それにレジスタが増えるメリットが生かせないんじゃない? Xvidに32bit/64bit共通.asmってのがあったっけ。制約きつそうだったけど。 面倒だけどインラインアセンブラからintrinsicsに徐々に置き換えつつデバッグ済ませとけば その後はコンパイラの違いや32bit/64bit、SSE/AVXにも対応しやすいよ。
857 : もちろん同時に使えるレジスタ本数は8本までになるけど そもそも16本フルで使うと性能上がるようなコードは intrinsicsで書くにしても分けると思うなあ (アンロールをどの程度するか、ループ内の定数をレジスタに置くかメモリに置くか等) MSコンパイラはどうか知らんけどgccはintrinsicsにおまかせすると レジスタのやりくりがタコで無駄なスタック退避が多かったりして あまり積極的に使う気にはならんかった。 AVXなコードも書いてるけどintrinsicsに移行するよりは 素のアセンブリで書く機会が増えた印象。 intrinsicsだと128bit VEXとnon VEXの使い分けとかやってくれないよね
858 : gccのインラインアセンブラで32bitと64bitを共通化するときに困るのは 自動割り当てを使うときに32bitな変数に割り当てられたレジスタを 64bitでアクセスしたい時かな。 例えばループ変数は32bitだけどそのループ変数をインデックスレジスタに使いたいとか。
859 : > intrinsicsだと128bit VEXとnon VEXの使い分けとかやってくれないよね コンパイルオプションで切り分けろ 複数のCPU向けの最適化コード書く場合、同じソースファイルにVEXとnon-VEXのコード 記述できないので面倒にはなったね そのくせ_mm_broadcast_ssとかload+shufpsなどに展開してくれないから困る
860 : >複数のCPU向けの最適化コード書く場合 それ以外に、単純にAVX対応CPU向けのコードでも VEXを使うと命令長が長くなる場合があるので(SSE単精度SIMD,REXなしでソース破壊可能な場合) 命令毎に使い分けたいという話なのだ さすがにintrinsicsでも2/3バイトVEXの使い分けぐらいはやってくれるのかな? まあuop cacheのあるSandyで命令長にこだわる意味がどこまであるのかという話ではある
861 : SSEはデコードが大変だから将来は遅くなるかもって記事があったよね。 そういう状況ではインラインアセンブラはlegacyってことなのかもね。 >>857 VCでも2008(std)から2010(EE)に変えたら速くなったし(2012EforD)ではほとんど差が無さそう) 2010のも自分だったらこう並べないよなぁって思う部分があったり、SIMD以外の部分との連携が 気になるとか、そういうのはあるよ。 IACAで手抜き解析するとCP(クリティカルパス)が並んでたし、スループットもその合計に近いので それなりにがんばってそう(ポートの表示はほぼ意味不明だけど)。 http://software.intel.com/en-us/articles/intel-architecture-code-analyzer VCの64bitはインラインアセンブラが使えないからIACAも使えないけど、 32bitより多少は速くなることが多いみたい。 SSEはdestが破壊されるから速いコードは寿命の長いデータがレジスタ間を漂うようなコードになるので 正直あまりやりたくないなぁ。 レジスタが余っていたらパイプライン化を目指すので共通コードにはしないかなぁ。
862 : > さすがにintrinsicsでも2/3バイトVEXの使い分けぐらいはやってくれるのかな? 大体のコンパイラはそのへんタコってるよ。-Osオプション何のためにあるんだか・・・ > まあuop cacheのあるSandyで命令長にこだわる意味がどこまであるのかという話ではある 小さいに越したことはないから余裕があったら手作業でコードサイズ縮小やってるね。 YASMで組む場合は変数を%defineで適当な変数名つけてレジスタ使ってるよ dest, src1に使う頻度の高いレジスタをx(y)mm8〜15に配置すれば大体2バイトVEXに収まるんだよね。 もちろんSSEでは全く逆の割り当てをやる。 > VCの64bitはインラインアセンブラが使えないからIACAも使えないけど VCの64ビット版は/FAsでasmコード生成して吐き出したコードにIACAマーカー仕込んでml64通すかな。 そこまでパフォーマンス解析が必要なコードならそもそも、コンパイラの最適化を信用しないかも
863 : ん…。
864 : >>832 亀レスですまんが 関数に _restrict 付ければ this に付けたことになるんじゃなかったか?
865 : 整数に関するCPU拡張命令って、あまり数が充実してないね。
866 : 需要がねーもん
867 : そうか…残念だ。
868 : あげ
869 : これからは固定小数の時代か… あれやこれやを固定小数で解けるようにするのは大変そうだね
870 : んなこたーない。
871 : 固定小数があれば 増税したい放題 公共事業費ネコババしたい放題 ノーパンしゃぶしゃぶ無料で接待 もうえらいことです
872 : 何言ってんだ?
873 : >>869 >>871 固定小数をクラスにしてみた。 http://ideone.com/x2uolH
874 : >>873 整数部がint_partなのはいいとして、小数部がdecimal_partなのは如何な最中と。 違うシフト値を持った固定小数点数同士のキャストオペレータが欲しいところだな。 floatは精度がintよりも精度が低いから、doubleとのキャストオペレータも欲しいな。
875 : あまりキャストオペレータばかり作ると曖昧になっちゃうんじゃない?
876 : だったら寧ろ、floatいらね。
877 : 固定小数点数のことを固定小数と書くやつのソースを見てあげる優しさは素晴らしい。 符号ビットの指定もできないし、幅も int 固定だし、ものを知らない。 固定小数点数ルーチンなんていくらもあるんだから、他人に見せるんなら、他と比べてメリットのあるものにしてほしいね。 decimal は通貨用のを恥知らずにも参考にしたんだろうね。
878 : >>875 今時のコンパイラなら、explicitをつければキャスト演算子必須な変換関数が作れる。 explict operator float() const { …… }みたいな感じ。
879 : >>878 ありがと
880 : vs2010 x64でアドレスに16bitのオフセットを加算しようとすると movzx esi、word ptr[] add rsi、r15 みたいなコード吐くんだけど、 これってパーシャルレジスタストールする?
881 : 32ビットレジスタへの書き込みは自動的に64ビットにゼロ拡張されるんじゃなかったっけ
882 : 64bitモードで32bit書き込みした場合上位32bitはクリアされるってwebで見つけたから ストール無しなのかな
883 : REXを省略するための工夫だからストールはしないよ。
884 :2013/09/26 >>883 >>881 スッキリしました ありがとう
TOP カテ一覧 スレ一覧 2ch元 削除依頼 ▲
ふらっとVisual C#,C♯,C#(初心者用) Part107 (667)
C++相談室 part105 (888)
ゲームプログラムなら俺に聞け29 (289)
VBで作られた有名なアプリって何? (168)
プログラミングを勉強したいのだが (141)
【漏れは】猫でもわかる質問スレ【猫以下です】 (496)
--log9.info------------------
【電凸】マス板電話突撃隊★18 (140)
【高2自殺】マスコミは桜宮“闇寮”の実態を報じろ (103)
TBS、日テレの韓流は黙認するフジTVデモ隊のバカさ加減 (207)
上杉隆さん、がんばれ (269)
共同通信VS時事通信 どっちが韓国通信? (105)
日本が暗いのはマスコミのせいだよな? (263)
民主党とマズゴミはマジで糞!!! (875)
マスコミも良かれと思ってやっている (235)
マスコミはいいよな (206)
【民団】フジテレビ・トクダネ【チョン】 (318)
【公益】共同通信、なぜ韓流エンタメ部門?【法人】 (194)
【海水】安倍晋三、菅チョクトに完全勝利【注入】 (342)
なんで産経新聞って部数少ないの? (574)
★★★原発を早く再稼働しろ(NO3) (122)
【震災】二十四時間連鎖祈祷【復興】 (101)
風評被害を無くすには▼全原発を廃炉に (115)
--log55.com------------------
福島県孤独な男のスレ
【R30指定】御機嫌如何【長編小説】
こういう画像貼ってけ
青春時代が全くなかった孤男2
昭和52年生まれの孤独な男のスレ その57
◆孤男HAPPYライフ.16◆
◆孤男HAPPYライフ.17◆
【孤高の】孤男一人酒 59杯目【酒呑み】