C++やインラインアセンブラ、SSEなどによる高速化の手法
について語りましょう。
まずはi++は++iにしろよ。
それで速度があがるならな
4 :
デフォルトの名無しさん:2005/10/27(木) 03:07:02
Intelのコンパイラ買って開発したほうがいいんじゃね?
ヘタに素人が最適化なんてやるより
アルゴリズムよりメモリアクセスが最大のボトルネックだったりする。
結局レジスタやキャッシュを意識するのが重要になってくる。
>>4 コンパイラを変えるんじゃなくてパフォーマンスの解析ツールを
買わないとダメじゃないかな。
コンパイラ自体はVC7も用途によっては悪くないし。
8 :
デフォルトの名無しさん:2005/10/27(木) 03:14:44
今月のCマガ買って読め。
STL使うなら自分で同じような物を作ったほうが高速。
その心は?
なんでいきなりSTLが・・・
主要部分をasmで書き直せばOK
>>7 VC++のプロファイラは、普通に一通りの機能を備えているのに、使われないんだよね。
VC.NET用だと、Compuware(Numega)がプロファイラを無償で提供してくれてるよ。
VC++6.0まで、TrueTimeは売り物だったのにねぇ。
>1
>>12 インラインアセンブラよりも、組込み関数を使ったほうがいいことが多い。
・コンパイラが最適化をしてくれる
・プログラムの記述が楽で、修正しやすい。
という2つの大きなメリットがあるよ。
なおVC系の場合、
組込み関数をインライン展開する
というオプションを有効にしてしまうと、
インライン展開されてしまい、最適化されない
という直感的ではない結果になるので、確認しながらやりましょう。
VCにプロファイラがあるなんて気づかなかった
というか2chで聞いたら無いっていわれてずっと信じてた
VC7でなくなったんだっけか
>>13 >使われないんだよね。
GUIに罠が仕掛けてあるからじゃまいか?
19 :
デフォルトの名無しさん:2005/10/27(木) 11:23:51
SSE2が付いてるマシンではインラインアセンブラで書かれた処理を実行したいけど、
それ以外のマシンでは普通のC++で書かれた処理を実行したいと言うような場合、
どうすればいい?
開始時に判別して関数ポインタで入れ替え
やっぱそれしかないか。
関数のインライン化されにくいなぁとか、
C++のメンバ関数だと面倒だなぁとか思ったんで。
>>21 インスタンスをやたら作る必要が無いならファクトリーパターンで作り分けしてもらうという逃げ方もある。
んなややこしいことしなくても、マクロ使って1つのソースから2つのオブジェクトを吐かせればいい。
関数ポインタだってコストかかるので、1つずつの関数を切り替えるのではなく、
2通りのプログラムを1つのプログラムに押し込むくらいの気持ちで、
もっとmain関数に近いところから切り替えてしまおう。
インテルコンパイラってプリフェッチ命令を挿入するとか言ってるけど
プリフェッチって入れても効果ほとんど無いよね?
あとこれからPen3コアをベースにしたCPUになっていくからPen4用に
最適化はしないほうがいい?
>>24 場合によるだろ。prefetch命令はL2へのロードのアルゴリズムを
変更するので、場合によってはメモリのレイテンシを劇的に減らす
事が出来る。というかintelのpdf嫁。
prefetch命令を使って具体的に速度改善を説明する本とかないのかな。
サンプルコードとか載せてるのがあったら欲しい。
Webでも以外と情報無いし。
27 :
デフォルトの名無しさん:2005/10/31(月) 20:11:01
28 :
デフォルトの名無しさん:2005/11/10(木) 03:07:31
>>27 なんだこれ。
マトリクスとかImageとか扱えるものなのか。
結構みんな使ってるんだろーか。
29 :
デフォルトの名無しさん:2005/11/10(木) 05:49:34
クイックソート以外の例えばマージソートやバルブソートなどはどのようなときに使うのでしょうか?
>>29 クイックソートは万能ではない。
特にソートする要素数が少ないときには他の方法が早い。
また、安定でないという欠点もある。(マージソートは安定)
>>29じやないんだが
>また、安定でないという欠点もある。(マージソートは安定)
これどーゆー意味なんよ?
高速化のスレだから速度の事を言ってるのか?
>>31 ソートで不安定といったら
比較関数の評価で重みが重複した場合に順序関係が保存されない
ことだと思うが…(;´Д`)
出席番号順にソート済みの身体測定データを身長順にソートしたいとする。
ただし、同身長の人間がいる場合は出席番号の若い順に並んだままになっていて欲しい。
そういうときは「安定したソート」の出番よ。
クイックソートだと出席番号はバラバラになるからな。
まあ「安定した速度」って点でもマージソートはなかなかのもんだと思うけど
それにしても
それは、キーの指定が悪い。
>>31 基本情報の資格でも取ったほうがいいお
言葉が通じないと頭良くても吸収できないでしょ
>>35 ソートで大小の評価を、
身長だけではなく、出席番号も加味してやればいい
と言いたいのだろう。
でもね、出席番号がついてなかったら、どーするの?
一般的にソート前のインデックス順序を比較で使えばいい
二次キーとして出席番号があるならそれを使えばいいし
インデックスがついていなかったら?
アドレスで比較すればいいだろ馬鹿か?
アドレスで比較? なに馬鹿いってるの?
IntelのライブラリはAMDでワザと遅くなるようにしてそうなんで
一般向けには使ってません
高速なメモリコピーするにはmemcpy?
それともキャシュ無視するためにSSEとか利用するのか?
memcpyの実装はたくさんあるから一概には言えないぞ。
最もシンプルなのは1バイトずつコピーしているし、
コンパイラによってはインライン展開どころか組込み関数として処理しちゃうぞ。
45 :
43:2005/11/15(火) 02:12:42
へぇー、組み込み関数(SSE?)で処理しちゃうのか。
ネットで調べてたらSSEのレジスタ4つにまず読んで、それを
また4つ書き出すとレイテンシとやらを隠蔽できるとかなんとか
あったけどそんな感じかな。
とりあえずmemcpy使っておきます。
組込み関数の意味がわかってない希ガス。
関係ないけど __divdi3 は組み込み関数なんだろうか。
直にCPUの命令またはその組み合わせに展開してしまえる関数だね。
組み込み関数の利用は#pragma intrinsic で明示できるよ。
逆に出来ない場合は組み込み関数として用意されてないといえる。」
ぶっちゃけIntel C++のオートベクトライズなんてあんま役に立たない。
処理を並列化できるところは明示的にMMX/SSEの組み込み関数
使って最適化したほうがいい。
CPUの動きを知り尽くしてレジスタカラーリングしてくれるから
へたなアセンブリコード書くより速い。
あとIntel C++なんかは、インライン関数を基本的に展開しない。
STL使ったら重いってことは結構ある。
ただし __forceinliceは受け付ける。
VC2005はcpuidとかローテート命令まで組み込み関数として使える
ようになったから、アセンブラ嫌いにはかなりフレンドリーになった希ガス。
ローテートはVC6の頃から組み込み関数であった希ガス。
51 :
デフォルトの名無しさん:2006/02/13(月) 23:04:16
U
\ |
\ 人 /
メ´ ヾ _,−'
−―< , -、 て_
C++とSSE! ) / / (´
/ / ⌒ 、
(⌒V ,'´`ヽ
ト、 ,ヘ ヽ ! :〉
ト、ヽ / /! / 、゙ーァ'
|,ノ ´ ̄` ヾ! / /`~´
,' > < ゙, / /
l 、ー―:ァ i/ /
゙、 Y⌒/ ,/ /
`''ァ‐`ー' /
/ i /
52 :
デフォルトの名無しさん:2006/02/14(火) 09:28:47
だんごって何の仕事してんの?
53 :
デフォルトの名無しさん:2006/02/14(火) 17:36:10
.NEETでFA
54 :
デフォルトの名無しさん:2006/02/17(金) 12:53:20
倍精度実数、うらやましいなー
constで最適化が促進させられる理由ってなんでそ?
56 :
55:2006/05/10(水) 23:28:03
書き込むスレ間違えました。失礼しました。
57 :
デフォルトの名無しさん:2006/06/03(土) 15:41:51
[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 カップラーメンを従来の1.5倍の速度で完成させる最適化技法
調理時間の短いラーメンほど短時間で伸びる
グルテンを加えるといい
62 :
デフォルトの名無しさん:2006/06/08(木) 20:36:36
麩になっちまう
63 :
デフォルトの名無しさん:2006/06/11(日) 01:52:05
即値で掛け算する場所を書き直してみたら?
PenMのSSE2って遅くね?
65 :
・∀・)っ-○◎● ◆toBASh.... :2006/06/11(日) 14:11:11
デコーダがネック。複合デコーダパスだからね。
汎用&MMレジスタベース命令と交互に配置するとデコーダネックを隠蔽できる。
Yonahでは解消されてる。てかめちゃくちゃスループットいい
じゃあPenMだったら無条件でSSE2不使用、ってコーディングはもうしちゃ駄目だね。
そもそもYonahな時点でPenMじゃないし。
つかPenMって3年前から更新されてない一昔前のチップだろ。
ド忘れされてるDothanとi915萌え
YonahもBanias、Dothanと同様Pentium-Mですよ。
ただ発表後にPentiumブランド消失と絡んでIntel Coreとも名付けられちゃったが。
ブランド展開がまだよく分からんのでこの先どうなるか知らんが
面白い話題なんでもっと調べたいんですが、
いい本ないでしょうか?
やっぱりパターソン&ヘネシーですか?
メーカのドキュメント
71 :
デフォルトの名無しさん:2006/10/12(木) 18:47:05
SSEはコンパイラが自動的に使ってくれるのですか?
コンパイラによる。VCだとスカラ演算のみ。
自動ベクトル化が可能なコンパイラはgcc4.0系とかiccとかPGIとか。
73 :
デフォルトの名無しさん:2006/10/20(金) 02:49:00
SSEで最適化してもメモリアクセスのほうがボトルネックになんね?
キャッシュとかよく分かんねけどメモリよりキャッシュを意識せな
いかんのだろうけど。
処理の内容によるんじゃない?
動画の画像処理みたいにプリフェッチの予測が当たりやすい処理だと
メモリ帯域の方がボトルネックになってる感じはしない。
他の分野についてはわかりません。
>>73 同じデータを色々な組み合わせで何度も使う場合
キャッシュをうまく効かせるのが腕の見せ所。
誰かSSEのプリフェッチをどう使えばいいのかまとめてくれ。
めちゃくちゃ大雑把に話せば、
メモリを使う100クロック前くらいで
64byteごとに1回プリフェッチ命令を置く。
どの命令がいいかは、全部試して速いのを採用。
詳しくは、たくさんコードを書いてから
キャッシュについて勉強してくれ。
俺も勉強せねば・・・。
GPUと組み合わせ使うて場合って
GPUができる計算はみんななげちゃうって方針でいいの?
低次元行列計算はDirextXでできるみたいだから、
DirextXになげちゃおかと思ってるのだけど
>>78 DirectXは誰が動かしていると思っているの?
ユーザプロセスは?
OSカーネルは?
80 :
デフォルトの名無しさん:2006/11/11(土) 01:02:00
インテルのペンティアムプロセッサのマシン語で
高速化を勉強できる良い入門書みたいなのあったら教えてください
ホント、よろしくお願いします。
このとおり!m(_ _;)m m(-.-;)m m(_ _;)m
そうおっしゃらず。。
なにとぞ、お願いします〜m(_ _;;)m
>>83 いやマジで、下手な本買うよりiccのアセンブラ出力眺めた方がよっぽど勉強になるって。
なるほど、そういう意味でしたか。
>>80 MMXテクノロジ最適化テクニック(ISBN4-7561-0797-4)の5章
86 :
80:2006/11/11(土) 22:35:35
>>85さん、ありがとうございます。
早速書店で探してみます。m(_ _)mペコリ
87 :
【凶】 【488円】 :2007/01/01(月) 10:52:18
SSEでどこか参考になるサイトはありませんか?
つ[google]
最近のコンパイラはSSEなどは指定しなくても自動的に使ってくれるのでしょうか?
ではまず最近のコンパイラの定義から(ry
インテルコンパイラです
自動的に使うようになってると、SSEがないCPUでは動作しないのでは。
O3を指定した場合、自動的に検出され使われる
95 :
デフォルトの名無しさん:2007/01/08(月) 19:03:58
_ ∩
( ゚∀゚)彡 オッサン!オッサン!
⊂彡
ここってこんなに人居たんだ
/Qx*とか/Qax*なしで使うことってあったっけ?
とりあえずboost:mt19937はICCのオートベクトライズでやたら速くなるが
AMD64向けだと強制的に使ってくれる。
自動ベクトル化は知らん。
101 :
サイザー専用JAVA演習場 その2:2007/01/08(月) 21:17:02
次スレまできた。飽きっぽい俺が良く続くもんだ。Σ(´∀`;)
どうぞよろしくお願いします。
SSE3は載ってたと思う。SSSE3は知らん
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命令を使った方が一見速そうに見えるのですが・・・。
BaniasかDothanかYonahかにもよるけど、SSEはあんまり得意じゃないよMは
106 :
104:2007/02/10(土) 16:29:40
>>105 Dothanコアです。
MはSSEが得意ではないのですね。参考になりました。
参考までに、姫野ベンチでも実験したところ、こちらは-mfpmath=sseありの方が速かったので、
コードに依るかも知れません。
Pentium M系アーキテクチャでSSE*が遅いのはデコーダがネックになってるらしい。
Complex Decoderのみでデコードされるから、倍精度は浮動小数が速くても不思議じゃない
Pentium MのFPUは加減算・乗算毎に倍精度×1、単精度×2だけど
x87とSSEスカラ演算だと単精度はクロックあたり1、SSEのパックド演算だと2つは
発行できるから、単精度ならまだ使う価値があるね。
演算ユニットの構成は
Port 0: x87ADD x87&SSE-MUL
Port 1: SSE-ADD(SP Only)
よってクロック毎に実行できる最大値は
x87-SP: 1
SSE-SP: 4
SSE-DP: 1
んでもSSE使うように最適化オプションつけた方が
遅くなるってのは不思議だよなぁ。
早くならないってことはあっても遅くなるってのはなぁ・・・
タスクスイッチのときにXMMレジスタも全部退避するようになるから?
そういやXMMレジスタまで対比するか否かってOSはどうやって知ってるの?
>>109 そもそも初期状態でFPUセットになっているのなら、SSEを使うだけで切り替えコストが発生する。
まあ、Complexデコーダパス命令だから、の一言なんだが
待避のオーバーヘッドなんてたかがしれてる
MXCSRレジスタってあるじゃん
>>110 それXMMレジスタじゃなくてMMレジスタの話では
でもSISDならデコードも速い。
単純にコンパイラが最適化しきれてないだけじゃないのか。
そもそも104氏が何の処理をさせてたのか書いてないから
イマイチ議論のしようがない気もする。
おそらく人間が書けばDothanでもSSEの方が速いとは思う。
Core 2 (Merom)ベースのCeleron Mももう出たし
116 :
デフォルトの名無しさん:2007/02/19(月) 20:47:39
二つの符号付及び符号無し 64bit 整数の乗算、
さらには 128bit 整数同士の乗算などは
SSE/SSE2/SSE3 命令群を使うことで高速化できるのでしょうか?
そもそもこれらの命令は SIMD 目的であって
ビット幅の長い演算が目的ではないので、
見当違いでしょうか?
64ビット同士の整数乗算は素直にx64命令セット使えと思うが。。。
16×16の積算・積和演算があるから組み合わせればいくらでも可能だ罠
118 :
デフォルトの名無しさん:2007/02/21(水) 14:03:24
海外旅行での現地のATMでのキャッシングって、
キャッシング枠ですか?それともショッピング枠ですか?
以前現金主義の友人がどうしても両替商見つからなくて
現地のATMでキャッシングしたら、日本に帰ってきて
ショッピングとして明細に出てたって聞いたんですが。
誤爆じゃないのか
121 :
デフォルトの名無しさん:2007/03/02(金) 21:40:36
浮動小数点モデルを /fp:fast にする
精度は落ちるが
マルチタスク/マルチスレッドで、セマフォを長時間握ったまま返さない奴とか見つける、とかは
やっぱプロファイラとかで動的解析しないと分らんよね。
そんなの静的解析でどうにかなるもんじゃないか・・・。
123 :
デフォルトの名無しさん:2007/06/04(月) 18:02:04
doubleは2つ同時にしか実行できないのか?
124 :
デフォルトの名無しさん:2007/06/04(月) 18:08:28
だぶる先生らいふのことだろ。
常識的に考えて。
ダブル先(の)生ライフ?
下がり過ぎ
SSEで大部分が記述された
正規表現エンジンって知りませんか?
闇雲にSSEを使えば速くなるってもんじゃないし、そんな阿呆な代物ないでしょ。
# 速度に寄与する肝腎な箇所に使っているってことなら話は別だが。
sseで正規表現・・・どこで使ったものやら
SSEって並列処理や積和なんかが1命令化で速くなる。
端からデータを舐めていくような処理はあまり効果ないよ。
特に検索には向かない。
bit列のマッチングはどう?
1bitずつずらしたのをxorしてall 0になったかどうか調べるとか
strlenをSSE2でやる人がいるくらいだし、その応用でstrchr/strstrのような単純な検索はできると思う。
ただ、正規表現となるとうまく使うのは難しいと思う。
sse4.2じゃないのか
137 :
,,・´∀`・,,)っ-●◎○:2008/12/21(日) 11:48:46
固定文字列部分を抽出してBoyer-Moore法とかで検索するのが良く使われる方法。
strstrなんかはSIMDを使った力技検索に置き換えることができる。
>>136 確かにあれは速いようだ
138 :
,,・´∀`・,,)っ-●◎○:2008/12/21(日) 11:51:30
固定文字列部分ならともかく「大部分」をSIMDに置き換えることに意味はない。
文字クラス程度ならSSE4.2で一括判定みたいなのも可能になるかと思うけど
つうかそんなのAltiVecでとうの昔にやられてる事だしな。
Intelは必要な命令(シャッフル、MIN/MAXなど)が揃うまでにどれだけかかるんだ。
ルーチンごとにSSE1があるか、2があるかと判定しなくちゃいけなくて面倒くさい。
140 :
,,・´∀`・,,)っ-●◎○:2008/12/21(日) 12:18:35
Macのこと言ってるのか?
SSE3以上使える前提できめうちで組めるからかえって楽だろw
大体にAltiVecに文字列比較命令なんてねーよ。
汎用レジスタ−SIMDレジスタ間のダイレクト転送命令ないし
レジスタ値を比較してbranchフラグを更新する命令もない。
そもそも更新が停まってるだけだろ。
141 :
,,・´∀`・,,)っ-●◎○:2008/12/21(日) 12:30:26
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 :
,,・´∀`・,,)っ-●◎○:2008/12/21(日) 12:47:01
俺の経験上文字列サーチでAltiVec使うと遅くなるケースのほうが多い。
だからMacOSでもstrcpy/memcpyみたいな分岐の必要ない操作に限ってだけAltiVecが内部的に使われてる。
同時比較でいいならロードして比較してvec_all_eq()するだけじゃね?
ストアと読み出しはいらん。
>vec_all_eq()
あのさー、それ複合関数だから。
ではマスク生成+縮約+ストア+汎用レジスタにロードって操作を1つの組込関数に纏めただけ。
1インストラクションで済んでるわけではない。
アセンブリコード読んだことある?無いだろうけど。
CPUネイティブのベクトル比較命令であるvcmpequb自体は、SIMDレジスタ上にマスクを生成するのみ。
マッチしたのか、マッチしてないのか、マッチした場合、どこの位置でマッチしたのかっていう判定は
汎用レジスタ側でやるしかないんだよ。
お前こそvcmpequbの仕様を読んだ事あるのかと。
> The CR6 is set according to whether all, some, or none of the elements compare equal.
最近論調がおとなしくなってきて改心したのかと思えば、
内心人を見下してるのは変わってないんだよな。
あ、なんでアセンブリコードとか的外れな事言ってるのかようやく分かった。
最適化オプションを全く指定しないと確かに複合になるね。
ていうかさあ、デバッグ用とはいえ確かにこのアセンブリは変態だけど
つまりはお前は大口たたいておきながら
その実
>>143を言われて顔真っ赤にして焦ってアセンブリ出力を確認したんだろ。
恥ずかしいなあ。
「.」付き版はcr6を更新するからptest相当のことだけはできるよ。それは正しい。
どこでマッチしたかを求めるには汎用レジスタ側でやんないといけない。
pmovmskb相当の命令がないから遅いんだって。
Cell SPEだと7ビットシフトしてギャザリングし、ビットスキャンすれば位置が求まるけど
>>147 で、pmovmskbの代用命令はどこにあるの?
っヒント:もうL1に乗ってる
>>149 無いよ。
そこを叩きたいなら叩いてくれ。
そんなことは聞いてない。
SSE*にはSIMDレジスタ上のベクトルデータのMSBを縮約してダイレクトに汎用レジスタに転送する命令がある。
bsfと組み合わせればマッチ位置まで簡単に求めることができる。
AltiVecには、そういう命令は、ない。
支離滅裂だな。
それが初めから分かってるなら慌ててアセンブリ確認なんてしてないだろ。
百歩譲って今お前が力説したい事にスポットを当てるなら
all_xx()が複合であるかどうかなんてどうでもいいんだからな。
ていうかstrchなのかstrstrなのかハッキリしろよ。
反論するのに都合の良い方を選択してるだけじゃねーか。
慌ても確認もしてないよ
じゃあall_xxが複合だと言ったのはどこのだれですか?
結局gather出来ないんだから、そこはどうでもいいんだけどね。
>>154 どっちもSSEより遅いよ。
PPCからの移植にSSE1まで使えるか2まで使えるかとか気にしなきゃいけないと思う方が馬鹿だよ。
Win32でもSSE2が使えないCPUなんてどのみちSIMDユニットの実装もショボイから最適化対象としては無視して良いくらいだよ。
非SIMDのパスに飛ばしておけばいい。
まあそれも論点ずれてるんだが、建設的な話をしたいからお前に合わせよう。
確かにSSE2が使えないCPUは大抵しょぼいから無視しても良いんじゃないかな。
強いて言うならAMD(笑)が例外だが。
でもx86陣営がそういう路線を歩んでいるのは間違いなくて
SSE3, SSSE3, SSE4.1, SSE4.2, AVX, LNIといちいちチェックしなくてはいけない日々が続く事には変わりない。
Core2 Duoと比較して、Athlon X2がそれほど酷いとは思えないんだけど。
整数演算はひどいな
一晩考えて、何故団子がgatherに必死なのかが分かった。
団子はトリップ検索が主だから検索対象が極端に小さくて、
詳細な位置の特定の方がボトルネックになっているんだな。
tawake
163 :
デフォルトの名無しさん:2008/12/22(月) 18:42:38
続きをどうぞ
変な事言った?
一晩考えることじゃないだろ。俺のブログ一通り読んだら30分以内に否定される。
で?
笑いしかとれなかったね
そうだね。俺もだけど団子も痛い子だね。
痛いのはお前だけですからwww
だから何故?
煽ってるんじゃなくて純粋に。
無知のまま過ごすのは恥だし勿体ないので団子でも名無しでも回答くれないかな。
名無しが答えられるかどうかは疑問だけど。
∩___∩
. \ | ノ ヽ
\ / ● ● |
\| ( _●_) ミ そんなエサでおれが釣られるかクマー!
彡、 |∪| ,/..
ヽ ヽ丿/ /⌒|
/ \__ノ゙_/ / =====
〈 _ノ ====
\ \_ \
\___) \ ====== (´⌒
\ ___ \__ (´⌒;;(´⌒;;
\___)___)(´;;⌒ (´⌒;; ズザザザ
都合が悪くなるとすぐ逃げるか話そらすからな。
結局161が図星だったのか。
名無しが寂しそうにしてるから構ってやれよw
ビット演算の代数的な性質、それを導き出す公理が知りたい
算術演算から式変形だけでアセンブリ言語のコードを導き出せるようになりたい
コンパイラでも作りたいの?
178 :
デフォルトの名無しさん:2009/01/07(水) 23:00:55
メモリアクセスとかを考慮すると構造体より配列のほうが高速?
SSE2でnビット左rolってどうやって記述すればいいのですか?
Intelのマニュアル読みなさい
好きなの使え
;;【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とかのシャッフル命令使った方がいい。
俺の質問には答えずに人の質問には答えるんだな。
要素ごとのは、例えば最上位に立っているビットからNビット欲しいとか色々使い道はあるよ。
floorみたいのを自力で実装しようとすれば分かる。
サーセンwwwpandじゃなくてporだwww
>>179 うほ?
>>178の意味がいまいち分からんが、
char array[0x100];
と
struct{char value;} array[0x100];
だったらレジスタサイズにパディングされる分、構造体の方が早くね?
ちなみに、同じ事だが容量気にして構造体のなかでshortとか使うと
パデイング入るんでメモリに無駄が発生する。
まぁ、パディングを知っていれば無駄を防ぐこともできるけど。
構造体にすればパディングされると決まっているわけではない。
だからその例だけだとどちらとも言えない訳だが。
構造体のメンバを一部だけshortにするのは意味が殆どない(寧ろ遅くなる)という点については同意。
187 :
デフォルトの名無しさん:2009/01/11(日) 01:26:48
>>185 short array[3];
と
struct{short value1;short value2;short value3;} array;
でどっちが高速かという意味です。
配列のindexが定数なら変わらんだろ
アセンブラ見ろ
>>185 > struct{char value;} array[0x100];
> だったらレジスタサイズにパディングされる分、構造体の方が早くね?
pragmaやattributeでパックしない限りpaddingは入らないだろ。
190 :
,,・´∀`・,,)っ-●◎○:2009/01/11(日) 06:03:24
16とか32になるのはいいけどメモリアドレッシングで使えるscaleが8倍までなんだよな。
添字によるアクセスは思わぬ性能低下を起こすことがある
191 :
,,・´∀`・,,)っ-●◎○:2009/01/11(日) 06:05:36
>>189 構造体やその配列の場合、パディングが入る。
デフォルトが4バイト単位だったかな?
おまえほんとにだんごか?
デフォルトなんて決まってるわけ無いだろ
193 :
,,・´∀`・,,)っ-●◎○:2009/01/11(日) 10:25:51
まあデフォルト値は処理系依存だな。
>>189の言ってることが嘘ってことで。
少なくともパディングが入らない保障はない。
コンパイラ依存だよな。
歴史的な理由で当時の最長のレジスタがdoubleだからCPUのアライメントが8byte推奨で、コンパイラも8byteに詰めてた気が。
もしかしたらx86じゃなくてPowerPCかも知れん。
195 :
デフォルトの名無しさん:2009/01/11(日) 14:47:57
VCやGCC辺りはパディングが入る。
Bitmapヘッダをそのまま構造体で読み取ろうとして引っかかった
やつも少なくない筈。(VCならpragmaを使えばパディングを消すことができる)
一応32bitCPUならVC、GCC共にcharもshortも32bitで確保される。
64bitなら64bitで確保されるとか聞いたことがあるが真偽は不明。
蛇足だが、VCでchar array[5];などと確保すると確保した容量+3
の領域が確保される。
将来AVXの1024bit SIMDが使えるようになった際に、128byteにパディングされるとかなるとイヤだな。
その頃にはメモリは数十GBで128byteなんてゴミみたいなもんだろうけど。
その頃までにSIB.scaleのビット拡張してほしいね。1ビット増やせばx16, x32, x64, x128になるのに。
\ \\ ____ // / /
< _-=≡:: ;; ヾ\ >
< / ヾ:::\ >
< | |::::::| >
< ミ|-=≡、 ミ≡==- 、 |;;;;;/ >
< || <・>| ̄| <・> |── /\ >
< |ヽ_/ \_/ > / >
< / /( )\ |_/ >
< | | ` ´ ) | >
< | \/ヽ/\_/ / | >
< \ \ ̄ ̄ /ヽ / / >
< \  ̄ ̄ / / \ >
/ /  ̄ ̄ ̄ ̄ ̄ ̄ ̄ \\ \ \
___
/ ―\ ナンミョウホウレンゲッキョウナンミョウホウレンゲッキョウナンミョウホウレンゲッキョウ
/ノ (@)\ ナンミョウホウレンゲッキョウナンミョウホウレンゲッキョウナンミョウホウレンゲッキ
.| (@) ⌒)\ ナンミョウホウレンゲッキョウナンミョウホウレンゲッキョウナンミョウホウレンゲッ
.| (__ノ ̄| | ///;ト, ナンミョウホウレンゲッキョウナンミョウホウレンゲッキョウナンミョ
\ |_/ / ////゙l゙l; ナンミョウホウレンゲッキョウナンミョウホウレンゲッキョウナンミョ
\ _ノ l .i .! | ナンミョウホウレンゲッキョウナンミョウホウレンゲッキョウナンミョ
/´ `\ │ | .| ナンミョウホウレンゲッキョウナンミョウホウレンゲッキョウナンミョ
| | { .ノ.ノ ナンミョウホウレンゲッキョウナンミョウホウレンゲッキョウナンミョ
| |../ / . ナンミョウホウレンゲッキョウ
パディングってむやみに入れるとキャッシュヒット率悪くなってかえって効率落ちたりしないんだろか
201 :
,,・´∀`・,,)っ-●◎○:2009/01/12(月) 00:42:04
逆にキャッシュラインを跨ぐと効率悪くなるんだよ
実測すれば済む話
>>191 cygwin上のgccで試してみたけど、padding入らないよ
>>204 CPUによるが
struct foo {
char a;
double b;
};
でパディングが入らなかったら例外起きるだろうが。
起こんねーよ、CPUによるが。
struct {char a, b, c;}だったらパディングなくても例外起きないよ。
コンパイラがまともなら。
アラインメント制約の厳しいプロセッサなら、例外が起きないようにコンパイラが勝手にパディングするんじゃないかな。
しかしミスアラインメントのデータに対するロード・ストアの扱いは各CPUアーキ毎に方針が違ってて面白いな
x86のSSE以降は、ミスアラインメントを許すが遅い命令と、許さないが高速な命令の2通りを用意。
対して、POWER/CellのSIMDは下位ビットを無視してロードし、プログラマが勝手にPermuteしてくれっていう扱い。
下位ビットを無視してくれるのはわざわざAND取ってアライメントする必要がないから楽でいいよな。
中を作る側もデコーダが軽くなるからウマー
>>205 >
>>204 > CPUによるが
> struct foo {
> char a;
> double b;
> };
> でパディングが入らなかったら例外起きるだろうが。
なぜ勝手にdoubleが入ってるんだww
誰もそんな場合の話はしていない。
団子にこんな基本的なことで嘘つき呼ばわりされたが嘘じゃないってことで
>>185 > struct{char value;} array[0x100];
ところでパディングの入らない環境ってどんな環境だろ?
PC用で32bitプロセッサじゃ大抵入ると思うが。
sizeof(struct{char value;})==4
見たいにね。
struct{char value;} array[0x100];
printf("%d\n", sizeof(array));
=> 256
gcc-4.3.2ではこうなったけど、パディングってそもそも何だ?無効領域?
>>212 Crayだとchar=short=int=32bitとかが普通らしい。
PC用じゃないけど。
>>213 ゴメン
sizeof(struct{char value;})じゃ1だね。
sizeof(struct{char v1;short v2})じゃ4になったから試さずに
書いちゃった。メンバーが同じサイズなら配列化されるっぽいね。
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 */
俺的に配列は__declspec(align(32))がデフォです
32?
16じゃないのか?
AVX化を視野に入れてるから
Alphaには16bitレジスタなかったよん
221 :
デフォルトの名無しさん:2009/04/07(火) 23:53:51
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);
:
っ _mm_set1_pi16
>>222 __mm_set1_pi16とか_mm_set1_pi8とかですと、MMXレジスタが対象と
ありました。
SSEレジスタにセットする場合、もしかして次のような手順になるのですか?
CPUでメモリ上にパターンを作成
SSEレジスタにロード
それとも、そもそもsseレジスタを使うのが遠回りで、MMXレジスタで2回
まわすのが普通なのでしょうか?
「e」pi16だな。
>>224 なるほど!
__m128i _mm_set1_epi8(char b)
見落としていました。ありがとうございました。
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]弱を要する。
極力、同じレジスタに連続して触れないように書こうとしても、
何かとやりづらい。
他に適当な方法があれば、教えて欲しいとか、書いてみる。
pmaddwd 2個で済むように書けるよな?
thx
pmaddwd - packssdw - pmaddwdで、vuかyyの二要素出せるのかー。
/(^o^)\
5[ms]弱に短縮。
適当に並び換えれば、もう少し行けるかも。
バイト列の入れ替えをしたいのですが、普通はどのように行うのでしょうか。
単に偶数、奇数バイトをスワップさせたいだけなのです。
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を取る
という方法しか思いつきません。もっと賢い方法がありそうな気がします・・・
4バイトならbswapで一発なんだが
言葉足らずですみません。xmmでの処理途中なんです。
psrlw psllw por
または
pshufb
あたりじゃね?
>>231 エンディアン変換命令使ってどうするw
>>233 なるほど、前者はSSE2までのマスク+シフト+orですね。
後者はSSSE3ってことはCore2Duo以降ですか・・・
CoreDuo以前を切り捨てれば楽だけど・・・ん〜。
2通りの関数書いてCPUIDで振り分けるのはどう?
SSSE3でも128ビット版は65nm版Core2やAtomは速くないよ。
ちなみにSSE5なら
protw xmm0,xmm0,8
で1命令ですな
>>235 >2通りの関数書いてCPUIDで振り分けるのはどう?
これでやってみます。サンクスでした。
あ、言い忘れたけどDLキーはデフォルトの1です。
ちなみに家の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
生のアセンブラで書けよ!インラインってw
実行せずとも分かる事を述べよう。
ソースを16バイトアライメントに合わせている?
ソフトウェアパイプライン化が行われていない。(これをやっていないとSSEの意味がない。)
そもそも速度計測しているコードが小さい。
SSE4.2だと1命令でなかった?
勉強し始めです。
リトルエンディアンと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で右シフトした状態というのは、
メモリ上では(上記表現では)左シフトした状態に相当
これ、認識あっていますでしょうか。
デバッガで見えるレジスタの状態は右が下位だよっと
糞長い128bit変数だと思えばいいよ
>>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;
}
【続き】
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のより遅い。
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));
}
訂正してくだしあ><
【これが正解】
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 :
240:2009/04/19(日) 06:24:28
>>,,・´∀`・,,)っ-○○○
うちのAthlonの環境でも
>>246のdango-sseの結果と大体同じくらいの性能うpが確認できました。
しかし、こんなに差がつくとはSSE侮りがたし。
団子さん、多謝です!
VC++ と gcc (言語は C++)のインラインアセンブラで
SSE の16バイトアラインメントされていることを仮定した命令を使いたいのですが、
float の配列変数全体を16バイト境界にアラインさせることって可能ですか?
>>250 __declspec(align(16))と__attribute__((aligned(16)))
マクロなりなんなりで切り替えればいい
__m128(あるいはその配列)との共用体にすれば勝手に合うけどね。
gcc で使えるの?
gcc で使えるの?
大事な事なので2回聞きました
#include <xmmintrin.h>
あとコンパイルオプションにフラグつけとけ
-msse
とか
そしてautotools地獄へ…
ああ、あのへんマジで何とかして欲しい。
Win32ではASMで書いた関数の頭にアンスコ付けないと認識しなかったりとか
頭に…アンスコ…?
アンダースコート被るんだよ
underscore、呼出規約云々のアレ。
こやつらには5Fhって言った方がわかりやすいかもしれんな
プログラマのくせに、「あんすこ」が通じないのはおかしい。
職業プログラマだけじゃないだろ
趣味でやるやつもいる
趣味グラマだけど理解してるよ
アンダーバーとか言う奴は素人
ひゃっひゃっひゃっひゃっ
なさけなや
アンダーバー。
今のVCのコンパイラは、インラインアセンブラを書くと、そのインラインアセンブラを含む関数が最適化がされないらしいけど、
xmmintrin.hなどは、使うと最適化されなくなる?
うん
274 :
デフォルトの名無しさん:2009/05/01(金) 21:45:13
インラインアセンブラだけインライン関数で分離すればいいじゃまいか
インライン展開されたら最適化抑制も伝播したりして。
>>273 いやいや、組込関数ならインラインアセンブラと違って最適化できるという触れ込みではなかったっけ?
sse使って、まだコンパイラが入り込むある余地があるのか?
xmmintrin.hなどの場合はxmmレジスタへの割付が最適化まかせなので、
最適化をしないと、1命令ごとにメモリとデータをやり取りするので非常に遅くなる。
__m128iってクラスはレジスタ的なもので局所変数にしか使えないかと思ってたんだが、
実はvector<__m128i> みたいな使い方もありなの?
typedef union __declspec(intrin_type) _CRT_ALIGN(16) __m128 {
float m128_f32[4];
unsigned __int64 m128_u64[2];
__int8 m128_i8[16];
: 略
} __m128;
てな感じで普通にメモリ上にとられるよ。最適化でレジスタに置きっぱなしになる。
281 :
279:2009/05/01(金) 22:54:29
そうなのか。ありがとう。
組み込み関数の最適化は
lstファイルでも出力して見てみるといいよ。
一応されるようだよ。
GCCはpshufb周りのコード生成が酷い。
284 :
デフォルトの名無しさん:2009/05/01(金) 23:36:16
まあgccはコードジェネレーター部がx86決め打ちじゃなくて汎用だからな
_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の引数の順番間違えてて、応急処置的に直したんじゃないかと思うんだ
そういうときはgccのソース読むのが基本だろ。
insn-attrtab.cが酷いな。SSSE3以降の命令の扱いがテキトーすぐる。
>>279 処理系によっては自作アロケータで128ビットアラインされた領域に確保するようにしないと酷いことになるかもしれません。
289 :
デフォルトの名無しさん:2009/05/04(月) 21:03:31
GCCはGPLなんだから文句ばっかり行ってないでお前らも
プロジェクトに参加して改良しろよ
それは本末転倒。アセンブラよりも作業効率を期待してCコンパイラで生成できないか試みてるのに
いっそう手間かけてどうすんだと。別にGCCである必要ないんだよ。
っていうかオープンソース界隈は今頃AMD SSE5がキャンセルで大荒れだと思う。
まあ、正論だな
292 :
デフォルトの名無しさん:2009/05/04(月) 22:21:05
ダンゴさんの正論でスレがピリッと引き締まったな。
キャンセルって何の事って調べたら・・・
俺的にはAVX一本のほうが楽でいいな。AMDは正しい判断をしたと思う。
当初の予定はSSSE3もSSE4もサポートせずに、SSE5追加だけだったよね?
いや、元々SSSE3はSSE5と一緒に追加、SSE4.1/4.2は順次対応する予定だったと思う
Intel様、3Dゲームとか画像とか動画エンコとか特殊な用途向けよりもっと一般人が
恩恵をうけれるような命令を追加して下さい。といいつつ、マイナーな事言いますが、
IEEE754Rで改訂された10進浮動小数点の命令を追加して下さい。
一般用途とかけ離れてるだろ10進浮動小数なんて
金融演算でもやるのか?
>>290-292 一度実装すれば以後恩恵を受けられるわけだし、そもそもサポート契約してないなら、正論とは言えないだろう。
本来そういうのはハードベンダーが技術協力名目でやるものだろう
インテル様はインテル・コンパイラを買えと仰っているからなぁ。
gccのauthorに-○○○@2ch.netとでも付け加えた方が
トータルで安く上がるだろ。
Intelコンパイラもたいがいだよ。
_mm_set1_epi8()はCore 2以降でなら
>>285の実装のほうが速いのに
-QxSSE4.1とか加えても使ってくれないのはどうしたものかね
_mm_set1_epi1(0)を pxor (_mm_setzero_si128()相当)に置き換えるのはさすがにやってくる
302 :
デフォルトの名無しさん:2009/05/08(金) 06:17:11
メディアンフィルタの高速なアルゴリズムを教えてください。
複数のピクセルから中央値を選べばいいだけなのですが、
ifステートメントを避けて並列化する方法はないでしょうか?
それを考えるのが面白いところなのに・・・
ちなみに言うと8要素のソートして真ん中の値をとればいいだけ。
pmaxub/pminubを使うことで大小入れ替えができる
ちょっと考えてみたが愚直な並列バブルソートでpmaxub/pminubを合計40回程度かな?
それでも1要素あたりにすると2.5回の比較で済む。
まあ、ベクトルのセットアップがちょっとばかし大変だが。
8?
自身含めて9か。
すまん素で間違えた
3.5命令・・・うーん
ダンゴさん何者なんだw CPUに詳しいな。
ダンゴさんへの賞賛でスレがヒートアップしたな
310 :
デフォルトの名無しさん:2009/05/10(日) 16:54:52
AGIストールとかパイプリングストールとか意味がわかりまセンチ
だんごー
だんごー
だんごー
だんごー
だんごー大家z(ry
だんごさんって鳥の方の人かしら。
もしそうだとすると、数年前に某荒板でCPUのこととかお話した元コテですがお久しぶりです(´・ω・`)ノ
人違いだったらごみんなさい。
島は鳥の左側です。
レフトシフト
おまえらだんごさんがいるうちにいっぱいためになる話聞いておけよ。
いっぱいだめになる話?
itoaを高速に書く場合
どうやってかけばいいのですか?
val % 10なんかで基数割してると
遅くてダメポなんですが.......
除算が遅いなら0.1を乗算すりゃいいじゃない
100でやれば除算回数が半分になる
テーブル引け
,,・´∀`・,,)っ-○○○先生
おられませんかー?
>>317 一体何桁の数字を変換したいんだ?
速くしたけりゃベクトル化すればいいだろ。
fbstpとか
10桁は遅いか
いっそ数値の方をBCDにしちまえ
ついでにCPUを6502にだな
10桁の数字を何回処理してどの程度時間がかかり、
どれだけ高速化したいのか位は言えよ。
fildしてfbstpするのが速そうではあるね
基数は可変...っと。
ふつーitoaの高速化は無意味。
> 基数は可変...っと。
それitoaじゃねー。
x86のAAMとかAADの基数って変えられたよな?
Opcodeがないからマシンコード直打ちになるけど
331 :
デフォルトの名無しさん:2009/08/27(木) 19:59:33
if (a>=b) a = 0;
これから条件分岐を取り除くにはどうすれば良いですか
(void)(a >= b) && (a = 0));
余計な括弧がついていた
(void)(a >= b && (a = 0));
334 :
デフォルトの名無しさん:2009/08/27(木) 21:50:02
それってアセンブラレベルでは分岐してないか?
アセンブラ以前に分岐しとるがな
if構文を使ってないだけでしかない
なぜ条件分岐を取り除きたいの?
倍精度・スカラだとこんな感じ
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でないと
根本的に高速化にならないと思うんだ。
なんのために分岐を除去するのか、本末転倒な解決策でもいいなら、他にいくらでも方法はある。
つーか三項演算子ってもともとハードがサポートしてるから、それを利用する為に作られたってどこかで読んだような。
x86がサポートし始めたのがC言語の登場に比べれば割と最近だからまるで最新技術のような錯覚を覚えるけどな。
Pentium Proが出た時期を最近とか言っちゃうか?
それを最近って言っちゃうならRISCでプレディケートをサポートするCPUはかなり新しい部類だよだよ。
分岐のオーバーヘッドを軽減するための機構が必要になったのはパイプラインが深いCPUが出だした頃の話だからな。
分岐(条件ジャンプ)が相対的にボトルネックになったのが動機。
つーか、Pentium Proの更に10年前、386の頃からCコンパイラはあったろ?
あと、こんなブログ見つけた
http://keisanki.at.webry.info/200908/article_8.html これARMそのまんまだな
Conditional MOVEで思い出したけど、cmovcなどのフラグレジスタを見るものは、前の演算結果が出るまでストールするから、普通に条件分岐するより遅くなることが多いって本当?
>>339 大嘘
>前の演算結果が出るまでストールする
これは大いなるミスリード。
CMOV命令の結果に依存しない命令は先行実行出来るだろ?
パイプラインの充填率を高める努力を怠ってはならない
>普通に条件分岐するより遅くなることが多いって本当?
分岐予測の精度と頻度によってはそうなる「こともある」程度
一般的には単純な3項演算に展開出来る程度の条件分岐ならCMOVのほうが速い
そうだったのか
サンクス
if - else のブロック中の演算式がいくつもあるようなのをcmovに展開して速くなるかって話なら
流石に無理。そういうイチャモン付ける奴は単に使い分けを見誤ってるだけ。
a &= - (a >= b);
あ、条件が逆だた
>>343 どういう命令に展開されるか意識して書いてる?
cond?0:1が表記上省略されてるだけで、大概のCPUでは演算回数は増えてしまうと思われ
条件フラグ値を汎用レジスタに転送する命令があればそれを使うんだろうが、
それなら既にConditional-MOVEより条件は悪い
フラグ確定までフラグに依存関係のある命令は(投機)実行できないのは同じだからな
346 :
デフォルトの名無しさん:2009/08/28(金) 16:30:21
だったら、最初のままでCMOVに展開されるから、何もしないでよい
で終了するだけじゃん。
コンパイラ次第だけど。
347 :
デフォルトの名無しさん:2009/08/28(金) 16:35:24
あ、比較とandの場合は
(cmp xx,xx)の後、
sbb edx, edx
and eax, edx
の2命令。
cmov の場合も
即値が使えないから、メモリアクセスをしないよう
比較の前にレジスタクリアをしなきゃいけないし
xor edx, edx
(cmp xx,xx)
cmovxx eax, edx
の2命令。
cmp->sbb->andで依存関係が生じる。
cmovはというと、P6以降のアーキではxorによるゼロクリアはALUを消費せず
リザベーションにゼロを入れるだけの操作にデコードされるから
実質cmp+cmovの2命令分のコストだけだな
349 :
デフォルトの名無しさん:2009/08/28(金) 19:13:14
そう言えばcmovを吐くコンパイラって見た事ないな
大抵前者のコードを吐く
単純にターゲットCPUがi386になってるからだろ。
cmp+cmovにもマクロフュージョン効けばいいのに
352 :
デフォルトの名無しさん:2009/08/28(金) 20:42:30
setccは普通に見るな
げっごめんageになってた
setccとcmovの違いが分からない
>>348 ただ、その分レジスタを消費するけどな。
内部的なレジスタリネーミングという話でなく、
アクセス可能なレジスタが足りずに内容を退避する必要が出て来るケースもある。
また、単純な比較命令ではなくサブルーチンコール等をまたぐ場合
フラグ保持のためにxor等でのクリアは使えない。
比較の後にmovで0を入れる等だと、「ゼロクリア時の特別扱い」の利点が弱くなる。
あと、当然だがcmovはP6以降。
まあこれは現在は問題にならないかもしれないけどね。
>>354 Intelが配布してるPDF見ればいいじゃん
cmovは条件が一致した時にソースをディスティネーションに転送する
setccは条件が一致した時にレジスタを1に設定、それ以外は0に設定する
C言語の場合条件は0か1で判定できるのでsetccで十分な場合が多い
但しcmov使った方がより短縮できる事もある
>>355 どんだけカツカツなんだよ
XMMレジスタにでも退避しろやwww
ダンゴさんって何者なんだw
このダンゴって本物のダンゴなの?
i5ってどうなのーって聞いてみたいんだけど。
だんごじゃないけどi5はi5だよ。それ以上でもそれ以下でもない。
>>360 おめーみたいなカスには聞いとらん失せろゴミが
ダンゴさんマダー?
i7にしろや
>>361 ちょwだれww
ほれ、なんかcore2の時とかこれはいいぜーとかなんか詳しく言ってたような気がしたから
i7なりi5なりのアーキテクチャ面からの意見を聞いてみたかったんだ
Phenom 2も悪くないCPUだから好きなの選べ。
>>363 i7ー900はメモリ周りが速い。(トリプルチャネル)
i5/i7(デュアルチャネル)で少し遅い。でもCore2よりは速い。
さあ選べ。
でもこれから6コアとか8コアとか12コアとか出てくるんだろ
少しでもFSBが速くないともっさりしてくるのは確実
>>365 Core2とi7を比較すると、とりあえずメモリが速いのと、デュアルコア*2からクアッドコアになったという利点が
あるのはわかる
i5はコア間でのやりとりがずいぶん遅いらしいので、場面によっては結構な影響を与えそう
iシリーズになって各命令が要するクロックとかパイプライン周りは変わってないの?
>>367 >iシリーズになって各命令が要するクロックとかパイプライン周りは変わってないの?
そのあたりは余り変わっていないと思われるが、大きく変わっているのはSSE4.2?(4.3だったか?)になっている。
メモリ周りと、キャッシュ周りが大きく変わっているので、iシリーズ用に最適化すると早くなるかもしれない。
iシリーズはQPIが速いので、Core2シリーズよりマルチプロセッサになったとき速い。
いずれにしてもメモリ帯域がボトルネックになりそうなプログラムを書くなら、
iシリーズを使った方がパフォーマンスが出る。
キャッシュに収まるレベルで、SSEの新機能を使わなければあまり変わらない。
今からならCore2Quadよりもi5の方がいいと思う。
i7って64bit時のパフォーマンスはどうなの?Core2より良いという話を聞くけど。
良いと言われる理由は、Core 2と違ってMacro-Op Fusionが64ビットでも使えることだったと思う。
2のx乗(xはfloat、絶対値が100未満)を、テーブル参照やFPUなしで、SSEで4並列処理できませんか?
精度は6bit程度で十分なんですが
無理ぽ
整数乗なら簡単
指数部に加算するだけですむからな
お前ら文盲か?
可能なら方法を書け。
できないならできないと書く。
わからないなら黙って首吊って死ね。
で、それは4並列可能なの?
整数+小数点以下にわけて
整数部は指数部直接操作
あと小数点以下はpshufbで勝つる
釣りにすらならねえ。。。
>>373 これ凄いですね
VS2005では_mm_castがないようなので、*(__m128i*)&に直してコンパイルを通しました
自前で用意した64kBのテーブルがばっさり不要になりました
log10を求める処理もあるので、log2のソースと底の変換を使うことでこのテーブルもなくなりました
書き忘れでSSE2までという条件がありましたが、これも満たしていました
完璧です。ありがとうございました
あれ。Debugだと上手くいきますが、Releaseだと0とか負の無限大になってしまいますね
直接アセンブラに落として使います
連カキ失礼します
Releaseだと、__m128への代入の時点でスタックが何バイトがずれるようです
この後でカウンタを1加算する処理がありますが、0に1を足して1になるはずが-2になっていてびっくりしました
_m128をグローバル変数に置いたら直ったので、とりあえずこれで誤魔化します
おい!テーブル使わん言ったじゃねえかよ。死ねカス。
>>382 テーブルと多項式の比較だから、下の方を見てみよう。
頻繁に整数を6で割った余りを使うプログラムなんですが、
除算が1回40クロック以上もかかると聞いて以下のようなロジック組んでみました。
試してみると若干早くなってるような気もしますが、
これは効率的って言えますかね?
387 :
デフォルトの名無しさん:2009/10/08(木) 03:33:43
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;
}
条件分岐入れるくらいなら素直に割れ。
考え方としては、偶数ビットシフトしても3で割った余りは変わらない
(ただしシフトして消える部分に立ってるビットがない場合のみ)のを利用します。
まず2の剰余を取った後、値を半分にして6の剰余から3の剰余の問題に変えます。
上位16ビットと下位16ビットを加算して17ビットに落とし、
6ビット/6ビット/5ビットに分割して加算して8ビットに落とし、
上位4ビットと下位4ビットに分割して加算して5ビットに落とし、
最後にテーブル参照して、その時点の3の剰余の2倍の値に変換して
最初の2で割った余りを足します。
>>388 条件分岐ダメですか?
もう一個レジスタ使って
mov edi, eax
and edi, 00000001h
…
add edx, edi
mov a, edx
ってやり方にもできますが。
x[]を読みに行く方が遅い説
・6割り算は本当にボトルネックか。
他にどうしようもなく遅い処理があるなら6割り算は無視していいはず。
6割り算だけする関数を作ってそれを呼ぶようにし、インライン展開を抑制してプロファイルを取るくらいはすべき。
・6割り算の代わりに6掛け算は使えないか。
つまり、データの持ち方を工夫して高速化したい処理全体で6で割った商と余りを利用するようにすれば割り算は無視できるはず。
余りも要らないなら、メモリコストも増えないだろう。
・値域はどのくらいか。配列参照で代用できないか。
値域が16ビット程度なら高高数十キロのメモリしか使わないで実現できる。巧くキャッシュに乗れば、速いかもしれない。
実に適切なレスだな、感動した
394 :
デフォルトの名無しさん:2009/10/08(木) 09:07:56
結論
人間よりコンパイラの方が賢い
コンパイラを作ってる人たちより賢いユーザは極少数
とも限らない
ゆとりはRDTSCの使い方も知らんのか
ちょっと面倒
逆数乗算で商を求めて元の値から引いたほうが速い
今のCore MAでは整数乗算は浮動小数除算機と兼用してて
非除数 − (除数×小数点以下切り捨てた商)
まあベンチ取ってみればわかるがコンパイラの吐くコードにも勝てんと思う
整数 ×乗算は ○乗算は 浮動小数除算機と兼用してて
static const int rcp6 = 1.0 / 6.0 * std::pow(2.0,16.0);
int x = 255 - ((255 * rcp6) >> 16) * 6;
確かにこれで十分な気がするし、
>>387より速そうだ。
結果を使う40clk程度過去に除算を投げておくとか:b
403 :
387:2009/10/08(木) 21:02:29
申し訳ないけど俺のレベルが低すぎてまったく理解できん。
>>399 その「小数点以下切り捨てた商」はどうやって出したらいいの?
>>401 …
考え方だけでも教えて欲しい。
ここはアホしかいないからビット演算スレで適当に質問した方がいいよ
>>403 x / 6 = x * 1 / 6
これで、除算がなくなる。
ただ、1/6は小数点数になるから、整数演算じゃ表現出来ない。
>>399は、整数演算も少数演算もコストは同じだから少数でやれと。
>>401は、一時的に2^16倍してるだけ。
>その「小数点以下切り捨てた商」はどうやって出したらいいの?
std::floor(x * 1.0 / 6.0)
手持ちのコンパイラで
int hoge(int a)
{
return a % 6;
}
をコンパイルしてasm吐かせてみてよ
div使われてないと思うよ
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 :
387:2009/10/08(木) 23:24:00
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
}
ぐはっ、まったく意味がわかりません!
VC5あたりで整数定数除算は掛け算になってたはず
剰余は確かめたことないな・・・
意味だけど、64bit固定小数点数で、小数点が32bit位置にあると考えると
(0x1_0000_0000 / 6) を掛けることは 6 で割ることになるでしょ
んでもって6掛けて元の数から引けば剰余になる
leaの計算は3倍してて、その後自身とのaddで2倍、都合6倍
>コンパイラを作ってる人たちより賢いユーザは極少数
ときどきasm吐かせてみたりしないと浦島太郎になるね。
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
あれ?
マヌケなコンパイラだと大変ですね(^^)
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使ったほうが速いかもな
んで6の剰余ってこれでいいよな?
mod3(n >> 1) * 2 + (n & 1)
414 :
デフォルトの名無しさん:2009/10/09(金) 01:24:41
>>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;
}
>>414 mod6 : 65536 % 6 = 4096
C : 65536 % 6 = 4
mod6の/6が0.15625と、精度が悪いせいか?
その通り
でもまあショートカットとしては十分優秀だよ
SSEを用いた3の剰余のショートカット方法
movq xmm0, rcx
pxor xmm1, xmm1
psadbw xmm0, xmm1
movd ecx, xmm0
これで64ビットが11ビットくらいに縮まる
418 :
414:2009/10/09(金) 02:22:00
>>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;
}
あんたらよくやるよ
templateで、任意除数版を作ってくれたら
俺様のライブラリに加えてやってもよいぞよ
>>419 コードが膨らんでキャッシュの効きが悪くなりそう
421 :
,,・´∀`・,,)っ-○○○:2009/10/09(金) 03:27:52
>>417 GCC4.4で-O3 -march=core2でコンパイルして
なぞの某パイプラインシミュレータ通したらトータルレイテンシ20サイクル, スループット10サイクルって出た
俺の
>>412-413使った方法だとレイテンシ18と6
後半テーブル化すればもう少し減りそう
0, 1, 2, 3になったときに3だけを0に丸めるためだけにあほなビット演算やってるが
なんとかならんかな
>>412は嘘ですたorz
シフト+加算ならいけるんだが
団子かわいいよ団子
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); }
mm...mmmとか読みにくくてかなわん
DirectXみたいなセンスが欲しい
……?
これがエスパー戦争の始まりである
結論
inline int mod6(unsigned int n) { return n%6; }
でおk
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
CedarMillの88クロックってひどいな。
この手のはIntelコンパイラに標準で付いてきてるんだがな。まあ有償だが。
どのみちプロプライエタリならGPL/LGPLには組み込めん。
>>432 こういうのはコンパイラがチート使ってくれなきゃ
威力半減な気がするんだが、どうなのかね?
435 :
デフォルトの名無しさん:2009/10/12(月) 23:26:12
それをするのがコンパイラの仕事だろ
AMDは自社コンパイラを持ってないからな(あのお粗末なAMD Stream SDK以外)
スカラなんかどうでもいいよ。
SIMDをどうにかしろバカIntel。
SIMDでどうにかしろ
SIMDとか用語が嫌になる
しむど!
かっこわるー
ネイティブはシムディーって言ってるぞ
MMX
むむっくす!
かっこわるー
ネイティブでは?
えめめくす
かっこわるー
はいはい無限再帰無限再帰
66 e8 fc ff
かっこいいと思った用語
XMS
EMS
VMS
なんと!最後にMSが付く・・・・
あっちがっ・モビルスーツ!だからね!
まい・・・・じゃないんだからね!
誤解しないでよね!
↓死ねよガンオタしないでよね!!
XMS
EMS
VMS
IMS
OMS
UMS
SMS
Large
Middle
Small
Long, Middle, Short corn.
CMS忘れるなよ
Chinko Manko, Sexだけどな
452 :
237:2009/10/21(水) 21:12:39
久しぶりにスレをのぞいてみたら、昔の自分のスレを発見。
そういや、こんなことしてたな。
団子さん、その節はお世話になりました。
あれからマシンもcore i7に代えたのでせっかくだからSSE4.2をためしてみた。
当たり前だけどやっぱり専用命令は速いね。
ところで_mm_popcnt_u32は使えたのに_mm_popcnt_u64はnot declared in this scopeって言われちゃった。
OSとかgccが32bitなのがいけないのかしら?
64bit専用です
454 :
237:2009/10/21(水) 21:28:49
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
文字数制限うぜぇ。削るのに手間取っちまった。しかも微妙にずれてるし。
>>453 どもです。
世間がwindows 7 で64bitへ本格的に移行してくれることを期待してまつ。
C/C++でメモリプール(int, doubleなど様々な型が共存)を作り、
メモリプール内部でメモリの詰め直しを行って最適化しようと試みています。
入門書+α(boostがわかるぐらい)なので、
キャッシュやメモリに関する特殊なことは全然わかりません。
何か気をつけなければならないことや忠告があれば教えてください。
>>456 メモリのことを知らずにどうやって最適化する気なのかね?
458 :
456:2009/10/22(木) 04:45:35
高速化が必要というわけではなくて、ガベージコレクションの宣伝文を見て
興味本位に詰め直しをやってみようと思いました。
空き領域を整えるだけでなく、アドレス配置を上手くソートすれば
キャッシュヒット率の向上ができると思いますが、それは難しいので
今回はプール内の空き領域を整えることだけに目的を留めて置きます。
プールはchar型の配列で確保し、memmove()でclassやプリミティブを
移動させる予定です。何か規則に反することなどがあれば教えてください。
そんな無駄な事をする意味がわからない
メモリコンパクションを実装するということは、
生ポインタから、ハンドル経由のアクセスに切り替えることになると思うけど
461 :
456:2009/10/22(木) 06:01:05
>>460 自作のスマートポインタを利用してアクセスを管理する予定になっています。
スマートポインタとコンパクションが同一のスレッドになければ危険ですが。
やってみりゃいいんじゃないの
下手の考え休むに似たり。
バウンダリに気を付けろよ
465 :
456:2009/10/23(金) 17:53:10
アライメント(構造体のサイズをバイトorワード境界に調整)はsizeof(...)使えば済むと思う。
でも開始アドレスもバイトorワード境界に調整する(これがバウンダリ?)のは知らなかった。
466 :
456:2009/10/24(土) 01:53:17
いや、アライメントを制御することをバウンダリと呼ぶという記事を見つけた。
だとすれば開始アドレスは特に気をつけることはないはず……。
467 :
デフォルトの名無しさん:2009/10/24(土) 02:02:00
他人に伝わらず、自分もよくわからない言葉を使うのは、とりあえずやめよう
何のためにアドレス調整するのか分かってんのか?
469 :
456:2009/10/24(土) 03:40:37
>>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 :
456:2009/10/24(土) 03:41:53
続き
3.開始アドレス
インスタンスが4byte境界を踏み越えないように、注意しなければならない。
具体的には、以下のように分類してインスタンスを配置すれば良い。
(※以下は正しいのか非常に不安)
・4byte以上の大きさを持つインスタンスの場合
開始アドレスが、4の倍数となる番号になるように配置する。
・3byteの大きさを持つインスタンスの場合
開始アドレスが、4byteで割り切れる番号になるように配置する。
・2byteの大きさを持つインスタンスの場合
開始アドレスが、2の倍数となる番号になるように配置する。
・1byteの大きさを持つインスタンスの場合
どこでもよい
参考URL
http://park21.wakwak.com/~yuiti/program/c/08_boundary_c.htm
OSつーか、ハードの制約では
double(IEEE754)を4バイト境界なんかに配置しねーよ。
4byteだと、キャッシュラインをまたぐ位置に置かれる可能性が出てくるからな。
だから32bitOSだから4byteなんて話にはならない。
473 :
456:2009/10/24(土) 04:45:04
>>471 >>472 ありがとう。わかった気がする。
アドレスの配置の仕方を訂正〜。
・8byte以上の大きさを持つインスタンスの場合
開始アドレスが、8の倍数となる番号になるように配置する。
(double=8バイトプリミティブを含む可能性があるため)
・4〜7byteの大きさを持つインスタンスの場合
開始アドレスが、4の倍数となる番号になるように配置する。
(int,float,longなど4バイトプリミティブを含む可能性があるため)
・3byteの大きさを持つインスタンスの場合
開始アドレスが、4の倍数となる番号になるように配置する。
(4バイト境界を越えないため)
・2byteの大きさを持つインスタンスの場合
開始アドレスが、2の倍数となる番号になるように配置する。
・1byteの大きさを持つインスタンスの場合
どこでもよい
(x86CPU環境限定)
そろそろ愚行に気付けばいいのに・・・
475 :
456:2009/10/24(土) 04:56:58
「32bitOSの境界は8byte」と認識するだけで十分ですね。
真性のアフォだ
javaもコンパクション捨てたよな
D言語は知らんが
478 :
デフォルトの名無しさん:2009/10/24(土) 12:06:39
情報系の学校でも最近はいきなりJavaとかから入る所もあるらしいしなぁ。
>>475 OSは全く関係ない。
関係あるのはCPUがメモリにアクセスする粒度。
同じハードウェアなら、16bitOSだろうか32bitOSだろうが64bitOSだろうが一緒。
OS が関係あるとしたらミスアラインメント例外を捕捉して(処理速度以外は)
何も無かったかのように振舞う実装をしていた場合だな。
マニュアルとかには良く書いてあるけど、実際に実装されてる OS ってあるのかね?
境界跨ぎじゃなかったかもしれんけど、IRIX では何かやってたようななかったような。
>>481 Linux/ARM(規定で有効)
Windows/IA-64(規定で無効)
Linux/ARMは規定有効じゃなかったわ
規定例外だけ無視だわ
485 :
デフォルトの名無しさん:2009/10/24(土) 21:27:11
456のベンチまだー?
487 :
デフォルトの名無しさん:2009/10/28(水) 04:42:22
配列の合計値を求めたいのですが、コンパイラがSSEを使いやすいようなコードはどのように書けばよいのでしょうか?
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 :
デフォルトの名無しさん:2009/10/28(水) 04:54:38
ありがとう。
SSEに最適化された組み込み関数なんてあるんですか?
_mm_add_ps
_mm_add_pd
>>487 インテルコンパイラを使って、普通に書けばなんとかしてくれる。
# つーか、そのアセンブリ出力を読むのが先ず一歩目だと思う。
xmmintrin.h
そこを高速化して意味があるのかどうか検証するのが先だな。
モノによっては、配列に入れる際に和を求めるっていう手もあるワケで。
まぁまずはどこがクリティカルなのかを割り出すのが一番大事だよな。
>>488 これってNがわかっていないと、だめだよね?
ICCだと出来るのかな?
GCCでは無理だった。
>>488 これってNがわかっていないとコンパイラはやってくれないよね?
ICCだと出来るのかな?
GCCではベクトル化してくれなかった。
499 :
497:2009/10/29(木) 08:45:34
>>498 Nが既知でなくてもベクタ化するよ。例えば4で割った余りの分は、ベクタ化しない処理になるだけ。
擬似的には>488にこれが追加されるだけ。
for (; i < N; ++i) {
sum += A[i];
}
>>500 そうなんだ。
以前やってみたときはaddssしか出さなくて、
addpsは使ってくれなかった。
ループが深すぎたからかなあ。
Visual C++は何やってもベクトル化しないぞ
>>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ならやってくれるのか?
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組み込み関数に置き換えやすい形に展開しただけ
コンパイラの自動最適化使うならここまでやる必要ない
↑前文引用してどうする俺
hello
Meow
高速道路無料化に関係ありそうだな( ・ω・)y─┛〜〜
509 :
デフォルトの名無しさん:2010/01/28(木) 11:52:03
(__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です。
(__m128)num->m128_f32[0]=0;
とかやらにゃならんとかいうオチではなかろうな?
511 :
デフォルトの名無しさん:2010/01/28(木) 13:47:58
>>510 レスthx。試してみたがやっぱダメ。
根本的に__ml128構造体のメンバとしてm128_f32が無いんじゃないかとおもてきた。。。
>>511 そうかもしれない。
自分とこのMinGW TDM gcc 4.4.1のxmmintrin.hを見たら次のように定義されていた。
typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__));
HTTPヘッダを高速に
解析する方法を教えてください
ggrks
保守
518 :
デフォルトの名無しさん:2010/09/19(日) 14:20:02
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
配列のデータをレジスタにセットするところもわかりません。
ハッシュ計算で見たような式だな
MASMなら答えれたが残念だ
95 :デフォルトの名無しさん:2010/09/19(日) 13:38:02
for(i=0;i<16;i++)
a[i]^=(d[i]+c[i])%16;
このプログラムをSSE2で書きたいのですがわかりません。
教えてください。よろしくお願いします。
マルチポストか
sse 4.2で大々的に文字列検索の命令追加されてたけど
あれ大文字小文字の変換とかサポートしてくれんの?
無理じゃね?
単純一致だけだろ
>>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でも積まないと大した効果なさそうだけど。
SSEに関する参考書とかってあるんですか?
『MMXテクノロジ最適化テクニック』で基本的なことを覚えて
SSE以降はIntelのマニュアルで独学した
ナカーマ
俺はノンケじゃwwww
女子中学生かもしれんやん。
みんなプロファイラは何使ってるの?
VTune と AQTime の評価版を落としてきて試したんだけど、結果が結構違う。
手法とかが違うのかな。
AQTime は計測対象のプログラムの動作が遅くなるから侵入型なんだろうか。
これは Windows での話ね。
AMDのプロファイラが世界で一番正確
研究者はAMDのプロファイラしか使わない
正真正銘プロのツールだよね
>>532 ヤな言い方だな。何か AMD に恨みでもあるの?
タダのネタでしょ
反応するほうが信者臭がしてキモイ
自演乙
for(int i=0; i<N; i++){
sum += a[i];
}
これってベクトル化効きませんかねぇ・・・
それも分からんようなら諦めな
というか*aとsumが浮動小数点数ならgccでもiccでも自動ベクトル化してくれるが。
問題は、メモリがボトルネックだからそんなの意味ないという事だ。
x86は浮動小数点が弱くて仕方がないからなあ
8087のコプロセッサの頃からの負の遺産を引きずっている
でもL1/大容量L2キャッシュを媒介にする事によって相当克服して来てはいるんだけどな
PowerPCなどにどうしても勝てない
釣れますか?
お前が釣れた
糞環境でちまちま最適化した後に
インテルチップでてきとーにビルドしたプログラム走らせると絶望できる
>>539 前世紀からタイムスリップしてきた人乙
理論値こんなもん
Core i7 2600(3.4GHz)
54.4GFLOPS/27.2GFLOPS(DP)
POWER7(4.1GHz)
32.3GFLOPS(SP/DP)
>>542 整数に点はない。
よって、浮動も固定も不動もない。
不動少数点演算を整数演算でってなかったっけ?
「不動少数」なんて言葉はない。
そもそも、「動かない、少ない数」とは何なのだ。
こじつければ「不動小数点数」ならあるかもしれないが、
これは「固定小数点数」と同義と解釈すべきだろう。
548 :
デフォルトの名無しさん:2011/01/31(月) 01:33:25
549 :
デフォルトの名無しさん:2011/01/31(月) 02:22:04
550 :
デフォルトの名無しさん:2011/01/31(月) 02:25:14
551 :
jagam00z:2011/01/31(月) 02:27:26
554 :
デフォルトの名無しさん:2011/01/31(月) 13:10:23
10年かかってやっとCellに追いつけたのか。
sse
いや俺も「不動点演算子」に、はぁ?と思ったよ。
山の浮動が居るスレはここですか?
いや不動点演算子は別に良いだろ
スレチだけどさ
>>554 またタイムスリップしてきたあたまのおかしい人か。
2001年にCellがあったんですか?パネエwww
てかCellのスカラ整数演算性能はクロック半分のAtomにも負けてるよ
俺もCellは肝心なところで使えないと思っていたクチだが、
これ系のスレで毎回スカラを持ち出すお前の頭が分からない。
スレタイ読め。
スレタイ読んだかスカラ演算がなぜ駄目なのかお前の頭が理解できない。
CellのSPEはC++ライブラリほとんど使えないしましてSSEなんて対応してないぞ。
スカラ整数演算が強い=(SIMDのデータ読み書きを含めた)メモリアドレッシングに強い
SPUはCのライブラリを使えるし(標準?んなもんは知らない。)C++コンパイラもある。
SIMD演算に特化したSPUは比較対象としては適切と言えなくもない。
だが、Atomのスカラ整数演算能力なんざ完全に場違いもいいとこ。
団子さ、年取って耄碌してきたんじゃない?
良い訳に必死だこと
ここのテーマは「高速化」であって並列化ではない。
スカラ演算の重要性を理解できないお前の存在自体が場違い。
具体的にはCellの整数加減論理演算のレイテンシは2〜6サイクル程度で
クロック半分のAtomはdual issueで1〜3サイクル程度だから実質同程度なんだよ。
CISCのコード密度の優位性と16バイトアライン縛りの問題の分だけAtomのほうがむしろ有利なんだよ。
いくらあがいても速度勝負ではクロック半分のAtomに勝てない。
モバイルデバイスの市場は拡大してるし、Atom向けの最適化技術の重要性は増すと思ってるけど
Cell(SPU ISA)はIBMも東芝も後継プロセッサの開発を事実上放棄してるし
誰もここでCellの話題なんて出さないだろ?
必死なのはどうみても連投までして言い訳を続けてる団子だろ。
みっともないから少し黙ってろよ。
まあ、日々進歩しているプロセッサと設計がおそらく6,7年前で止まっているプロセッサを比較してもなんだかなあ。
Pentium4とCellはどっちが速い?と言われれば浮動小数演算であれば後者だからな。
Cellがインテル並に進化していたら、整数演算も改善されていたんでは?と思えなくもない。
それはそれで面白いんだろうが。
うん、まあ取り敢えずお前らまとめてゲハ板にでも行け
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]));
…
のようにすれば速いかと思ったのですがそれほどでもありませんでした
良いアイデアありませんか?
データ設計をやりなおして、部分的にコピーする必要がないように並べる事をオススメする。
571 :
デフォルトの名無しさん:2011/02/19(土) 16:59:31
行列の演算ですが、高速化する方法はありますか?
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];
}
>>571 それぞれの配列の構成が判らんとなんとも。
h1みたいな二次元配列っぽいのが配列の配列なのか、ポインタ配列なのか、演算子オーバーロードなのか全く判らん。
兎に角、動く形で提示してくれ。
この手のものは式テンプレートというものを使うと早いんだそうだが
あまりに複雑でいまだに自分のものにできん^^
574 :
デフォルトの名無しさん:2011/02/19(土) 18:03:49
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 :
デフォルトの名無しさん:2011/02/19(土) 18:23:07
movdqu命令はレイテンシ6のスループット1だとあります。
movdquを使った1クロック後に、それと依存関係の無い別の命令を実行でき、
movdquと依存関係のある命令は6クロック後まで待つ必要があるってのは分かるんですが
movdquのロード命令と依存関係の無い、別のロード命令を使いたい場合は何クロック待ちになるんですか?
メモリに依る、という回答では駄目だろうか。
素人から見ると団子のレスは読んでて面白いけどな。
批判するほうもちゃんとデータとか出してくれるとより面白いんだけど、俺を楽しませるスレじゃないしな。。。
Cellくそはええ!みたいなのは結局そうでもなかったってことなのかな。
BOINCあたりで活躍してたけど、結局i7とかのがはやいの
>>578 > movdqu命令はレイテンシ6のスループット1だとあります。
それってネトバのmovdqu xmm,xmm命令の事?
もしそうなら、それはxmmレジスタ間コピーのレイテンシ・スループット
であって、ロード命令のレイテンシ・スループットではない。
582 :
578:2011/02/22(火) 17:09:50.56
理解しました
測ってみることにします。
SIMDとは関係ないけど他に見当たらないんで、ここで聞くことにしたけど、
誘導してくれれば幸い。
ビット・オンの最上位のみ残したい場合、
ビットスキャンリバースを使わずに、いい方法ないかな。
ビット・オンの最下位のみ残す場合は、例えば対象の値を80としたとき、
mov eax,80
mov ebx,eax
neg eax
and eax,ebx
こんな感じよね。
これを最上位ビットでやりたいんだが、何かいい方法ないかな。
最下位フラグを消していく方法を繰り返すくらいなら、素直にビットスキャンしちまうんだが。
なければ、ない、と言ってくれ。
撃墜100超えたんでやめよっと
すれ違い誘導職人の晩年である
,.ィ'" ` 、
/ ,.--、 :.:.\
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
沖縄は良いところです。
ただし原住民にとってのみだが。
暑い所は嫌だなあ。PCが熱暴走しやすくなるし。
>>591 昨日は暑かったけど、ビデオカードが膨張したのか接触不良を起こして
画面がいろとりどりの模様になって停まっていました。
夏場はエアコンがないと人もPCも死にそうになりますね。
アライメントを逐一管理するのがめんどいんですけど、
コンパイラーなりリンカーオプションで、スタックからヒープまで
一括して指定することはできんとですか。
環境:GCC と CL。
マクロ書いて、めんどくさくならない程度に短くして対処するんじゃだめじゃろか。
質問です。
画像処理で画素同士の加算や減算をSSEで高速化したいのですが, 速くなりません。
処理は, int型で,
for(i = 0; i < width*height; i++)
dst[i] = src1[i] + src2[i];
といった簡単なものです。
これに対して, ポインタを__m128iに変え, ループ回数を4分の1にし, 加算を_mm_add_epi32に変更しました。
しかし, 速度はint型とほとんど変化はありません。
平均化フィルタをSSEで実装したところ, 2倍近く高速化できたので, こちらもうまくいくと思ったのですが・・・。
もしどなたか原因がわかる方がいましたら, ご教授お願いします。
結論から言うとメモリの転送がボトルネックです。
書き出しのアライメントを揃える事とstreamを使う事で何割かは改善出来ますが、基本的に速く出来ません。
最適化とは遅い部分を探し出す事に他なりません。
安直にSSEとかマルチプロセッサにしようと思わず、真にボトルネックを見つけられるようになりましょう。
真に遅い部分が分かったなら、平均化フィルタと何が違うのか、どうしてもう速く出来ないのかが理解出来るようになります。
つまり, メモリがボトルネックになっている以上, いくら演算速度をあげても効果は薄いということですね。
高速化に対するアプローチも教えていただき, 大変勉強になりました。
速度に影響する要因をまだ一部しかわかっていない私には難しいかもしれませんが、これから知識を得ていきたいと思います。
御回答ありがとうございました。
>>596 メモリの転送がボトルネックなのか、演算部分がボトルネックなのかは
どうやって判断すればいいのですか?つまりどこを見たらよいのか。
あるいはあなたはどうやってますか?
ツールとか使うのでしょうか?
メモリに対する操作や演算の大半は、ツールを使って調べるまでもなく、単純で十分に短い。
なので、ソースコードを眺めれば、そこがSIMDを使う事で高速化すべきか否かは、すぐに見分けが付く。
演算そのものが単純で短い場合は、複数種の演算を1命令にまとめることが出来るかどうかで判断していい。
>>598 理論値と実際の処理時間の差で見積もる。
また、CPU メーカのプロファイラを使えば、命令のリタイア数とか、キャッシュミスなどのイベントの数を計測できる。
Cのソース眺めるだけじゃわからんだろうに、汗で判断できるぐらいにならんと
最適化もしない状態のことだったりして
CPUのつもりになってメモリアクセスパターンを想像したら見えてくるかもしれんね
>>600 理論値ってアセンブラニーモニックを命令毎にスループットやレイテンシの累計計算して
全体で何クロックかかるかを算出した値という意味ですか?
それで実際にどれだけクロックかかるかとの比較をする、と。
メモリ参照をいかに少なくするかでしょ、今時の高速化は
>>598 すまんレス遅れた。
メモリのアクセス回数と演算回数は見積もれるな?
c[i] += d[i] * e
だったらeはレジスタに乗っているものとして無視して、
読み込み2回(c, d)、書き込み1回(d)、加算1回(+=)、積算1回だ。
回数を見積もったら、加減積算はそのまま、メモリアクセスと除算とsqrtは10倍、その他sin/pow/log/expとかは100倍するんだ。
比率はいい加減なので、数倍しか違わないなら全体的に最適化。
その中で、演算が効いてそうならSIMD化だ。
あとは、何よりも実測が重要。
>>606 ありがとうございます
ソースの式から各演算毎にウエイトを用いてかかるコストを見積もるって意味だったんですね。
それでメモリアクセスより演算のコストの方が高そうであればSIMD化すると。
例の c[i]+=d[i]*eの場合
メモリアクセスコスト 3*10=30
演算コスト 1+(1*10)=11
なのでメモリアクセスのほうがコストが高いから、SIMD化しても早くならないだろうと考えるわけですね。
>書き込み1回(d)
揚げ足とるつもりではないのですが
これは(c)への書き込みの間違いですよね?
SSEで例えると、メモリの読み書きはSSEでやったほうが断然高速だから
そんなコストとか馬鹿な計算する以前に速くなることは確定している。
そんな前時代的などんぶり計算しても意味ないよ
プロファイラにかけな
キャッシュが考慮されてないよね
> 間違いですよね?
その通り。
>>608 総和とか本当にメモリがボトルネックだとスカラでやっても大して変わらない。
>>609 そう、机上は本当に大ざっぱな見積もりだけで基本的には実測が重要。
でもVTuneなんかは他にも項目が多過ぎて目星付けるのも勘がいるんだよ。
SSE使わんと絶対にプリフェッチされない、とかだったら正しかった。
>>610 畳み込みとの違いのヒントを示し忘れてた。
同じアドレスを複数回読むなら、最初の1回を見積もりに入れておけばいい。
勿論キャッシュに入らないサイズだと全てカウントする必要がある。
メモリ周りがボトルネックなら、prefetch*とmovnt*。
とりあえず、CPUによっては32[bit]のmovntiは遅いから使わない方向で。
実行環境が単一でない場合、大雑把な見積もりで十分だと思ってみる。
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));
とすると、一時オブジェクトがアラインされてなくてこけます・・・・
何か抜け道ないですかね(´・ω:;.:...
間違えたorz
”make_pairの返す一時オブジェクトが”アウトですた。
make_pair(1, Hoge); ←×(落ちる。)
aligned_stl::pairArg(1, Hoge); ←○(落ちない。)
なのでコンストラクタで直接渡せばいけるけども。
Hogeにもpairにもアライン指定つけてるんだけどなぁ・・・
また間違えた・・・・連投すみませんorz
誤:aligned_stl::pairArg(1, Hoge); ←○(落ちない。)
正:aligned_stl::pair<int, hoge>(1, Hoge); ←○(落ちない。)
mapの方がアライメントされてないんじゃない?
std::pair<int, hoge>からaligned_stl::pair<int, hoge>へのコードがバグってるんじゃないの
620 :
618:2011/07/03(日) 00:21:26.44
>>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 :
621:2011/07/03(日) 03:25:25.25
あと、x64をターゲットにすれば落ちませんでした(デフォルトのアラインメントが16バイトだから?)
ついでに質問なのですが、
>>620のchar unused1__とunused2__はどういう意味でしょうか?
それって構造体のメンバのアライメント指定であって、アドレスのアライメント指定する機能って基本的になくね。
x64だと関数の始まりのスタックは16バイトアライメントになるようになってるから、問題発生しにくいとか。
というか、落ちる落ちない以前にデバッガで逆アセ見れば、どういうコードが生成されているかすぐわかると思うんだが。
>構造体のメンバのアライメント指定であって
あああ、なるほど・・・x64なら安全、と考えるのは危険ですね。
>逆アセ見れば
見てます、きっちりmovaps使ってますw
で、ウォッチ窓で見ると一時オブジェクト側のアドレス下位1バイトが0でないので
明らかにアラインされてないのが問題です。
__m128を使うだけなら、構造体の代入演算子やコピーコンストラクタで
_mm_loadu_psとか使えばいいんでしょうけど。
誤解されるような書き方だったかもしれません、決して手詰まりというわけではないです。
どうにかしてアラインメント保ったままmapに突っ込めないかなー、というだけでした。
625 :
618:2011/07/03(日) 11:13:12.43
626 :
621:2011/07/03(日) 15:51:09.00
>星野好造風に
渋すぎるwww
ありがとうございます、試して無事動きました(#if 1でも0でも)
予測しておられた?通り、char unused1__が含まれていようと問題ないんですね。
構造体の型自体は(__m128のような16byte境界を要求するものが含まれていれば)
先頭アドレスが16byte境界でさえあればいいような配置になっているけど、
2008は関数の返す一時オブジェクトのアドレス調整が抜けている、ということかな・・・
大変参考になりました、ありがとうございました。
int i = 10;
int * p = &i;//int型ポインタpにiのアドレスを代入する
簡単。
char str1[] = "abcde";
char * str2 = "abcde";
上と下は同じでどっちを使ってもいい。
sizeof(str1) != sizeof(str2)
str1++;
630 :
sage:2011/07/05(火) 07:42:33.24
sizeof とか return とかにかならずカッコをつける人がいるけど何で?
sizeofとdefinedは関数として意味が通ってるから括弧付けちゃうな。
(a || b) && (c || d) も括弧いらないけど、あった方が読みやすいのと似てる。
returnに括弧付ける人の気持ちは聞いた事が無いから分からない。
間違えた(a && b) || (c && d)だ。
>>630 sizeofの中身によって括弧つけたりはずしたりしてるのかい?
おれはそんなとこ気を使っても意味ないと思うので常につけてる。
sizeofの括弧省略してるコードってほとんど見たこと無いしな。
>>630 struct s{int i;};
sizeof struct s;
:b
20年以上C書いてるけど、sizeof のカッコが省略可能なんて知らなかった…実際そんな記述を見たことがなかった。
return にはカッコつけない。
return (0); とかは見たことあるけど、sizeof int は見たことないからなぁ。
それは違反です
余分なカッコが多すぎるコードってみにくくて嫌いだ。
if (a == 0 && b == 0 || c == 0 && d == 0)
if ((((a == 0) && (b == 0)) || ((c == 0) && (d == 0))))
この二つだと上の方がはるかに見やすいと個人的には思うが、
見やすさを優先してカッコをつけるとか言って下のように書く人がいる。
LISPに慣れているせいか、かっこをつけておくと
式の構造が立体的に(ネストが深いほど浮き上がって)見えるんだ
確かに人間が見ると見やすいかも知らないが、
人間以外(コードアナライザの類とか)には
見やすくないと判断されるんで仕方がなくつけてる。
>>638 if ( ((a == 0) and (b == 0))
or ((c == 0) and (d == 0)))
って書く。論理演算はキーワード使う方がビット演算との取り違えも防げる。
AndAlsoですね、わかります
>>638 何処からが"余分"なのかを巡って紛糾する事も多し。
#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))))
見づらいって言うか、吐き気がするほど読みづらい。
こんな手法でちまちま高速化したところで、もっと簡単なGPGPUの並列処理に
圧倒されるだけ。
GPGPUが簡単? OpenCLの厄介さを身を以て知って濃い。
if ((!a && !b) || (!c && !d))
括弧が
649 :
デフォルトの名無しさん:2011/10/10(月) 19:26:30.72
指定桁数で四捨五入する以下の関数の実行速度を上げたいの。
(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];
}
ベクトル化は不要よ。
あら、なんかデジャブ
でもベクトル化で少しは早くなるわよ
655 :
デフォルトの名無しさん:2011/10/11(火) 20:37:34.29
なんで PSLLB だけないんだろう?
658 :
デフォルトの名無しさん:2011/11/05(土) 00:09:14.57
x64の組み込み命令で、xmmレジスタに定数を代入したいんですが
__m128i xmm0;
xmm0.m128i_u64[0] = 0x1212121212121212;
xmm0.m128i_u64[1] = 0x1212121212121212;
これより速い方法はありますか?
各バイトが必ず同じ数字になるとして
>>658 定数はループの外で置きっぱなしにするし、x64だとレジスタが多いから、そのままで良いと思ってみる。
mov eax, 12121212H
movd xmm0, eax
pshufd xmm0, xmm0, 000H
VC++だと
__m128i xmm0 = {0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12};
でmovdqaを使うようになる
VC++だとそれでいいけどGCCだとコンパイル通らなかったりするんだよね。
最適化ルーチンが腐ってなければ大体これでいけるけど。
__m128i xmm0 = _mm_set1_epi8(0x12);
というかアセンブリ出力読むと良いよ。
スクカジャの方が良いよ
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;
それ、どう考えても実数型⇔整数型のコストがでかすぎる。
たった100件でいいなら実数で持てないの?
>>665 100は例で実際はは数千万程度
waveファイルPCMの加工で
>>664 自分で学習しないと答えを聞いても使えんよ。
そもそも意味不明なコード書かれても誰も答えられない。
自分語り 乙w
s = s[a] * f; って何がしたいんだw
話の内容を察するに、s[a] *= f; ってことだとおもうけれど
それじゃ飽和処理してないし
つーか、コンパイル通るの?
何も書いて無いけどどうせ色々特殊処理もあるんだろうから、予め
0x0000-0xffffに対する結果を128K byteのテーブルに計算しておき、
後はテーブルルックアップすれば良いだろw
いっそ0x0000-0xffffffffに対する結果を16GByteのテーブルに(ry
>>666 音を大きくしたり小さくしたりしたいだけなら、0.0〜1.0を、0〜255 とか 0〜65535 とかにして、
整数演算に帰結させてMMXのほうが速いんじゃ…
お前らやさしいな
初めて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 :
679:2011/12/19(月) 02:15:55.13
_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 :
679:2011/12/19(月) 02:17:15.89
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 };
パイプライン化したコードでもないし、スタックチェックが行われている気がするが。
逆アセ確認したかい?
40倍も遅いというのはインライン展開されずに普通に関数呼び出しされちゃってるんじゃないの
インラインアセンブリは関数のインライン展開を阻害するから
どうしてもASMを使いたいとか宗教的な理由が無い限りintrinsicsを使うべき
強いて関数呼び出しにするなら__fastcallにするかな。
685 :
679:2011/12/19(月) 02:59:52.23
>>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 :
679:2011/12/19(月) 03:16:03.78
すみません、
>>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 :
679:2011/12/19(月) 03:17:00.05
■SSE未使用
for( int i = 0; i < 10000000; i++ )
{
pfC = f4pakAdd( fA, fB );
0040114A fld dword ptr [__real@40c00000 (40213Ch)]
}
これって、定数演算だから、事前に計算した結果をメモリに置いておいて、
ロードするだけってオチでしょうか・・・(汗ンブラ)
SSEなんてたいして効果無いんだろ。
コンパイラまかせでいい。
小手先のテクより、アルゴリズムやGPU使用など劇的変化が見込める所を研究すべき。
SSEは最高が20%とかだろ。
689 :
679:2011/12/19(月) 03:19:44.86
>>683 Debugモードではいずれも関数呼び出しありで、
Releaseモードではいずれもインライン展開されていました。
両モードでこういった差があることは意識していなかったので勉強になりました。
>>684 団子さん、ありがとうございます。
今回は勉強の一環としてアセンブラを使いましたが、
できるだけ組み込み関数を使うことにします。
(__fastcallにしたら速度が半分に低下してしまいました・・・)
実用上はインライン展開で速くなることは稀。
関数にするからには一カ所より多くの所からコールされる可能性が高く、
インラインにしなければCPUキャッシュに乗っている場合に関数を使い回しができて高速化される。
変数をスタックに積むのって結構無駄だろ?
呼び出し元の関数が小さい場合は特にね。
VC++の32ビット版の場合、__fastcall規約だとxmmレジスタで3つまで渡せるよ。
失礼
VC++だと__m128{,i,d}は呼び出し規約にかかわらずレジスタ渡しになるね
てかレジスタ渡し以外不可能。
ちなみにgcc(Linuxなど)とかだといったんストアしてポインタ渡しになる。
なりすましとか勘弁してください
>>690 今の時代のインライン展開って、call命令減らすというより、コンパイラの最適化効きやすくするためというほうが大きいんじゃない?
うまくいけば数命令ぐらい減るし。
ステップ数の少ない小さい関数限定だな
C++の話なら、たんなる要求に過ぎないので、
ステップ数が大きければコンパイラがinline指定を無視するような気もするな。
gettimeofday()してusecを返すだけの関数はインライン展開したけれど、
(sec%1000)*1000*1000を足したら関数呼び出しになった(gcc4)。
>>698 1関数呼び出しのみの関数はエイリアスとみなしてるんじゃね?
後者は引数渡しのオーバヘッドが無いし、インライン展開のメリットがあるか微妙な線だな。
おいらC++の場合だとそれほど大きくないクラスならヘッダ内に関数実装も含めて書いちゃうし
最適化時にどれがどう展開されるかはコンパイラ任せという罠。
インラインやマクロは最初から使わない方が良い。
EXEでかくなり、メモリ使用量も増える。
自分はオプションでインライン展開しない設定にしてる。
それで実測してみて、関数コールが実際に負荷になっていれば書き換えれば良い。
しかしそんなことが有ったことがない。
速いという思い込みでインライン指定してるだけとおもう。
templateなんか駆使すると
インライン展開されないと
桁違いに遅くなるけど
maxとかabsとかSSE一命令でいけるのにわざわざレジスタ退避してcallしてたら
コードサイズもでかくなるしいいことないだろ
関数のサイズをちょっとずつ大きくしてくとわかるけど
インライン展開の閾値を超えた瞬間にインラインで展開されてた数命令規模の関数が
一気にcallに置き換えられてサイズが爆発するから
mapとか、コンテナにvoid *を突っ込む癖が付いてしまう。
C++は面罵関数がインライン展開されなかったら話にならないからな。
自分はオプションでインライン展開を積極的に行なう設定にしている。
それで実測してみて、EXEの大きさやメモリ使用量が実際に問題になっていれば書き換えればいい。
しかしそんなことがあったことがない。
増えると言う思い込みでインライン設定を毛嫌いしているだけだと思う。
実際、ベクタ化の方がよっぽどコードサイズが増えるよ。
あと、SSEの場合アラインメントの推論が切れるのがかなり問題で
関数単位でコンパイラが見てしまうと
ポインタにはアラインメントの情報が乗っていないから
iccなんかは気を利かせて一旦アラインメントされたスタック上にコピーする
コードを挿入してしまったりする
アラインメントされてないとペナルティが大きいからね
インライン展開されると
アラインメントされているスタック上の変数や
明示的な_mm_load_psなんかから
変数やポインタのアラインメントを推論するので
アラインメント前提のコードを生成させることができる
どんな変数も問答無用でアライメント16にするようにコンパイルする設定があれば
面倒な記述を減らせると思うんですが、何かデメリットあるんでしょうか?
メモリの隙間ができて勿体無いとかあるかもしれませんが、メモリ量の多い昨今、
それほど問題にならないのでは?と思います。
むしろアライメントすることでメモリアクセスの冗長さを減らせて帯域を節約する効果も
あって一石二鳥ではと思うんです。
gccだと-mpreferred-stack-boundary=4がデフォルトだから既に16バイトアライメントだよ
構造体の詰め物は互換性もあるし難しいじゃないか
>>707 なにそれ君いまだにPS3向けのゲームとか組まされてるわけ?
>>708 glibcのmallocは8バイトだよ
>>710 SandyBridgeでもアラインメント取れてないと遅いでしょ
構造体はCの規格だと順番を入れ替えられないだけで詰め物はし放題だよ
実際4バイトアラインメントのアーキテクチャだとコンパイラが詰め物するでしょ
>>711 Nehalem以降はmovups/dquもペナルティ無く使えるでしょ
まあ結局Core2以前も考慮するとコード振り分けるから労力は変わらないのだけれど...
714 :
707:2011/12/24(土) 02:12:26.59
すみません、自分は日曜プログラマレベルで、対象CPUはx86、環境はVC++です。
VC++の設定を見ていると、「構造体メンバのアライメント」というのがあって16バイトアライメントを選べるようになってました。
同様に通常の変数もアライメントできる設定があるかと思い探しましたが見付かりませんでした。
どう考えてもこれ以上削れないってくらいの手書きインラインアセンブリコードに対し、
C記述版をVC++のReleaseモード(最適化O2)でコンパイルしたもののほうが1.3倍速かったです。
生成されたアセンブリを覗いてみたところ、
変数 * 3
というコードを
lea edx, DWORD PTR [eax+eax*2]
としていてびっくりしました。
これって、アドレス演算を行うローダ(専用の演算器?)を使うことで、
通常のALUと並行して演算(スーパースカラって言うんでしたっけ?)し
高速化しているということなんでしょうか??
>>714 __declspec(align(N))
717 :
707:2011/12/24(土) 02:44:05.59
>>716 ありがとうございます。
それは知っているんですが、
>>707でも書いた通り、
そういった記述をわざわざせずとも、自動で全てアライメントしてくれるような設定があればイイのでは?
と思った次第です。
しかし、上でも仰られたように、互換性の問題があったりで難しいのでしょうね・・・
でも二重インクルード防止の「#pragma once」のように、互換性を考慮しない機能があったりするくらいですから、
自分のようにずっとVC++しか使わない人間を対象にそういうオプションが用意されていても良いのではと思いました。
>>715 ついでにPartial flags stallも回避できるな
>>713 Nehalemでmovupsのペナルティがなくなったのはアラインメントされている場合だけ
Penrynまではアラインメントされていてもmovapsより遅かった
ハードウェアがどういう実装になっているのかをよく考えてほしい
さらにSandyBridgeでは非アラインメントの場合
2つあるロードユニットが生かされないばかりか追加ペナルティもあるので
アラインメントされている場合に比べて非常に性能が落ちる
movaps/movups使い分けの時代はSegmentation Faultの温床だったので
movupsオンリーで書ける様になったのはうれしいよね
Haswellで32Byteアラインメントが出てくるかと思うと頭が痛いが
>>716 VCの__declspec(align(N)) や gccの__attribute__ ((aligned(N)))は
スタックやベースポインタからのアラインメントは保証されるけど
ヒープにどう確保されるかは保証されないよ
ランタイムライブラリ依存だからね
そのクラスのnew/deleteをオーバーロードするか
大雑把にグローバルでオーバーロードするかしないといけないが
どちらも一長一短ある
>>717 ぶっちゃけそれやってどれだけの速度向上が望めるの?って事情もあるんじゃねーの
たかだか1MBに満たないスタックに、って
最近のCPUだとunalignedアクセスの性能低下も軽減されて古いCPUだと速くなるって言われてもなーって気持ちもあると思う
SandyBridgeもL1D$は1R1Wの4bank構成で
うまくバンクコンフリクトを避けないとペナルティがある
非アラインメントのmovupsは2bank使ってしまう
725 :
715:2011/12/24(土) 14:11:41.35
>>718 おお、そんなメリットもあるんですね。
>>724 覚えておきます。
コンパイラの吐くアセンブラを見てると眩暈がしてきましたw
SIMDやプリフェッチ等のキャッシュ制御を除けば、
手書きでアセンブリ書くのはほとんど効果的でないような気がしてきました。
726 :
707:2011/12/24(土) 14:22:27.84
>>719 なるほど、バイト境界を跨いでしまってアクセス回数が増えることより、
キャッシュに収まって低レイテンシでアクセスし易くなる効能のほうが上回るわけですね。
いかに外部DRAMへのアクセスがコストになっているかがよく分かります。
あと、スレ誘導もありがとうございます。
>>722 >最近のCPUだとunalignedアクセスの性能低下も軽減されて
そうだったんですか。
それだったらmovupsでいいですね。
でも
>>723さんの御意見も気になりますので、パフォーマンス測りながら追い込むようにします。
>>720 64ビットだと、当初MMXが使えなくなるとか言ってた関係で
VCはMMX用の組み込み関数が使えないんだよなぁ
でもって、MMXをSSE2に書き換えるとメモリオペランドのアライメントで
例外が発生したりするんだorz
もう最初から全部、256バイト境界にアライメント揃えて実行ファイル作っとくかw
グローバルのnewをオーバーロードしたくなる時は結構ある
32bitOSを切り捨てたい時もよくある
intやポインタが64bitになっても面倒なだけだと思うけどな。
お前がそう思うんならそうなんだろう
お前ん中ではな
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で高速化する方法があれば教えて下さい
byte配列ならPHMINPOSUWで速くなりそうだけど、そのコード基本的に検索だからSSE向きではないな。
最大値求めて、それを検索して位置返すのもありだが、速いかは知らんw
>>733 src[m]をキャッシュした方が速いと思う。
要は、SSE以前にやることやってからにしろ。
unsigned intだとSSE4使わないと素で書いたより無駄に遅くなりそうなのしか思いつかないわ
SSE使った方が遅くなるのは何故でつか?
日本の道路をF1で走るようなもんだから
>>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]);
}
>>739 SSEは max命令とunpackv命令があるんだから
32bitのsrc[i]値を64bitのsrc[i]<<32|iに変換して最大値を求める方が速いと思うね
740だが、64bitのmax命令はないんだな それなら
>>739でいいと思う
スカラーコードより速く
すまん
>>739 signedの比較命令しかないからダメじゃない?
なんか知らんが、そんなのずらせば済む事だろ
実際にコード書いて検証しようぜ。
思い込みと現実は違う場合が結構あるしさ。
古いPCを使ってるからかもしれんが
>>733を単純にアンロールしたのが一番速いな
スレチではあるが、このコードを高速化する必要がある処理を見てみたい気がした。
>>742 0x80000000を引く。
足してもいいしXORでもいいけど。
横レスだけどおおすげー。
そもそも正数同士・負数同士の比較ならsigned/unsignedで結果は変わらないので
問題は正数と負数の比較のみ。確かに最上位ビットを反転させれば万事うまくいくね。
256個ぐらいだと、最大値を見つけて最大値と同じのを見つけるのだと遅いかな
signedとunsignedの変換が凄いのか。
この手のテクをまとめようと思ったらどのレベルから書いていいか分からんな。
>>749 俺は実装が面倒という理由でそれでやってるが
やっぱメモリに2週アクセスするから遅いのでは
pxor x2+pcmpgtbとpblendvbで最大値のインデックスを保存
インデックスは0x01010101でインクリメント
最後に4要素を比較
4要素あたり2サイクルで回るかな
signed intだったら4要素あたり1サイクルでいけるかも?
unsignedでもcharだとpsub+pblendvbだけでいけるからよいんだけどね
あpmaxudも必要か
__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 ) );
}
以下略
実行してないのであってるかは知らん
> unsignedでもcharだとpsub+pblendvbだけでいけるからよいんだけどね
その程度ならpacked floatにキャストしてblendvpsでもいけるけどね。
SSE4対応以前ならpmovmskb/maskmovps+test+jccでもいけるか
(メディアンならともかく最大値ならcmovより分岐のほうが速いはず)
>>755 pbledvbは7+8nのビットしか読まないから符号の判定に使える
SSE4以前だとmaskにはand+andnot+orが使われてたね
Penrynだと下手にblendv系使うより速い場合もあったりした
ごめんblendvpsも31+32nビットしか読まないのか
勘違いしてた
符号の判定に使えるね
>>757 PenrynのPBLENDVBはレイテンシ1、スループット2で
SandyBridgeはレイテンシ2、スループット1か…
Penrynはデコーダの制限もありそうだし、and,orでもよさげ
HTが使えるCPUならblendの方がいいかな?
どうせ全検索するんだしレイテンシの長さ分だけインタリーブすればレイテンシ隠せるよ
packed unsigned intの比較(マスク生成)だけど、両項のMSBを反転してからpcmpgtdするより
psubd + psradのほうが速いかもしれない
>>762 どっちも2命令でXORの方が実行出来るポートが多い分有利そうに感じるのだが
pdangod
>>762 blendvps用のマスクならpsubdだけでよい
blendvpsは最上位ビットしか見ないから
話の流れぶった切るけど団子さんよ〜。
今の静的分岐予想って相変わらずifよりelseの方が速いの?
ifとelseのどっちが速いか正確に計測するにはどういうコード書いたらいい?
あれ?ifの方が速いんじゃなかったか
P6,P2,P3,P4はforwardならnot taken backwardならtakenがデフォルト
P4はPrefixでヒントを出せる
PM,Core2はランダム
ソースはAgner
分岐予測履歴がない場合あるいは予測そのものがない場合、条件付ジャンプは前のアドレスに
飛ぶ場合(多くの場合ループ)は原則ジャンプ、後ろならスルーが多くのCPUの実装ですね。
大体のコンパイラってforやwhile文はこんな感じに展開するでしょ?
if (cond) { do { ... } while(cond); }
>>769 モダンなCPUはどんな感じなのよ
>>768 はランダムだと言ってるけど
モダンなCPUでも静的予想だとifはスキップ
whileはループ確定なのけ。
分岐履歴が無いのに前方への分岐を予測したら命令フェッチをやり直さなきゃならないじゃん
後方への分岐はループの場合が多いから特別扱いなんだと思う
大概returnやthrowが行われるからifをすっ飛ばせば速いのは解る。
反復も反復する事を優先した方が早いのは解る。
それはいいとして、今のCPUは分岐ヒントとか投棄とかあって単純じゃないんだろ。
そこを知りたいんだがね。
>今のCPUは分岐ヒントとか投棄とかあって単純じゃないんだろ。
パイプラインが深いだけでしょ
わかってないのにわかったつもりになって
単語だけ並べているように見えるのは何故だろう
そう思ってくれるのはいいが、間違いの指摘と
実際はどうなってんのか答えてくれ
批難だけの回答はいらん。
>>773 分岐予測の話はパイプラインが深いこと前提で話してるわけで・・・
>分岐予測
って、言い方してるだけなの?
>>775 じゃあ間違いを指摘してやる。
>大概returnやthrowが行われるからifをすっ飛ばせば速いのは解る。
前方への条件分岐は、「分岐しない」と予測される、とオマエ以外の全員が言っている。
if (xx) return
で「すっ飛ばせば云々」なんて、理解していないまま「わかったつもりになってるだけ」の証拠。
>今のCPUは分岐ヒントとか投棄とかあって単純じゃないんだろ
ヒントはともかく、投機はまさに「投機実行するために分岐予測をする」のであって
「投機実行もあるから分岐予測が複雑になる」はナンセンス。
もちろん、エンプラ系/VLIW系では「分岐の有無の両経路を実行する」なんてのもある(らしい)が
一般的とは言いがたい。
>>778 内容じゃなく国語的に誤解されてるな。
>前方への条件分岐は、「分岐しない」と予測される、とオマエ以外の全員が言っている。
if( xx ) throw xxx;
throwなんて実行するケース殆ど無いんだから基本if実行しないってのは同じ話。
矛盾してないでしょ。
まず分岐予測が複雑になってるって話はしてないよ。
投棄実行については投棄実行を考慮した上での静的予測方法があるでしょという話。
>>779 だから、ifの内部は「実行すると予測される」んだよ、バーカ
781 :
779:2012/03/24(土) 22:05:34.03
尤も、わかりやすいからifと書いたけど、
実際はコンパイラの最適化でif、elseは反転するから
この言い方は正しくは無いんだけどね。
せめて正しい漢字使えよ。
一度なら単なる変換ミスとして納得できるけど
繰り返しているってことは、別の意味に捉えているとしか思えない。
>>780 お前バカだろ
みんなアセンブリ前提で言ってんだよ
jze label if() {
・・・処理・・・
labeli }
>>782 ん?尤も(もっとも)か?無い(ない)か?
>投棄実行については投棄実行を考慮した上での静的予測方法があるでしょ
理解できる日本語で書いてくれないかな。
分岐予測というのは、投機的に(結果が判明する前に)実行する前提でのもの。
(無条件分岐や間接分岐もあるから、厳密には正しくないけど)
予想して(投機的に)実行するのでなければ、単に結果が判明するのを待って、それから実行すればよい。
つまり、投機実行するからこそ分岐予測が必要なのであって
投機実行しないのであれば、分岐予測など元々必要ない。
そのことをちゃんと理解していれば、
そもそも「投機実行を考慮しない分岐予測」などというものが存在しないから
>投棄実行を考慮した上での静的予測方法
が意味不明に感じられる気がするんだけどな。
>>783 わかってるよ、そんなこと。
>>782 ああ投棄実行ね投機の変換ミスそのままにしてたわ
投棄実行については誤解してたわ。
2つの分岐を両方実行して実際実行対象にならなかった方の結果を破棄するものだと思ってた。
>大概returnやthrowが行われるからifをすっ飛ばせば速いのは解る。
もう一度考えてみたけど、この意味が全然理解できない。
ぱっと見で、何故returnや、
増してthrowなどという言葉が出るのかわからない。
(GP等の例外の割り込みは全く別物)
で、次の行の
>反復も反復する事を優先した方が早いのは解る。
の意味は、「ループであることが推測されるから分岐すると予測する」だよね?
それとの対比で、「ifをすっとばせば」の意味が
「ifの内部は実行されないと予測」と捉えれば
「ifの部分での分岐は分岐すると予測すれば
if内部のreturnやthrowに制御が来ないので別の分岐の予測を避けられる」という意味にもとれる。
それならようやく意味が通じるような気がして、そういう意味だと思ったんだけど。
つまり、ifの部分(=前方分岐)を「分岐すると予測する」という意味だと。
でもそれ(前方へ分岐すると予測する)は実際のプロセッサの動作とは違うわけで
ならばどういう意味なのか、さっぱりわからなくなってしまってね。
お前の文章が解らんわ
一応。
突然returnやthrowが出てくるのが
if (xx) return
という意味じゃないか、というのも勝手に俺が頭の中で補って想像しただけで
実際には何の説明も無く(ifの多くがreturnやthrowというのにも同意しにくい)
唐突な「rerturnやthrow」「すっ飛ばす」を必死に理解しようとしたのがそもそもの間違いかもね。
実行時の分岐予測って、どうなってるのかわかってないと、グダグダでしょ
>>794 >>779だとしたら
>>780だっての。
「前方分岐は分岐しないと予測する」のが実際のプロセッサの動作なわけ。
>>779の「throwなんか滅多に起こらないから実行しない(と予測する)」は
「前方分岐は分岐すると予測する」ことになるから実際の動作と矛盾するという話。
それを、「わかってないくせに」の根拠の一つにしたんだよ。
実際、「分岐予測とはどういうものか」も「なぜ分岐予測するのか」もわかってなかったわけでしょ(
>>789)。
口汚い言葉で罵倒せずには居られない奴って下品・・・。
団子さんの紳士っぷりを少しは見習ったらどうだろうか。
え?指摘するの780だけ?
露骨だなぁ。恥ずかしくないんだろうか。
お前がなwww
頭が悪すぎて理解できなかったらしいから仕方ないな。
>>796 投機実行という言葉については誤解してました。
分岐予測については、分岐ミスでパイプラインに読み込んだ
命令を破棄が発生するという認識です。
そもそも、それが気にならないのであれば分岐予測なんて
気にする必要はないでしょう。
>>803 なるほど。いい話が聞けました。ありがとうございます。
>>803 >と書いてあって、wikiで調べたらPenM以降は広域分岐予測を取り入れた関係で静的予測はしなくなったみたいだね
P4もグローバル履歴を使ってるよ
おそらくだけど ある分岐命令を最初に実行したかどうかはBTBのエントリが割り当てられているかで判断するので
分岐先予測より分岐予測のヒット率が十分に高い場合は動的分岐予測が当たる条件で誤って静的予測してしまう確率が高いから
1回目の分岐予測を諦めても静的予測をやめたほうがヒット率が上がるということなんじゃないだろうか
×分岐先予測より分岐予測のヒット率が十分に高い場合
○BTBのヒット率より分岐予測のヒット率が高い場合
807 :
デフォルトの名無しさん:2012/09/07(金) 22:44:12.83
これからSSEを使ってみようと思うんですけど、Cから使う場合の
SSE Intrinsicの解説書でおすすめのものはありますか?
Amazonで探したんですけど、SSEの解説書はアセンブラのものしか
見つけられませんでした。
>>808 これ、日本語が用意されてないあたり、もう日本は完全に商売の相手としてみなされてないんだろうな・・・。
中国語はあるのに。
米中の長期的戦略では日韓は中国に併合される
おまいらも今のうちから中国語勉強しておいた方が良いぞ
中国に併合?なら大丈夫だ。
中国語の一方言として日本語は残る。
やつら、言葉が通じなくても全然気にしないし。
すぐ暴力に訴えるからな
>>808>>809 まとまった書籍があればと思いましたが、そういうのはないですか。ありがとうございました。
>>810 スタッフに日本人はいないが中国人はいるだけの話。
あと、日本人で必要な人は英語を読んでしまうので、いらないと言えばいらないからじゃないか?
それもあるだろうが、日本人は押しが弱くて文句言わない(言えない)とか
中国人なら「読めない!何とかしろ!」とIntelに怒鳴むに違いない
中国語のサイト見るとあっちのプログラマはかなりがんがってる
理系離れ技術者軽視でバカマスゴミに蹂躙されてる日本はもうだめだ
Intelの日本法人が人手不足っていうだけかと
現実見ろや
中国語圏の人口は日本語圏の10倍以上いる
つーかどう考えても世界最大勢力w
コンピューターの世界では英語が最大勢力ではないか
いまのEmacsのコミッタって中国人なんやね
あっちはgeekの受け皿も多いからなあ
英語もできないくせにコミュニケーション能力とか言って
オタを弾き出してる日本人が食っていける仕事じゃなくなったね
中国人は日本以上に英語ができないからな。
んなこたーない。
ピンキリのスパンが大きくて
ネラー級の教養で大陸ならピン側寄りで
キリの人数が日本の人口超えてるのは事実
ループ内不変のクラスメンバ変数の参照を自動変数に代入して置き換えると
結構違いが出るね。
自動変数は可能ならレジスタに配置するからね
>>828 だけじゃなくて、メンバ関数の呼び出しが
あれば、少なからず実際に呼び出す
必要があるからじゃね。
うかつにキャッシュできるもんでも
ないしね。
クラスオブジェクトはポインタで管理されてるから
エイリアシングの最適化と似たような問題があるんだと思う。
エイリアシングってあれか
ポインタの値をレジスタに持ったままに出来ずその都度ロードするあれか
だからFORTRANよりも速く出来なくて restrict って予約語がC99に作られたんだな
VCなら__restrictを付ければ同じなんで少しはクラスは速くなるかな
あ、だめか
thisをrestrict化出来ないや
constつければいいだけだろ。
constは安全だけどrestrictは相当注意して使わないと危険。
「ポインタは基本的にどこでも指し示せる」という性質が問題なんだよ
これがFORTRANにもアセンブラにもない(厳密にはアセンブラにもあるけどそんな馬鹿な事はしない)
厄介事を引き起こして最適化の妨げになっている
カプセル化をうっかりブチ壊せちゃうOOP気取りのクソ言語
だからC++の哲学は「うっかりミスを防ぐ」だけであって、故意にOOPのバリアを
ぶち破ろうとする悪意には抵抗力はない
Cはむしろエイリアスの問題を無視すればよかったのに
どうせバッファーオーバーフローだって無視されてる
アセンブラと同じくエイリアスが問題が原因のバグはプログラマのせいにするとか
Win32でいうCreateThreadのパラメータにthisポインタを渡して・・・みたいな厨テクってやってる人いるけど
やっぱ害悪なんだろうな。
SSEとか駆使するときは極力クラス使わずベターCで使ってるわ。
VC++の場合、thisポインタはecxレジスタに渡され、メンバ変数や仮想関数テーブルは
ptr[ecx + offset]みたいな形でアクセスされると思うんだけど、
パラメータにecxをとる命令って結構多い(シフト・ローテートなど)
当然、ecxの中身を都度入れ替えるよね
ローカル変数にコピーしたら速くなるってそういうことなのかも
メンバ関数は特に必要がなければstaticにしてthisポインタを渡さないようにしてみると
いいかもしれない
>特に必要がなければstaticにして
ベターCどころか記述が面倒な糞言語
それがC++
そりゃC++を積極的に使う理由がないですわ。
templateを使ったメタプログラミングは便利だけどね
そんなレベルで最適化が必要なら、最初からアセンブラ使えとおもうのは俺だけ?
intrinsicを使うと、32bit, 64bit両方を一発で書けるのがいい。
>>844 だけじゃないけど少数派だろう。
動くものを作ってから置き換えないと、どこのバグなのかわかりにくい。
_mm_slli_si128のシフト量は即値だけど、可変にしたい場合は替わりに何を使えばいいのかな?
switchで切り替えるかshuffleのmaskを配列で用意しておくというのは思いついたけど。
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に入れておく)
zeroとpalignrするというのを思いついた。
palignrも即値だけ
妙なことやるよりstoreしてlddquが一番シンプルな解決策だったりするかもな。
くそー64bitモードでCompiler Instinctsじゃなくてasm復活させろよ
何のためにC++にわざわざasmキーワードが予約されてんだよ
解決策: gccかclangを使う
gccは-masm=intelでintelシンタックスでもasm使えるけど、
ダブルクォートはどうにもならないよねぇ。
ただでさえSSEのバージョンに応じたコード用意するのが面倒なのに
64bitとgcc向けで組み合わせが膨れ上がるよ。
intrinsicsでいいや、って思うようになったよ。
64bitと32bitは工夫すれば共通化できるよ
確かにダブルクォートはどうにもならんけどね
あれのせいでメンテナンス性が落ちてるのは確かだ
>>855 >64bitと32bitは工夫すれば共通化できるよ
intrinsicsなら同じソースで簡単に64bitに出来るけど、gccのインラインアセンブラで
共通にするには制約無い?それにレジスタが増えるメリットが生かせないんじゃない?
Xvidに32bit/64bit共通.asmってのがあったっけ。制約きつそうだったけど。
面倒だけどインラインアセンブラからintrinsicsに徐々に置き換えつつデバッグ済ませとけば
その後はコンパイラの違いや32bit/64bit、SSE/AVXにも対応しやすいよ。
もちろん同時に使えるレジスタ本数は8本までになるけど
そもそも16本フルで使うと性能上がるようなコードは
intrinsicsで書くにしても分けると思うなあ
(アンロールをどの程度するか、ループ内の定数をレジスタに置くかメモリに置くか等)
MSコンパイラはどうか知らんけどgccはintrinsicsにおまかせすると
レジスタのやりくりがタコで無駄なスタック退避が多かったりして
あまり積極的に使う気にはならんかった。
AVXなコードも書いてるけどintrinsicsに移行するよりは
素のアセンブリで書く機会が増えた印象。
intrinsicsだと128bit VEXとnon VEXの使い分けとかやってくれないよね
gccのインラインアセンブラで32bitと64bitを共通化するときに困るのは
自動割り当てを使うときに32bitな変数に割り当てられたレジスタを
64bitでアクセスしたい時かな。
例えばループ変数は32bitだけどそのループ変数をインデックスレジスタに使いたいとか。
> intrinsicsだと128bit VEXとnon VEXの使い分けとかやってくれないよね
コンパイルオプションで切り分けろ
複数のCPU向けの最適化コード書く場合、同じソースファイルにVEXとnon-VEXのコード
記述できないので面倒にはなったね
そのくせ_mm_broadcast_ssとかload+shufpsなどに展開してくれないから困る
>複数のCPU向けの最適化コード書く場合
それ以外に、単純にAVX対応CPU向けのコードでも
VEXを使うと命令長が長くなる場合があるので(SSE単精度SIMD,REXなしでソース破壊可能な場合)
命令毎に使い分けたいという話なのだ
さすがにintrinsicsでも2/3バイトVEXの使い分けぐらいはやってくれるのかな?
まあuop cacheのあるSandyで命令長にこだわる意味がどこまであるのかという話ではある
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が破壊されるから速いコードは寿命の長いデータがレジスタ間を漂うようなコードになるので
正直あまりやりたくないなぁ。
レジスタが余っていたらパイプライン化を目指すので共通コードにはしないかなぁ。
> さすがに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通すかな。
そこまでパフォーマンス解析が必要なコードならそもそも、コンパイラの最適化を信用しないかも
ん…。
>>832 亀レスですまんが
関数に _restrict 付ければ this に付けたことになるんじゃなかったか?
整数に関するCPU拡張命令って、あまり数が充実してないね。
需要がねーもん
そうか…残念だ。
868 :
デフォルトの名無しさん:2012/12/01(土) 17:08:51.43
あげ
これからは固定小数の時代か…
あれやこれやを固定小数で解けるようにするのは大変そうだね
んなこたーない。
固定小数があれば
増税したい放題
公共事業費ネコババしたい放題
ノーパンしゃぶしゃぶ無料で接待
もうえらいことです
872 :
忍法帖【Lv=40,xxxPT】(1+0:5) :2012/12/03(月) 07:57:12.83
何言ってんだ?
873 :
片山博文MZボット ◆0lBZNi.Q7evd :2012/12/04(火) 13:12:49.38
>>873 整数部がint_partなのはいいとして、小数部がdecimal_partなのは如何な最中と。
違うシフト値を持った固定小数点数同士のキャストオペレータが欲しいところだな。
floatは精度がintよりも精度が低いから、doubleとのキャストオペレータも欲しいな。
あまりキャストオペレータばかり作ると曖昧になっちゃうんじゃない?
だったら寧ろ、floatいらね。
固定小数点数のことを固定小数と書くやつのソースを見てあげる優しさは素晴らしい。
符号ビットの指定もできないし、幅も int 固定だし、ものを知らない。
固定小数点数ルーチンなんていくらもあるんだから、他人に見せるんなら、他と比べてメリットのあるものにしてほしいね。
decimal は通貨用のを恥知らずにも参考にしたんだろうね。
>>875 今時のコンパイラなら、explicitをつければキャスト演算子必須な変換関数が作れる。
explict operator float() const { …… }みたいな感じ。
880 :
デフォルトの名無しさん:2013/09/25(水) 22:42:54.37
vs2010 x64でアドレスに16bitのオフセットを加算しようとすると
movzx esi、word ptr[]
add rsi、r15
みたいなコード吐くんだけど、
これってパーシャルレジスタストールする?
32ビットレジスタへの書き込みは自動的に64ビットにゼロ拡張されるんじゃなかったっけ
882 :
デフォルトの名無しさん:2013/09/25(水) 23:12:56.51
64bitモードで32bit書き込みした場合上位32bitはクリアされるってwebで見つけたから
ストール無しなのかな
REXを省略するための工夫だからストールはしないよ。
レガシーSSEもYMM上位ゼロクリアならどれだけ楽だったか
部分的な入れ替えはシャッフル的な命令使うことを強制しておけば、CPUを作る側も楽だったろうに。
MC68000にはmovqという命令があってだな(しみじみ
なにその clr.l より速い命令
x64のgccで使われているmovqはmove quadって意味だよね
move qwordです
8086時代からの伝統でword=16ビット
512bit SIMDはまだかのう。
19x19の碁盤を一レジスタに収めたいんだが。
512bitシフト演算もできるとええのう。
碁石ってシフトのような動きするのか?
シフトすれば斜めに置いてあるのを同時に扱えるんじゃない?
石の繋がりを調べるのにシフトしてandとったりする。
特にアライメントせずに確保した配列(std::vector標準のアロケータ)に対し、
AVXの_mm256_load_psや_mm256_store_psでアクセスしても何事もなく処理が実行されます。
以前、SSEのときは、アライメントされていない配列に対し、_mm_load_psや_mm_store_psを行うと、
プログラムがクラッシュしていました。
アライメントされた配列に対し、loadu_psやstoreu_psを使っても、
load_psやstore_psと比べてパフォーマンス低下が起こらなくなったというのは聞いていますが、
アライメントされていない配列に対し、load_psやsotre_psを使っても動くようになったというのは聞いたことがありません。
AVXになってから、このような挙動に変更されたのでしょうか??
された。
聞く前にまずIntelが出してるリファレンスマニュアル目をとおしなよ。
君は仕様書も目を通さずにプログラムを書く人間なのかい?
897 :
895:2014/08/21(木) 01:00:22.02 ID:gFJa9U99
団子さん、ありがとう!
Intel CPUはどんどん便利になっていくね。
でも、アライメントを保証できる状況の方が-mavxを指定したときに
ループがベクタ化されて出力されるアセンブリがより高速な組み合わせになった希ガス。
1024bit SIMD搭載CPUが廉価で発売されたら本気出す。
AVX-1024なんて出るのかしら
マスクレジスタが128ビットになるからそのままだと汎用レジスタの幅が足りなさそう
それまでにIntel 128が必要ですね。
AVX-1024・・・。
8bitデータだったら128並列・・・ハァハァ・・・。
囲碁や将棋のAIが捗りそうだね
それよりOSが使わないアプリ専用のコアをつけてほしい
OSってそんなにオーバーヘッドあるの?
OSが管理しなかったらどうやってアプリから使うの?
Cell-SPEみたいなのは御免だけどな。
cooperativeなマルチタスクは今日日はやらない。
タスクスイッチせずに占有させろってことかな?
カーネルモードで割り込み禁止にすりゃいいだけ
OSに管理させないとか仮想化の流れと逆行するからまず受け入れられない
自分が考え方を変えるほうが早い。
Linuxならオープンソースだからカスタムカーネル作れるんじゃね?
つーか、カーネルのAffinity設定して特定のcoreに拘束すればいいんじゃね?
割り込みなかったらキーボード入力とかどうすんの
つ GPGPU
Xeon Phiとかはこのスレ的にどうなの?
高嶺の花だなぁ・・・。
全部のプロセスのアフィニティ設定しなおすとかできんのかな?
特定のプロセスだけcore4とかに
今のWindowsはGPUのコンテクストすらプリエンプションやってますが
>>914 権限のあるプロセスに対してはやれるといえばやれる