1 :
デフォルトの名無しさん :
04/12/21 15:08:57 PentiumMにて addpdは4-2(レイテンシ-スループット) imul 4-1 Pen4、Athlonなどデータを集めてみる
∧∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
(,, ) <
>>2 ゲットしようと来てみれば
.( つ | こりゃまた とんだ駄スレだなぁ オイ
| , | \____________
U U
| まあ せっかくだからやっといてやるよ |
\ ハイハイ 今だ
>>2 ゲットズザー っとくらぁ /
 ̄ ̄ ̄ ̄ ̄ ̄V ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
∧∧
(゚Д゚O =3
⊆⊂´ ̄ ソ ヤレヤレ
ドッコイショ・・・・・・・・・
 ̄ ̄ ̄ ̄ ̄∨ ̄ ̄ ̄
∧∧ (´;;
(゚Д゚ ,)⌒ヽ (´⌒(´
U‐U^(,,⊃'〜... (´⌒(´⌒;;
ハァ、ダルッ・・・帰るか
 ̄ ̄ ̄ ̄ ̄∨ ̄ ̄ ̄
ポ ∧∧ ポ
ン (゚Д゚ ,) . ン
(´;) U,U )〜 (;;).
(´)〜(⌒;;UU (´ )...〜⌒(`)
(・3・) エェー OS上で正確な測定が出来るのかYO
そこでMS-DOSですよおとうさん
PentiumMはまた他と異なるからじゃないかと
それなら、
>>1 はそうとわかるように、スレタイと
>>1 の内容を書くべきだったね。
>>3 できるよ。
>>5 Intelのマニュアルは持ってるが、Pen4しか詳しくない。
PenIIIも概略はのっているが、細かいクロックはない。
PenMのSSE2はみたことないし。
P4以外のSSEは、おそらく2μopで、それぞれのμopが並列実行されたりするから
内部構造を意識しないとクロックがわからない。
実行ユニットの数、レイテンシ、スループットをうまく求める必要がある。
PentiumM addsd 3-1(レイテンシ-スループット) addpd 4-2(addsd2回に相当。連続して行うと実質4-1) sqrtsd 57-57
PentiumMのSSE2は糞っていうのをどこかで見たな。 計測プログラムを公開して、色んなCPUで実行してもらうのが、いいんじゃない?
>>10 PenMのSSEはNetBurstより圧倒的にレイテンシもスループットも良いんだがな
乗算やシフトもIntel系の伝統を破っていて不思議と速い
実クロック以外に糞と呼ばれる要素あるんかいな?
ベストケースのレイテンシ・スループットはAMD, Intelともに
ドキュメントがある。しかし、それが何の役に立つというのだ?
ちうわけで
>>12 のようなシミュレータの出力を眺めつつ
あっち立てればこっち立たずの局所最適化に明け暮れることになるわけだ。
スループットって何? スループット1なら、最も条件が良い時に1クロックで実行できる。 スループット2なら、2クロックで実行できる。 ってことだと思っていたのだけど、間違ってる? 論理演算は、64ビットのMMXがスループット1で、128ビットのSSE2がスループット2だから、 どっちでやっても変らないや、と思っていたのだけど、実際にやってみると、SSE2のほうが速い。 もしかして、コーディングがヘタ糞で、ストールしまくってるのかな・・・。
メモリアクセスのレイテンシはいっしょ ロード&ストア回数が少ないほうが速くて当たり前
メモリアクセスのレイテンシは隠蔽されないのですか・・・。
>>15 PentiumM, AthlonのMMX ALUは、スループット1/2
依存関係のない2つの演算が同時に2個実行できる。
(Pentium4 は スループット1 のハズ)
たいていのSSE演算は、いずれのプロセッサもMMXを2つ束ねて
実行しているようなものなので、スループットは半分になる。
レイテンシに関しては、メモリアクセスのレイテンシは
ベストケースでL1キャッシュにヒットしたとき。
メモリアクセスのレイテンシは、他に実行しているロード/ストアに
引きずられたりするので、予測するのはけっこうメンド。
コアループをここに貼ってくれれば添削はできる。
解説ありがとうございます。 せっかくの添削の話ですが、 アセンブラではなくCで書いてコンパイラにスケジューリングさせてるので辞退させてください。
コンパイラは確かに優秀だが 仕様上どうしてもできないことがある 漢なら__declspec( naked )で書くんだ
>addpd 4-2(addsd2回に相当。連続して行うと実質4-1)
>>9 のこれは間違いだった。
3-1を2つで3-2が正解。
上位と下位で並列性が生まれ、少しレイテンシが減る。
今はVC++6のインラインアセンブラとnasmで計っているが、
分岐ミスのクロックからパイプラインの長さ計ろうとしても
いまいちはっきりせん。
14段ぐらい?
そういや、VCは不思議な挙動をするね。 インラインアセンブラで書く → その前後でコンパイラの最適化が無効になる intrinsicを使って書く & 組み込み関数のインライン展開OFF → intrinsicを含め、コンパイラが最適化してくれる intrinsicを使って書く & 組み込み関数のインライン展開ON → その前後でコンパイラの最適化が無効になる リリース・ビルドでは 組み込み関数のインライン展開ONよりもOFFのほうが速く、 デバッグ・ビルドでは 組み込み関数のインライン展開ONよりもOFFのほうが圧倒的に遅い
VB高速化のため、VCの__asmで書きDLL化したのをVBから呼び出している漏れ。 21の言っていることがよくわからない。 悔しいのでキャッシュの仕組みでも書いてみる。 話がPIIIなのは昔考えたことだから。 キャッシュというのはアドレスを言われたらすぐそのデータを差し出さなければならない。 PentiumIIIのL1キャッシュでのこの時間はわずか3clk。 キャッシュのどこにどのアドレスのデータがあるかを把握していなければならないのは当然だが、 突然言われたアドレスのデータが16KBものデータの中からどこにあるのかを調べて データを転送するまでたったの3clkで完了させるというのは、 データの配置に制限をかけて検索しやすいようにしなければできないことである。 そこでL1キャッシュは4ウェイ・セット・アソシエイティブ、キャッシュラインサイズ32byte、 キャッシュライン512本で容量が16KBのキャッシュになっている。 まずL1キャッシュは512個のキャッシュラインに分かれている。 16KB÷512個でそれぞれが32byte。 ここには必ず32byte境界にアライメントされた連続データが入る。 これが4個ずつ128グループになっている。 アドレス値の5〜11bitには、7bitあるので128通りがあるが、 各グループがその128通りに割り当てられる。 そのグループ内のキャッシュラインには必ず割り当ての7bitをアドレス値の5〜11bitに持つデータが入る。 すると、このアドレスのデータがほしいと言われたときに、アドレスの5〜11bitからグループを特定し、 その中4つのキャッシュラインについて一致するアドレスがないか調べればいいことになる。 これなら3clkでできそうだ。
って22の間違いね。 >21の言っていることがよくわからない。 まあ、アセンブラのおかげで、Cが内部的に何をやっているのかは けっこう理解しやすくなった。 22がそんな難しいことを言ってないというのはわかるが アセンブラ使いのVB厨つうことで勘弁。
>>24 インラインアセンブラを含む組み込み関数(intrinsic)をインライン展開すると
最適化が効かなくなる。
→普通は速くなるはずのインライン展開が、却って遅くなる原因になることもある。
ってことでしょ。
EAX,EDX以外のレジスタを使うとちゃんと保存してくれてるんだよな エライもんだ
>>25 サンクス。こっちの指定が大域的な最適化を阻害するわけか。
そりゃそうだわな。コンパイラ作った人えらいなあ。
調べた(PentiumM)
命令 レイテンシ スループット
MOVDQA 1 1
MOVDQU 1 1
MOVD 1 1
MOVD 1 1
MOVDQ2Q 1 1
MOVQ2DQ 1 1
MOVQ 1 1
PADD(B/W/D) 1 1
PADD[U]S(B/W) 1 1
PADDQ 2 2
PADDQ 2 2
PMADDWD 4 2
PMUL(L/H/HU)W 4 2
PMULUDQ 5 2
PMULUDQ 4 1
P(AND/ANDN/OR/XOR) 1 1
PS(L/R)LDQ 3 3
PS(L/R)L(W/D/Q) 2 2
PSRA(W/D) 2 2
PCMP(EQ/GT)(B/G/W) 1 1
PACK(SSWB/SSDW/USWB) 2 2
PUNPCK(L/H)(BW/WD/DQ) 2 2
PUNPCK(L/H)QDQ 1 1
続き PAVG(B/W) 1 1 PSADBW 5 2 PEXTRW 4 2 PINSRW 2 2 P(MAX/MIN)(UB/SW) 1 1 PMOVMSKB 1 1 PSHUFD 2 2 PSHUF(L/H)W 1 1
OV(A/U)PD 1 1 MOVSD 1 1 ADDPD 4 2 ADDSD 3 1 MULPD 7 4 MULSD 5 2 DIVPD 62 62 DIVSD 32 32 SQRTPD 114114 SQRTSD 57 57 ANDNPD 1 1 ANDPD 1 1 ORPD 1 1 XORPD 1 1 CMPPD 4 2 CMPSD 3 1 [U]COMISD 1 1 MAXPD 4 2 MAXSD 3 1 MOVMSKPD 1 1 SHUFPD 2 2 UNPCKHPD 3 2 UNPCKLPD 3 2
CVTPD2DQ 4 2 CVTPD2PI 2 2 CVTSD2SI 4 1 CVTDQ2PD 4 2 CVTPI2PD 4 2 CVTSI2SD 4 1 CVTPD2PS 5 2 CVTSD2SS 4 1 CVTPS2PD 3 3 CVTSS2SD 2 2 PINSRW 2 2 P(MAX/MIN)(UB/SW) 1 1 PMOVMSKB 1 1 PSHUFD 2 2 PSHUF(L/H)W 1 1 CVTDQ2PS 4 2 CVTPS2DQ 4 2 以上。全部SSE2でした。
実行ユニットがガラ空きだったときのベストケースのクロックです。 SSE2は2μopのようなので、MMX2命令(1μop*2)の方が デコーダには優しい場合もあり。
thx. 予想通りだな。ちなみにK8も似たような感じかな、 SSEはMMX×2なので。 かといってこんだけの情報でオプティマイザ作るのは至難の業 次はMMX命令の計測 pls. (たぶんP6系と共通だろうが)
orz...
Excelでまとめたのをそのままコピペしたらあかんわな。連投&&間違い多くてスマソ。
2回書いてある命令がかなりあるが、無視してくれ。
pmuludqは、下はMMXレジスタが対象のときのクロック。
>>10 自分でも試行錯誤して計ってるからなあ。配布できるようなものを作る自信もないし、
アセンブラで叩いて肌で感じる、CPUごとのクセみたいのを知りたいなあ。
>>11 PMのSSE・SSE2は、P4と大分性格は違うもののIPCは同じ程度と予想している。
PMは整数・論理演算が得意で小回りがきく。
P4はメモリから高速転送して浮動少数点演算が得意。かな?
ていうかPMは実クロックこそが糞なのだと思われ。SSE2では(実性能で)P4に張り合えないでしょ。
>>12 それ激しく面白そうだが、何?
>>14 自分はマンデルブロ集合の描写速度で理論値に迫りたいと思ってこの道にはまった。
確かに、「楽しいから」「知りたいから」以外、役に立つということは少ないかもなあ。
>>18 その「スループット1/2」という表現だと、「レイテンシ1・スループット1/2の演算器が1個」だよね。
実際は「レイテンシ1・スループット1の演算器が2個」なので厳密には違うと思う。
(18の言わんとしていることは正しいと思うが表現が気になっただけ)
>>26 VCのインラインasmはホント親切だね。そういうことは大分後で知ったよ。
VB+VC__asmって一番ぬるま湯なアセンブラ環境やも知れぬ・・・。
>>32 K8の情報激しくキボンヌ。
SSE命令を2つ同時デコードできるかとか、
SSEの単精度と倍精度の差とか。
ちなみにPentiumMの乗算だと、単精度2個で4-1、倍精度1個で5-2。
倍精度だと、拡張精度のFPUと同等で、あまり速くない。
MMXだとP6と一緒みたいです。
ただ、μopフュージョンのおかげでメモリ周りがP6より速い。
例えばmovq [edi],mm0という命令は普通だと
「ストアするアドレス[edi]の計算」と「データmm0をストアバッファへストア」
の2つのμopに分解される。これをくっつけたまま処理する。
すると、デコーダはこの命令を複数μopに分解しないで済む。
1つの命令を複数のμopに分解するのはデコーダにとって相当に大変らしく、
これでこの命令はデコードに際し1μop扱いとなる。
当然リオーダバッファも1エントリしか占有しない。
実行ユニットに送られるときに分離され、それぞれ処理される。
OoOなのでこの処理は同時でなくてもいい。
結果は元のリオーダバッファに戻され再び合体、両方の処理が終わった後で
命令はリタイヤされる。リタイヤも1μop扱いなので楽ちんだ。
特に、P6ではリタイヤがボトルネックとなり、最大でも
3μop/clk(デコーダは6μop/clk吐けるのに)だったので、
PMは「思い通りのスピードが出る」名石だと思う。
いつも使ってるコテトリップつけると、ストーカーヴァカがやってくるので(汗
>>34 SSEのデコードが、K7/K8でもっとも違うところですね。
K7(Palomino)では、動けばいいやって感じの VectorPathだけど
K8では、SSEはDouble pathといって、Decoderを2つ同時に駆動するような
感じになるのね。だから、Double path命令は、2命令同時発行はできないけど
Double path+DirectPath は可能(なハズ)。
文章では、AMDサイトに Optimization guide(英文)があがってるので、参照されたし。
uops fusionに関しては、K7の頃から似たような感じの実装があった。
issue stageまでは一緒にスケジュールされる。
Retirement が3ってのがいちばんボトルネックになりうるというのを知って
愕然とした、俺であった。合掌。
>>33 >>12 で紹介されてるのはAMDのフリーウェアで、
ターゲットの実行ファイルに対して、
CPUのパフォーマンスカウンタの値を表示したり、
CPUシミュレータによってパイプラインの状況を1命令ずつ表示したりできる。
>>35 DoublePathでも論理演算とかはFADD、FMULに並列に送ることが
可能じゃないの? 最適化マニュアルをみるとThroughputは1になっているし。
>>37 Yes, FADD, FMUL で同時に喰うから、スループット1だね。
Load も、たいていの場合だと 64bit x2 がイケるし…
Store は、64bit x1 なんだな、これがネックになりうる。
>>35 >uops fusionに関しては、K7の頃から似たような感じの実装があった。
P6対K7でK7優勢だったのはこのおかげだろう。
確か、「メモリ読み書きとALUのセット」が3つあるんだよね。速すぎ(^^;
その上FPUが強力だし、よくP6で張り合えたものだ。P6がよかったのはL2キャッシュの性能?
>Retirement が3ってのが
デコーダも実行ユニットもしっかり考えて作るのになぜかIPCの壁があって、意味不明だった。
マニュアル読んでコレダ!と思ったよ。なぜか他所では見たことないが。
あのマニュアルはIntelに不利な点を隠すように書いてあるから、読みづらいったらない。
>Optimization guide
お、いいなこれ。ありがと。英語は読むのに時間がかかりすぎだが・・・。
もっとも、Intelの直訳マニュアルも意味不明だった。
>
>>32 かといってこんだけの情報でオプティマイザ作るのは至難の業
手動で最適化できる知識を身に付けたいというのは大きな動機だったなあ。
しかしオプティマイザ作るってのはやり方の見当もつかん。
前も書いたが最適化の効いたコンパイラ作る人えらい。
>>36 サンクスコ・・・。やってみたが、StartSimulationを押すと即落ちる(XPで青い画面初めて見た)。
AMDのCPUじゃないとできないとか?APICがないとか出るがそれか?
ヴ〜パイプラインの様子見てえぞゴルァ!!
>>10 >PentiumMのSSE2は糞っていうのをどこかで見たな。
遅レスだが、これはまるも製作所のことではないだろうか(戯言の04年11月9、11日参照)。
MMXをSSE2にしたら、PMは遅くなりP4は速くなったという話。
この人が使っている「psadbw」という命令が最悪(SSE2化で使い勝手が悪化した命令の1つ)。
P4ではSSE2で高速化しているが、PMの倍の帯域を持つL1キャッシュの力を引き出したのと、
糞性能(PM/P6の半分程度)のMMXを使わなくなった効果だろう。
psadbwを使う状況では、PMは素直にMMX版でいくしかないと思われ。
>>11 の言い分は「P4よりPMが速い」なので正しい。ただ、キャッシュのスループットは例外。
MMXよりSSE2が遅くなるのはPMでもレアケースのはずだが、不満の声を聞くのが
動画処理(SIMD系命令本来の用途)をしている人からなのが意外だった。
>>37 >>38 あたりはOptimization guideよく読んで考えよっと。
ついでに。
このスレの主眼となるクロック計測だが、「addpdが4-2」で終わりじゃない。
「addpdは2μopに分解され、クロックは両方3-1で、実行できるユニットは1個」まで調べる。
>>39 > その上FPUが強力だし、よくP6で張り合えたものだ。P6がよかったのはL2キャッシュの性能?
初代K7と河童の最大の違いだね、L2は。低レイテンシ高スループットのL2は、
正直うらやましかった。今でもL1, L2とも、K7はP6系よりレイテンシ高い。
> サンクスコ・・・。やってみたが、StartSimulationを押すと即落ちる(XPで青い画面初めて見た)。
AMDコードアナルはAMD専用っぽいっす。プロファイリング用のドライバが
AMD-Specific Registersいじってるんだと思う。
俺に必要だったりするのはパイプラインシムだけだったりするんだがな。
あとのプロファイリングは RDTSC で事足りてるし。
俺のメインマシンである Crusoe ノートに入れたらやっぱり市んだので。
>>41 即レスありがと。K7のレイテンシってどのくらいなの?
調べたが、P4とかはよくCPU-Zのが晒されてるんだがAMDは見かけない。
そもそもP6のL2バスが256bitのハーフスピードで4byte/clkのスループット
というのからして理屈がわからないのだが。
>AMDコードアナルはAMD専用っぽいっす。
残念。まあ仕方ないか(夢のようなソフトなんだが)。
さて。
クロック測定には、内部構造の知識も必要なので書いておく。
CPUの速さを決めるのは、キャッシュ性能・命令のフェッチ・デコーダ・命令の所要クロック・
実行ユニットの数・分岐予測・パイプラインの段数・OoO性能・リタイヤユニット・・・など。
PentiumMでは具体的にどうなっているかを解説する。
キャッシュは、L1がデータ32KB,命令32KB、L2が2MB。巨大です。
L1がレイテンシ3、スループット8byte/clk。L2はレイテンシ10、4byte/clk?
速さについては
>>23 も参照。詳しいデータが欲しい。Intelはキャッシュが強い印象がある。
命令のフェッチ(L1命令キャッシュから読む)。何か16byteごとに持ってくるらしい。
なので16byte境界をまたがないように命令を置くといい。
デコーダ。3個ある。その内、複数μopの命令をデコードできるのは1個だけ。
つまり4μop、1μop、1μopと来たクロックには6μopも吐けるが、
2μop、2μopと来たらクロック当たり2μopしか吐けない。
よって1μopでない命令は連続しないように配置するとよい。
ここでμopフュージョンが効く。メモリへ書く・メモリから足すなどが1μopとなった。
命令の所要クロック。このスレの住人様(俺かよ)お願いしまつ。レイテンシをうまく隠蔽しよう。
実行ユニットの数。5個ある。0〜4の番号を付けると、
0はALU(整数・論理)・移動・浮動小数点乗算。1はALU・浮動少数点加算・移動。
2はメモリから読む。3はメモリへ書くアドレス計算。4はメモリへ書くデータをバッファに入れる。
メモリは読むより書く方が手間なんですね。処理を違うユニットに分散させれば最大5μop/clk。
ここでのμopは、フュージョンしたのを分離したμop。
分岐予測。今のCPUはパイプラインが深い。作業を細分化して流れ作業なわけです。
その作業の最初が命令のフェッチで、分岐はそのフェッチする場所を変える命令なので
早い内に変えることを予測して作業しないと効率悪すぎです。
今までのパターンから予測する他、ループ検出器なんかも付いていて強力らしい。
当然パイプラインの段数は少ない方が良い(クロックは上げにくくなるが)。
OoO。アウト・オブ・オーダーの略。 レイテンシが長い命令の結果待ちμopなどがあったら、先に別の命令を処理しちゃおうという機能。 デコードが終わった段階で、μopたちはリオーダバッファとかいうのに格納される。 この中から今すぐ実行できる命令を選んで実行ユニットにガンガン送り出す。 バッファの数や送り出しの決め方なんかが性能を左右するのか? リタイヤユニット。リオーダバッファから実行済みの命令を見つけて、 「順番通りに」結果をレジスタやメモリに書き込み、消していく。 最大3μop/clkでリタイヤさせることができる。 ってここに来る人はこんなのわかってるか・・・。 でも昔の俺はこういうのを猛烈に知りたかったのよ。
>>44 俺もマイクロアーキテクチャを真剣に調べるよーになったのは
ここ1年くらいのことなんで、マターリ逝こうや。お互いにな。
>>44 PenMのレイテンシ/スループットは英語版の最適化マニュアルおとせば
主要なのは載ってるよ。
>>47 横槍失礼。見てみました。
データシート記載のものとほぼ同じ数字のようですね。
プレスコは…(ry
>>49 しかし、
>>1 が欲しいのは
>>27 以降の書き込みをみるかぎりx86/x87ではなくて
SIMD系のデータらしいが…。
Pen4に関してはもっと詳細なソースもあるが、ここでは秘密にしておく。
まぁP6以降スーパースケーラx86石専用スレつーことでヨロ
>>45 俺走りすぎてる?(^^;
まあ、たまにしか来られないのでこのぐらいやらないと。
・・・と思ったら、俺のレスの割合多いな。orz
>>46 そうか。以前探して、無かったので、PMは無いという先入観ができていたようだ。サンクス。
>>47 これはイイ!しかしP4のL1はすごい。そういうのに特化した設計だから当然と言えばそうだが。
Prescottはキャッシュレイテンシが増えても、実際の性能がそこそこ出るのはなぜだ?
キャッシュ容量は増えてるが、内部的にも改善のある希ガス。
>>49 >>50 俺は全て知りたいが、古いマニュアルに載っていなくて未知数だったSSE2を特に知りたかっただけ。
整数命令は使った経験が多いので、比較的挙動がわかる。
IntelのFPUは加算3-1、乗算5-2でPPro〜PenMまで変化ないと思うが、
加算と乗算の並列実行やfxchのコストなど、詳しい資料があれば是非見たい。
並列実行はPMになった時点で有効になったと見たがどうか?
つうか秘密にされると知りたくなる罠。
>>51 ま、そうだね。俺がアセンブラ始めたのが河童-128k。Celeronにしては、いい石だった。
VBを始めたのはPenIIで、BASIC始めたのはポケコンだった。
ポケコンで機械語できなかた雪辱をやっと(w
>>52 俺もたまに実生活でパイプラインが浮かぶ。スーパースカラの方が多いが。
両手で作業してるとき、右手と左手をUパイプとVパイプに見立ててP5ごっことか。
勉強になります!
両手で作業してるとき、右手と左手をUパイプとVパイプに見立ててP5ごっことか。 両手で作業してるとき、右手と左手をUパイプとVパイプに見立ててP5ごっことか。 両手で作業してるとき、右手と左手をUパイプとVパイプに見立ててP5ごっことか。
可愛そうに・・・「させられ体験」をしているなんて、間違いなく統合失調症だな。
>>54 わかった点や疑問点なんかも書くと更に嬉しいぞ。
>>56 頑張ってアセンブラの勉強をしていた頃は、かなりの事象がCPUの動きに見えてたなあ・・・。
>>57 マジレスでスマソ(スレタイからも脱線だが)。
人間は相対的に物事を捉える、言葉で物事を考える、とすれば、
CPUの仕事と自分の仕事の類似点があったら、アセンブラの経験を生かした捉え方ができる。
誰でも、P5のUVパイプの比喩でなくとも、もっと一般的な何かにたとえて捉えているにすぎない。
俺はコンビニのレジをやったことがあるのだが、おつりを取るときに、
距離の関係で、1円玉は右手で取れない、500円玉は左手で取れない(取れなくはないがw)。
つまり、片方のパイプでしか実行できない命令がある。
また、10円玉4枚を取るときのこと。
10円を入れる所が1個しかないので、2枚/clkの手を2本持っていても2clkかかってしまう。
依存関係はないが、実行ユニットの競合が起こってしまう。
8byte/clkのキャッシュでも、mov eax,[esi]/mov edx,[esi+4] には2clkかかるような感じ。
店員が2人で1つのレジをやっているとき。
確かに1人でやるよりは速いが、小額の客ばかりだとあまり変わらないことも多い。
客:タスク、客に対する様々な作業:スレッド、店員:CPU、
レジの個数:ソフトの仕様、お金の授受:外部記憶のアクセス。
1人の客に対して複数のスレッドがある時間は短いため、デュアルCPUを生かせない。
素直にレジ2つ使えば(ソフトをデュアルCPU向けに最適化すれば)速くなる。
ただ、このソフトをシングルCPUで実行すると、レジを行ったり来たりのオーバーヘッドがある。
だが、お金を出すのが遅い客ばかりだと、このソフトの方がいい場合もありうる。
(本当にやったら客に失礼すぎ)
店員がHT対応(2つのレジに手や目を分散できる変態。頭いいのが前提)だったら問題ないが。
>>58 やっぱり、病気ですから。
もっと抽象的な捉え方するなら兎も角、特定のCPUのアーキテクチャと捉える辺りがもうね。
その程度だったら精神科いけば直るよ
あすろんについて。 K8でxmmレジスタに対するpandとandpdのクロックが違うのはなぜ?同じ動作なのに。 DoublePathなのは1.5命令/clkと書いてあったが、1個のデコーダで2clkてことかな。 P6のデコーダの1つは1clkに最大4μopを吐くが、 K7/K8は、それよりは少し弱いデコーダが3つあるということか。 2μopの命令が連続するとP6は弱い。μop自体K7の方が大きいし。 つーかロードが2命令/clk出せるのがうらやましい。 確かにPenMと同等かより上の高性能だが、Intelのとは 内部構造が別物だね。 Crusoeの叩き心地とかも知りたいが・・・。
>>61 >K8でxmmレジスタに対するpandとandpdのクロックが違うのはなぜ?同じ動作なのに。
>DoublePathなのは1.5命令/clkと書いてあったが、1個のデコーダで2clkてことかな。
フシギだねぇ。似たような動作なのに。
どちらもデコーダは DoublePath だから、実質的にデコードは1命令/clk
その後、PAND類は、FADD/FMULへissueされるが、
ANDPDはFMULへのissueのみなので、その分スループットもレイテンシも
大きい、そういう理解でいよう。
>P6のデコーダの1つは1clkに最大4μopを吐くが、
>K7/K8は、それよりは少し弱いデコーダが3つあるということか。
スケジューラに叩き込まれるまでに macroop になるようだね。
marcoop は、1〜2uopで構成されてると推測。
>つーかロードが2命令/clk出せるのがうらやましい。
けっこーこれができない条件があって、シミュレータでも実機でも
ストールを見ることができるよ。だからこそ、Load が 64x2 連続で
逝けまくってるときって楽しくてしょうがない。実際にはLoadするばかりでなく
Store(こちらは64x1)も混在するから、このときにいろいろ引っかかりが出てくる。
>Crusoeの叩き心地とかも知りたいが・・・。
俺は現役の Libretto L2使い。ほい。
Crusoe Exposed: Reverse Engineering the Transmeta TM5xxx Architecture
http://www.realworldtech.com/page.cfm?ArticleID=RWT010204000000 http://www.realworldtech.com/page.cfm?ArticleID=RWT012704012616
>>62 andpdもALU使えよ・・・てのは素人考えなのだが。
しかし手元にないCPUを調べるのは、ある意味むなしいな。確認ができん。
1kHzくらいでいいからエミュレータ欲しい。
age
整数用のALUとSIMD用のALUって、別に存在して、同時に動くの? なんか、SIMDの計算の間に、整数用の命令を挟んでも所要時間がほとんど変化しないよ。
あーおもしれー
>>62 Athlonでの
>>65 を考えて気づいたが、AthlonではMMXすらFPU側なのだね。
andpdはFADDを使いたいときに有効かなあ。
これは(AGU+ALU)*3とFADDとFMULが同時に稼動できるの?
DirectPath Singleのでかい命令をガンガン入てけばとんでもない性能になるな・・・。
>>65 Athlonは上述の通り、別にありそうな気がする。
PMだと、共通に使うALU(64bit以下の論理演算を1clkに1回できる)が2個あるだけに見える。
正確には、別にあるけどポートが競合して同時には稼動しない。
たくさんある実行ユニットは、パイプラインを共有しているものがあり(整数ALUとMMXALUとか)、
競合すると同時には実行できないのだ。
使用CPUとそのコードを晒してくれれば何が起こっているか分析したい。
あと、同じレジスタに続けて書き込むと2clkストールするとPIIIのマニュアルに書いてあった。
そのストールの間に整数命令を実行できたとか?(レジスタリネーミングで回避できないんかな)
PIIIはandpsが2-2だったんだよね。片方のALUしか使ってないかも。
P4も片方かな。P4はどんなμopに分解してるのかわからん。P4使いいないか。
pand xmm0,xmm0を8個の後dec ecx/jnz。これをPenMで9clk/loop。
1ループあたりALU(2個ある)行きのμopが18個なので9clk。
ALUの数で理論値を出しているので、ここでは整数命令を入れると必ず遅くなる。
理論値は出せたものの、結構シビア。使用レジスタによってコロコロ変わる。
xmm0,xmm0 xmm1,xmm1 xmm2,xmm2・・・とすると11clk/loop。意味不明。
ここで3と4の間にand eax,ebxをはさむと12clk、nopをはさむと10.66clk。誰か説明ぷりーず。。
このあいだ、僕のかよってるCPU行ったんです。PentiumIII。 そしたらなんか命令がめちゃくちゃいっぱいで入れないんです。 で、よく見たらなんか別スレッドが来てて、エンコード中、とか書いてあるんです。 もうね、アホかと。馬鹿かと。 お前らな、新作アニメ如きで普段やってないエンコしてんじゃねーよ、ボケが。 まほらばだよ、まほらば。 なんかでかい命令とかもいるし。1命令4μopでCPUか。おめでてーな。 よーし複雑命令デコーダ使っちゃうぞー、とか言ってるの。もう見てらんない。 お前らな、実行ユニットやるからデコーダ使わせろと。 CPUってのはな、もっと殺伐としてるべきなんだよ。 リオーダバッファに入った奴同士、いつ実行ユニットが競合してもおかしくない、 足すか足されるか、そんな雰囲気がいいんじゃねーか。マクロ命令は、すっこんでろ。 で、やっと入れたかと思ったら、隣の奴が、ロード・ストア同時で、とか言ってるんです。 そこでまたぶち切れですよ。 あのな、キャッシュバンクずらして使うなんてきょうび流行んねーんだよ。ボケが。 得意げな顔して何が、ロード・ストア同時で、だ。 お前は本当にそのμopリタイヤできるのかと問いたい。問い詰めたい。小1時間問い詰めたい。 お前、同時にできるぞって言いたいだけちゃうんかと。 PenIII住まいの僕から言わせてもらえば今、僕らの間での最新流行はやっぱり、 MMX、これだね。 MMXとMMX2。これが通の最適化。 MMXってのはレジスタが長めになってる。そん代わり小回りが効かない。これ。 で、それにMMX2(SSE整数命令)。これ最強。 しかしこれを実行すると次にFPUを使うとき切り替えが必要という危険も伴う、諸刃の剣。 素人にはお薦め出来ない。 まあお前、ビデオエンコードは、Pentium4でも使ってなさいってこった。
すまん。全然わからん。orz できればここにコードを貼ってほすぃ・・・
別の話題でも。 色々調べて思ったのは、同時にμopを発行できる実行ユニットの数を増やすのは大変だということ。 Athlonの、マクロ命令の段階でスケジュールして振り分けてしまうのは、今更ながら感心。 (スケジュールを2段構えにして負荷を軽減) デュアルコアよりも、実行ユニットを倍に増やしたHTの方がいいじゃん、とか思ってたが これはOoO周辺を作るのがすごく大変なのだろう。 lp: addps xmm0,[esi] addps xmm1,[esi+16] addps xmm2,[esi+32] addps xmm3,[esi+48] add esi,64 dec ecx jnz lp これはPMで11clk/loopなのだが、mulps xmm1,[esi+16] を追加挿入すると10clkになる。 まあ、addを全部mulに置換すると理論値の8clk/loopを叩き出すわけだが。 add系が不思議に遅い。
>>1 漏れは>71じゃないが、そのURIにディレクトリ構造がそのまま見えているのだが。
coresをクリックしてみるくらいできないわけじゃなかろうに。
>>74 スマソ。
ディレクトリが見えてるのはわかってたが、
適当にクリックしても何も出てこなかったのだ。
今やって、できますた。ありがd
信じられないだろうが、
>>73 の前に30分ほど試行錯誤してできなかった。
ちょっと見た感じ、SSE2整数と32bitALUを混ぜると
デコーダ的にも悪くないし、
レイテンシの隠蔽にもなるのでイイと思う。
理想状態でALUが余ってなくても現実はストール多いので、
色々な命令を混ぜると速くなるだろう。ソフトパイプラインだね。
SSE2だけの演算でも、 MD5みたいに同じレジスタに頻繁にアクセスするものは、 複数まぜることでレジスタストールのペナルティを逃れて性能がアップする。
普段はそれをやろうとしてもレジスタが足りなくなるな。 うまくいくと気持ちいい。
俺がやってる分野は、L/Sネックなんだよなー だから、AMD64でやったら明らかに効率が上がった。
>>78 レジスタ足りなくなってロードストアしても、それでも速かったりするんですよ。
ロードストアが空いてれば同時に実行できちゃうから。
>ロードストア メモリは遅いというイメージが離れないんだよなあ。 整数で汎用レジスタが足りないときはmovdでMMXに退避させたりしたことがあるw 確かにmovはALU食うからロードストアが空いてたらそっちがいいんだよな。 しかしSSE/2の最適化を詰めていくとPM弱いな。 小回りはK8以上だと思うが、メモリ帯域や重い乗算平方根に対して力なし。 AMDの√×÷は神の領域だが、P4にすら負ける細腕PM・・・。 分岐をちょっとやってみた(いつものようにPentiumM)。 ループの中にif〜then〜elseみたいな構造を作り、 条件分岐で分岐してもしなくても3clk/loopのコードを用意した。 0〜7fffhのランダムな整数が閾値以上かどうかで分岐する/しないを決める。 ここで閾値を0や8000hにすると3clk/loop。 4000h(分岐は完全にランダム)にすると12.5clk/loop程度になった。 単純に予測ミスのペナルティを出すと、2回に1回の予測ミスで9.5clkの差なので、 なんと19clkもの損をしていることになる。 これがパイプラインの段数なのかはわからないが、思っていたよりかなり大きい。 短いループなので予測ミスの他、ループ処理にも影響があるだろう。 分岐(する/しない)を交互に繰り返すパターンを食わせると4.5clk。 予測はすべて的中していると思われるが、やはりパイプラインが乱れるのだろうか。 最近のCPUらしく分岐予測ミスは痛いようだ。 (ループなど、完全に予測できる分岐に関してはP6に比べて速くなっている)
そんな短い処理だと分岐が確定する前に次の分岐が何個も来てしまう 同じ位置の分岐をパイプラインの中に何個も貯めこんで履歴テーブルは大丈夫なのか
確かに、パイプラインの中に分岐命令が多数流れている。 分岐を含めて6命令を3clkでやっているのはすごい。 20clk/loopくらいのでやり直してみるわ。
久々のカキコでしかも亀レス。
>>63 AMD64だったら、MMX論理演算も整数ALU使えyp とか思ってみたり。
ていうか、128ビット演算のSSE2はあまり速くないし(MMXのおよそ半分)
64ビット演算のMMXはレジスタ本数少なくって虐げられてるし、
64ビット演算の整数ALUは…ANDNがない(ワラ
>>65 ・デコード条件制約
・発行条件制約
・じつはヘンなトコでストール
だったりする可能性があるので、シムでプロファイル取ってみれ。
>>67 >DirectPath Singleのでかい命令をガンガン入てけばとんでもない性能になるな・・・。
俺が測ったときは、DoublePathはデコーダをふたつ占有してますた。
>>81 俺が言うところのL/Sってのは、実行ユニットとキャッシュのインタフェイスね。
通常用途だとAMDでもBaniasでもキレイに働いてくれるんだけど、
カリカリにチューンし出すと、L/Sが真っ先に参ってる希ガス。
分岐は詳しくないのでパス。ただ、二重ループの内側を
CMOV にしたら、ちょっと速くなった。
>>85 そうか、Athlon64はその名の通り整数レジスタが64bitあるんだ。
初め32bitの書き間違いかと思ったよ。整数とSSEが16本ずつとは・・・、
非64bitで使っていたら、MMXを使わないMMXPentiumぐらいもったいないぞ!
・・・MMXはandnがあるけどnotがないんだよねえ。
ところでDoublePathは一般的な言葉?
検索しても日本語ではこのスレぐらいしかかからない(w
(今やってみたらなぜかここもかかんなくなってた)
長いコードにしてやってみた。
結果は分岐の向き固定で22clk/loop、ランダムで26clk。
いや、たった8clkのペナルティで済むわけないんですが・・・。
交互にしたときも22clk/loop。
よく考えたら
>>81 の短いコードだと、予測失敗のときに、多数の予測分岐が破棄される。
でもパイプラインの段数分損するの自体は変わらないと思う。
パイプラインが10段程度というのはありえないのだが・・・。
>>86 ランダムのつもりでも実はパターンを読まれていた
>>87 質がよくないとは聞いていたが、
C標準のrand関数はそこまで性能が悪かったのかw
でも最近の分岐予測って精度はいいんだけど人間には全然予測できないなー。
>>86 関数呼び出しの時にパイプラインが破棄されてたって案はダメでつか?
randって関数でそ。無条件分岐とリターン(これも分岐)があるはず。
マクロ版randってのもあるんだっけ。
どういうコードだろ?
結局乱数テーブルの質じゃないの?
randは線形合同だから
VC6のCランタイムのソースを見ると、
return ((x = x * a + b)
>>16 ) & 0x7fff ;
と書いてあるね。aとbは定数ね。
いまどき線形合同法で実用に耐える乱数列が得られると思ってる香具師ぁいねえよな? これ以上は擦れ違いなので別擦れに誘導してくれ。
同じくスレ違いだが、MT使っても安直にstd::time()関数をseedに使ってる香具師も
問題だとか言ってみる。
ソフトの起動時刻が大体わかれば擬似乱数系列のクラックも可能になります。
もち定数なぞ問題外。
seedの値だけど、私はWin32APIでいくと、timeGetTime()か、QueryPerformanceCounter()
の下位DWORDあたりを使ひますね。あといろいろ組み合わせてみたり。
これだけで解析はだいぶ困難になります。
つか、ほんの数回呼び出す程度ならstd::rand()でも十分実用範囲。
>>86 > 非64bitで使っていたら、MMXを使わないMMXPentiumぐらいもったいないぞ!
レジスタ論理数の制約のあるx86のコード体系自体がもったねーす。
MSの圧力でAMD互換になる前のIntelの64bit拡張がPentium 4の128本ある物理GRを
ある程度自由に使える仕様だったとしたら(妄想)、かなり遊び倒せた希ガス。
(しかしPrescottの実物がアレじゃいくら命令セットがよくてもどうしようもない気もした)
あと、MMX/SSE*にpnorやpxnorが欲しいと思うの漏れだけか脳?
同じモノ作っててもPPCのAltiVecだとNOR命令があるのでずいぶん書きやすく感じる。
それ以前に3オペランド命令主体でレジスタ32本あるのがかなり大きいと思うけど。
わたしわHacker's Delight厨なので、速度云々じゃなくFP_MUL使ったら負けかなと
思っている。
PenMの性能で困ったことがないのは整数演算主体だからだろうな。
???(゚∀゚)???
101 :
97 :05/02/17 23:40:38
で、とりあえず「乱数系列を完全に読まれてる」説について勝手に検証
VC++の疑似乱数の範囲は0〜32767で
乱数値が >= 0x4000 のときとそうでないときで分岐してるのでしたよね
ようはこいつと一緒なわけでしょ。
std::rand() & 0x4000 != 0
rand()のおもっきし古典的な実装だと、下位ビットの出現が規則性を持ってしまう、たとえば0と1が交互に出現する
ってことは有り得たらしいのだけど、実際有効なのは乱数の有効桁の最上位1ビットだけなのでどっちにしろ関係無し。
で、うちもためしに乱数の最上位1ビットだけ1000回くらい出力してみたけど、規則性は見られなかった。
たぶん乱数系列自体と同じ周期になりそーな気がします。
いくらなんでもPenMの分岐予測機構が全部これを先読みしてるってことはあり得んでそ。
詳しいことはこのへんにのっとるようです
http://www001.upp.so-net.ne.jp/isaku/rand.html
投機実行で上手く先読みされているのかもしれんな 乱数を実数演算で作って書き込んだメモリの特定ビットを参照させたらどうかな
103 :
90 :05/02/18 04:34:34
測定前に、あらかじめ、乱数値を一通り求めてテーブル化しておいて、 測定中は、テーブルから乱数を読むだけにした方がよくない?
そうするとキャッシュヒットしないメモリアクセスが 入ることになるから、命令実行時間の計測には向かん のじゃない?
予測アルゴリズムを逆手に取って常に外れ続けるパターンを作ろう
106 :
97 :05/02/18 14:01:31
とりあえず1氏の実験結果から分岐の処理にかかわるPenMの中の人の動き を好き勝手想像してみました 妄想1. 分岐予測ミスのチェック、および投機されたパイプラインの破棄 は、分岐より前の、分岐条件の値が確定した時点で行われる。 投機された命令は破棄されるが分岐より前の命令は破棄されない。 このため、分岐予測ミスのペナルティは必ずしもパイプラインの 長さと一致しない。 妄想2. 1.の機構を有効利用のため、分岐先の決定にかかわる命令 (およびそれに依存する命令)は優先的にリオーダされる。 妄想3. 分岐Aのあとにすぐ分岐Bがあり、分岐Aについてのプロファイル 結果が予測に効果を発揮しない場合、一時的に投機が中断される。 つまりこの状態では分岐のたびに必ずストールする、古典的なCPU と同じ振る舞いになる。 1.および2.について、もし正しいなら、依存関係のある命令を連発して 分岐条件の決定がクリティカルパスになるようにし、故意に分岐の直前まで 確定させなくしてやると、違った値が出る可能性はあると思う。 3.については、電力馬鹿食いのPen4より更に強力な分岐予測機構を 搭載してまで命令投機の無駄を減らそうとしてるわけだが、 やたら強力な分岐予測機構を積んでもそれが大して役に立たない状態で 無理矢理パイプラインに命令を突っ込み続けてもかえって無駄が多い。 場合に応じて投機自体を止めることは、開発者の語る「投機の無駄を 無くすことで電力の消費を抑える」というアプローチにはなんら矛盾しない。
107 :
90 :05/02/18 19:17:59
>>104 キャッシュ1ラインが128ビット分でしょ、
で、分岐に使う乱数値が16ビット整数。
キャッシュミスは、最大でも8回のうち一回。
また、テーブルのサイズが過剰でなければ、
作ったテーブルがまだ二次キャッシュ上に残っている間に実行できるから、
キャッシュミスによる影響も小さくなると思う。
少なくとも、レジスタリネームとかでCPUコア内に
データが残ることによる先読みよりは、実行時間の正確さが上がらないかな?
108 :
97 :05/02/20 01:05:58
1次キャッシュはミスさせるのかよ つか、MT19937も基本的に4byte×624のテーブル参照(詳しくはソースを見れ)なので 多分PenMのL1データキャッシュ32KBにすっぽり収まると思うのですが。 何ならテーブルを念入りにprefetchやってやるとか?
109 :
90 :05/02/20 02:38:55
テーブルを大きく取りすぎたら1次キャッシュからはずれてしまうけど、 可能ならば、1次キャッシュから外れない程度の、 小さめのテーブルを使う方が正確にはなると思う。 P4でもPenMでもAthlonXP/64でも、 どれの1次キャッシュにも収まるサイズだと、 比較しやすくていいかな。
うかつ、測定ミス。
前置してあるC上で配列に乱数などを入れるコードを変えたときに、
測定対象コードのアライメントが影響受けるということをすっかり忘れていたのだ。
測定はint d[1000]に乱数などを予め入れてから行っているのだが、
実は、同じはずのd[i]=i%2とd[i]=i&1(交互に分岐)のクロック数が違ったので混乱していた。
詳しい原因はわからないが、アライメントの違いで5.5clkと18clkの差が出る。
しかも、コードがアライメントされた16byteに収まっている場合でもこれが起こるのだ。
そういえば、不明な低速化原因が「音楽聴きながらだから」だったこともあったなぁ・・・
なんだか考えたことはここまでのレスでみんな言われてしまったな。
こちらの説明不足も多かった。すんまそん。
乱数は配列に入れて、オールL1ヒットなので問題なし。
>>88 はギャグだとわかっているよな?
ていうかrand()を予測できる分岐予測があったら神(w
>>101 実験サンクス。特定ビットが規則性を持つという一抹の不安は正直あった。
>>99 >>102 みたいな動的スケジュール説はちょっと考えていた。
>>106 を参考に実験しよう(時間ないので後で)。つか普通にOoOするだけでOKな気もする。
PM以外のCPUの話題、ないっすか(むしろそっちが知りたい)。
「測定の環境・スキルはあるが面倒」という人いないかね。汚いけど測定ソース貼る?
結局、無意味なテストコードを速く実行するためのCPUじゃないので、
何かで必要な処理を限界まで最適化して、何がボトルネックかを調べる方がいい気がする。
Prefetchは、分岐とは別に興味があるところ。
L1、L2の帯域・レイテンシやロードバッファ・ストアバッファの数が既知のとき、
連続したメモリに簡単な演算をするのに必要なクロックを計算で出せないだろうか。
ストール中に別の命令を実行するため、リオーダバッファの数も影響しそうだ。
さて、新規にコードを書き直してアライメントも揃えてやってみた。
分岐あり5clk、分岐なし10clk。交互が7.5clk、ランダム13.3clk。
素直に計算するとペナルティは11.6clk。ちょっと少ないねえ。
分岐なしではmulを1回余計にやらせるのだが、そのときALUが片方空いてるからか?
そう思って、mulをor*8(4clk)に変えてみたらペナルティ11clk。
で、
>>105 のP6向けパターンが
>>84 のリンクにあって、それを食わせると、
ランダムより3clkほど速く、mulのではランダムより1.5clk速いとなっていた。
かなり外してはいるようだがランダムより速い。必ずどころか半分も外してないようだ。
d[i]=i%nでn回に1回分岐方向を変えてみると、過去4回の履歴で予測する傾向はP6と同じ。
しかし、ループ検出器というのがあって(詳細は
>>99 のリンク先にある)、
これが本来の目的じゃないのに反応して少し精度が上がった感じもする。
次に、発想を変えて、1回だけの分岐で測定。
P6では、前方分岐はしない、後方分岐はすると予測するのがデフォルト。PMもそうだろう。
これはループがないため安定した結果。13〜16clkのペナルティで、ほとんどが14か15clk。
パイプラインの段数はこの辺で間違いないだろう。
ループ検出器の仕様も知りたい。ダウンカウンタの空ループ(lp:dec ecx/jnz lp)は、
P6で2clk/loop。PMではecx=64までは2clk程度で、65から急に速くなる。
μopフュージョンとループ検出器は、PentiumMを知らない頃から欲しかった機能で、
Baniasが出たときには本当に嬉しかった。
>>97 、最後の1行。
惚れてる女の悪口言われると気分がよくないものです。
確かにマンデルブロ集合のSSE2ではパワーのなさを痛感したが、あばたもえくぼ。
>>106 「予測(投機)しない」について。
PentiumMの設計思想は「タスク当たりの必要エネルギー量の最小化」にあり。IPCじゃない。
パイプラインの各段が同じ消費電力(1[電気])で、リーク電流などがないモデルで考えると
予想が半分外れる最悪の状態で、予測をやめると消費電力はどう変わるか。
(全部外れるのは予測器が予測できると勘違いしてる→CPUは最悪と思っていないので除外)
n段のパイプラインでm命令ごとに予測できない分岐が来るとき、2m命令当たりの数字、
予測する:n+2m-1[clk] 2mn+n(n-1)/2[電気]、予測しない:2n+2m-2[clk] 2mn[電気]。
ここで、静的な電力(リーク電流・CPU以外の電気)をa[電気/clk]とすると、
2aがnより小さいなら、予測(投機実行)しない方がタスク当たりの電気を減らせる。
つまり、mには依存せず、システム全体の静的電力が動的電力の半分以下ならいい。
DothanULV-1.1@dynabookSSSXでは、静9W、動4Wだった(静は設定で6.5Wまで減らせる)。
これだと無意味だ。通常電圧版なら、静10W、動20Wとかになるか?これでもギリギリ必要ない。
ひょっとして外れたとき投機実行の破棄のコスト(計算外)がすごいのか?
リオーダバッファの占有率も変わるし、計算モデルが現実とかけ離れていたんだろうな。
ただ、「予測しない」によって電気を節約しても、それで遅くなるのだから、
「クロックと電圧を下げる」という強力な技にはそう簡単には勝てない。
#静:PCアイドル時SpeedStepオフの消費電力。動:「CPU負荷100%、その他は静と同じ(ファンも回さない)」-静
>>106 の測定結果。
分岐する:15.5clk、分岐しない:30.7clk、ランダム:30.1clk、交互:23.4。
いやピッタリ14.0clkのペナルティです((30.1-(30.7+15.5)/2)*2)。無意識に捏造したな>俺。
これは偶然だが、パイプラインは14〜15段ほぼ決定でいいかな?
俺は106の妄想1が非常に難しく感じられた。パイプラインの長さと一致しないのなら
OoOコアにおけるパイプラインの長さって一体何なんだ、と。
リタイヤはインオーダーだが、命令がリオーダバッファにいる平均clk数を何が規定する?
ひょっとしてリオーダバッファが混んでいるときは実質パイプラインが長くなるのか。
それだと
>>81 の19clkも納得できる。こじつけ臭いけど。
で、追試。
上の測定はmulを3回、分岐しないと更に3回というコード。mulは実行に時間がかかる命令だ。
そこでこれをadd15回に変えてみた。する:16.3、しない:31.8、ランダム:30.6。
ペナルティ13.1clk(少ないナ)。ここで依存関係をなくすと、ランダム:27.0。30.6-27.0=3.6。
mulの場合は依存関係あり:30.1、なし:27.0だった。差は3.1。
3.6と3.1は、誤差の範囲で一致、だろうか。
mulの方が、長い実行時間中にフェッチ・スケジュールできて差が広がると予想したが外れた。
114 :
97 :05/02/24 13:15:43
妄想に行き着いた過程を説明いたします。 ちょっと前、Visual C++ + Prosessor Packで、たとえばこんなコード 書いてたとき /* MMX系組み込み関数大量 */ if (i == j) { //foo } 最適化ONにしてアセンブラの出力見たら、i == jの評価が MMX命令の前のほうまで移動してたんです MMX命令はフラグレジスタを書き換えないから、前のほうに 置くことができるのだ、と。 じゃあそもそも何でこんなことやるの? 分岐予測・投機実行のないRISCだと分岐毎に必ずストールするのだけど、 いわゆるソフトウェア・パイプライニングというやつで分岐条件を 早めに確定させ、分岐のペナルティを隠蔽するテクニックが使えた。 これと同様の原理が、ひょっとしたらP6コアでも通用するんじゃないかな、と つまりi == j の評価を先に行うことで分岐のペナルティが無くなるのでは?と。 少なくともゲイツコンパイラはそう判断したのでは?と。 ただし、x86命令は大概命令実行毎にフラグレジスタを書き換える ような仕様だから、もしそうであっても大抵のケースでは扱いづらい気がする。 Intel謹製のやつだとどういうコードを吐くのかしら
volatile
正直、俺は最近アセンブラを“使って”はいない。
プログラミングを始めた頃はカオス・フラクラル系の絵をPenIIとVB5LEで描いていたが、
PenMでFPUを使う(100倍速くなった)今ではマンデルブロ集合も見飽きた。皮肉なものだ。
>>114 なるへそ!妄想1が理解できますた。
ていうか俺がまるっきり106を読めてなかったことに今気づいた。恥ずかすぃ。
110のこれも間違いだな>つか普通にOoOするだけでOKな気もする。
なぜなら、投機実行が「フラグを見ない分岐予測」によってのみ行われるとしたら
フラグが先に確定していても、jccをフェッチした直後には正しいフェッチはできず、
jccを実行して初めて正しいフェッチの場所がわかる。
しかもそのRISCの仕組みは「フラグを見る分岐予測」ですらないのか。
分岐後の命令は、あくまでも確定してからパイプラインに流すのね。
で、実験。
1回の前方分岐・MMXがダミー処理のループ、共にフラグを早く確定させても変化なかった。
(i == j)を先に持ってくるのはi,jの入ってたレジスタを早く解放したいからなど、他にも考えられるが
PMにはなくても、P4やK8ではそういう仕組みが入っているのかもしれない。
まあ、Intelが速くしたいのは、手で書いたアセンブラじゃなくてVC++の吐いたコードだろうけど。
おそらくPMではjccが実行されるまでは投機実行の破棄は行われない。
それでも
>>113 のように3clkほど速くなることについて考えてみた。
14段のパイプライン、1clkで3命令フェッチ・2命令実行、リオーダバッファ40個と仮定する。
80命令ごとに外れる分岐が来るコードを食わせる。以下、脳内シミュ。
time00:今、パイプラインは投機実行を破棄したばかりでからっぽ。 time01:3命令をフェッチ。 time14:パイプラインが埋まる。2命令を実行中。ROB(リオーダバッファ)に3命令。 time15:ROBに3命令入ってくるのに2命令しか出て行かない。ROBに4命令。 time51:ROBに40命令。もう入れないのでパイプラインが一時止まる。 time52:ROBに40命令。2命令ずつ実行中。 time53:分岐を実行、予測ミス発覚。time0に戻る。 80命令を54clkで実行。予測ミスがなければ40clk。ちょうど14clkの損。これじゃダメ。 依存関係を調べて分岐を先に実行する。そのためのROBだ。するとこうなる。 time40:OoO発動。実行できる命令は他にもあるが、フラグに関する命令を先に実行。 time41:そして分岐を実行、予測ミス発覚。ROBに30命令。 time42:投機実行は無駄になったが、ROBには24命令生き残っている。それを2つ実行。 time43:改めて3命令フェッチ。ROBには22命令。内2つ実行中。 time53:ROBの最後の2命令を実行。 time56:パイプラインが埋まる。2命令を実行中。ROB(リオーダバッファ)に3命令。 time84:time42と同じ。 80命令を42clkで実行。2clkしか損してない! この損はtime54-55でROBが空だったため。ここでネックになったのはROBの数ではない。 命令フェッチの能力だ。フェッチ・デコード能力は過剰でも役に立つんだねえ。 time42-43でROBの命令数が6減っているが、これは2つがtime42に実行され4つが破棄された。 実際は、長いループにランダム分岐を入れてみても、どうしても7〜9clkのペナルティがある。 これが8clk前後で一定なのを説明できる理由が思いつかない。 まさかtime42での4命令のリタイヤごときで8clkはかからないだろうし。 ROBが一杯のときは性能が落ちるのかな。
これを考えた後、コンビニに行った。 「またお越し下さいませ」を、おつりを渡す前から言ってる店員を見て、 「そこはインオーダーだろ〜」と思ってしまった。 久しぶりに何か作ろうと思って、ライフゲームをやってみた。 VBのインタプリタで1.8fps。Cで36fps、MMXで57fps、SSEで56fpsだった。 表示部だけだと79fpsなのだが、かなり隠蔽できる気配。グラフィックのclk数はわけわかめ。 SSEは、paddb xmm0,[edx] が16byte alignでなければならないのが痛かった。 レジスタが余っていたのでMMXは1回アンロール、計算部だけならSSEより2割速くなった。 (なのになぜfpsは1しか違わない・・・) アンロール前のMMXとSSEは互角。MMXをアンロールすると2本束ねてSSEと同じ動作になる。 この状態で、デコーダもメモリアクセスもMMX有利となる(P4だとSSE有利と思う)。 実はSSE2の整数命令主体のコードを書いた経験がほとんどなかったのだが、 やってみると64bitの壁を感じた。MMXが16本あればSSE2整数は要らないと思った。 Load/Storeが128bitいけるCPUじゃないと、本当にただの「2本束ねたMMX」だ。 結局PenMのSSE2整数は、こんな感じ↓ 小回り効かない(・A・)イクナイ & レイテンシ隠蔽できる(・∀・)!!イイ ていうか面白い!昔MMXの256*192くらいで遊んでいたが、今回はXGAをフルに使ってみた。 初期配置を512*1の線にすると、300世代くらいまでフラクタルな感じになる。 菱形に広がるクラスタの縁に沿って列をなし進むグライダーが壮観。 その後もきれいなシンメトリーで、トーラス世界(ねじり)なのでグライダー同士がピタリ激突する。 スレチガイスマソ
119 :
デフォルトの名無しさん :05/03/01 22:44:46
うんこ
よくVBで作る気になったね
>>120 おいらの基本はVBなので。
アセンブラ直書きが難しいときは、Cで書いてそのコード見ながらアセンブラを書くが、
昔はVBで書いてからCにコンバート、アセンブラ化なんてやってたのう。
nasmでSSEをアセンブルし、VCでDLLを作成、それをVBで呼び出す。
表示するAPIもVBで呼ぶ。てかVCでGUI作れね。
次はアライメントかな。P6では、キャッシュラインをまたぐと9clkほど損した。
ただ、キャッシュラインをまたぎさえしなければズレたアクセスも特に問題はないみたいだった。
P4とかじゃズレたら即死しそうだけど。
(別にP4を貶すわけじゃない。PenMの「性能/電力」の高さは、
絶対性能の低さに甘んじているからだと思うので)
ところで糞P4使いは、いないのかい?
倍速ALUや高スループットのキャッシュ、ぶっちぎりの絶対クロック。
アセンブラレベルでご機嫌とれば、かなり化ける希ガス。
心配なのはライトスルーのL1Dataや等速ALUの遅さ、MMXとFPUは捨ててる感じだし。
>>116 いや妄想に付き合っていただき感謝
まあゲイツコンパイラの気まぐれの気もしたのだけどね。
GCCもそうなのだけど、PentiumでいうUVパイプライン最適化
ってやつがあんまり利いてないっていうか
ちょっと式が複雑になるとスタックフレーム生成しまくりやがる。
実はcl.exeの最適化エンジンってレジスタ数の多いRISC
由来だったりとか?
最近Prescottマシンに触れる機会があってMMX/SSEバリバリ
のソフトでベンチマークとってみたけど、
同クロックのNorthwoodに比べて、確かに処理能力は落ちてる
のだけど、レイテンシ増大の割にはあんまり低下してないと思った。
NorthwoodでHT enableだとただでさえ小さいL1キャッシュを
分断するので逆効果になるケースがあったけど、
Prescottだとキャッシュの増分、効果は得やすくなったと思う。
ただロード・ストアまわりが・・・
コテ名乗れ。 あぼ〜んできないじゃないか。
>>1 誠にすまんが、このスレはしばらくROMに徹しさせていただく。
進展がないようだったら巡回から外す。
>>124 む、それは残念。97よ、おまい何したんだ。
関係ないが、漏れも来週を最後に数週間来られないかもしれん。
何か話し続けといてちょ。
>>122 次来たときうpする。
>>123 コンパイラ作成はかなり大変で、しかたなくメモリアクセスが増えてると思っている。
SIMD対応コンパイラでも大して速くなったという話を聞かないし。
単純なロジックなら人間、複雑な大域最適化はコンパイラじゃないかな。
その辺の知識はないのでハズレかもしれんが。
プレスコは、よりHT向きになった石だね。レイテンシ増はHTで隠蔽できそう。
ところで、だれか上の吉野家コピペに反応してくれ。
けっこう時間かけて作ったんだからさ。
複雑な大域最適化なんて今のコンパイラにはなおのこと荷が重いだろ
10年ぐらい前のmipsコンパイラでも当たり前にやってた 気もするけど。
128 :
97 :05/03/03 23:28:19
じゃあネタ振りでも
http://www.hackersdelight.org/HDcode.htm のMMX/SSEを使った高速化について。
とりあえず64×64. 128×128の転置行列を作る。
で、基本的なアイディアとして、
1.サンプルコードと同様、素直にシフトと論理演算の組み合わせ
(原著によれば完全にアンループするとRISCで3886命令程度なるらしい)
2.とりあえず8/16/32bitシフトしてマスクして重ね合わせの部分は
pupk[hl][dwb]でインタリーブすれば同様のことできるじゃん
(去年の4月ごろ考案)
3.そーいやSSEにpmovmskbあるけど、マスク演算無しで
8bitずつビットの間合いを詰められるぜ?(最近おもいつく)
で、気合い入れてコード書いてみた割にはあんまり期待しただけの
パフォーマンスは出なかったのね。
思うに演算ユニットが並列動作してねーんじゃないかと。
まあマイナー命令連発だからな。
8×8bitだとmovqでMMXレジスタに一気にロードしてpmovmskb
+左論理シフトを繰り返す方法がダントツ最速ですた。
てか、このへんの命令ってどんな命令と並列動作できんのかしら?
>>128 MMX演算ユニットって、
用途の限られたユニット二つで構成されてるでしょ?
MMX命令の大半は、どちらか片方でしか動かない。
ちゃんと工夫しないと、並列動作は無理だと思う。
>>128 0x80getおめ。
転置行列は2次元FFTで使ったな。Cでそのまま書いて全く最適化してないが。
pmovmskbはビットインバースのインクリメントで見て面白いと思ったが、
「8bit間合いを詰める」とはまた面白い捉え方だ。本当にイイ命令だなあ。
並列実行云々を論ずるのであれば使用CPUを書かないと。
PenMならpmovmskb(MMX)はpaddと同じ負荷しかない(1-1 add/mul)。
K8は3-1 add/mul。これも一応並列実行できるが、デコードが1命令/clkしかできない。
P4は7-2。SSEの128bit pmovmskbも7-2。使えるユニットは1個。P4はMMX自体糞。
思うに128はAthlonを使っていてデコーダがネックになったと見るが、どうか。
>>129 MMXで並列実行できないのは、P6,PM,K7,K8ではmul系同士ぐらいしかないんじゃないかな。
P4のMMX/SSEは、そもそもALU・mov系以外との並列実行ができないのでダメだし。
基本的に、fadd系がaddユニットのみ、fmul・int mul系がmulユニットのみ、ALU・mov系が両方、
という感じだろう。
P4は、2倍速ALUは速いが、SIMDはmov系以外並列実行できない。
というか2つのユニットが合体したものが1つあると言った方が正しいか。
だから、MMXは遅くても、SSE/2では問題にならない。
http://haiiro.info/up2/file/8226.zip ライフゲーム、うp。自分用フルセット。
>>130 濃緑研究所はなつかしいなあ。初めて行ったのが更新されなくなってからだけど。
SSEをコンパイラまかせにしているんじゃ、遅いだろう。
単純にアセンブラにすれば相当速くなるだろうが、長いアセンブラは頭がこんがらがるのよね。
PeniumMのL1Dataはキャッシュラインが64byteになっている。 8KB分のintの総和を求めるコードでロード性能を計測。MMXだと当然8byte/clk。 ここで、アライメントを崩してやる。すると半分の速度(8load/16clk)になった。 MMXレジスタが8byteなので、8(=64/8)回のロードにつき1回キャッシュラインをまたぐ。 つまりキャッシュラインをまたいだ8byteのロードは9clk。P6と同じだ。 またぎさえしなければ一応ペナルティなし。 次に32bitの整数レジスタでやってみる。4byte/clk「弱」。 MMXでは完全に隠蔽できていたループのオーバーヘッドが、なぜか隠せていない。 同様の実験をして、またいだロードはおよそ11clkだったが、addが負荷になっている感じ。 movだけでやるとこれも11じゃなくて9clkっぽい。 そしてSSEのmovdquで実験。結果は9clkより少し大きい感じ。 #8byte alignであればペナルティはない。8byteのloadを2回している状況証拠。 #9clkというのは、(16byteではなく)その8byte loadのこと。 ストアの計測もした。一応ゼロフィルのコード。 movdquだが、おしなべてmovdqa(8byte/clk)の倍遅い。またいだクロックも20clkと倍。 MMXだと普通に8byte/clk。またぐと15clk。clk数が大きくて不安定なのはSSEと同じ。 32bit整数だと10clk。movdも同じだった。 そもそもキャッシュラインをまたいでいるときはどうやって転送しているのだろう。 SSE3にlddquというmovdqu(load)と同等の命令がある。 16byte alignのloadを2回行って合成するため、「またぐ」心配がないのが存在意義。 常に倍のloadをするので、「そもそもが遅い命令である」というのは忘れないように。 さて、わざわざlddquという命令を作ったということは、movdquでまたいだときには 「2回読んで合成」ではないと考えるしかない。 ・・・じゃあどうやってんだよ。ダメだと判明してから2回読むから遅いとか? IntelのP6最適化マニュアルには「6〜12サイクルのストールが生じる」とあった。 対症療法は書いてあるが、原因部分が書いてない。
間違い!上で整数レジスタが微妙に遅かったのはeaxにだけ足していたからだ。 MMXではmm0とmm1に分けていた(すみません、ひいきしてました)。 アドレスの計算が依存チェーンを長くしているので普通のOoOじゃ原理的に隠蔽しきれないか? Prefetchもやってみた。 上述の足し算コードで、paddd xmm0,[esi] の前にprefetcht0 [esi+64]を置く(64byte毎)。 すると、L2は4byte/clkだったのが5.33byte/clkまで上がった。ちょっと感動。 ただ、これが上限である理由がわからない。もっといけるのかな。 キャッシュラインを意識した使い方をする必要がある。 ところが、prefetcht0 [esi+64] をmov eax,[esi+64] で置換したら5.8byte/clkまで上がった!orz おまいは一体何のためにSSEで実装されたのかと小一時間・・・ それはさておき、L2の真の実力が8byte/clkあるとすれば prefetcht0 では64byteごとに4clk、mov eax,[ ] では2clkの無駄がある計算だ。 (movは3clkだが、実際にeaxへ転送する1clkを引いてある) つうかPenMにはHWプリフェッチがあるはずだが、こんなわかりやすい処理でも HWプリフェッチなしのP6と同じってどないなっとんねん。 ・・・と思ったらそれはメモリからL2への話か。確かに、L1へ勝手にフェッチされたら嫌かも。 ライフゲームにprefetcht0使ったが、遅くならないようにするのがやっとだった。 キャッシュラインまたぎまくりだから仕方ないか。 次はL1Dataが8Wayであることの見えるコードでもやろうかね。
>>134 プリフェッチは正直わからない。
やらないよりは速いので、効果はちゃんとある。
mov eax,[ ] はeaxを汚染するので、一応prefetcht0の存在意義はあるのだが、
実際の転送を行うmovよりも遅いのは説明がつかない。
転送終わるまで指くわえてるのかな。
>>126 局所的なコードの目的をつかんで必要な命令だけ書くというのは人間の独擅場。
ただ、Cで10行とかになってくるだけで人間アセンブラは思考停止になるので(俺は)、
長いコードでは相対的にコンパイラに負ける。
俺が初めてMMXのライフゲームを作ったときはCコンパイラに負けた。
当時経験が少なかったために冗長なコードしか書けなかったのだ。
16byte境界を表示してくれるアセンブラのエディタが欲しいな。
メモリの読み書きは、全てL1キャッシュに対してのみ行われる。 メインメモリからL1への転送は、常にキャッシュライン毎。1ラインをフィルする。 L2は、役割としてはメインメモリと一緒、ひらすらL1へキャッシュラインのバースト転送を行う。 ネタと言えば、 命令キャッシュのアライン・ROBの数・必ず分岐予測を外す方法・L2キャッシュへのプリフェッチ 頭痛くなってくるな。じゃ、さよなら。
今時のCコンパイラは賢いよ。 SIMD命令でも、組み込み命令を使ってコンパイラに最適化させても、かなりの速度が出るよ。
それはVCとかでなんか指定すんの?素人でスマン。
>>138 何も指定しないでいい。
むしろ何か指定すると、最適化が阻害される。
_mm系の命令を普通に使ってるほうがアセンブラでSSE使うより 高速なのかな。
インラインアセンブラで書くと、コンパイラの最適化の対象外になります。 インラインアセンブラで書いた命令だけでなく、その前後までもが最適化されなくなります。 (インラインアセンブラの部分をまたいでの最適化が行われなくなる。)
素人は組み込み関数使っておけって事だね。
そして、 組込み関数をインライン展開する という一見速くなりそうなオプションは、この場合のみ、逆効果になる。 なぜなら、インライン展開されたコードは最適化されないから。
リリース版だと組込み関数は、そのままSIMD命令になるのに、 デバッグ版だとライブラリ関数の呼び出しになるので、 やってられないくらい動作が遅くなって、デバッグに差し支える。 なので、デバッグ版ではインライン展開してしまったほうが、いいかも・・・。
>>139 おなじVCといっても、LearningEditionとBasicとPrpfessionalで
最適化の規模が段違いでそ
LEでは、確か、まったく最適化してくれないんじゃなかったっけ?
でも今はVC Toolkit 2003(Pro相当)がタダで手に入る。
そうなんだ・・・。 MSDNエンタープライズ版で送られてくるのを使ってたので、エディションの違いは気にしていなかったよ。
>リリース版だと組込み関数は、そのままSIMD命令になるのに、 >デバッグ版だとライブラリ関数の呼び出しになるので、 あぶねー。そんな事しらずにデバッグ版で最適化試すとこだったよ。
149 :
97 :05/03/13 13:01:58
>>132 > movdqu OR lddqu
その合成処理って例の8ビット単位しかできないシフト演算で実装されてるんじゃねーかなと
思った。なんであんな中途半端な命令の実装にしたのか考えてみたがそれしか思い浮かばない。
MMXのpq[lr]lq×2でもいいから1bit単位のシフトは用意しておくべきだな。
俺多用するから
整数の絶対値命令と丸めモード固定のfist系命令が無いのは許せん
151 :
97 :05/03/13 15:20:07
すんまそん
>>149 訂正psrlqとpsllqね。
152 :
1 :2005/03/24(木) 12:21:19
ちょっとP4に触る機会があって、試してみた。北森3.06GHzのHTオン。 SSEの加算・乗算は、並列実行できるみたいだ。 実行ポートが同じなのでできないと思ったが、ユニットが違えばいいみたい。 スループット2の命令を毎クロック発行すれば並列実行になる。 Pentium4のMMXはかなり糞だが、SSEは各ユニットが128bitで並列実行するので、 クロック表ではPM・K8より遅いもののポテンシャルは高く、しかも思い通りの性能が出る。 P4のMMXはSSE int用のユニットを半分だけ稼動している感じなので遅い。 PMのSSE intがMMX用のユニットを2つ同時稼動しているのと好対照だ。 SSEのコードだと、クロック表どおりの結果で、ループのオーバーヘッドもない。見事。 ここはハーフスピードだろう。P4のSSEは(例外はあるが)クロック数が偶数になる。 普通の整数命令だと、ループ処理とユニットが競合するのかオーバーヘッドあり。 倍速ALUは本当にすごくて、実際にレイテンシが0.5。それが2個もある。 トレースキャッシュから取り出すのが最大3μop/clkなのでフル稼働はできない。 まあ、倍速ALUは高速化のためと言うより、低速化を抑えるギミックなんだろうけど。 L1Dataがライトスルー(StoreされるたびL2にも書き込む)なので、L1ヒットでもStore性能は低い。 movapsでも3.5clkかかり、movqが2.22clk。ハンパなのはL2に書いてるからだろう。 これでもPenMのL2(movapsストアが5clk)よりは速いが、けっこう性能に響きそうである。 そのために6キャッシュライン分のストアバッファがあるらしい。 バッファの性能はけっこういいみたい。 意外にも、アライメントが合ってないのは平気だった。 キャッシュラインをまたいだときはL1/L2Loadで1回13〜17clk、L2Storeで78clk。これがでかい。 ロードはまだしも、ストアが悲惨だ。全体で平均すると通常の4〜5倍くらい遅くなる。 PenMのL2も調べてみた。 帯域は命令によらず3.2byte/clk。プリフェッチありで4byte/clk。 またいだときのクロックが、命令によって違う。movups 19.5、movq 6.5、mov 15clk。 またしてもMMXマンセーな結果に。
153 :
1 :2005/03/24(木) 12:23:27
一応この前のプリフェッチについて補足。
mov eax,[ebx] というのは、[ebx]周辺をプリフェッチする昔ながらの手法。
あらかじめロードバッファに[ebx]のロードを突っ込んでおけば、しばらく後で使いたいときに
もうL1キャッシュに乗っているのだ。1つのロードで1キャッシュラインを移動できるのがミソ。
これとprefetcht0 [ebx] は、eaxを汚染しないということぐらいしか違わない。
使い方は、キャッシュラインのサイズが64byteでメモリ(またはL2)のレイテンシが20だったら、
64byteの処理毎に、ロードの20clk(以上)前の位置にプリフェッチ命令を入れる。
>>137-
組み込み命令っていいね。
今まで「アセンブラ使えよ」とか思っていたが、アセンブラには最適化を阻害するという弱点があり、
ループ内の一部だけインラインアセンブラとかやると絶望的に遅かった。
この弱点なしで明示的にSIMD命令を使えるのはいいなあ。
>>149 pslldqがバイト単位って知らなかったよ。今度、命令リファレンス通して読んでみようかな。
それにしても、「P6以降はクロック計算できない」「OS上では測れない」と言うヤシが多すぎ。
154 :
97 :2005/03/26(土) 04:29:38
で、SSE3のlddquがmovdqaとpslldq, psrldqなどを組み合わせて実装してるってのは どーやら間違いない模様。 movdquは、おそらくmovdかなんかのより細かい単位でロードし組み合わせてるものと予想。 lddquは、ロード回数が少なくなる反面、256bitの連続した領域に対して読み込みが 発生するため、依存関係によりかえって遅くなるケースもあり得る模様。 だから使い分けのために2つの実装を用意した、と。 YonahでSSE*にもμOPsフュージョンが適用されるそーだけど、これは Athlon64なんかと同じく、「あまり遅くならない」程度の効果と見るべきでせうか。 ユニット数据え置きでL/Sを128bit化してくれるとかなり使い甲斐もあるのだが。 浮動小数の強化については単純にユニット増加と見てますが。
Yonahなら単純にマルチコアだから現状維持だとしても 作り方によっては大幅性能UPで使いやすくなりそうだなぁ 今後は1命令の単純なスループットとかより マルチコアによるキャッシュの取り合い具合とか マルチスレッドに対応した効率のよいアルゴリズム変更のほうが 重要になっていく希ガス
そんなのは従来のSMPと同じで、なんら新規性がないのですが。
バス経由しないからな キャッシュの統合とかそういうのもあるし
今度のマルチコアってキャッシュ分離型じゃなかったっけ? キャッシュスヌープするんかな?
159 :
97 :2005/03/26(土) 19:23:23
Smithfieldはダイごと分離されてますが。Prescott2つをパッケージ化したものですよ。 YonahはL2がシェアードになってます。レイテンシ増えるんだろうな(欝
すでに現状でもHTうまくつかえばかなり性能向上になるな。 ただ、Pen4系列だけしか早くならないのでうまみが無い。 日本では省スペースデスクトップもPenMばかりだからな。 デスクトップとノートと同じパーツが使えるんで仕入れの関係かもしれん。 マルチコア全盛になればシングルスレッドのチューニングが ばからしくなるかもしれない。
161 :
97 :2005/03/27(日) 01:34:24
1コアを複数のフロントエンドが共有するHTみたいなアプローチのマルチスレッディングだと、 確かに馬鹿らしくもなる。 ただ、マルチコアはシングルスレッドでの性能アップは十分意味あると思うけど。 1コアあたりの空きユニットを埋める手段は従来の最適化手法の延長なわけだから。
162 :
160 :2005/03/27(日) 02:26:18
ああ、ごめんごめん、そういう意味で言ったわけじゃない。 シングルスレッドしか考慮しない人とマルチスレッドでアルゴリズムを ちゃんと考えられる人との差が大きく差がついてしまうと。 シングルスレッドでガリガリにアセンブラでチューニングしたところで、 JavaやC#等でマルチスレッドで動かしたほうがはるかに早くて 開発効率もいいということがありえそうだからね、と。
Yonahっていいよな。
細かい粒度でマルチスレッドにするのは面倒くさいし、 スレッド同期のオーバーヘッドだって馬鹿にならないと思う。 現実的には、キャッシュの共有とか考えてまで、コーディングしてらんないよ。 スレッド間で同期したって、OSが違うスレッドと同時に走らせてくれたら台なしだしね。
165 :
97 :2005/03/28(月) 06:01:51
てか、もっとも効率的なスレッドの並列実行方法は スレッドの依存関係を極力断ち切れ(鉄則) ループを小分けしてやって並列実行させる以外何にも変わらん。 マルチコアコンピューティングはアルゴリズム云々じゃなくて力技。 各コアに負荷を均等に分散すればあとはインストラクションレベル最適化が全体の パフォーマンスにおいてかなりのウェイトを占めるのは何も変わらず。
166 :
1 :2005/03/29(火) 10:24:11
>>154 movdquはmovq2回じゃないかな。それでP4・PM共に大体クロック数の辻褄が合う。
ていうかmovqがアライメント関係ないので、movdまで細かくする意味がない。
それにしても、なぜ16byteの読み込みだと急にアライメントを要求されるんだろ。
信号線が128bitで、アライメントの合ってないmovqのときは128bit中の64bitを使うのかな。
>lddquは、ロード回数が少なくなる
むしろ将来的にはmovdquが(movqのように)1回のロードになるかも知れず、
lddquは原理的に2回ロードするので、回数ではlddqu不利と見るべきではないかと。
lddquはキャッシュラインをまたいでも遅くならないというだけの命令なので、
平常時はシフト・合成の手間の分だけ遅いはず。
依存関係とはストア・フォワード機能がらみのことか?
(ストア命令がリタイヤする前ならストアされたデータを高速にロードできる)
>YonahでSSE*にもμopフュージョンが
朗報ですな。
まあ、K7でVectorPathだったときも、スループット2の命令を1clkでデコードしてたんだからね。
理論性能がそれほど上がるわけではないが、タイトなループが思い通りに回ってくれる予感。
浮動小数の強化は気になる。やはりユニット増加か。
単純に倍の個数載せれば128bit演算のスループットが1になる(すげえ)。
ただ、これはハードの負担が大きすぎる。ただでさえデュアルコアでトランジスタ倍増なのに。
もうひとつ考えられるのは、mulsd/mulpdの強化。
PMのmulsdはfmulと同じクロックで、mulpdのスループットは4(K8/P4の倍)とかなり遅い。
80bitと64bitで浮動小数の計算コストってどのくらい違うんだろう。
でも、YonahのコアはDothanと同じじゃなかった?
>>165 禿しく同意
167 :
1 :2005/03/29(火) 10:25:35
プリフェッチの実験@PenM。 paddd mmx,[source] で、640,000byte分のintの総和を求めるコード。 64byte/loopで普通にやると147800clkくらいかかる。L2キャッシュで4.33byte/clkは大したもの。 次に、ループの先頭にprefetcht0 [esi+128] を置くと、120500clk。5.31byte/clk。 それをmov eax,[esi+128] にすると、110500clk。5.79byte/clk。 で、新アイデア。余分なプリフェッチ命令を使わないプリフェッチ。 ループ先頭のpaddd mm0,[esi] をpaddd mm0,[esi+128] に変える。 多少ループの外に細工をすれば同じ結果が出せる。101100clk。6.33byte/clk。 これ以上はループをアンロールなどしても変わらず。64byte/10clkに壁がある感じ。 ちなみに、河童Celeronではどうやっても4byte/clkをわずかに上回る程度しか出なかった。 400KBのデータのコピーは、2.32byte/clk程度。どういじっても殆ど変化なし。 そもそもストアのスループットがL2で4byte/clk出ない。 そういえば、L2に書くためにはL2からL1にキャッシュラインを読み込まないといけないんだ。 mov [esi],eax / add esi,64 / dec ecx / jnz lp これがL2ヒットで19.7clk/loop。 たとえeax1個のストアでも、64byteのキャッシュラインをL1/L2間で往復させないといけない。 add eax,[esi] / add esi,64 / dec ecx / jnz lp これはL2ヒット時に6.1clk/loopで回る。 64byteのキャッシュラインを6clkで読めるのか? P3のL2がオンダイになったとき、昔の記憶だが雑誌で「256bitを2clkでできる」と見た気がする。 ひょっとして転送自体は16byte/clkくらい出てて、レイテンシが問題になってるだけ? そういやロードでもライトバックの手間はかかるな。ややこし・・・。
このスレ非常に面白いんだけどバカなオレにはどんな コードを書いているのかさっぱりわからん。 短いやつならたまには載せて欲しいな。
169 :
1 :2005/03/30(水) 11:20:05
P6系(含むPM)にとって、2μopの命令はデコードで不利だ。
1μopなら3命令同時デコードだし、4μopなら1命令で4つもμopを送り出せる。
μopフュージョンは、この忌わしい2μop命令を1μopにしてしまう嬉しい機能。
Athlonは、みんなフュージョンした状態で流れていく感じだ。実行ユニットの配置がP6と違う。
なにしろadc [eax],ebx みたいのがDirectPathで3命令同時デコードできる化け物。
ただ、SSEは64bitごとに分割するのでDoublePathになっている。
AthlonがフュージョンできるのはLoad/Op/Store みたいなカタマリであり、
Op/Op とかLoad/Op/Load/Op とかはデコーダが分割しないといけない・・・とか勝手に予想。
上位と下位の並列性から、続けてaddpsするとレイテンシが1減るのはP6と同じだね。
P4ではその現象がない。本物の128bit演算器を積んでるのはさすがというべきか。
Athlon使いに質問だが、3つのDoublePath命令のデコードには何クロックかかる?
2clkか3clkだろうけど、どっちだろう。
ていうかどっちでも性能には大した影響ないか。
>>168 アセンブラは未経験だけど興味があるという人?
とりあえず
>>131 にライフゲームがうpしてあるので、その中のb.nasを見るとソースが出てる。
ソースの解説がほしいとか、VCでSSEを使うやり方を知りたいとか、質問があれば
俺が次来たときに(気が向いた範囲で)答える。
ていうか俺としては初心者歓迎。
「アセンブラを始めた人が読んで勉強になるスレ」になればなあって思いはあるし。
>>167 の主要部分を貼っとく。↓
ポインタがesiで渡されて、それから256byteアラインされるという非実用的ルーチンだが。
一応eaxに総和が入るはず。PenMで110500clkのコード。
170 :
1 :2005/03/30(水) 11:20:54
proc pp mov ecx,10000 pxor mm0,mm0 pxor mm1,mm1 and esi,0ffffff00h add esi,256 align 16 lp: mov eax,[esi+128] paddd mm0,[esi] paddd mm1,[esi+8] paddd mm0,[esi+16] paddd mm1,[esi+24] paddd mm0,[esi+32] paddd mm1,[esi+40] paddd mm0,[esi+48] paddd mm1,[esi+56] add esi,64 dec ecx jnz lp paddd mm0,mm1 movq mm1,mm0 psrlq mm0,32 paddd mm0,mm1 movd eax,mm0 endproc
171 :
1 :2005/03/30(水) 11:30:11
11 AMDな人はこのシミュレータが使える。 15-18 MMXとSSEのQ&A 22で組み込み関数の話は出てるよ。137-148は気づいていたのかな。 23 キャッシュの仕組み 27-30 PentiumMのSSE2のクロック数 34 μopフュージョンについて 35 K7/K8のデコーダ 40 P4/PMのSSE/MMX比較 41 P6のL2はエライ 43-44 CPUの内部構造 47 P4とK7のレイテンシ(リンク) 52 パイプラインの比喩(リンク)。58はコンビニ。 61-62 K8の128bit pandとandpdは違う?/K8のLoadは64bit*2/clk 65,67,69,75,77,85 SIMDとALUのQ&A。 68 吉野家コピペ 73 mulpsを入れると速くなる謎。 78-81 ロード・ストアする派とレジスタで何とかする派 81-117 分岐。実験結果は81,86,111,113 84 初心者のためのアセンブラリンク 87-97 乱数について盛り上がった 99-110 内部構造を予測しつつ測定法を吟味 114 RISCの分岐処理など 116-117 予測ミスのペナルティがパイプラインの段数より少ない理由を予想 118 ライフゲームを作った感想 123 Prescottの触り心地 128-131 MMXの並列動作。よく考えたらMMX2はユニット限られてた。 132 キャッシュラインをまたぐペナルティ 133-135,153,167 プリフェッチについて 149,154 lddquはps[lr]ldqで実装されてる。 152 Pentium4の触り心地 154-165 デュアルコアの話
>>169 >Athlon使いに質問だが、3つのDoublePath命令のデコードには何クロックかかる?
>2clkか3clkだろうけど、どっちだろう。
シムの上では2クロックに近くなるようだ。
DoublePath2つのうち1つが、1クロック遅れて出てくる感じ。
実機では、MMXとくらべてあからさまな差が出なかったので、
(すくなくともK7のVectorPathとくらべて)デコーダの負担は少なくないだろう。
ていうかカリカリに書くと Retirement unit がボトルネックになるねぇ。
173 :
97 :int 2ch =05/04/02(土) 05:09:29
で、結局3IPCが限界と。 Banias→Dothanは本質的に単純シュリンクしてキャッシュ増やしただけと思ってるのですが Yonahは激しく別物になる気がします。デュアルコア化とは別に浮動小数ユニット強化を うたってるので、やはりユニット増加もあり得るのでわ? ここから電波垂れ流し↓ リアル128bitのAltiVecは良かとね〜 でも実機無いのよ PearPCはストレスたまりまくるぜい で、クロック数正確にカウントできないので資料読みながら脳内シミュレート、これ最強。 SSE2はなんつーか、Octet-WORDじゃなくてDouble-QWORDなのが腹立つのよ えっと、base64エンコードっぽいものをAltiVecとSSE2でやろうとたくらんでます。 16並列で処理いぇい
PS3やXBOX2でもAltiVec使えるからこれから使う人増えそうだね。
175 :
1 :2005/04/05(火) 12:59:25
Yonahは本当に中身が強化されるみたいね。
「YonahのコアはDothanと同じ」という記憶があったが、新規のコアじゃないってだけか。
L2キャッシュが共有2MBで増えてないから、コアのロジック部だけ2つ積んでもおつりがくるね。
この前、μopフュージョンの効果はそれほどでもないようなことを書いたが、
浮動小数の強化もあることを考えると話は違ってくる。
SSEのμopフュージョンと浮動小数の強化は、ペアで実装されて力を発揮するものだろう。
SSE命令のスループットが向上して初めてデコーダが深刻なネックになる。
>>172 なるほど、シムがあったか。
2clkでできるのか。サンクス。つまり、DirectPathのデコードに関して
「Doubleは3個のデコーダの内2個を使うので(Singleが来ないと)1個は遊んでしまう」
わけではない、ということだね。
「デコードはDoubleでも簡単だけど出口が3つしかない」という感じかな。
リタイヤがボトルネックになるとはどういうこと?
デコードもリタイヤも、3macro-op/clkで同じだから、パイプラインがスムーズに流れていれば
ネックになりようがないと思うが。
ストアでキャッシュラインをまたいだときは、ストアユニットが9clk消費するだけかな。
軽く実験したが、どうもわからん。
他の処理をたくさん入れると、あと1〜2clkというところまでは隠蔽できる。
ただ、10clkの処理を入れても5clkしか隠蔽できなかったりもする。
別のμopを発行してるわけではなさそうだが、何か素直じゃないclk数のかかり方だ。
Retirement は in-order なので、キューが満杯に近づいていっても もの凄い勢いで空になることはないのだ(K7にて確認)。 デコード順に、デコードされた列が同時に retire する。 で、retire 前の ops が溜まりすぎると、decoder がストールする。 L/S は、同時駆動の問題があって、どうしても理想スループットで流す ことは困難なので、せっかく out-of-order であるコアも、 retirement ネックになってしまう…っていうのはこちらでの事例。
177 :
1 :2005/04/05(火) 13:45:42
なるへそ。意外と簡単に溜まりすぎちゃうんだな。 ただ、そうなるとデコード能力よりもリタイヤ能力が低いP6/PMなんぞは もっとストールしてることに・・・。 リタイヤがin-orderなのは知ってたが、今までまともに考えてなかったな。 分岐ペナルティの隠蔽などをまた考えてみよう。
178 :
1 :2005/04/06(水) 11:51:25
うーん、リタイヤネックな処理を考えるのはむずいな。 分岐ミスの隠蔽も、リタイヤというよりOoOでの実行順序の選び方が重要そうだし。
179 :
97 :2005/04/08(金) 23:13:04
180 :
97 :2005/04/08(金) 23:31:46
やっぱりMMX整数の大半、レイテンシ−スループット:1−1ですなPentium M。 Pentium MだとAthlonみたく依存関係の解消のためにロード・ストア頻発させたりする必要があんまり無い分、 逆に効率が良くなる面ってないっすか。そもそも内部命令数を押さえ込めばユニットの少なさをカバーできるのでは、と。
VC++スレから誘導されてやってきました。 Pentium4に最適化されたコンパイラを使った場合に、 同じコアのCeleronとPentiumで吐き出すコードが違うことってあり得ますか? また、プログラムは単純な計算の繰り返しとして、 同周波数・同コアのPentium4とCeleronで 計算速度に有意な差は出てくるのでしょうか? ここでいうコンパイラは、VC++2003で「/G7」オプションをつけた場合です。 よろしくお願いします。
>>182 コンパイラオプションに、CeleronとPentiumの指定なんてないぞ。
あとコンパイラが出力するコードくらい自分の目で見ろ。
184 :
97 :2005/04/12(火) 04:07:08
このへんは自分でデータシート読みながら、実験繰り返してみるしかないぽ 現行CeleronとPentiumの演算性能上の違いってのはキャッシュ容量の差くらいだからね。 そーだね、Celeronだとデータ配置アラインメント無視してでもL2キャッシュにヒットさせたほうが 効率いい場合もある、くらいかな。 VS2005ではIntel C++にあったIPOが搭載されるので、各CPUの特性に合わせたコードは 吐かせやすくなるのではないかと思いますが。 うとりっぱーでL2キャッシュが小さいCPU用のバイナリ吐くオプションもあったかな。 これはコード上で明示的にやってマクロで切り分けてるだけだけど。 Celeron用最適化コードなんてそれくらいしか見たこと無いな。 余談だが、一度試したことあるけど、crypt-core MMX版だけGCCで吐かせれば、 ほとんどVC++上でビルドできた。snprintfみたいなPOSIX依存関数をどうにかして、あと 正規表現はPCREか鬼車あたりに差し替えればいいんちゃうかな。
185 :
1 :2005/04/12(火) 13:06:26
>>179 うちのPC、なぜかVS6.0がインスコできず。CDからコピったVC++6.0SP0だからSSEが使えん。
でも、そういうマクロ使えば測定ラクだね。今後の測定に生かそう。
・・・つってもネタがな。
命令のアラインやROB関係は、何か「見えない」からやる気が起きないんだよな。
完全に分岐予測の裏をかくのはやってみたい。
あとはメインメモリからのプリフェッチか。L2が2MBもあるからコンソールで手軽にできない罠。
>>181 NetBurst哀れだな。最後まで叩かれ役のアーキテクチャだった。
アセンブラでP4最適化すれば、絶対クロックの高さも考慮に入れれば
性能/価格はK8以上、じゃないかなあ・・・。
もちろん手で最適化できる規模のアプリなんて少ないんだろうけど、
ベンチの結果を見るにつけ、無駄なストール食わせまくるタコベンチなんじゃないかと心配する。
まあ、発熱という弱点があるから(NetBurst降板の理由もこれだろう)俺はPenMだけど。
次買うのはMeromの予定。デスクトップだったらAthlonがいいかな、触ってみたいし。
TDPが100Wになっていいとしても、現状のDothanは大したクロックで回らない気がする。
つまり、(各種ベンチでの)絶対性能でP4(つーかK8)に勝てないコアであると。
PenMは製造コストとかもかかってそうだしね。
今度Meromがデスクトップに来るのは、
モバイルより高くできるTDPを、クロックではなくコア数で生かせるようになったからだと推測。
(クロックを倍にするとTDPは8倍(単純計算ね;)になるが、コア数を倍にしてもTDPは倍で済む)
まあ、NetBurstの寿命と言っちゃえばそれまでだが。
PentiumMは、「遅くない」CPUという感じ。
演算器の数やクロック(つまり理論性能)は平凡だが、様々な遅くなる要因を少しずつ改善。
結果、一見P6だが速さは別物、しかも省電力というナイスなCPUになったが、
腕力はP6程度なのでK8のパワーやP4のクロックにはどうしてもねじ伏せられてしまう。
186 :
1 :2005/04/12(火) 13:09:05
>>182 >吐き出すコードが違う
どんなCPUでコンパイルしようが、コンパイラの吐くコードは全く同一に決まってるだろ。
それとも、最適化の対象がPen4かCeleronかによってコードは変わるか、という質問か?
それなら変わるけど、コンパイラのオプションにはないだろう。
>計算速度に有意な差は
Pen4とCeleronの違いは、HTの有無・FSBクロック・L2キャッシュ、だけだと思う。
「単純な計算」がCeleronのL2に収まる程度のメモリしか使わないなら全く同じ速度。
そうでないならガクッと遅くなるはず。
Pen4とCeleronのL2容量がそれぞれ1MBと256KBだったとして、
例えばCeleronでL2ヒットしない処理だったら、処理単位を256KBより小さく分割するとか
入念なプリフェッチを行うとかすれば速くなる。
ただし、そういう小細工のオーバーヘッドでPen4での速度は逆に遅くなる場合もある。
まあ、メモリ上の処理を局所的に済ますのは基本じゃないかね。
昔マージソートを書いたとき、マージの回数だけ全体を舐めまわすコードにしたが、
再帰とか使ってキャッシュ上のソートを終わらせてから次のデータに移った方が速いだろう。
わかりにくいね。
つまり、データを0,1,2,3,4,5,6,7、キャッシュサイズを数字4個分とすると、
01234567 01234567 01234567 と処理するよりも、
01230123 45674567 01234567 の順番でやった方が速いということ。
上のだと、また使うキャッシュ上の0123を追い出して4567の処理をやってるから効率が悪い。
でも下のコードは再帰使うから面倒で(つーか難しくて)書かなかった。
てか182、レスはもらえてるけど欲しい情報は得られた?(w
VC初心者スレからいきなりこんなとこに誘導するのもどうかと思うが。
俺は/G7オプションとか言われてもわかんないし。
PentiumMは体感速度がいいんだよね、特にJavaとか.NETとか P4にくらべて中間言語系が恐ろしい速度でまわる JavaのサーバーVMがC言語ネイティブより早くまわる場合がある理由が 実行時に統計取りつつインライン展開やプリフェッチ命令生成とか 面白い技術が大量にはいってるんだな そういうのがネイティブコードでつくれると楽しそうだが 自己書き換えってhotspotのもっとも原始的な技術だったのかもしれん
188 :
1 :2005/04/12(火) 14:48:55
ユーザが設定するパラメータを、その場でマシン語に埋め込みレジスタを節約、 なんてのを考えたことがある。まだうまく行ってないけど。 しかしJavaがCより速いことがあるとは、Cにとっては皮肉だなぁ。
JVMの方が、制約が多い(=付加情報が多い)ので、
それが最適化していいかどうかの判断になりうる、というのはある。
FORTRAN, Pascal などは、アグレッシヴな最適化をかけやすかった。
Cは自由度が高すぎる故に、ヘタに高度な最適化をかけると
作成者の意図しない(=作成者の書いたとおりとも言えない)コードが吐かれる
というのも、よくある話。
>>187 コアの効率がいいというのもあるけど、L1キャッシュがVM(インタプリタ)を
効率よくカバーしててツボに入っているのかもしれないね。
ていうかP4のつくりが問題外、ってのは言及したらダメ?
>>188 NTカーネルも、Unix系も、実行形式の .text は読み込み専用ページに置かれるから
自己書き換え可能なコードをつくるためには、自ら「読み/書き/実行可能」な
領域を作ってあげてそこにコピーし、場合によってはリロケーションも行って
あげる必要があるよ。
それから、近い場所の自己書き換えは、レジスタの節約になるかもしれないけど、
命令キャッシュフラッシュとか、果てはパイプラインストール/フラッシュが
起こる可能性がある(マイクロアーキテクチャによって違う)ので、
使う際にはよくよく吟味してくれたまい。ていうか実験して報告汁。
190 :
182 :2005/04/12(火) 15:05:34
ご丁寧なレス、ありがとうございます。だいたい欲しい情報はいただけました。 Pen4(2A)とCeleD(2.66)の2台のマシンがあり、どちらの方が速いという話をしていたのですが、 VisualC++2003のコンパイラはPen4に最適化されているから、 Pen4の方が速いと、自分より詳しそうな人が言っていたので、疑問に思い質問させていただいた次第です。 この2つのCPUで比べたら、 L2キャッシュの差が出ない程度のプログラムなら、クロックの分当然Celeronが速い、 L2キャッシュの差が出るプログラムでも、クロックを考慮すればCeleronの方が速い場合が多いと 考えたのですが、こういう認識でよろしいでしょうか? 吐き出すコードが違うというのは、 VC++2003は、Pentium4とAthlonに最適化されており、 Pen4とAthlonでそれぞれコンパイラしたときには、 それぞれに最適化された違うコードが出てくると考えたのですが、 Pen4とCeleronは基本的に同じものであり、 出てくるコードも基本的には同じものであるという認識でよろしいでしょうか? (NorthwoodとPrescottの違いはありますが、AthlonとPen4のような違いはないはずですよね?) →これも、そのコンパイラの作りによるのかもしれませんが
191 :
187 :2005/04/12(火) 15:17:13
制約が多いほうが最適化かけれるというのはたしかにある JavaのアトミックパッケージはCPUの命令を積極的に使ってくれ という面白いクラス群だが、こういうのを使えばSSEとか自前で最適化 が余裕になるのかなぁと思ったり 現状でも勝手にSSEが使われたりはしてるけどね>Java 少ないメモリでユーザーに負担をかけないで扱いやすかったCは 今となっては非常に厳しいというか、こまかいのやりたかったら アセンブラと併用せよというスタンスだよね 結果C部分とのやりとりで最適化の範囲とかに制限が出て あまり代わらずとかいったかんじも多い VS2003もってないんだけど、C言語での最適化指定ってどの程度できるもんなの?
>>188 自己書換やると命令キャッシュが悲惨なことになるし、
RISCにとっては、即値ったってロードするし・・・
JavaがCより速いのは、
最適化を阻害する要素を色々と排除してることと、
無駄なコードが減ること、
その2点だと思う。
Javaだと簡単に書けることが、C++だと色々と気を使って処理たくさん書くしね。
193 :
192 :2005/04/12(火) 17:11:35
って既出だったorz
>>190 四の五の言ってないで実機で試せ、というのがこのスレの信条ですよ。
>>186 をよく読み直したほうがいい。
コンパイラを走らせるCPUと、出力されるコードのターゲットのCPUは、関係ない。
たとえば、SSE2を使ったPentium4用のコードを、
SSE2を持たないAthlonでコンパイルして出力することも、普通にできる。
というか、少しはVC++の設定画面とマニュアルを嫁。
実際にやってみれば、すぐわかることだぞ。
データシーツ嫁
>>193 スレ違いだが、クロスコンパイラなら、コンパイルするCPUと、吐き出すコードの
CPUが全く違っていてもいいね。gccなんかでは当たり前。
>>192 Javaだと動的にプロファイルをとって、実行時間の
かかる処理を重点的に最適化できるからじゃないの?
loop unrolling とかってやりすぎると命令キャッシュ的
に逆効果になるけど、動的なプロファイルを行えば、
時間のかかっているところだけ重点的に unroll するとか
できるわけだし。
まあ昔の mips コンパイラも、実行結果のプロファイル
をファイルにセーブして、再度最適化し直すってことが
できたわけで、Cでもできないわけじゃないというか、
単なるロストテクノロジってだけかもしれんけど。
ループバージョニングとかGC時の配置最適化とか狂ってるな GCがあることを速度的にメリットがあるという方向へもっていったのはすごい 最初すごく遅かっただけに、速度へのこだわりはすごいんだろうね 昔はi++よりi=i+1のほうが早いとかびっくりしたからなぁ
いくら実行時に情報を収拾できるとはいえ、その情報収拾にもCPUを食うわけで、 原理的にできるからといって、実際にパフォーマンスが良いとは限らないと思う。 プログラムの最適化のために、プロファイルを取って見るんだけど、 Instrument有効にして走らせると、まるで止まっているかと思うくらい重くなるし、 しかも、それによってCPUのキャッシュのヒットの仕方が変化しちゃうから、 あんまりあてにならなかったりするよ。
200 :
97 :2005/04/13(水) 02:42:56
>>185 SP4&SP5までなら対応のプロセッサパック入れれば使えますが。
SP6だとプロセッサパックが強制削除されるので仕様不可。
あと、Visual C++ Toolkit 2003も無償でDLできますね。Boostもほとんどビルド通るし。
漏れが良く逝くオフでコンパイラの話になると、IDEはStandard版でコンパイラだけToolkitにしてるって
人が多数ですね。
で、やっぱりWindows最強はゲイツコンパイラが最強な気がする。
Intel C/C++は、命令スケジューリングは最強だけどANSI C++な機能使うとなにかとトラブる。
テンプレート引数とか。
SIMD対応のコンパイラだと、まだ実用に足るとはいえませんが、こんなのもありまつね。
http://www.coins-project.org/ > TDPが100Wになっていいとしても、現状のDothanは大したクロックで回らない気がする。
> つまり、(各種ベンチでの)絶対性能でP4(つーかK8)に勝てないコアであると。
これは選別さえすればどうにでもなりそうな要素かと思ってますが。
http://www.gamepc.com/labs/print_content.asp?id=770ct479 ノート用CPUであるためマージンをとってあるだけで、TDPの縛りさえなければ定格電圧で
2.4GHz(Carmel, 7x5シリーズ)もしくは2.53GHz(Sonoma, 7x0シリーズ)動作する石が採れる
という話を聞いたことがありますが。
あと、意図的に抑える理由も十分あると思いますね。
Yonahでシングルスレッド性能も向上させて、インパクトを与える必要があるでしょうしね。
基本的にDothanは浮動小数以外は弱点の無いコアだと思ってますが。
L2キャッシュの容量も帯域もロードレイテンシの短さも十分強みだと思います。
PenMがオブジェクト指向の動的コードに強いというのは分岐予測まわりの効果だと思いますよ。
これもIntelのサイトに解説がありますた。
201 :
97 :2005/04/13(水) 03:22:42
>>191 えっと、浮動小数でSSE/SSE2を使うオプションはあるけど、
たとえば__int64型を使ったら自動的にMMX使ってくれるとか、またループを自動的に
ベクトライズしてくれるとか、そのレベルの最適化機能は皆無。
IA32の基本命令オンリーでなら最適化性能は最高クラスと思ってますが。
あと、MMX/SSEを使うなら組み込み関数やそのラッパークラスがかなり便利ですね。
決して使い勝手がいいとはいえませんが。
呼び出し規約を__fastcallにすれば3つまでならMMX/SSE組み込み型の変数をレジスタ渡しできます
(それ以上、もしくは__stdcallや__cdeclだとコンパイルエラー)
>>200 Standard版とVC Toolkitのコンパイラの違いってどこかに比較表ありませんか?
203 :
1 :2005/04/13(水) 09:37:52
>>189 俺がやっていたのは、VBで配列にマシン語のサブルーチンを読み込み、APIで実行というもの。
自己書き換えではなかったな。スマソ。
その後、nasmを使ってVBのコードに埋め込んだアセンブラをアセンブルして
状況依存のコードを作るというのを試みたが、これはなぜか失敗。
それ以来ろくに追究もせずやってない。
>>190 そういう質問意図を最初に書いてればもっと的確なレスがもらえたと思うよ(ていうか回答しやすい)。
その認識でいいが、キャッシュの影響がどの程度か考えるのが難しい。
P4コアの場合、ベンチ結果見るとキャッシュの量はかなり重要。その程度のクロック差など引っくり返る。
それに256KBのL2で完結するアプリなんて、どっかのCPUベンチぐらいだろう。
>吐き出すコード
それは違う。まず言葉遣いに禿しく注意。
・VC++はP4に最適化されている=VC++でのコンパイル作業はP4でやると速い
・VC++はP4に最適化されたコードを吐く=VC++でコンパイルしたコードはP4で実行させると速い
下の意味で言ったんだと思うけど。
大体、開発マシンによって最適化対象が変わったら不便でしょ?
それはコンパイルオプションで指定するもの。
#まあ俺も以前VC++6.0でSSE命令がコンパイルできないのをCPUがSSE非対応だからだと思っていたがな。
>>193 >>195 にあるように、SSE非対応のCPUでSSE命令をコンパイルすることは当然可能。
クロスコンパイラ然り。例えばMacOS用のアプリをWindowsマシンで作れる。
>>84 あたりを見て、182もクロック測定の道に踏み入れてはどうかな?(w
204 :
1 :2005/04/13(水) 09:39:24
>>193 >このスレの信条
いいこと言うね。俺も口先だけで言うよりも、なるべく実験結果を貼るよう心がけてきた。
(最近あんまりやってないけどな)
ただ、(測定の)初心者には実機で試すのが意外と荷が重いのよ。いくつか書いとく。
まずVC++2003のマニュアルをよく読む。
CPUは、得意分野と苦手分野で性能が意外と変わる。一般のベンチではなく、
自分が書いてVCでコンパイルしたプログラムでPen4とCeleronの性能比較をすべし。
測定ルーチン作りたくなかったら、PCの前でストップウォッチを使え。
VC++6.0だと、プロジェクト>設定>C/C++>ファイルリスティング>マシン語コードとソースを含む
とするとコンパイルしたときに一緒にファイルが生成されてCのコードとアセンブラの対応が見られる。
コンパイラオプションを変えるとこのコードが変わるのかーとか思っているだけでもいいと思うよ。
何かコンパイラの吐くコードに興味が出てきたな。
VC++6.0に簡単な処理をコンパイルさせて、俺のアセンブラと速度や構造の違いを考察するとか。
試しに100から199まで足させてみた。PenPro最適化でこんな感じ。
xor ecx, ecx
mov eax, 100
$L528:
add ecx, eax
inc eax
cmp eax, 200
jl SHORT $L528
まあ普通だ。即値で比較してるのが気持ち悪いけど。カウンタにeaxてのも変な感じ。
また、この即値(100や200)は内部4byteである。この方が速いのかな。
205 :
1 :2005/04/13(水) 10:08:32
>>200 いや、VC++が正規インスコできないからSP5も当てられないわけで。
リンク先のベンチ結果を見たが、PenMを2.7GHzにするとすごいんだな。さすが。
俺は価格の面でPenM-2.7GHzは不利なんじゃないかと思った。パイプラインも短いし。
NetBurstをやめるのに引っ込みがつかないから、
Pen4を追い越さないように意図的にPenMの性能を抑えるというのはあるかも。
>>180 PenMは、素直にアセンブラで書けば理論性能が出てしまうという組みやすいCPU、
というような認識だね。俺は。
Javaの仕組みはよく知らないが、JavaがCに勝つのは単にCを書いた人がヘボという気がする。
でもそれはCとアセンブラの関係と同じで、原理的にはアセンブラの方が速くても、
複雑なプログラムの場合アセンブラで書くと頭がこんがらがって遅くなってしまう。
適材適所っていうか、人間の頭が回る範囲で低級言語を使い、あとは素直に高級言語を使う
ってのがいいんだろうな。
>>1 >190を誘導した張本人です。色々とご迷惑を。
で、このスレは基本的に読むに留まってますが、手元にgcc/vc7.1があることだし
最適化に関してはCのソースを貼ってくれれば追試しますよ。
尚、>204のコードでカウンタにeaxを使うのは単にeaxが一番壊れる機会が多いレジスタだからかも。
Cのロジックが変わると他のレジスタを使うかもしれません。
ecxも同様で、ロジックによってはesi辺りに置き換わる可能性が高そう。
#この辺はもう少しロジックが複雑じゃないとなんとも言えません。
即値が内部4バイトなのはどうなんでしょうね。gccでは1バイトの即値を使ってた気もするんですが。
#これも調査対象かな。
Javaが速い件については、>189の言う「自由度が低いから大胆に最適化しやすい」からでは?
総体的(≠相対的)にはCの方が速くなる余地があると思いますが。
207 :
1 :2005/04/13(水) 11:20:55
>>206 いえ、ネタ提供ありがとうです。
とりあえず自分でVC++6.0と勝負して来週にでも結果貼るので、そんときはよろしく。
俺は自分以外の人やコンパイラの書いたアセンブラをあまり読まない(読めない)ので
レジスタの使い方なんかがすごく新鮮だった。今は完全に自分流だからな。
>自由度が低いから大胆に最適化しやすい
ちょっと話がそれるかもしれないが、自由度を削ると最適化しやすくなるのは確か。
カリカリにチューンしようとあがいてもこんがらがってまとまらないとき、
データの配置とかを(理論性能を削ってまでして)きれいにすると、
簡単にその制限内での理論性能を出せたりする。
ヘタレなので、Cコンパイラの最適化に連敗してます。 それに、速度を上げるためにコードをあれこれいじり倒すとなると、 アセンブラで書くよりも、Cで書いたほうが短時間で多くのパターンを試せるし。
>>205 JavaがCより早いってのは適当にコードかくとわりあいよくでるよ
JavaとCはほぼ同じ構文なので書き方の差はうまれない
ハノイの塔とかソートとかかいてみそ
もちろんCが早い場合もあるが、速度的な差はほとんどないねぇ
210 :
190 :2005/04/13(水) 17:20:46
いろいろと皆様ありがとうございました。 もう少し自分でも勉強してみます。 やっぱりまずやってみることですね。
211 :
97 :2005/04/13(水) 21:54:02
>>208 Knuth本やHD(ハッカーのたのしみ)あたりの本を一通り読むと手動最適化のセンスが身に付くかも。
コンパイラの性能よりも使う人間のテクニックのほうが重要だったりします。
>>202 TKはVisualStudio Professional以上についてるコンパイラの英語版と同等。
Standardのコンパイラは最適化自体が出来ない。
Toolkitは専用スレもたってるしそちらのほうが詳しいと思われ。
あと、コンパイラ差し替えても使えるには使えるが、結構メンドイ、とのこと。
もしこれから購入を検討されてるのなら、2005だとStandardクラスにも最適化コンパイラが
含まれるから、それまで待つのもアリかと思いますよ。
Pentium Mは今年の中旬に780(2.26GHz)を出すとか。
番号的には790までで打ち止めな気がするので、Yonahが万が一延期になってDothanで引っ張ったとしても2.4GHzまでか。
Yonahは2.5GHz超えてくるという話だし、Meromを待たずしてPentium 4を食っちゃうかも。
212 :
1 :2005/04/13(水) 22:10:45
>>200 Toolkit 2003のを入れたらSSE2までコンパイルできるようになったよ。
サンクスコ。嬉しい。
VC++2003エンタープライズ使ってるけど、 SSE2のサポートがちょっと変。 _m64 a[] = { 0xd76aa478d76aa478, 以下略 っていうのはできるけど、 __m128i a[] = { 0xd76aa478d76aa478d76aa478d76aa478, 以下略 ってのはできない。 _m128iの定義を見ると共用体で、 最初のメンバが__int8が16個なので、 __int8で初期化しないといけないようで。
>>213 それハマったことがある。
そもそも__int128型が無いから仕方が無いとの結論。
うちは大体これでやってますが。
__m128i a[2] = {
{ 0xFFFFFFFFFFFFFFFFi64, 0xFFFFFFFFFFFFFFFFi64 },
{ 0x00000000000000000000i64, 0x00000000000000000000i64 }
};
intrinsic使うなら _mm_set_*系の組み込み関数使うのも便利かと。
C++でやる場合はdvec.hをインクルードして
static const Iu32vec4 n(a, b, c, d);
とかやっちゃったりすることもありますが。(定数化すればコンストラクションのオーバーヘッドなし)
>>214 素で0の数多かったorz
実はリアル知り合いに某エミュの開発者がいるけど、VT(Vanderpool)対応が云々とかなんか楽しそうな話題を
しておりますね。CPU側のVMサポートがあるとかなりパフォーマンス面でも有利らしい。
現行Pen4ではまだdisableらしいですが。
216 :
1 :2005/04/19(火) 12:33:29
コンパイラはToolkit 2003で、オプションは実行速度でP6最適化。 PentiumMでのレイテンシ-スループットは、 fadd 3-1, addsd 3-1, addpd 3-2(内部3-1を2回。別の種類の命令相手だと4-2) for (i=0; i<1000; i++) q+=p[i]; //double p[1000]の総和を求める これをVC++にやらせると3065clk。 $L591: fadd QWORD PTR _p$[esp+eax*8+8016] add eax, 10 cmp eax, 1000 fadd QWORD PTR _p$[esp+eax*8+7944] fadd QWORD PTR _p$[esp+eax*8+7952] ・・・6行分中略・・・ fadd QWORD PTR _p$[esp+eax*8+8008] jl SHORT $L591 fstp QWORD PTR _q$[esp+8016] #_p$ = -8000なので、_p$[esp+eax*8+8016]は[esp+eax*8+16]と同じ。 なんと10回もアンロールしてくれた。10*100=1000だ。 そこでちょっといじわるしてi<997(素数)にしてみた。すると、8回アンロールのあとに追加で、 $L591: fadd QWORD PTR _p$[esp+eax*8+8016] add eax, 1 cmp eax, 997 jl SHORT $L591 なんと8*124+5だ。コードに5が出てこないところにセンスを感じた。eax=997-997%8 なのがミソ。 俺ならfaddを5個書くが、こうすれば何個半端がでるか考えずに書けるんだな、と感心。 ていうか、機械のくせに997-997%8を計算してその個数のfaddを配する手間を惜しんでることに感動した。 (本当は1*5を5*1にアンロールしてもコードサイズが増えるだけで速くならないからだろう)
217 :
1 :2005/04/19(火) 12:34:15
さて、手動で1段だけアンロール。これが最適化を阻害するか検証。 for (i=0; i<1000; i+=2) q+=p[i]+p[i+1]; $L591: fld QWORD PTR _p$[esp+eax*8+8024] ;st = p[i+1] q add eax, 2 cmp eax, 1000 fadd QWORD PTR _p$[esp+eax*8+8000] ;st = p[i]+p[i+1] q faddp ST(1), ST(0) ;st = q+p[i]+p[i+1] jl SHORT $L591 なんと2100clk(4clk/loop)。faddのレイテンシは3なので、これはすごい。アンロールはしてない。 まとめてから足すのでレイテンシ3をまともに食らうのがfaddp ST(1), ST(0)だけになる。 これはCで並列性を持たせて書いた人がえらいのだろう。 for (i=0; i<1000; i+=4) q+=p[i]+p[i+1]+p[i+2]+p[i+3]; 調子に乗ってこんなことすると1700clkにまでなった。でもこれは謎。 $L621: fld QWORD PTR _p$[esp+eax*8+8040] add eax, 4 cmp eax, 1000 fadd QWORD PTR _p$[esp+eax*8+8000] fadd QWORD PTR _p$[esp+eax*8+7992] fadd QWORD PTR _p$[esp+eax*8+7984] faddp ST(1), ST(0) jl SHORT $L621 どう見てもレイテンシ3を3回食らってる。2500clk以上かからないとおかしいのになぁ。 ひょっとしてPenMはFPUのスケジュールが強化されてる?Athlonならどうだろう。 for (i=0; i<1000; i+=2){ q+=p[i]; r+=p[i+1]; } これは2000clk。アンロールしてくれたらもっといくはず。 for (i=0; i<500; i++){ q+=p[i*2]; r+=p[i*2+1]; } こうするとアンロールしてくれる。1700clkくらい。
218 :
1 :2005/04/19(火) 12:34:47
では、いよいよ組み込み関数を使う。"emmintrin.h"をインクルード。 for (i=0; i<1000; i+=2) s=_mm_add_pd (s, _mm_loadu_pd( &p[i])); アライメントが合ってない状態でmovapdしてたのに気づかず長時間悩んだ。Cだと油断する。 $L1941: movupd xmm1, XMMWORD PTR [eax] add eax, 16 dec ecx addpd xmm0, xmm1 jne SHORT $L1941 2300clkだった。変数のsはqとrをくっつけたもので、addpdはfaddを2回やっている。 実行ユニット的にはに上の2000clkのコードと同じなのだ。 で、更に並列性を上げる。 for (i=0; i<1000; i+=4){ s=_mm_add_pd (s, _mm_loadu_pd( &p[i])); t=_mm_add_pd (t, _mm_loadu_pd( &p[i+2])); } $L1975: movapd xmm1, XMMWORD PTR _t$[esp+8064] npad 9 ;この9byte nop って意味あるのか? $L1943: ;ここへジャンプしてループに入る。 movupd xmm2, XMMWORD PTR [eax-16] addpd xmm0, xmm2 movupd xmm2, XMMWORD PTR [eax] add eax, 32 dec ecx addpd xmm1, xmm2 movapd XMMWORD PTR _t$[esp+8064], xmm1 jne SHORT $L1975 これが2400clk程度。遅い。どう考えてもmovapdが無駄なのだが。 直前にこれを書いた。 s=_mm_xor_pd (s, s); t=_mm_xor_pd (t, t); このtの部分をt=s; としたら無駄なmovapdはなくなり、1900clkになった。 更にもう1回アンロールで1700clk。意外と伸びない。
219 :
1 :2005/04/19(火) 12:35:16
faddとjccがユニット競合してるのと、複数μopを連発してるのが微妙に効いてるか。
FP_ADDフル稼働で1000clkが理論値。
>>73 のコードが11clk/loopもかかる謎と同じっぽいな。ADD側のユニットが混むと妙に遅くなる。
最適化なしのコードは本当にCのそのまんまで笑った。
必ずメモリに書き戻してから次の計算するし、順番もCの規約通り変わってない。
さて、俺も書こう。まず素直にやって3200clk。
lp:
fadd qword ptr [eax]
add eax,8
dec ecx
jnz lp
FPUって謎多いよな。並列実行の方法は色々あるが、それをまぜたら少し速くなった。1600clk。
lp:
fadd qword ptr [eax+ecx*8-32]
fld qword ptr [eax+ecx*8-24]
faddp st(2),st
fxch st(2)
fadd qword ptr [eax+ecx*8-16]
sub ecx,4
fld qword ptr [eax+ecx*8+24]
faddp st(4),st
jnz lp
addsdを使ったが、1700clk。FPUと同じだ。
そしてaddpdを使って16byteアライン許しても1800clk。うーん遅い。
コンパイラの実験というよりFPUの調査になってしまった。
しかしこんな簡単な処理で4レス分も食うとは思わなかった。
クイックソートとかやろうと思ってたけど、やったら壮絶なことになりそうだ。
220 :
1 :2005/04/19(火) 12:35:50
/arch:SSE2 オプションでSISDのSSE2を使ってくれるようになるので追試。 当時PenMは認知されてなかったみたいで自動的にPen4最適化となるらしい。 for (i=0; i<1000; i+=2){ q+=p[i]; r+=p[i+1]; } $L1939: movsd xmm2, QWORD PTR _p$[esp+eax*8+8008] addsd xmm2, xmm1 movapd xmm1, xmm2 movsd xmm2, QWORD PTR _p$[esp+eax*8+8016] add eax, 2 cmp eax, 1000 addsd xmm2, xmm0 movapd xmm0, xmm2 jl SHORT $L1939 3200clk。なんかタイミングが合ってない。まともに最適化できてません。なんでだろ。 for (i=0; i<500; i++) にしたらアンロールしてくれて1700clk。 ただ、これもxmm2にだけ足していくコード。なのにレイテンシ3を食らっていない様子。 上の2500clkかかるはずのコードと同じ謎だが、ここで謎が解けた、レジスタリネーミングだ。 10回に1回だけであっても依存関係を断ち切れば、ほぼ完全な並列実行が可能。 恐るべしリネームの威力。そしてROBの数。 コンパイラと勝負と言ったが、そもそも勝負できる類のものではない気がしてきた。 コンパイラが理想的なコードを吐くならアセンブラに勝ちはないし、 アセンブラでないとできない(原理的にCでは表現できない)手法を使うならコンパイラは必ず負ける。 もちろんコンパイラの最適化は完全じゃないし人間アセンブリにも隙があるから勝負にはなるけど。 完全で隙がない理想を見ているからかな。変なこと書いてスマソ。 Cレベルで高速化する技術なしにやったって、コンパイラ不利になるのは確か。 アセンブラはCPUのご機嫌とってればいいからまだマシだが、 CだとコンパイラというCPU以上に顔色の見えないヤツ相手に書くから大変。
VB5.0Proが出てきたのでVB5.0LEを消して入れ直し。ネイティブコードが吐ける。 Cができない頃は、マンデルブロ集合やFFT作るのにネイティブコードコンパイルは重宝した。 最適化フルオプションにしたのを逆アセ。 For i = 0 To 999: q = q + p(i): Next xor eax,eax lp: cmp eax,edi ;edi==999 jg exit_lp fld qword [edx+eax*8] add eax,ecx ;ecx==1 fadd qword [ebp-0x38] fstp qword [ebp-0x38] jmp short lp 8000clk。即値は4byte。即値比較やincを使ってない。なんかCのよりRISCっぽ。 ちなみにCでコードサイズ優先だと8000clk。最適化なしだと26000clkかかる。 For i = 0 To 999 Step 2: q = q + p(i) + p(i+1): Next xor eax,eax lp: cmp eax,edi ;edi==999 jg exit_lp fld qword [ecx+eax*8] fadd qword [ebp-0x38] fadd qword [ecx+eax*8+8] add eax,edx ;edx==2 fstp qword [ebp-0x38] jmp short lp これだと5600clk。Cではコードサイズ優先が4000clk、最適化なし15000clk。 VB5.0の速度優先はVC2003のサイズ優先に速度で勝てない。所詮は昔のVBか。 でもVB5.0Pro→VC++Standardではガクッと遅くなってしまうんだね。
222 :
1 :2005/04/19(火) 13:00:30
「【激論】最適化厨vs高スペックヲタ」の94がきっかけで120辺りでコンパイラとアセンブラの話がある。 コンパイラは、人間と違って頭(CPU)がこんがらがってしまうことがないから大域最適化向きだよ。 「C、C++の最適化について語るスレ」でも色々話されてるね。 今回の実験の並列性持たせるのは200で言われている。有名なのか。 関係ないけど212がわかりやすい。変な議論する前にバシッとこういうこと言えたらいいとオモタ。 275のレスはすごい。 それで思い出したが、キャッシュのWay数についての実験はまだなのでやってみよう。 で、キャッシュの実験。PenMのL1Dataは8Way,32KBとなっている。 イメージとしては、メインメモリ全体を32KB/8Way=4KBずつに切って重ね、 重なった同じ場所の64byteラインで8つまでがキャッシュに置けるって感じか。 lp: add eax,[esi] add esi,8000h ;32KB(8Wayが既知なら4KBでいい。どちらでも結果にはほとんど影響なし) dec ecx jnz lp これでecxの値を変えてクロック測定。ecxが1〜20のときのクロック数は以下の通り。 1 3 3 7 9 11 15 17 33 36 42 46 48 78 86 94 103 119 131 148 ecx>=8ではかなりクロック数がふらつく。 ふらつく場合、最も少ない値を採用した。 ecx=8では、運悪くアドレス値を4KBで割った余りがesiと同じメモリを測定ルーチンが使うと L1から[esi]が追い出され、L1ヒットしなくなる可能性が大きくなっている。 これでL1が8Wayであることが検証できた。 L1ヒット時は2clk/loopとわかる。また、使ったメモリが640KBなのでL2なら完全ヒット。 結果をプロットすると、[1-8][9-13][14-17][18-20]のきれいな4本の線になる。 まずecx=9の遅さが謎だ。2回のL1ミスで済んでない? あと13と14の間に断絶があるのも不可解。78-48=30clkも増えてる。
223 :
1 :2005/04/19(火) 13:01:15
182は、コンパイラの最適化をこんなイメージで捉えていたのではなかろうか?
「特定の道路(CPU)で速く走る車(コンパイル後のアプリ)を、実際に道路で試しながら作る」
これだとコンパイル作業をしたCPUに最適化される。
ていうかこういうコンパイラ誰か作らないのかな。コンパイルは重くなるけどけっこういいんじゃ?
あと、「VisualC++2003のコンパイラはPen4に最適化されているから、 (Celeronより)Pen4の方が速い(有利)」
かどうかというのが182の疑問の発端なわけで、これの答えはNoだと思う。
P4最適化というのはNetBurst最適化のことでキャッシュの量はさほど考えてないだろう。
/G7オプションとはP4最適化のことだな。これをつけるとinc eax がadd eax,1 になった。
P4のincはフラグでパーシャルレジスタストールを起こす。
>>189 FORTRAN, Pascalのコンパイラを書いたの?
俺はコンパイラもインタプリタも書いたことないから感覚がわからない・すごさがわからないよ。
>>208 どんなコードで負けた?
俺が作ったのはライフゲームやマンデルブロ集合(←SIMDで効果絶大)、せいぜいintのクイックソート程度。
小さいプログラムだからコンパイラには負ける気がしない。
Cだと短時間で多くのパターンを試せるというのは同意。まずはアルゴリズム、これ基本。
実際、実用のプログラムでアセンブラはほとんど使うべき場合がないと今さら気づく。
速度ネックな処理でアルゴリズムも詰めてあるのが前提で、開発期間や拡張性を考えたらねえ。
ていうか少し前までは本当に負ける気がしなかったし、コンパイラに負ける人は本当にヘタレだと思ってた。
でもそうじゃないんだよね。
FFTとかやろうとしたら手が止まる。アルゴリズムを完全には理解していないのが露呈する。
一応は理解してるからCのFFTなら書けるけど。今アセンブラで書いても勝てる自信がない。
アセンブラを書くって、Cを手でコンパイルするというより
理解したアルゴリズムをx86語で話す感じで、逐次処理の論理じゃなく全体構造のフィーリングなんだな。
そうでないと手書きasmのスピードにならん。
224 :
1 :2005/04/19(火) 13:57:32
Cで書くとき、後でアセンブラに直すときに書きやすいアルゴリズムを選ぶことがある。
Cレベルじゃなくてアルゴリズムレベルの話。Cのコードもこの方がきれいになる。
>>209 そうなのか。俺はJava書いたことないので何もわからんです。
Javaってインタプリタってよりも、その場でコンパイルするコンパイラって感じだね。
Cに同じ最適化技術が入れられないのは「自由度が高い」からか。
ていうかJavaのが速いんだったらJavaをx86ネイティブにコンパイルとかできないの?(Javaの意味ないけど)
>>211 そのYonahのクロックまじ!?少なくともスミス3.2GHz*2なんかじゃ歯が立たないだろ。
TDP31W→1コア当たりのTDP15Wだからクロック据え置きだと思ってた。
それにしても長文過ぎる・・・orz
1000個足すだけの単純極まりないコードごときで。
あとで、関連スレを眺めてみよう…時間ないけど。
>>224 >ていうかJavaのが速いんだったらJavaをx86ネイティブにコンパイルとかできないの?(Javaの意味ないけど)
「gcc gcj」でぐぐれ。
>>225 スマソ。あるのね。
アプリをCのソースで配布して各環境でコンパイルすれば一番だと思ったけど、
ソースコード強制公開になっちゃう。
あれ!?このトリップはダメだな。
229 :
● :2005/04/19(火) 23:34:28 BE:1674825-#
>>222 C++.NET 2003の /G6オプションは レジスタ・メモリ間命令をかなり避けるような。
μOPsフュージョン大して生かせないんじゃねーかとか思ったり
で、G7なら速くなるかというと、そうでもないみたいで(Pen4の長いレイテンシを埋める最適化をしてるような)
このへんはまだPentium III向けの悪寒。2005でようやくモダンなCPUに追いついてくる気がする。
Professional以上ではPGO(前のレスではIPOと言ってたがこれは間違い)も搭載されるので
チューニングがきいたときの性能にはかなり期待できそう。
ちなみに今無料で落とせる2005のβはグローバル最適化が無効でかなり悲惨な出力になる罠。
230 :
● :2005/04/19(火) 23:36:30 BE:5357748-#
ひとつ訂正 >無料で落とせる2005のβ こっちはStandard相当のね。最適化がついただけでも相当な進歩かと思われ。 MSDN限定のベータは幾分かマシ。
>>228 実験サンクス。
4回アンロールか。10回のもあるね。VC++で俺が見たことあるのは8回と10回。
アンロール回数っていうのは命令キャッシュ量依存なのかね。
add/cmp/jcc という流れなので非常に読みやすい。
まあ、P4以外ではFPUとALUの命令を混ぜた方がいいので若干最適化が甘いとも言えるかも。
アンロールの半端部分は先に足しちゃうんだね。
なんか人間の書いたコードみたいだと思った。
>>229 確かにP6はデコード・リタイヤネックが大きいからそういうコード吐くだろうね。
でも上でVCが吐いてるコードはfadd [mem] だな。FPUは命令分けるとかえって遅いとか?
測定はせずに、オプション変えてコードを眺めるってのもいいかもね。
最適化したコードは、P6向けとK7向けが似ていて、PMで更にAthlonへ近づいたと思う。 だからAthlon向けに最適化すればいいかと(PMじゃパワー不足かな)。 だけど/G7オプションの説明見ると「Pen4またはAthlon」ってあるのよね。 一緒にできるアーキテクチャじゃないと思うが。 やっぱMicrosoftはIntelびいきなのか? 足すだけはさすがに単純すぎた。 次は、最適なアセンブラ化がすぐにはわからない例でやってみたいけど、いいのがない。 昔クイックソートをCとアセンブラで書いたが、長くて読む気がせん。 (cmov使ったら遅くなった覚えがある) 再帰のマージソートかな。安定で、独自に発見したので愛着がある。メモリ倍食うのが痛い。 で、このスレの主題となるのはクロック測定。 それはつまりCPUの(この辺は物理的制限かなとか思いつつ)論理構造を知るということ。 (PenMと、1THzのPen4でエミュられたPenMは原理的に区別できない。THzじゃ無理?) アセンブラやるまでL1キャッシュとレジスタの違いを知らなかった。 アセンブラをやるとCPUの仕組みがわかってくる(少なくともL1とregの区別はわかる)。 クロック測定をするとCPUに関して更に時間軸も見えてくる。 今のところ、命令毎のクロックや使用ユニットは大体わかった。 謎なのはキャッシュ。特にL2とL1の間のバス。当然メインメモリもだが。 PMのキャッシュについてはレイテンシがP6より大きいと言われるが、 河童Celeron-400より確実に性能はいい。L/Sバッファ周りかも知れないけど。 L2容量を減らしたせいか、たまにCeleronはキャッシュのWay数が半分だったりもする。 同じコアのキャッシュを削るという荒技なのでオーバーヘッドがあるのかしら。
233 :
1 :2005/04/20(水) 11:04:59
PC雑誌の表紙に「Athlon64のすべて」みたいなことが書いてあったので立ち読みしたが、 期待したCPUコアの詳細については書いてなかった。 P6とK7が争ってた頃は、形だけでも実行ユニットの数やパイプラインの段数が書いてあったのになぁ。 まあ、Prescott31段!とか書けないか(w Trip-MonaでAthlonの性能がやたら低いが、これはキャッシュだろうな。 多分、低レイテンシのキャッシュが256KBあるかどうかで数字が分かれるソフトなんだろう。 つーか1+8コアのCELL萌え。 x86も、従来コード向けで1コア確保して、小さいコアも4個乗せるとかダメかな。 従来アプリの高速実行というシバリがでかすぎる。ある程度捨てたP4でも酷評されるからな。 ただ、CELLみたいのって、外付けでもいいから欲しい。 あ、それはGPUか。
>アセンブラやるまでL1キャッシュとレジスタの違いを知らなかった。 さすがにそれは・・・ つーか、俺が始めたときにキャッシュなるものはなかった・・・ Cellは元々あれでビデオ描画やる予定だったのでああいうつくりになったかと PS2よりは汎用性あるけど、所詮そこまでという感じのあくまでも延長線上に あるもので、いわゆるマルチコアというくくりではないねぇ スレッド切り替えで退避できないつくりでは そもそもMAXが256KB
235 :
1 :2005/04/20(水) 12:54:11
>>234 まあ、ポケコンやVBで育ったので勘弁してちょ。
Cellについては確かにそうだが、自分で遊び倒すという意味で萌えた。
できれば倍精度浮動小数があるとよかったな。マンデルブロ集合とかやらしたらめちゃ速そう。
236 :
228 :2005/04/20(水) 13:31:39
>>235 私ゃ逆に、マイコンから入って386辺りで挫折した人間ですが。
68KやSparc触りだすと、CISCアセンブラ書くのが億劫になってくるんですよ。
>>234 >俺が始めたときにキャッシュなるものはなかった・・・
同意。
(つか、俺の場合、「まだ、『始めた』内に入ってない」といわれそうだが。)
Z80とか68000にはキャッシュがなかった。
(68020以降ならキャッシュもあったが。)
8086の「プリフェッチバッファ」って、
なんとなく、命令キャッシュの超簡易版みたいなもの?
(P4のトレースキャッシュとか、通常の命令キャッシュと違って、
ホントに先読みだけだけども。)
>>236 >68KやSparc触りだすと、CISCアセンブラ書くのが億劫になってくるんですよ。
68kはCISCだと思う。
>>237 >236は68Kでアセンブラを書いているとは言ってないな。
68KやSparcだとそもそもアセンブラを使わないんジャマイカ?
sparcはともかく68Kでアセンブラ無視ってのは正直納得いかんがね
240 :
● :2005/04/21(木) 01:54:02
>>233 > Trip-MonaでAthlonの性能がやたら低いが、これはキャッシュだろうな。
> 多分、低レイテンシのキャッシュが256KBあるかどうかで数字が分かれるソフトなんだろう。
128KBの定数テーブルテーブルサイズを8byteずつランダムルックアップする感じだから
L2ロード性能依存と。
帯域も広くレイテンシも小さいPentium IIIマンセーなコードですな。
うちもあのサンプルコード見てSSE/Enhanced 3DNOW!で追加されたpextrw/pinsrwの使い方の
芸術性を見た、と言う感じですな。
utripperも基本的に同等のものですね。
この2つ、PrescottだとあのL2のレイテンシのせいでやたら遅いのでつが、
HT有効時二重起動でトータル40%くらい速度アップした。
でも普通にNorthwoodのほうが速いです(爆
241 :
237 :2005/04/21(木) 14:36:35
流石にSparcのアセンブラは書かなかったけど68Kは書いた。 つーか、かなりの物作った。CISCという意識はなかった。スマソ
違う、レス番間違えた。重ねて失敬。
>>241 CISC vs RISC論争の時、
内部が複雑なのでクロックを上げれない例として
引き合いに出されたのは、むしろ68040ではなかったかと。
80486に比べても、クロック・実効速度で大きく遅れてました。
結局、「複雑」ってのは、アーキテクチャよりも
むしろ、マイクロアーキテクチャの部分だったのでしょう。
本気度とか市場シェアかと モトローラがインテル並のシェアがあったら大量の金つぎ込んで いくらでもいいの作れたと思うが 040は486とくらべて実行速度で大きく遅れてる感じはしないのだけれども 060はPentiumにくらべるとバス周りがなぁ でも、68Kはアセンブラによる最適化が異常に進んだおかげで 非常にいじり倒す人にとっては面白い石ではある 68000-16MHzは386-20MHzより大概早かった まぁ当時はキャッシュ容量もほとんど無く、メモリのウエイトとか レジスタ数が純粋に速度に貢献してたからね そもそもZ80にくらべれば68000-10MHzは天国だった(ぉ
とうとう俺はMC68040を見ることがなかった…(出回ってたらしいが)…遠い目。 ※俺が使ってたのは XC68040 当時の68040は、同クロックの486より速かったというのは俺の感想。 ただ、-25 品には、x2クロックである 50MHz も与えてたんだよなー。 その後間もなく、486DX2 などで速さチギられてくワケだが。 ところでここ、何のスレだっけww
そういや当時モトローラは外部クロックを表記していたんだよね
回顧スレ(ぉぃ
248 :
243 :2005/04/21(木) 17:17:59
まあ、あれだ。 68kは、むしろアセンブラ使って、 手動で最適化した方が良かった、って話。 だっけ?
で、どうやってクロックを測るの? 測定ツールをオープンソースで作って、結果を持ちよってまとめたほうがよくないか?
250 :
241 :2005/04/21(木) 18:37:02
>>248 んだんだ、ある装置の開発部隊にいたんだけど、うちらはアセンブラで隣はCだった。
そのCコンパイラのできが当時だから仕方ないかもしれないけれどよくなくて、
アセンブラで普通に書くほうが速かったと言うお話。
そう言えばPalmOSが68Kなんだけど、これがMacOS同様無効命令例外でAPIを呼ぶ仕様。
Cのランタイムなんてないからstdio.hやstring.h系の関数がAPIで実装されていて、
呼び出しがなかなか遅くて笑えた。
それで思い出したのだけど、8086のintってDOSでは幅を利かせていたけど今でも使われている?
INT3だけはブレークポインタで使っているんだろうけど。
#この辺りに如何に遠ざかっているかがw
251 :
● :2005/04/21(木) 20:59:59
>>249 計測用マクロ集はIntelが公開してるじゃん。
http://www.intel.com/cd/ids/developer/asmo-na/eng/microprocessors/ia32/pentium4/optimization/20243.htm?page=1 あとは各自VCTKかあたりでコンパイルして実行と。
gccでも-masm=intelでコンパイルすればよさげですが。
理想ケースだけ測るより組み合わせで地道に計測したほうがよさげ。
>>250 >そう言えばPalmOSが68Kなんだけど、これがMacOS同様無効命令例外でAPIを呼ぶ仕様。
Sunもでそ。RISC系は大体そんな感じじゃないでつか。
ぶっちゃけきょうびstring.hの関数がVCの最適化で内部命令に展開できるってのもどうでもいいような話だったり。
普通にMMX/SSEで自前で書いたほうが速いし。
>それで思い出したのだけど、8086のintってDOSでは幅を利かせていたけど今でも使われている?
割り込みであれこれやるより、OSがCPU時間を割り当てるんで、スレッド起こして
処理するのがナウい開発技法かと。
特に意識しなくても、複数プロセッサが乗ったマシンであれば、OSが勝手に
プロセッサ毎にスレッドを振り分けてくれたりするので。
ドライバとか組み込みレベルならともかく、アプリレベルで使うことはまず無いと認識してます。
そもそも割り込み系の命令ってNT上じゃ特権無いと使えないんじゃ・・・。
>そもそも割り込み系の命令ってNT上じゃ特権無いと使えないんじゃ すると当然、割り込み命令を使うと「特権違反例外」を発生するから、 システムコール用に使うことだって、できなくはない...と思う。 OSの例外処理の仕様とか、システムコールの仕様とかに依存。
メール欄そのままやった・・・ LibdesをC#.NETに移植したコードでちょっとトリップのエンコードのパフォーマンスはかってみたけど さっぱり性能出ませんなぁ。 これだからネイティブコード言語は今後も安泰だなと思ったり。
実はロード時間も含めてるとか?
というか特権レベルを上げる方法はコールゲートとソフトウェア割り込みしかない。
で、CとC#でどれだけの時間差が合ったのかよろ あとは.NETもJavaみたいに最適化の種類たくさんいじれるのならその調整 hotspot技術だとしたら1回目はほとんどインタプリタで動いてる可能性も高いし
ソフトウェア割り込みはWindowsNTでも、OSのAPI呼び出しに使ってたと思う。
とはいえ、普通のプログラマはそれを意識しない。
なぜなら、普通のプログラマが使うのは、Win32 APIというラッパーで、
それらはDLLのexport関数として提供されているので、
Win32 APIの呼び出しは、DLL内のexport関数の呼び出しになるのだけど、
たいていはimportライブラリを使うので、単なるCの関数としてしか意識されない。
>>251 同じソースで測定しないと、結果の比較とか、やりづらくない?
一人でいくつものCPUを持っているなら、ともかく・・・。
じゃぁ藻前がやれって? 今は他のフリーソフト作ってて手一杯でつ。
259 :
258 :2005/04/22(金) 18:48:18
260 :
258 :2005/04/22(金) 19:00:15
ちなみに、NTは4.0までがint 2EH 2000以降は、インテルならsysenter、AMDならsyscall、だって。 もうint使ってないんだ、知らなかった。
う。 C#を持っていないせいか、はたまた、 AthlonXPだからか、実行できない。 「アプリケーションを正しく初期化できませんでした (0xc0000135)。[OK]をクリックしてアプリケーションを終了して下さい。」 と出た。 とりあえず、ランタイムを探してくる。
あ... .NET Frameworkがないからだ。 先日、削除してたよ。スマソ
>>261 AthlonXP 2500+@3000+ (FSB333、×13.5)
WinXP SP2 1Gで実行。36868trips/sが1000000回の平均ですた。
それはおそいのかはやいのかわからん・・・
VMで動くバイナリの割には速い気もした。 デバッグビルド(最適化無効)だと半分くらいの速度しか出なかった。
>>261 C++のソースがないと速いのか遅いのかわからん・・・・
PentiumM725(1.6GHz/2MB) XPSP2 32756.8 って値が出た。停止させたら結果が消えたのでやり直したが。 クロック数の割りにさすがに早いな
Baniasだと見知らぬ国のトリッパー(wで4倍は出てますが
それは単純に2次キャッシュ速度に依存しているということか?
作った人、メモリ使用量とかGCの頻度とか細かい情報もよろ
やっぱし、.net frameworkだった。 AthlonXP 2500+の@1466MHz(定格では1833) L2=512kB (FSB266x11.0。この季節ですでに熱が...クーラー変更準備中。)で 24000〜24300ぐらい。
実メモリ15MB、ページング11MBくらい。あとはわからない。 C#もさわりの部分しかまだ使えてないので こいつ試しに組んでたとき、表示の更新やるところで固まったりした。 たぶんデッドロックがおきたのだと思う。 メインフォーム上のテキストに書き戻す文字列ははローカル変数にいったん格納して、 クリティカルセッションはって纏めて更新するようにしたらまともに動いた。 どうせワーカースレッドひとつだけだと思って甘く見ていたのがまずかった。 検索してないときでもこいつ1プロセスで5スレッドは動いてるっぽい。 (検索中はワーカースレッド1個立ち上げてるから6スレッド) ちなみにうちのPenM1.5GHzで30900/sくらいですが とりあえずAthlonXPに比べてPenMの性能がかなりいいことについての仮説 ・L2の帯域・レイテンシ依存?(オリジナルのコードではあり得ないけど) ・キャッシュのアソシエイティビティ(あり得る)
276 :
274 :2005/04/23(土) 01:39:34
他のアプリを閉じて、 NISも無効にしてから測り直したら、 24400〜24500付近、平均は24470ぐらいになった。 PentiumMに比べて遅い理由は、メモリのバンド幅じゃないかと。 AthlonXPの場合、2500+などはDDR333のFSBで、 デュアルチャンネルに対応しない。 こちらのダウンクロック版に至っては、 FSB266だから、PenMの半分だ。 しかも、L2も、512kBと、PenMの半分(旧PenM比)〜 1/4(現PenM比)と少ない。 PenMに負けても、 「こりゃあ、しかたないな。」という感じかも。
PentiumM725は通常シングルチャネルDDR333がMAXだで
JavaもPenMがPen4とかにくらべて圧倒的に早い やはり中間言語系はPenMか 今後のトレンドもCじゃないのでこれはこれでいいだろう あとCネイティブ版との差とVMの実行オプションが.NETにはみつからんかった 実行時コンパイルがあるのでJavaのようにチューニングできるといいのだが このへんは.NETはまだまだ進んでいないということだろうか
279 :
274 :2005/04/23(土) 12:59:32
PenMって、CPU - チップセット間は、 QDR400かQDR533でしょ。 チップセット-メモリ間はDDR333が最大? AthlonXPの2500+は、 CPU-チップセット間がDDR333。 3200+(AthlonXPの最速)でも、DDR400。
つい最近出た最新のExpressチップセット以前は855GMEが最高峰 これはシングルチャネルのDDR266かDDR333が限界 バスクロックは400MHzまでだな しかも統合チップセットが95%なのでメモリ大域的には不利なことが多い その分キャッシュ周りとかの強化が昔から多かった モバイル系はPen3やPen4,Celeron等デスクトップの倍あったわけで 意外とこれが貢献していたが
WinXPx64版はインラインアセンブラ不可能とかx87不可か
.NETはそもそもタイムクリティカルな処理はネイティブコードで書いたDLLを呼んでください、みたいな仕様なあたり、 Javaほどには積極的にプロファイルによる最適化をする気がないようにも思える。
いつかは通るであろう64bitへの完全移行 中間言語系はこれが強いな・・・ だからUnix系ではjavaが当たり前か
284 :
デフォルトの名無しさん :2005/04/24(日) 18:27:19
>>285 Pen4の新イベントカウンタには対応してないのか・・・。
対応してないとどうなるかと試したら、 エラーメッセージのダイアログを閉じた瞬間に BIOSの初期化中だった。 再起動後も何か残っていて不安定だったし。 Athlonの人は試さないように。
つか、Intelの開発ドキュメントやMSDNでも散々既出だったし
>>284 の223書いたの実は俺だったりする
>>287 Athlonには最強のCodeAnalystがあるから必要ないさ!
290 :
1 :2005/04/26(火) 13:02:50
>>236 386で挫折・・・何かカコイイ。
俺は結局、Windows上でインラインアセンブラを使ってしかCPU叩いてないんだよな。
「んなもん叩いてる内に入らん」とか言われそうだ。
CPU関係のスレでRISCの話を読んでたら、
x86命令が、x86CPUにハード実装された高級言語に思えてきた。
スレタイがx86なんだけど、他のCPUも知りたくなってくるね。
>>240 HT40%upさすがと思ってたら、オチにワロタ。
128KBのテーブルにランダムアクセスか。なるほどね。
クロック当たりの性能で比較してみたが、P3(L2on-die)・P4はストレートにコアの能力が出ている。
L2が128KBのCeleronは、惜しいけど遅いメモリアクセス(レイテンシがL2の20倍位)が入って沈没。
DuronはL1Data64KB、L2が排他64KB。やはり128KBギリギリなので少し足りず。
(L1命令が別にあるのでCeleronよりはマシか)
L2のレイテンシが大きなP2やK7は、P3の倍以上遅い。
しかしCeleronの方がもっと遅い。少しのL2ミスがこんなに痛いのだ。
>>261 Dothan-1.1で21500(対象が6桁)、24000(10桁)。
275のPenM1.5GHzってBaniasだよね?Dothanと同じ速さに見えるが。
モノがトリップ検索なので、ホットスポットは大してメモリ食ってないんじゃないかな。
中間言語系だとPenMのL1が8Wayってのが効くのかもしれん。
ちなみにTrip-Monaだと、189600trip/s。
291 :
1 :2005/04/26(火) 13:03:24
>>276 PM-725のFSBは400MHz。最新の915GM以前だとDDR333が最高。
メモリが遅いのにFSBだけ速くたって無意味。
逆にFSBが遅いときは、余ったメモリ帯域をチップセット内蔵ビデオに有効利用できる。
また、メモリでも、帯域よりレイテンシが重要な処理だと思う。
単純にL2のレイテンシが大きいだけかと。
>>284 80bitの拡張精度FPUは消えていくのだろうか。
ちょっと精度を伸ばしたいときに便利だったのにな。
VC++も80bit使うコードは吐いてくれないし、拡張精度はもうFPUの盲腸だな。
MMXとFPUが使われなくなると、Pentium4にはかなり有利になる。
どちらも遅かった。
もっとも、あと数年でNetBurstは消えるんだっけ。
>>289 うらやましいぞ、こんちくしょう。
292 :
1 :2005/04/26(火) 13:03:59
ランダムリードの実験。 [esi]には8の倍数な乱数が入っている。そこの値([esi]自身だけど)を足していくコード。 あらかじめesiからのメモリにアクセスして、キャッシュに乗るだけ乗せておく。 lp: dec ecx mov edx,[esi+ecx*4] paddd mm0,[esi+edx] jnz lp 乱数の上限を変えることで、L1・L2・メモリのランダムリード性能を測定する。 L1が32KB、L2が2MB、メモリはPC2100。cpu-zでのレイテンシはL2:10、メモリ:169。 ecx=1000で開始。 乱数の上限が16KB〜256MBまで、倍々にしていった結果(clk)。区切りは、L1 / L2 / メモリ。 2020 2087 / 3301 4191 4703 5012 6504 8406 / 53084 81613 109998 144810 187812 226188 254978 L1ヒットだと2Load 2clkの理論値。 L2ヒットだと、やや幅がある。L1ヒットの確率も低くないが、だんだんclk数が増えていくのが謎。 キャッシュヒットしないと急に遅くなる。4MB(半分近くL2ヒットしてるはず)で53clk/loop。 これも「だんだん」遅くなっていく理由がわからん。 ecx=1000000で4MB〜256MBまでやってみると、 55 81 91 97 98 99 102(clk/loop) これはわかりやすい。メモリの(隠蔽できない)レイテンシが100clk程で、L2ヒットした分速くなる。 繰り返し回数が多いと「だんだん」現象が起こらない。何なんだ。
293 :
1 :2005/04/26(火) 13:04:32
ecx=1にすると、またわからない結果が。 L1ヒットで2clkはOK。 L2ヒットでは6clkだが、1MB以上だと急に18clkになる。 メインメモリだと、159clkから1000clkオーバーまでバラバラ。だんだん増えていく傾向はある。 ちなみにシーケンシャルリードならメモリも5.6clk/8byteLoad。 プリフェッチなしのL2が2clk/8byteLoadだからけっこうな帯域。まあ、コアが1.1GHzだけど。 (HWプリフェッチは有り) 64byteおきにロードするとL2が6.1clk/Load。これは以前やった。 メモリは40clk/Loadだった。64byteのキャッシュラインを40clkで満たすなら妥当なところ。 prefetcht0 [esi+512] を使うとL2が1.5clk/Load、メモリが5.0clk/Loadまでいった。 この5.0clkに8を掛けると40になる。多分40clkで64byte転送でOK。 メモリに対してはなぜかmov eax,[esi+512] プリフェッチが全く効かなかった。 ストアは18clk/8byte。 prefetcht0を入れても、L2の効く範囲しか速くならないが、prefetchntaにすると12clk/8byte。 プリフェッチをやめてmovntq(キャッシュを通さずメモリに書き込む)を使うと、 5clk/8byteになり、ロードとほぼ同じ帯域で書ける。 普通にmovqでストアすると、 まずメモリからL1に読み込み、そこに書き込んで、L2に追い出され、メモリに書き戻す、 という手順を踏む。 ライトスルー方式のキャッシュだとどうだろ。常にmovntqなのか、読み込むのか。 ライトアロケートが付いてるかどうかか? prefetchntaはL2を使わないので効果があったのだろう。 movntqだと余計な読み込みがないので速い。 ただし、書き込んだものを読もうとしてもキャッシュに乗ってないのであしからず。
movはプリフェッチじゃなくてOoO実行しているだけじゃないの?
295 :
1 :2005/04/26(火) 14:32:24
>>294 俺は
>>153 のように思っていたのだが。
実際、L2からL1へのプリフェッチとしてはprefetcht0よりも高速に動作した。
なんでだろうなー。
ぶっちゃけるとPentiumMとか(最近はNetburstでもか)IESTで可変クロックだから いろいろとおかしい値が出ることはある
297 :
276 :2005/04/27(水) 00:26:14
AthlonXPだと、L2のLatencyが13cykleもあるので PenMより遅いというわけかな。
ロード帯域も関係してくるかも。 あと排他処理でVictimBufferに待避されたL1のキャッシュラインをL2に書き戻してる最中のフェッチなら13程度じゃ済まないでしょ。 ちなみにPentium MのL2ロード帯域は256KBでmovq4回分 レイテンシはBaniasで8クロック、Dothanで9クロック。
AthlonXPのL2キャッシュのバス幅が64ビットというのも影響してるのかな? AMD64ではL2のバス幅は拡がったのかなあ?ぐぐってもあまり資料がない。
定番だけどloadbench 改造してmovdqaのも調べてみた load 帯域 計測ツール v0.4 CPU動作クロック : 1498.7 MHz アクセス範囲 Int32bit Float64bit MMX64bit SSE128bit SSE2128bit 1KB : 5582 MB/S 7895 MB/S 11167 MB/S 11297 MB/S 11325 MB/S 2KB : 5583 MB/S 7896 MB/S 11166 MB/S 11289 MB/S 11325 MB/S 4KB : 5582 MB/S 7893 MB/S 11164 MB/S 11295 MB/S 11324 MB/S 8KB : 5581 MB/S 7894 MB/S 11167 MB/S 11290 MB/S 11325 MB/S 16KB : 5580 MB/S 7895 MB/S 11166 MB/S 11297 MB/S 11324 MB/S 32KB : 5583 MB/S 7907 MB/S 11165 MB/S 11256 MB/S 11303 MB/S 64KB : 3796 MB/S 6507 MB/S 6523 MB/S 6507 MB/S 6508 MB/S 128KB : 3795 MB/S 6521 MB/S 6507 MB/S 6525 MB/S 6507 MB/S 256KB : 3797 MB/S 6508 MB/S 6515 MB/S 6526 MB/S 6520 MB/S 512KB : 3795 MB/S 6505 MB/S 6505 MB/S 6522 MB/S 6503 MB/S 1024KB : 3634 MB/S 6110 MB/S 6128 MB/S 6126 MB/S 6124 MB/S 2048KB : 1466 MB/S 1927 MB/S 2070 MB/S 2069 MB/S 2070 MB/S 4096KB : 1458 MB/S 1852 MB/S 1960 MB/S 1955 MB/S 1955 MB/S 8192KB : 1456 MB/S 1848 MB/S 1955 MB/S 1942 MB/S 1944 MB/S 16384KB : 1454 MB/S 1849 MB/S 1955 MB/S 1942 MB/S 1942 MB/S 32768KB : 1454 MB/S 1849 MB/S 1955 MB/S 1940 MB/S 1941 MB/S 実に気持ちの悪い結果だ
303 :
1 :2005/04/27(水) 11:00:03
>>296 さすがにキャッシュ外の測定では最高クロック固定でやってるよ。
ここはキャッシュ管理の複雑さが所要クロックに出ているのだろう。詳しいとこ知りたいね。
ROBやL/Sバッファもあるな。よくわかんないけど。
そういえば、P4はコンパイルして2回目以降の実行クロックがめちゃくちゃだった。
なんかビルドしたてじゃないと遅くなるの。
>>298 ビクティムバッファとは久しぶりに聞いたな。
Athlonも最近のはL2を1MB積んでるんだし、もう排他にするメリットがないと思うのだが。
トリップ検索では、それはもう次々にL1ミスL2ヒットするので排他式にはきついと思われ。
で、Dothanの256bit9clkというのは何が9clkなんだろうね。
前に聞いたのは、Athlonが64bitフルスピード、河童が256bitハーフなので河童が倍速い、だった。
Athlon64が128bitなら速くなってるんだけど、Loadbenchの結果見ると8byte/clkには程遠い。
最近のCPUはキャッシュラインが64byteだが、何clkでフィルできるんだろう。
>>301 普通の結果じゃないの?
加算だけなら32bitの整数レジスタで簡単に固定小数できることに気づいた。
floatは32bit中8bitを指数に使っているので割と簡単に同等以上の精度が出せる。
水面のシミュ(2次元の波)では加算だけでいいのでCレベルではかなり速くなった。
64bitALUがまともに実装されてきたら面白そう。
まあ、その頃にはFPUも強化されてるだろうけど。
>>303 最近のは1Mということではなく
1Mと512Kと2つ容易しておいて同クロックでレートを下げて販売戦略
おかげで同じレートでもクロックが違ったりキャッシュ容量が異なるので厄介
ソフトによって下位レートが上回ることももちろんあるし
>>303 Cで固定小数点小数やるのは、書き方が回りくどくなるからねぇ。
…汗んブラでもメンドくさいことには変わりないワケだが。
このへんは趣味でも業務でもやったので蘊蓄垂れれるが
あまり書くと擦れ違いなので割愛。
トリップ云々も蘊蓄垂れるとキリがないので割(ry
ていうかここ何のスレだっけ?
>>1 の勉強部屋?
時々良ネタを持ってきてくれるから見てるけど。
昔を懐かしむスレです
307 :
1 :2005/04/27(水) 11:37:42
>>305 加算だけなので、FPU使うのとほぼ同じソースでいける。
(数個のシフトを入れただけ)
確かにおいらが勉強させてもらってまつ。その点は感謝。
てか本来どうあるべきスレ?
>>307 x86命令の所要クロックを計測するスレだろww
…ってだけではネタが尽きると思うので、マイクロアーキテクチャから
最適化まで、果ては昔話とか「近頃の若いモンは」グチなど
なんでもありでいいんでわ? と思う。
もうすぐ新しいオモチャを入手するので、遊ぶ機会ができたら寝た振りするわ。
>>303 気持ち悪いと思ったのは普段絶対遅いはずのSSE*命令であるmovaps/mopvdqa のほうがなまじmovqより速いから。
Opteronもこのベンチだとmovapsで十分な速度が出る模様。
ひとつ訂正。L2単体のものではなくL1キャッシュからのロード試行にかかるサイクルからカウントした実質レイテンシです
これだとBanias8→9, Dothan 9→10ですね。訂正
K8はL1の3クロックとL2単体の8クロック、プラス1クロック(何なの?)の計12クロックくらいで帳尻が合いそうな。
これもVictimBuffer空の場合のベストケースだろうけど。
スレ違い
全部読んだけど理解できたのはほんの少し。 ここに来ている方々は戦乱の時代を過ごしてきた猛者の棲家に見える。
>ここに来ている方々は >戦乱の時代を過ごしてきた猛者の棲家に見える 我々は家に見えるらしい。せめて人間らしく見られたいものだ。
正直、パソコンの使用者が増え、相対的に「パソコンの中の人」の立場に なって物を考えられる人が劇的に減少した。ソフトウェアの複雑化で、 ハードウェアに寄せられる興味が減少した事も原因としてある。
というか、 CPUの中を気にせずにプログラムを書いてもよくなったし、 そもそも、なるべく低レベルのことは隠蔽しないと、大きなシステムは作れない。 今時のアプリケーションは、昔からすると恐ろしく巨大で複雑なシステムですよ。
仮想メモリあつかったりしてすでにネイティブ度はあまりないんだけどな 今後もどんどん仮想化は進む
むしろ、プリミティブな部分しかわからず、 エンタープライズ・ジャバうんたらかんたらとか言われても、さぱーりさぱーりで。
ぶっちゃけ、いくらアセンブラでガリガリに書けてもスレッドアンセーフなコード書く人は 負けかなと思っている。
データストレージをスタックにとると、場合によってはアラインメントのずれの問題が起きるんだな が、グローバルにとるとスレッドアンセーフなコードの出来上がり TLS使うのも手だけど ヒープからとってきて手動でアラインメントあわせてやらないと安心できないのは俺だけかな。
シングルスレッドな環境ならそもそもスレッドアンセーフもへったくれもないわけだが。
>シングルスレッドな環境なら マルチコアCPUのリリースが相次ぐこのご時勢に マルチスレッド非対応アプリの話ですか はぁ 恐れ入りました
>>322 自分で(アセンブラで)OSの一つも組んだことない香具師に言われたくはないな。
つーか、8ビットCPUのアセンブラを使いこなすこともできないジャマイカ?
組み込み系の方ですか? いっぺん開発現場見たことありますが、RAM容量が限られてるから 変数をほとんどグローバルにとってたりしますよねあの手の人たちって いずれにしてもWindowsアプリケーション開発とほぼイコールな x86とはフィールドがぜんぜん違う話と思われ。 1からWindows同等のシステムを構築して、OracleやASPサーバを走らせてみることなんかできますか? 無理でしょ。 SIMDで高速化できる部位とTLPで高速化できる部位って基本的に被ってると思うのだけど。 マルチスレッド化を阻害しない限り命令レベル最適化も有効な手だとは思うけど TLPは単純計算でプロセッサ個数分のスループットは得られる(実際にはI/O待ちなどが 発生して単純n倍にはならない)ので、1割2割程度の小手先のチューニングよりは 優先させるべきではある、と思う。 現実問題としてMMX/SSEを使う以前にアルゴリズムがまずかったりする例も かなり多いと思うのだけど。 つか、今まさに、最適化はされてるけどスレッドアンセーフなコードの 書き直しをやってる(別に業務じゃないですが)わけですわ。
thread-safeなんて理想上の物であって現実には無理。 だから、意図しないところでヤバイ事が起こるのを防ぎましょうねってくらいに落ち着くんだけど、 それはアセンブラ云々のレベルで扱う事柄じゃないわけで。 スレ違いも甚だしいYonah..nWQはシカトの方向で。
>thread-safeなんて理想上の物であって現実には無理。 なんかおもしろい時代についていけないやつがわいてるな
>>320 そりゃお前さんがヘタレなだけ。
マルチスレッド・プログラミングが下手な人って、スレッド分割の設計が悪くて、
オブジェクトをすべからくスレッドセーフにする羽目になったりするんだよね。
もしくは、すべてスレッドセーフに書かないといけないと誤解しているか。
いや、すべからくスレッドセーフにしないと、まともに動かないコードを書いちゃうのかな。
細かい粒度でスレッドセーフにするのはオーバーヘッドが大きくて無駄だよ。
とかいうと、ジャイアントロックは無駄が多すぎるとか、飛躍したことを言われそうだが・・・。
水平分割でも垂直分割でも、
スレッド間のオブジェクトの共有をなるべく減らすのが基本原則だよ。
うちが今作業してるのは、単純に、複数のスレッドから、1つの関数を呼び出す際 グローバル変数を読み書きしてるので、是を全部スレッドローカルに持っていく作業。 単純にクラス化するだけで済みそうですが。 てか、ロックかけてシリアル化なんかやったらスレッド化する意味ないし。 もち他人の書いたコードですが。
糞コードの話を一般化されても困る
まぁたしかにそれはクソコードだしな
331 :
1 :2005/05/03(火) 13:01:20
>>314 ソフトウエアを複雑にするには、低級言語で開発していくわけにはいかない。
そのために複数のレイヤーを重ね、結果ハードが見えなくなるのは仕方ないだろう。
もちろん現在でも速度が必要でアセンブラを使うケースは存在する。
ただ、それとは別に、「CPUを自分で直接叩きたい」という欲求を満たす手段は確保しといてもらいたい。
インラインアセンブラ廃止って本当ですか。
慣れてる人ならそんなもの使わないでできるだろうけど、
表面的にでも低レベルなものが隠されると、PCってのが(ますます)萌えないものになってしまう。
マルチスレッドはMerom買ってから勉強しよかな(藁
とりあえず共有L2の使い方でかなりのネタになりそうだ。
>>329 アセンブラレベルの最適化はケースバイケースだから、
現場によって感覚が異なって自然だと思う。
>>310 楽そうと言うけど、具体的にどうやればいいの?
物理計算をやってくれるのは最近聞いたけど、
GPUメーカーの提供するライブラリを通して特定処理をやらせることになるだろう。
332 :
1 :2005/05/03(火) 13:02:07
BIOSでL2キャッシュを無効にしてみた。 Trip-Monaで10500trip/s。18倍も遅いよ。。 スーパーπは68秒→138秒。これは2倍。 エクスプローラも何か引っかかる感じ。これが「もっさり」か? メモリのロード帯域は、9.8clk/8byte。(L2有効では5.6clk) これはL2へのHWプリフェッチが効かないために遅くなったと思われる。 プリフェッチ命令を入れると、L2があるときと同じ5.0clk/8byteが出る。 ストア帯域は、17clk/8byte程度。わずか(1〜2clk)だが、L2有効より速い。 プリフェッチありだと12clk/8byte。movntqで5.0clk/8byte。これはL2ありと同じ。 次は、64byteおきに8byteのメモリアクセスをする。 ロードはL1ミスで60clk。 ストアは140clk前後。L1-メモリ間を64byteが往復しているはず。 L2有効の場合は、ストア150clk、ロード40clk。 ストアはキャッシュ処理のオーバーヘッドが少しだけあり、ロードはHWプリフェッチが効く。 キャッシュがあるとちょっと不利なストアだが、movntqを使えば33clkと激速い。 movnti(4byte)も33clk、movntdq(16byte)は66clk。 これは帯域の問題ではなく「内部命令数×33clk」ということだろうな。 64byteまとめてストアすれば、まとめて転送してくれるらしく、8byte*8が40clkで済む。 L2に書き込むときもL1が邪魔。L1を通さずにL2へ書き込む命令が欲しい。 ところで、movntdq・movntpd・movntpsに別々のマシン語を割り当てた意図がわからん。 てっきり同じ命令の別ニーモニックだと思ってた。 デコードがやりやすいのかな?
333 :
1 :2005/05/03(火) 13:03:07
mov eax,[mem]プリフェッチが効かないのは、実際に[mem]をフェッチするまでmov命令がリタイヤできないからだな。
L2程度のレイテンシは隠せても、メモリのレイテンシを待ってたらROBもロードバッファも詰まってしまう。
・・・と思ったんだけど、ロードバッファに5個程movを入れておけば済むわけで。やっぱ謎。
(5≒レイテンシ170÷キャッシュライン読み込みのクロック40)
で、L1も無効にしてみたのだが、WindowsXPの起動に20分くらいかかり、
VCも待てど暮らせど起動しそうにない。時間がなくなったので電源落として設定を戻した。
今更だが、キャッシュって偉大だな。
測るとしたら、あらかじめ計測プログラムを用意しておくしかない。
>>309 SSE*命令だが、そこまで遅くはないと思う。
movdqu xmm0,[esi]
movdqu xmm1,[esi+16]
movdqu xmm0,[esi+32]
movdqu xmm1,[esi+48]
add esi,64
dec ecx
jnz lp
こんなコードでもL1ヒットで8clk/loop出る。L2が16clk/loopとやや遅いが、メモリ帯域は同じ。
デコードが1命令/clkになってしまうことが多いが、実行に時間のかかる命令が多いので
ネックになるケースは少ない。
SSE*で痛いのは、xmmレジスタとメモリのやりとりに16byteアライメントを要求されること。
そうじゃないとLoad & opもできないし、movdquは若干だが遅い。
逆に言えば、アライメントさえ合っていれば、多くの場合SSEはMMXと同等の速度が出る。
不明なのがL1ヒット時のmovdquストアの遅さ。
16byteのストアに4clk以上もかかる。
>>331 ハードウェアを触って楽しむならPC止めないとダメだな
もしくはOSなし状態で
俺は直接触って楽しむ楽しみは仮想記憶が入ってから止めた
昔はDMAコントローラガリガリとかやってたころは楽しかった
ソフトウェアを楽しむという意味ではいかにラッピングして
使いやすいクラスライブラリを整備するか、という点が面白い
あとキャッシュを切ると言うのは意味なし
なんせキャッシュが効いているというのを前提に作られてるから
別にヒット率とかそういう意味ではなくてバースト転送とかが
そのへんべったりだからキャッシュがありなしで何倍という数値には意味がない
2次キャッシュなしでも早く動くようなコントローラ積んでる石はもうない
486の頃ですら、キャッシュを切ると386よりも遅かったな。
337 :
1 :2005/05/04(水) 15:58:26
>>334 >PC止めないとダメだな
悔しいが同意。OSまかせの仮想化が進んでるからな。
さりとてOS書くような技術もなし。
キャッシュを切る意味がないというのは、
ハードがキャッシュを前提としているから、キャッシュを切ると必要以上に遅くなるってことか。
L1に関してはそうだと思う。
L1キャッシュを使わないメモリアクセスは今のCPUにとって余りにも不自然だ。
でも、L2を切ることは、L2の役割を知るという意味があると思う。
実際、L2がなくてもちゃんと「0MBのL2を積んだPenM」になってるように見えたし。
逆にL2がないとHWプリフェッチが効かないのがわかったりもする。
ぶっちゃけL1の場合でも、どの程度「べったり」なのかを知るという意味はある。
L1はL2を前提に作られているとなぜ思わないのだ?
339 :
1 :2005/05/04(水) 18:42:04
>>338 測定してきた経験やIntelの資料からそう思った。
338も、そう思わない?
だれもおもわんだろ
OSだって、アセンブラで書くのは、本当にごく一部だよ。
その記事おかしいよな クロック勝負なのはいいが、汎用化されればその分固定化されたハードと違って 並列動作が期待しにくいから性能がクロックどおりには上がるまい すでにチップの面積とか販売される数、価格を考えてもかなり厳しいのに 正直Pentium4をCeleronの価格でうってるよーなものだよ
GPUでのSIMD演算の利点はピクセル単位で並列処理されるのと HLSLなんかで処理を書けばいいので簡単ってところだね。 それにただでさえCPUに比べて圧倒的な演算能力があるのに 今後はShaderアレイの数が増えてどんどん並列化が進むから 今からGPUを使う事を考えるのは悪くない。
チラシの裏 1. 現実問題Cで書いてるコードって大概、グローバル変数直読み書きしてるもの多いんだわな 現実的にはC++クラス化が一番確実だったり。 Boostなんかはよく出来てる。 regexのconstなオブジェクトを複数スレッドから参照してみる実験やってみた ドキュメントどおりまったく問題なく動作する。 C++の模範的なコーディングポリシーに則って設計したコードは そのまんまスレッド化できるような気がする。 要はメモリ管理の手間を惜しまなければ良いらしい。 Crypto++というSIMD命令を多用した暗号化クラスライブラリがあるが こいつはスレッドセーフかつ、速度に妥協しないために使った各CPU依存のコードを うまくラップし、なおかつクロスプラットフォームなライブラリの模範としてかなり面白い。 2. あとQueryPerformanceCounterってRDTSCのラッパーなのね 可変クロックじゃ使えねーじゃん でもSpeedStepでクロック落としてみても正しく秒数を計測できた(かのように見えただけ?) という経験ががあるが、何か落とし穴あり? ベースクロックさえ変わらなければ倍率変わってもOKな仕様なら敏感になる必要ないのかもしれないが。 3. Win32のスレッド調停関連APIのInterlocked〜の組み込み関数版を使うとincとかdec, xchgなどの 単純な命令に展開されるようだ。 これらの命令はタイムスライスしても実行完了か未実行かが保証されるから マルチスレッドでの使用に耐え得るらしい。ちょっと感動。
てかGPUを使うっつーてもWinアプリから気軽にネイチブ叩けるものぢゃないでしょ。 仮に使えるにしてもどうせGPU専用のコード書いてデバドラ書いてデータの受け渡しでそ? いくらなんでもそれはまんどくさー 互換性の問題もあるし結局DirectX叩けって話になるわけで Cell用のプログラムコードはどうなってるのか気になる。Power互換なのは真ん中のコアだけらしいが。
そーいやDirectX9でGPUからメモリへのデータ転送がめっちゃ速くなったという話があったような
でも年々統合チップセットのシェアが上がっている現状では ビデオチップにまかせるというのは厳しいような
で、Crypto++はx86特有のとこよくみたらinteger.cppだけですたね。しかもSSE使ってませんですた。カン違い
こっちですね。
Hacker's DelightでみたようなコードがそのままSSE2に移植されてたり
http://bmagic.sourceforge.net/ ビットカウントってそんなに需要あるアルゴリズムなのだろうか
>>346 Cellのマルチコアは他のタスクを気にしなくていいという時点で
PCと比べる意味はないな
>>345 1. 複数のスレッドから使われないグローバル変数は構わない
つーか、グローバル変数をプロセス全体で共有するために使っているのは、構わないだろ。
そうでないのは、そりゃ糞なだけだ。
何でもかんでもスレッドセーフにしてたらオーバーヘッドが無駄無駄無駄
2. クロックが変わったらQueryPerformanceFreqencyが変わるんじゃないか?
ちなみに単なるRDTSCのラッパーじゃないぞ。
単なるラッパーで1kクロックも消費するかよ。
3. 単なるincで良ければ、なにもInterlocked〜なんて必要ないだろ。
お前は本当にレベルが低いな。
>>351 の1
マルチスレッドでの話しなんじゃねーの?
開発者が複数いる場合単純にグローバル変数を使うのはあまりにも愚か
おもいらスレ違い杉
関係ないけどスレ違いとかいい始める奴がいると大抵は荒れる。
というわけで
>>353 は氏ねとか書いて見る。
>>351 1. まあ糞なだけのコードを弄ってたんでしょうな俺は
2. 〜Frequencyは先頭で1回だけしか呼び出してないとしても?
ちなみにこんなコード
QueryPerformanceFrequency(&freq) ;
QueryPerformanceCounter(&time1) ;
whiile (hogehoge) {
//
//何かの処理
//
QueryPerformanceCounter(&time2) ;
cout << ((double) (time2 -time1)) / (freq * 1000000.0) << endl;
time1 = time2 ;
}
バッテリーモードにしたらクロック落ちる設定にして作動中にACアダプタぶっこぬいて
みたけどやっぽりそれでも正しくカウントされてるっぽい。
rdtsc直接使ったときは調べてない。
3. インラインasm文使うと前後に無駄にレジスタ待避のコードが追加されるんですが?
移植性(あくまでWindows同士)の面からしても良いとは言えない。
関係あるけど阿呆な固定が出てくると荒れ始める。
まあアレだ、◆Yonah..nWQ shineと。
>>355 __declspec(naked)
>>355 3番だが・・・
変数1つincするだけなら、レジスタ退避のコードなんて追加されないぞ。
デメリットは、最適化を阻害するということだ。
つーか、誰がそんな話をした。
単なるincなら、++で生成されるだろが。
まぁとにかく、
InterlockedIncrementが単なるincだと思ってることは許せない。
お前にマルチスレッドのプログラムをいじる資格はない。
デバッガでステップ実行してみろよ。
lockプレフィックスつけてxaddしてるだろがボケ。
↓チラシの裏 確かに。 でも厳密に言えば俺が言ったのは _Interlocked〜 だし、 ~ まあいいですけどね。 でも、許そうが許すまいが、弄る資格云々なんてあーたが決めることじゃないっしょ。 スレッド間共有してる変数を書き換えるときはAPIを使って排他ロックかけるという原則を、 こちとらべつに拙い憶測をもって破ろうってんじゃないんだから。 OSベンダが安全性を保障してくれてるAPIを使わずに敢えてトリッキーなことをやる必要も 無いわけだし、CPU依存の命令を極力直叩きしなければ、モバイルからIA64まで Windows間のソース移植性は高まるわけで x64移植を見越してSSE2のコードも全部Intrinsicsで書いてたりするし、かなり移植性や 流用性には拘りを持ってますが。その意味でどこからでも書き込める変数作るのは嫌い、と。 てか「お仕事」ではASMどころかWinAPIすら叩かないし、言うだけ言って実行はしない 人間なので被害者は居ませんよ、ってことで。つか、いちおうこれでもたとえば while (GetMessage(lpMsg, hWnd, 0, 0)) { DispatchMessage(lpMsg) ;} が一目で間違いだとは解る人間ですので。
リバースエンジニアリングしたわけでもないので怪しい情報ではあるが 各省電力機能のクロック切り替えを実際に指示しているのは 基本的にはソフト側らしいので そっちに制御を渡さなければ切り替わらないし、 切り替えの頻度も高くはなさそうだ
スレ違いだからどっか他んとこでやれや チラシの裏とか抜かしてんじゃねえ
>>358 だから、デバッガでステップ実行してみろって。
_InterlockedIncrement
でインライン展開されるコードでもlock xaddだぞ。
362 :
1 :2005/05/10(火) 12:19:55
>>342 thx.
でもそっち方面はよくわからない。すまん。
現状ではCPUの方がいいんだよね?
その次世代GPUとやらも、やっぱりGPUであって、グラフィックに無関係な処理は想定してないだろ。
対象が32bit float程度で処理だってプログラマブルとはいってもCPUとは別物、
あまり使い道がないように思う。
128bitのSSEでさえ「小回り効かねえよ糞」とか思うのに、
モバイルで2GHzのデュアルコアが出る時代に1GHzの爆熱GPUでSIMDしてもって気はする。
ピーク能力はGPUがずっと上ってのはわかるけど。
どっちにしろ342の目的次第だ。もちろん俺もSIMD演算が高速にできるなら方法を知りたい。
設計思想としては「低クロック小回り効かないけどすごい量の並列演算」なGPUだが、
扱うデータ・演算が限られているからできる芸当。
逆に言えば、特定のケースではGPUで圧倒的な高速処理が可能な潜在能力はある。
ラクに叩けるようにハードとAPIを整備してくれたらよさげ。
ただ、
>>348 の言うように激しく環境依存になりそう。
>>350 CellのSPEは、PCのマルチコアってよりも、超強力・大がかりなSSEって感じに思えてきた。
タスクスイッチ考えなくていいのは強みだよな。
Windows用x86でも、「1スレッドだけが使える」とか制限つければいけるよな。
どうせ動画エンコぐらいしかしないんだから実用になるだろ。
#まあ、本気でそう思うわけじゃないが。
でもそう考えるとx86のヘテロジニアスマルチコアってCellとは全く別物になりそうだな。
てか346の文脈だとGPU=SPEの位置づけだろーが。
タスクスイッチでVRAM退避させたりしないよね。
そもそもCellとx86じゃなくて、x86にとってのGPUとCellにとってのSPEを比べてるんじゃない?
>>345 2.(QueryPerformanceCounterをQPCと略す)
QPCはrdtsc使ってるのにQPCとrdtscでCPUの動作周波数が測れるYO!
プログラムを作って確かめた。
QPCで時間、rdtscでクロックを得ている。
http://www.uplo.net/souko/vip1972.zip 俺の環境だとFreqencyは3579545。
CPUのクロックを600MHzにしても1.1GHzにしても変わらない。
更に、負荷がなくなるとCPUは省電力のためにクロック自体を止める(rdtscの値が止まる)が、
そのときも変わらずQPCは動いている。
カウンタのペースが変動しまくりのrdtscだけで時間が測れるわけがない。
QPCはどこからか時間を得ているはずだが、じゃあ何のためにrdtscを使っているのだ?
>>359 初代SpeedStepはクロック固定。2代目は対応OSの指示で動的にクロック変更。
PentiumMは3代目で、CPU自身が負荷を見てクロックを変える。
つまりOSの知らない所で勝手にクロックを切り替えている。
上の測定プログラムでグラフ表示にすると頻繁に切り替わってるのがわかるよ。
364 :
1 :2005/05/10(火) 12:26:21
メモリレイテンシの測定。 ロードバッファに多くの命令を溜め込まれてはレイテンシが隠蔽されてしまうので、 次に読むべきアドレスをメモリ上に置くことで完全な依存チェーンを作る。 mov eax,esi lp: mov eax,[eax] dec ecx jnz lp [esi]から確保してあるメモリには、*eax==eax+64 となるように数値を入れておく。 ecxの繰り返し回数を変えることで色々なサイズのメモリに対する測定ができる。 (要するに、(ecx*64)byteの領域に対して4byteのLoadを64byteおきにecx回している) 64byteおきなのは、キャッシュに収まらないデータのとき必ずミスヒットさせるため。 キャッシュラインサイズが64byteね。 L1:3clk/loop。 L2:15.1〜10.4clk/loop。アクセス範囲が広いほど速い。 メモリ:68〜45clk/loop。これもL2と同様、なぜか広いほど速い。 規則的なアクセスなので、HWプリフェッチが効いている点も注意。 結果はアンロールしても変わらなかった。 なんか今まで意識してなかったL1のレイテンシが見えて嬉しい。文句なし3clkレイテンシだ。 つーかこの測定コード思いついたあとloadbenchのlatencyのソース見たら、 mov eax,[eax]が、だーっと並んでるよ。 以前ながめたときに一体何を考えてたんだ俺は。自分のわからないコードはスルーかよ。
365 :
1 :2005/05/10(火) 12:26:54
L2はレイテンシ10+何か。メモリも45+何かに見える。 ちなみに、メモリの結果から44.5を引いた数字を4MB〜256MBまで並べると、 23.9 18.2 10.2 5.0 2.4 1.2 0.6 左の方はL2が効いて速かったとでも解釈して、右の方は見事に半分半分となっている。 L2のもそうだった。 アクセス量を倍にするとループ当たりの「何か」が半分になる→「何か」自体のclk数は一定 と推測される。 更に、64KBの結果が15.1clkで理論値である10clkの1.5倍(=半分の3倍)であることから 32KB分の処理の3倍、つまり32KBLoad*2+32KBStoreを思いつく。 結論を言うと、準備した[esi]の最後の部分がL1止まりで未だL2へ退避してなかったのが原因。 最初に[eax]を読むときに、L2のデータをL1に移動するが、そのときのL1にあるデータはL2にない。 だからライトバック後のLoadとなって、最初の32KBは倍の時間がかかったというわけだ。 メモリの方は、「何か」のclk数を計算すると80clk*2MB/64byteだった。 以前の実験では40clkで64byteの帯域だったので、単純計算より倍遅いことになる。 プログラムを修正してライトバックが起きないようにしたら、 L2のclk数はきれいに10clkぴったりとなったが、メモリは4MB時で60clk前後と遅い。 16MB以上では、44.5clkでほぼ一定となっているので別の要因がかんでいる。 キャッシュ階層が2つあることによるオーバーヘッドか、HWプリフェッチ関係かだと思うがわからない。
366 :
1 :2005/05/10(火) 12:28:26
次に、FFTを想定したメモリアクセスで実験。 番地が0、4、2、6、1、5、3、7というようにアクセスする。CPUにとっては多分ランダムに近い。 (そういうアクセスするように[esi]をセットするの大変だったよ) 測定ルーチンは上と同じ。 結果は、L1:3clk、L2:10clk、メモリ:211〜215clk。 この測定でも、同じメモリは1回しか読まないので、基本的に必ずキャッシュを外す。 これをL2を無効にしてやってみた。 L1:3clk、メモリ:182〜185clk。メモリ64MB以上:360clk。 速くなっている。 L2が有効でも、L2にないメモリを読むときはL2を通さずにL1へ読むはずだが、 その読んだデータがL1を追い出されるとき、L2にないので破棄されずにL2へ転送されてしまう。 そのオーバーヘッドかも。movntqのLoad版が欲しいぜ。 HWプリフェッチが邪魔になっていたというのも考えられる。 64MBで遅くなったのは、32MB分も離れた反復横跳びメモリアクセスが半分を占めるため、 DRAMかメモリコントローラの構造上レイテンシが増えたんじゃないかと推測。 L2が有効だと遅くならないのだが、これはHWプリフェッチ以外に原因がなさそうなので それが原因なのかな。 平常時で215-185=30clk程遅い。215clkを丸々プリフェッチに使っても、せいぜい320byte程度。 360clkというのが遅すぎなだけなのか? 64byteおきのも測定すると、メモリ:159clk。 L2有効なら44.5clkなので、これは大負け。HWプリフェッチの力だ。 「HWプリフェッチの裏をかく」ってのもやってみたいな。 勝手にプリフェッチされるので、それが邪魔になるケースは存在するはず。 メモリの実験中はSpeedStepが使えないからファンがうるさい。
>>361 デバッガでステップ実行しなくても、コンパイラの出力を見るだけでいいと思うけど・・・。
_InterlockedIncrementを単なるincにしてしまうコンパイラがあるなら、
コンパイラの名前を知りたいです。ぜひ教えてください。
>>362 GPUの演算機は徐々に汎用性を高めつつある。
次の9.0d(?)世代で、DSPとして使えるほどの汎用性を
付けようってことじゃないかと。
多数の演算機が並列実行できることも合わせて考えると、
クロックでCPUを下回っていても、総演算量ではCPUを上回るのでは。
まあ、現状では、動作クロックだけではなく、
データ転送のオーバーヘッドもあるし、まだまだ使いにくいのだろう。
たぶん
>>362 はノートPCを考えてるからWGF2.0世代のGPUなんか
ノートに載せて使えるかって事なんでしょ。
しかしデスクトップで最新のCPUとGPUを積んだらおそらくGPU使ったほうが
SIMD演算は速いだろうね。
640*480の画面全体に1枚のポリゴンを表示すると640*480=307200ピクセルを
出来るだけ並列演算するわけで、それを1フレに何枚も処理出来る事を
考えると速いなぁーと思う。
最近流行りの物理演算をGPUにやらせようってのもうなずける。
とっくのむかしにデスクトップよりノートが販売数うわまわってるし 流行のTV機能付省スペースデスクトップはPentiumM搭載とかふつーにある ビデオ視聴するのにファンは邪魔だからねぇ ノートベースで考えるのも必要では?
371 :
1 :2005/05/11(水) 11:34:37
>>368 ハードの人ですか?おおかた同意。ていうか俺も同意見。
DSP並なら萌えるね〜。
>>369 デスクトップで1GHzGPUのパワーがあっても小回りが効かないから
結局Yonahにすら負ける(いわんやデスクトップ用CPU)ケースが多いだろ。
→わざわざGPU使う意味なし、って意味で書いた。
SSE使うのすら難しいのに、それより多並列のGPUを使えるケースは少ないだろうと。
てか、369といい、俺の論調がGPUを否定してるように見えたのかな。そうじゃないよ。
一応「ピーク能力はGPUがずっと上」「342の目的次第」って書いてたんだけど。
SIMD演算って具体的には何を指す?何をしたい?性能は激しく用途によるぞ。
こういうのは「○○という処理」をするのにCPUとGPUどっちがいいか、という
「○○」を言わないと、まるで生産性のない話になってしまう。
俺は、アセンブラで最適化するのが好きで、GPUの扱いを何も知らないから、
362みたいな論調になってしまい申し訳ない。
372 :
1 :2005/05/11(水) 11:35:31
CPUとGPUの違い 1.ピーク性能はGPUが圧倒的に上(チップセット内蔵などはこの限りでない) 2.GPUが性能を発揮できる処理はSSEやデュアルコアと比べて少ないと思う 3.現状でGPUを叩くことは、API(使いやすさ)・ハード(効率)のサポートがない 4.GPUの性能・種類はPCによって大きく異なる 例えば、物理演算がGPUの仕事になっていくのは自然だ。3Dゲームで使うから。 「3Dゲームのための」物理演算は1.の利点がある上に2.3.4.が問題にならない。 で、これは完全にGPU側の話題で、このスレとは関係のない分野だ。 3.は将来的に解決されるかもしれない。 それはメーカーがGPUをグラフィック以外の用途でCPUから叩かれることを前提に 作るようになることを意味する。 そのためには2.4.の問題にある程度見通しが付いていないといけない。 2.動画エンコ・画像フィルタ・重力シミュ・FFTなど、できる? 4.はB5ノート使いとしてはやっぱり悔しいところ。 うまくAPIでラップして、チップ内蔵だろうが「遅いけど動く」ようにして欲しい。 CPUとGPU並列動作(今思いついたんだけど、これはいいなあ)とかも遊べそうだし。 ぶっちゃけですね、 2.の問題をろくに考えもせず、アセンブラで最適化することもせず、 「ピーク性能は元々高い上に汎用性も高まり、GPU使えば速そう」 と、何となく思っている。 そういうニオイを感じたのでGPUに文句ばっかりつけてたのかも。 思い過ごしかね。 なにぶん、GPUについての知識が皆無で書いたから的外れだったらごめん。ほんとに。
入力も出力もデータ量が比較的少なく それでいて計算量が多いが それほど複雑ではなく GPU処理完了待ちによる遅延が問題にならない処理
374 :
1 :2005/05/11(水) 12:37:35
(;´Д`)・・・ていうか本当に何のスレだっけ。
昔サブCPUボードとかDSPボードをいじった人ならたぶんわかるだろう 結局マルチスレッドでやるのとかわらんよ ただ、メモリ転送がどこかではいるのでオーバーヘッドが大きい ゲームとかはGPUはビデオのほうだけに専念してほしいという場合もあるだろう リアルタイム性が必要とされない場所でならそれなりに普及しそうだが 比較的扱いやすいMMXやSSEがほんの一部でしか使われてないことを考えるとどうだろうね マルチコアもあるしどっちにころんでも並列処理がかけない人はもうだめだろうな
GPUに処理を投げる実験をやったことがあるのだが、 当時は(CPU内部キャッシュバスに比べ)激烈に遅いAGPしかなかったので、 GPU-主記憶-CPU転送の帯域がモロボトルネックになって 「主記憶-CPUキャッシュ-CPUコアで完結させた方が速いや」ってことに なったよーな。 GPUローカルで完結する演算だと、GPUの演算器をこき使うのは大いに メリットがある。昨今のGPU内部はかなり広帯域だし。 で、ここ、何のスレだっけ?
ここは ハードウェアを使い倒すためのスレ でいいんでない
378 :
1 :2005/05/11(水) 13:43:26
俺は「ある処理をとにかく高速化スレ」なイメージだった。 でも377を見て、そういう表現もいいと思った。 ハードの性能を引き出す=コードを最適化して速くする、だからな。 遊んでるユニットはGPUでも使え、と。 転送が非同期にできれば(できる?)CPUでも処理できるから遅くはならないし。
(´-`).。oO(FPGA基板をPCIスロットに装着…は、邪道?)
380 :
368 :2005/05/11(水) 17:44:35
>>369 >>370 まあ、そのうち、GeForce5700やRADEON9600クラス以上じゃないと、
Windowsそのものが動かなくなるわけだし(Longhornの必須環境)
再来年までには、ノートでもその程度のGPUが主流になるでそ。
たぶん。
381 :
368 :2005/05/11(水) 17:45:08
>>371-372 いや、知識に関して(も)、確実に 1 さんより下だと思う。
368に嘘や間違いが入っていないと保証できない。スマソ
まあ、最終的にはあんまり意見の違いはないみたい。
MMXやSSE以上に使いにくくなってくるし、あんまり普及はしなさげ
3.番の問題は、この使い方を提唱しているのとセットで投入するんだと思う。
まあ、DirectXの9.0dか9.0eあたりで出てくるんじゃないの?
まあ、GPUだって、それに合わせた改良を盛り込む「予定」なんだろう。
いまのはまだ対応してないはず。
382 :
368 :2005/05/11(水) 17:45:51
>>376 AGPの場合、「GPUが主記憶を読む速度」だけが高速で、
(それでも主記憶より遅い)、それ以外のアクセス速度は
単純にPCIの速度=133MB/sだったからねぇ。
そもそも、GPUをDSP様に使おうって発想は、
PCIe x16にともなって出てきたんじゃないの?
AGPの速度じゃダメだったことができる! とかぬかして。
誰が言い出したことかは知らないけど。
PCIExpressを売るため あとLonghornの必須環境は915Gの統合チップで一応満たしてるはずだけど?
XBOX360の石美味しそう 6並列か〜インテル製なら10万こえそうだ 並列処理はレイテンシが見かけ上大幅に減るから面白そうだよね ナイアガラも興味あったり
XBOX360だとPowerPC系だから6スレッドで(FPU+SIMD)*6の計算が 並列で出来るんだよね? それに比べるとインテルのCPUは性能低すぎ。
しかもSIMDは定評のあるAltivecだ
定評と言っても、 「クロックあたりの性能こそ高いが、 これを実装するとクロックを上げにくくなる」という、 いわば「負の定評」だと思う。
>>131 のZIPを昔落としてたのでコンパイル。
a.obj : error LNK2001: 外部シンボル "_pp" は未解決です
Debug/life2.dll : fatal error LNK1120: 外部参照 1 が未解決です。
なんじゃコリャー!なんでだろ〜。
3.2GHの3コアなら問題ないんじゃね? それともPen4の3.8GHzのほうがいいってか。
390 :
デフォルトの名無しさん :2005/05/15(日) 07:17:34
かけ算の方が割り算よりも高速なのですか?
昔熱揺らぎを利用した乱数命令をPentiumに追加するとかいう話を聞いたんだけど 結局追加されなかったの?
ハードウェア乱数ですか。 PenIIIぐらいから追加されるとか言ってたんだっけ? (それより古い時代ではあり得ない、って程度の意味で。) 結局、どうなったんでしょ。記憶がありませんw
>>390 一般的には乗算の方が速い。Cの整数除算はコンパイラが乗算に最適化してしまうこともある。
除算は全パイプライン占有するから圧倒的に遅いね
熱雑音を使った乱数ジェネレータは、VIAのCPUに乗ってるらしい。 あれじゃないか? CPUにuniqueなIDを振る件と一緒にポシャったのかも。
乱数発生器ならチップセットの方に入ってなかったか?
PentiumMで実験。 divのレイテンシは39clk。スループットは37clk以下。多分P3と同じ。 lp: mov edx,ecx mov eax,ecx div ebx mov [esi],eax add esi,4 dec ecx jnz lp これが37clk/loopだった。レジスタリネーミングが効いてるね。 ただ、レイテンシとの差が小さいのは確かで、あんまり意味ない。 lp: add eax,1 add edi,edi//←この行を増やす div ebx dec ecx jnz lp これが、40clk/loop。divとaddのチェーンで39+1=40レイテンシの計算通り。 そしてadd edi,edi を何行か挿入してclk数の変化を見る。 32行までは40clkで、それ以降少しずつ増えて40行で42.5clk。更に増やしても行数+2.5clk。 関係ない処理を並列実行するのはあまり問題なし。 addps20個とmulps20個で試すと、43.8clkと51.0clk。mul側のユニットを少しだけ多く使うようだ。 謎なのが、shr edi,1 でやったときにaddと同じ結果だったこと。 shrはmul側のユニットしか使えないはずなのに、なぜかdivとは競合しない。
398 :
1 :2005/05/17(火) 12:28:22
簡単な割り算だと速くできるみたいなのでこれも調べた。
どうやら8bit単位の256進法で割ってるようだ。詳しい内部構造は知らんけど。
各ケースの所要クロックの表を示す。
12333---
112333--
1122333-
11223333
タテ軸は除数の桁数(上から1〜4)、ヨコが被除数の桁数(左から1〜8)。桁数は256進法で。
レイテンシが、1:15clk、2:23clk、3:39clk、-:オーバーフローで除算エラー。
>>384 PCWatchで見てきたが、2スレッド/コア×3コアだね。
レイテンシが減るってのは微妙なところだな。
P4のHTでは、メモリレイテンシ・FPUレイテンシ・分岐ミスなどを隠蔽できる。
ただしそれはノーマル1コアと1コアHTを比較しての話。
ノーマル2コアで2スレッドを動かすと、当然1コアHTより速いが、
コア当たりの性能では全くレイテンシを隠蔽していない。
(もちろんHTも、スレッドあたりの性能ではレイテンシは減らない)
ループアンロール程度の思いで2コアを使うとレイテンシが半分に見えるが、
2倍の性能を期待して2コアを使うとレイテンシが同じでメモリ帯域は狭く見える。
つまり、「2スレッド/コア」の効果に「見かけのレイテンシが半分」はあるが、
「3コア」の効果はレイテンシの面から見るのはナンセンス。
3倍の性能からマルチスレッド化・メモリなどの共有のオーバーヘッドを差し引いたものが
その性能になるだろう。
399 :
1 :2005/05/17(火) 12:28:54
>>385 アセンブラでクロック測定やってると、IPCばかりに目が行き、
「高IPC=良CPU」みたいな錯覚に陥りがちになる。
クロックは重要。冷静にベンチ結果見ると俺のDothan-1.1なんて低い低い。
まあ、ベンチに表れない体感速度や発熱がナイスだし、「好き」なコアだからいいんだけど。
それにしても3.2GHzとはすごいな。IPCもクロックも高いやん。
>>388 SSE2対応のnasmw.exeにパスが通ってないんだと思う。あと俺Releaseビルドしかしてない。
VCがSSE2に対応してるならnasm用のコードでCのcall pp を置き換えるとかでいけるかも。
希望があれば直したの再うpするけど。
>>390 自分で5〜10桁ぐらいの手計算して、乗算と除算のどっちが楽か試してみ。
除算に苦労しているCPUの気持ちがわかるよ。
これに限らず、アルゴリズムを考えるときなど「手計算ならどうやるか」を考えると
いい気がする。
>>391 ハードウエア乱数は、確かマザーの機能として見た。
「CPUに叩く専用の命令ができるのかな」とか思った記憶がある。
「乱数に熱ゆらぎを用いることで暗号のセキュリティが強化される」みたいな記事だった。
・・・うろ覚えもいいとこでつ。
VIAのはもちっと最近の話だっけ?ちょっと欲しい命令だ。
>>393 乗算にしてくれるのはどういう場合だ?
もちろん除数は固定だろうが、被除数の範囲もある程度わかっていないと
精度保証ができないのでコンパイラにはきついのでは?
そう思ってやってみたら、VCは見事に乗算のコードを吐いてくれた。あはは。
mov eax, 0aaaaaaabh
mul edi
shr edx, 1
これで、edx=edi/3; となっている。
shr edx,1 は思いつかなかった。0aaaaaaabhを大きくとることで精度を上げている。
普通に考えると2^32/3を切り上げた55555556hを使ってしまうが、
これだと、edi>2^31かつedi%3==2のときに計算結果が1大きくなってしまう。
(「^」はxorじゃないよ。念のため)
mov eax, 40140141h ; r=esi/819とおく。esi=819r
mul esi ;edx=205r
sub esi, edx ;esi=614r
shr esi, 1 ;esi=307r
add esi, edx ;esi=512r
shr esi, 9 ;esi=r
これなんか、esi/=819; だぜ。人智を超えている。まあ、人智の生んだコンパイラだが。
40140141hは2^32*205/819で、205の大きさで精度を上げて9bitシフトで仕上げている。
一般的な式を出したいな。
Hacker's Delightは人智を超えまくっていたな 使いどころが解らんけど。
>>399 >SSE2対応のnasmw.exeにパスが通ってないんだと思う。あと俺Releaseビルドしかしてない。
thx。nasmw.exe拾ってきてReleaseビルドしたら出来ました。
知らないんで質問するんだけど何でnasmwが必要なの?
VC6ではSSE2の命令はコンパイル出来ないって事なのかな。
ついでに組み込み関数(_mm系)を使わないのは何故?
403 :
1 :2005/05/18(水) 11:08:26
>>401 「ハッカーのたのしみ」本屋にあったのでパラパラと読んでみたが、
ぱっと見、全然わからんw
(もちろんちゃんと読めばわかると思うけど)
やっぱこういうのは、必要に迫られて自作した方が理解も早いと思う。
自分で考えた上でこの本を見れば、「うわ、この本すげえ」と感じるんじゃないかな。
>>402 素のVC6.0ではSSE/SSE2を使えない。
プロセッサパック入れれば使えるが、それにはSP4or5が必要で、
>>185 の理由で無理だった。
今はコンパイラだけToolkit 2003のやつに差し替えている。
組み込み関数はアセンブラよりも高級だからねえ。
なぜと言われたら、その方が簡単で速いからと答える。ライフゲームなら。
組み込み関数の名前覚えるのも大変だし、レジスタ叩けないし、使う変数の宣言必要だし。
逆にアレが全部組み込み関数で書かれてたら嫌じゃないか?w
組み込み関数は、コンパイラの最適化が効いた状態でCのコードに埋め込めるのが、(・∀・)!!イイ
でもオールアセンブラで書けるなら組み込み使う理由はあまりないと思う。
何をどのレジスタで、何はスタックで・・・なんて考えるのが面倒だから、intrinsicsを使うよ。 そういう割り当てだけでなく、最適化まで自動でやってくれるんだから、使わなきゃ損。 しかも、今はx64が目の前に来てるから、コンパイルし直すだけで済むのは魅力的。
405 :
402 :2005/05/19(木) 00:20:09
>素のVC6.0ではSSE/SSE2を使えない。 そうなんだ。自分はsp5入れてたから普通に使えてたよ。 >なぜと言われたら、その方が簡単で速いからと答える。ライフゲームなら。 やっぱりアセンブラのほうが速いのか。コンパイラの最適化のほうが 速いのかと思ってたけど。組み込み命令は最近知ってあまり効果的に 使ってないから遅いとは知らなかった。
>>404 x64が来てもコンパイルし直すだけでいいのは強いなあ。
MMX禁止になったらpaddb mm0,mm1は使えないけど、_mm_add_pi8(m0, m1)これなら
コンパイラがSSEintで計算するよう変えてくれるだろう(SSEの下位64bit使うとか)。
レジスタ増などのCPUの変化に合わせた最適化も自動でやってくれるし。
そもそもVCのインライン廃止だから話にならないか。
まあ、ライフゲーム程度ならフルアセンブラの方が簡単に作れて動作も速いわけだが。
64bitになったらMMXをSSEにしてnasm使えば済むし。
組み込み関数では、CPUに自分の気持ちをアセンブラほどよく伝えられないのが痛いのよ。
・・・でもレジスタ倍増でアンロールされたら下手すりゃ負けるかもな。
>>405 当たり前だけど、コンパイラが吐いたのと同じアセンブリコードを書けば引き分けになる。
どちらが速いかは、あくまでも書いた人間とコンパイラによる。
コンパイラの最適化に変な「すごさ」を感じてないか?魔法みたいな「すごさ」はないよ。
誰が最適化しようと、理論性能以上のものは絶対出せないのだ。
それでもコンパイラは
>>400 みたいな基本事項は確実に押さえてくるし、十分すごいと思う。
コンパイラは仕様書ではなくCのコードだけからマシン語を生成するが、
人間は仕様書から直接アセンブラを書くことができるから、そもそもコンパイラ不利。
遅くなんてないよ、組み込み命令。むしろアセンブラが速いと思って欲しい。
アセンブラは圧倒的に表現力が高いのだ。Cでは表せないアルゴリズムを簡単に使える。
ただ、処理の流れをイメージもできないのにアセンブラやるとデバッグで死ぬ。
遅いとかいう問題以前に完成しないし、保守・拡張・再利用が事実上無理になる。
ていうかみんな組み込み関数orアセンブラで何を作ってるの?
俺は趣味にしか使わないからある程度いい加減なことができるわけだが。
>>406 すごいね。うまく使えばただのアセンブラより速くなるポテンシャルを持っている。
除数が変動するときでも
>>400 みたく割り算コードを作れるのはナイス。
VBでnasm使って状況依存のコード生成みたいだ。
何か面白い応用例ないかな。
SpeedStepを試す。
PentiumMの600MHz〜1.1GHz。瞬発力がどの程度のものかをVBで計測した。
Dim i As Long, k As Long, t As Long
For k = 1 To 30
Sleep 2000
t = nTime
For i = 1 To k * 1000000: Next
Text1 = Text1 + Format((nTime - t) / nHz) + vbCrLf
DoEvents
Next
ただし、nTime、nHzはQueryPerformanceCounterの下位32bitを返す。
結果をExcelに貼ってグラフにすると、0.29秒で1回折れている直線になった。
>>363 の測定プログラムで見ていると、0.16秒以下の処理ではクロックが変動していない。
0.16〜0.29秒の処理だと少しクロックが上がるが、ほとんど効果がない。
切り替えのオーバーヘッドかと思ったが、数値が最低クロックのものとほとんど同じことから
処理が終わってからクロックを上げるというマヌケなことをしていると予想。
もちろんこの挙動は一般にはマヌケではなく役に立つ。
よく、PentiumMよりCeleronMの方が体感速度がいいという話がある。
600〜1100MHzで動くPenMの場合、0.29秒以下の処理なら600MHz固定と同じレスポンスだ。
キャッシュの差こそあれ、これでは900MHzのCeleronMに負ける。
SpeedStepはオフにできるけどね。
うちのCPUは速さをレベル1〜7の7段階に変えられて、クロックはそれぞれ 600,600,600,800,900,1000,1100MHzとなっている。 SpeedStepで可変クロックにするとレベル3〜7を動く。 600MHzが3つあるが、cpu-zでレイテンシを測ると、 普段はL1が3、L2が10だが、レベル2では4、14。レベル1では6、21となる。 でも実験してみるとこれはメモリレイテンシのせいじゃないっぽい。 lp: mulps xmm0,xmm0 mulps xmm1,xmm1 dec ecx jnz lp これの1000回ループで普通は4000clkだが、レベル1だと変な挙動を示す。 ほぼ交互に4007clkと13871clkになるのだ。 繰り返し回数を変えて調べると、どうも突発的に9875clk休んでいるような感じだ。 その周期もバラバラで、平均すると約2.12倍遅くなっている。 レベル2だと約1.40倍遅い。 短いループでキャッシュレイテンシを測ると普段と同じで遅くなってなかった。 これは実質的にクロックを2.12倍または1.40倍遅くしたのと同じに見える。 また、ファンの設定をCPU速度低下を優先にすると、ファンは回らなくなるが、 そのときに同じ現象が起こる。 クロックは600MHz〜1.1GHzで動いていても、CPUが熱くなる毎に 1.40倍、2.12倍と、順に遅くなっていく。 1.1GHzの2.12倍遅いのだと518MHz相当だが、駆動電圧は下げていない気がする。 それなら600MHzの方が速くて涼しいわけだが。単に不行き届きなだけだろうか。
>>410 ドキュソメントにあたらずに発言するが
MCHとかバスがサボってんじゃないかな?
あと、遅くしても、OSが司ってるタイマ処理の間隔は変わらないので
相対的に割り込みなどの外乱に弱くなるのでわ?
んー、CPUの外のバスが止まるだけなら内部でALU稼動とかは普通にできるはず。 いわゆる「熱ダレ」ってやつだと思う。 休んでるけどrdtscは普通に動いてるんだよねえ。 外乱に弱くなるとは思った。どう検証したらいいかわからんけど。
バスは一切サボらんぞ
ヤバイ。Prescottヤバイ。まじでヤバイよ、マジヤバイ。 Prescottヤバイ。 まずリーク電流。もう漏れるなんでもんじゃない。超漏れる。 リーク電流とかいっても 「TDPの半分くらい?」 とか、もう、そういうレベルじゃない。 何しろ漏れまくり。スゲェ!なんか単位とか無いの。何Vとか何Aとかを超越してる。 しかもパイプライン長いらしい。ヤバイよ、ハイパーだよ。 だって普通はPentiumMとかパイプライン短いじゃん。だって分岐予測ミスったら困るじゃん。 ジャンプの度にやり直しとかで困るっしょ。 パイプラインが伸びて、北森のときは20段だったのに、プレスコは31段とか泣くっしょ。 だからPentiumMは14段だ。話のわかるヤツだ。 けどPrescottはヤバイ。そんなの気にしない。細分化しまくり。今実行している命令とかでも、 30クロックも前にフェッチされてる。ヤバすぎ。 消費電力は多いけど、もしかしたら性能はいいかもしんない。でも性能いいって事にすると 「じゃあ、あの体感速度ってナニよ?」 って事になるし、それは誰もわからない。ヤバイ。誰にも分からないなんて凄すぎる。 あと超高クロック。3.8GHz。MHzで言うと3800MHz。ヤバイ。速すぎ。 それに超何も無い。パイプライン超ガラガラ。それに超のんびり。熱くなったら平気で寝る。 みんな寝るみたいだけど、最近のCPU。 なんつってもPrescottは馬力が凄い。100Wとか平気だし。 PentiumMなんて、たかだか21W消費しただけで上手く扱えないから低電圧版にしたり、 SpeedStepしてみたり、Sonomaやめたりするのに、 Prescottは全然平気。100Wをそのまま熱にしている。凄い。ヤバイ。 とにかく貴様ら、Prescottのヤバさをもっと知るべきだと思います。 そんなヤバイPrescottを2個載せたPentiumDとか超偉い。もっとがんばれ。超がんばれ。
もう世の中全部CELLでいーじゃん。 どーせ高スペックなCPU使うとこなんてSIMD使うゲームかシミュなんだし。 インテルにはもう期待出来ない。
問題はいかに低スペックなCPUでも処理を間に合わせるかなんだよ。
DSPボードでいいやん 拡張すればするほど高速になると
DSPというアプローチは(DSPに失礼ながら)Pen4に似ているが、 SSE非対応コードや体感速度で散々糞扱いなのを見ると、それは時期尚早な気がする。 付け足していくにしても、発熱が大きくなる。もうモバイルだけの問題じゃない。 それに拡張してリニアに性能が伸びるのはGPUぐらいだろう。 特に、x86ならばWindowsを動かすという大仕事がある。SIMD性能だけじゃ無理。 中間言語系もそう。遅い中間言語に対してCPUを速くする意味はある。 個人的趣味から言えば416に同意だが。
主流な中間言語系を高速化するのなら PentiumM系列のマルチコアしか選択肢ないな やっとJavaで最適化でSSE類使い始めたのが2年位前だからな .NETも次のバージョンで最適化がJavaに追いつくだろうか ボーランドから移籍した例のおっさんが今後はJavaに最適化で追いつくようにするとかいってたような 最適化できそうなコンポーネントを実行時に調べて最適化ってのは 今後加速するっしょ
エンディアンをリトルにしたCELLをIBMが作ればいいんだよ。 そして対称型コアx3+SPEx8にして性能アップ。
つーか86と他の石とだとFPUの計算結果違う
87系は80bitで内部処理したりしなかったりするしな
まぁでも、MPEG2や4のエンコードなんか、CPUにやらせちゃ激しく無駄。 リアルタイムでVGA解像度をエンコードするチップにはヒートシンクすら付いてないよ。 シャープのMT-AV1は解像度もフレームレートも低いけど、 携帯電話クラスのACアダプタの電力で手のひらに乗るサイズでエンコードできるしね。
>>420 SPEはゲーム用途(ある程度限定的)で単精度のみだからあの性能が出るわけで。
アプリがメニーコアに対応するのは現実問題(残念ながら)時間がかかるし。
でもウチのPenMじゃ、ギコナビの動作にも多少の不満が出るもんな。
pdfの閲覧、メモ帳の「置換」(他のエディタ使えばいいんだが)、など
けっこうCPUパワー足りない場面がある。
ちょっと気になったのだが、ビッグエンディアンの利点って何?
リトルだとメモリにアクセスするサイズで値が変わらない。
例えば、x86ではmov [edx],eax/ mov ax,[edx] としてもaxの値は変わらない。
>>421 どうせx64ではx87使わなくなるんだから別にいいんじゃね。
個人的には寂しいが、性能のためなら仕方ない。
SSE2とPPCの倍精度浮動小数点も違う?
>>423 汎用プロセッサは、何でもできるからチップ数は減らせるけど、電力効率も性能も悪いんよね。
GPUは特殊用途とはいえCPUと別にPCに入っている。
ほんとにエンコのためだけのマルチコアだったら無駄もいいとこだよな。
CPU側が普及してから新しい使い道が開拓されてくると信じているが、どうなることやら。
ビッグエンディアンだと多少ダンプが読みやすい PDPエンディアンみたいな変なのでなければべつにどうでもいいが 初期のPowerPCはリトルビッグ両対応だったはずだが今は違うのかな
「人間が読みやすい」かよw 時代を感じさせるな。
>>424 ギコナビってそんなに重いのか?
ファンレスのPenMずっと使ってたけど、ファンつきPenMにしたらすげぇはやくなったよ
もちろんファンを動かさないでクロック低下優先設定もできるけど、通常電圧版だから
すぐにさがっていく
ビッグエンディアンはさわったことがあるなら利点分かるはず
ハンドアセンブルとかダンプをながめてデバッグとか生々しい時代はね
あの当時は68Kしかビッグエンディアンはなかったから、メモリ空間も16Mとか
そういうのも含めて憧れだったかもね
今でもリトルとどっちをとるかときかれればアセンブラやハード周り
さわるならたぶんビッグというと思う
浮動小数点の話はXBOXの互換性の話
ゲームの場合精度が落ちることによって描画結果が多少異なるから
完全な互換性はないなとおもったり
そうでなくとも個別エミュとかいいだしたので互換性怪しいらしいな
日本では問題ないが
>>426 思ったより
>>1 は若いのな
現在でも普通にダンプ眺めるが
>>427 重いと言うほどではないが、瞬殺ではないので。ギコナビ。
それに普段は電源つないでてもSpeedStep使ってるから0.29秒間は600MHz。
>ビッグエンディアンはさわったことがあるなら利点分かるはず
そこまで利点があるとは知らなかった。
慣れればリトルエンディアンでも普通に読めると思ってたよ。
俺は、Cが吐いたアセンブラと機械語のを眺めたり、命令フォーマット調べたりしたぐらいかな。
あんまりコアな経験がない。
そういうの今でも憧れるよ。
>思ったより若い
初めてPCでプログラミングしたのがVB5.0@PenII-300だし、
自分のPCでアセンブラやる以上の経験が全くないので甘々なまんまでし。
私ゃ>427よりもっと年上だと思うが、リトルエンディアンはメモリを介したcastみたいなことが 簡単にできるので寧ろ好きだったな。 今でもそう言う意味でバイトダンプ見ながら普通にリトルエンディアンで読み取りしているし。 #つーか、16進二桁なら瞬時に10進に変換できるといったら周囲に呆れられるやら驚かれるやらw
431 :
427 :2005/05/28(土) 13:54:01
一応俺はリトルエンディアン出身だよ ただ、アセンブラもテキストエディタもない状態で直にマシン語をうつ ハンドアセンブルをやってる時代なのでアドレスのうち間違いがどうしても多かったのさ 基本は紙とペンでの机上デバッグやね それでビッグエンディアンさわったらびびったと テキストエディタとかデバッガとかアセンブラがある今ならさほど困ることはないかもね PCベースならとくに しかし、16進で驚かれる時代になったか
432 :
430 :2005/05/28(土) 14:12:30
いや普通に、16進キーボードで直接入力してましたがw 8x8のフォントくらい、イメージから直接16進にしてたし。 その後もRomWriterで直接コーディングとかね。
>>425 MacはG5からビッグエンディアン専用になってしまったらしい。
それで、リトルエンディアンを使っていたVirtualPCが動かないらしい。
ムカつくのが、ネットワークバイトオーダがビッグエンディアンなこと。
昔のMC68000の頃のSunのワークステーション等では都合が良かったろうが、
今となってはリトルエンディアンが大半なわけで、
世界中で膨大なCPUサイクルが、変換に費やされていると思うと、ぞっとする。
434 :
427 :2005/05/28(土) 15:34:06
>>432 ビットマップを16進で作成ってふつうだったよな
ベタフォーマット時代だったからこそみんなビット列が見えていたという時代だな
抽象化は業務アプリを考えると安全性の観点でもべつにいいのだが
教育ではある程度教えてほしいもんだ
2の補数とか知らないで符号付と符号なしで悩んでた人を何人も見てきたし
浮動小数点誤差しらないでイコールで判定していたりとかね
業務系で浮動小数点使ってたのも何度見たことか
>>430-434 おまいらかっこよすぎです。
QueryPerformanceCounterとrdtscでSpeedStepの実験、今度はVC++でやってみた。
時刻・rdtscの値をループでひたすら配列に入れて、それを見る。
測定ルーチンに入る直前にはSleep(3000); で3秒休ませている。
0.2905秒くらいで600MHzから1.1GHzになる。
切り替えのオーバーヘッドは10μs程度。中間のクロックは現れない。
初め、その場でprintfで表示させていたら、なぜか0.1秒毎に0.09秒間止まってた。
SpeedStepに関係なく。改行処理か何かか?
QueryPerformanceCounterはオーバークロックすると狂うらしい。 SpeedStepなら大丈夫。倍率変更でもOKかなあ。 クロックジェネレータ辺り?
RDTSCってさ、SMPだと不幸になるんだよね・・・。
そういうときはシステムコールを処理するCPUを限定するだけ
アフィニティマスクを設定するだけか。
これからゲーム機はみんなビッグエンディアン。Macもビッグ。 マイクロソフトもPowerPC触り始めたんだからPowerPC版 Windows出せば世の中ビッグエンディアンだらけ。
だうと PowerPCは触りはじめたのではなく、やめたのを復活させただけ。 PowerPC版のWindowsは昔は市販されてたけど、あまりに売れないので打ち切られたのさ。
>>433 ネットワークがビッグエンディアンなのは自然だと思うけど。
IPに限らず、アドレスの書き方は日本語式(ビッグエンディアン)の
方が英語式(リトルエンディアン)よりも、振り分け処理がしやすい
でしょ。リトルエンディアンだと、最後のオクテットが来るまで
振り分けが開始できん。
それに、TCP/IPの実装が広まったのはVAX上の4.2BSDからだけど、
VAXはリトルエンディアンだったんだよ。
DEC はリトルエンディアン好きね
R3000以降のRISCって、起動時にビッグエンディアン/リトルエンディアン を切り替えられるようになってる物が多くなかったか? PS1はなぜかリトルエンディアンで動くように作ってあったしな。
R4000以降だとプロセスごとに切替えられる。 RISC 系は load store architecture だから、こういうの は難しくない。今ではたいていの RISC がこうなってる筈。 Itanium もそうで、HP-UX はビッグエンディアンで動かす ことになってるね。
http://pcweb.mycom.co.jp/special/2003/centrino/005.html Baniasが出たときの記事。今見ると内容がアレだが、このテスト結果の考察を少し。
前のページにコードが載っているが、要するに、
100MBのデータをランダムに1億回32byteずつ足し算するのにかかる時間を測っている。
アライメントは合っていないが、高々2つのキャッシュラインに読むだけなので
メモリの高レイテンシの前にはさほどネックにならないだろう。
最速タイム22.16秒を出したPenM-1.6は、1ループ(連続した32byte)当たり355clk程度。
PenM-1.3では315clk。俺のDothan-1.1では24.61秒、271clkだ。
100MBクラスのメモリアクセスレイテンシとしては妥当なところだ。
が、クロックを600MHzに落とすと31.83秒となった。
クロックがリニアに効く部分もあるようで、内部クロックが無限大なら17秒くらいまで縮まりそう。
Pen4-2.8が24秒なのはいいとして、モバセレ1.6はひどい。55秒。
FSBやメモリはPenMと同等だろうに。L2サイズなど関係ないテストだと思うのだが。
やはりL2に何か悪さがしてあるのかな。
NetBurstのCeleronは本当に性能が悪い。何なんだ?
AthlonXPもイマイチ。今でもメモリまわりはパッとしないイメージがある。
Athlon64も、排他式のキャッシュやめて普通のL2を載せればかなり速くなるように思うのだが。
つーかL2の速いAthlonは無敵な希ガス・・・。
相違や最近mycomこういったExcelとかCのコード実際に動かして その結果乗せるというのがないな 洋物のベンチのせるよりよっぽど癖が分かりやすくてよかったのだが NetBurstのCeleronは体感速度もすさまじくわるいのでそれくらいの結果でも納得してしまう 乱数でメモリアクセスしている以上キャッシュ容量に純粋に比例しやすい気がするが
>>447 ランダムアクセスに、どうやってキャッシュ容量が役に立てる?
俺が
>>366 でやった測定ではL2を切った方が速かった。
ランダムってことはキャッシュにのる可能性もあるというわけだが 順次アクセスより早い可能性はある つーか実際に順次アクセスより早く終わる結果がでた
うーん、100MBのランダムだと載らないんじゃないの? たしかに不思議。 > つーか実際に順次アクセスより早く終わる結果がでた それって、ランダムアクセスの範囲が8MBとかそれくらい なんじゃないの?
同じところを2回読む場合があるってことか。なるほど。 順次アクセスより速いとはびっくり。 確かに、プリフェッチのないシーケンシャルアクセスは意外と遅い。
で PenM-1.6G と NetBurst Celeron-1.6G の 355clk と 880clk の違いはどこから来るの? パイプラインがたとえ30段余計に深い としても、これだけ差をつけるには、メモリアクセス1回ごとに パイプラインが17回以上完全ストールしなきゃいけない計算にな るんだよね。ありえる?
512KBのL2を持つPen4なら、128byteのキャッシュラインが4096本ある。
で、>446のベンチはrand()を使っているので32768通り。
つまり1/8ぐらいの確率でL2ヒットする。
128KBのCeleronだと1/32だから、多少の差は出るはず。
とはいえこれだけではCeleronの遅さは説明できない。
つーか100MBで799byte毎にアクセスする変なベンチなんだ。
普通なら
>>451 の言うように範囲が狭い場合にしかキャッシュは効かないだろう。
最近はHWプリフェッチが付いてるから、順次アクセスもかなり速くなった。
>>448 さんきゅ
見てみた
しっかし、これだけレジスタリネーミングとかキャッシュ大容量でがんばってきたのが
結局レジスタ数増えて大幅に早くなったというのが笑えるというか、
昔からちっとも変わっておらんというか
昔386の高速性を自慢していた友人が実際にメモリアクセスが入るベンチとらせてみたら
68000に負けていたとか思い出した
もちろん場合によりけりなんだがね
>>453 パイプラインは14段と20段だから6しか違わないし、段数は関係ないと思う。
原因としては、メモリアクセス以外の足し算や配列のアドレス計算が遅いというのが1つ。
でもこれはPen4-1.6(32秒)も同じはず。
L2しか違いがないと思うのに。全然わからない。
できれば誰かNetBurstのCeleronを持っている人に実験してもらいたい。
原因を見極めるためのベンチ作ってうpするから。
仕事中でJavaのIDEが目の前でたちあがっとる
というわけで
>>446 のベンチをそのままJavaのコードにかえてみた
ほとんど変更しないでうごくのはやはりCをベースにしているのは面白いな
●PentiumM725(1.6GHz/2MB)
Start Initializing.....Done
21661 milliseconds
クロックを下げてみた
●PentiumM725(1.0GHz/2MB)
Start Initializing.....Done
26578 milliseconds
Cとほぼ同等の速度が出てるってことかな
ポインタ演算でメモリ破壊することがない言語なので
ネイティブの1/2の速度で動けば万々歳だと思ってたけどね
ベンチ系ならJITでもそこそこ速度が出るね。 基本的には使い物にならないけど。
ネトバセレのパフォーマンスが劣悪なのがL2の容量に依るものかどうかについて。 トレースキャッシュが猫の額ほどしかないので、ループ外のコードシーケンスは L2キャッシュに依存することになるが、L2はデータキャッシュとも共用なので ちょっと大きめのワークセットではキャッシュミス連発しまくり。 と愚考するが、いかに? あと、セレは足回りを窒息させてるんじゃないかな。 俺が計測したときは、コアの処理能力に差異を見いだせなかった。
>>459 いまだに現実を直視できないのがいるな。
>>459 現行のC#でさえ、重いアプリを組んだら3G以上のx86でもストレスを
感じるってのに、勘弁してくれ。
JITという考え方は素晴らしいし、適材適所と言うように、JavaやC#
がピッタリな場面もあるが、今のパソコンじゃやっぱりバイナリには勝てん。
>>460 コアの能力は同じっぽいですか。むう。
トレースキャッシュは12Kμopだから、主要部分は入るだろうし、
ループの外なら秒単位の遅さにはならないかと。
足回りを窒息とは?
>>462 3GHz以上のx86→中間言語苦手なNetBurstという罠。
重いアプリを作ったら重かった というのじゃぁねぇ。 C#ではなくC++で組んだのと比較してどうなのよ。 もちろん、ManagedのC++でね。 そもそも、 JavaもC#も、コンポーネントを繋げてシステムとして組むための言語で、 コンポーネントは必要に応じてネイティブで作ればいいじゃない。
ネイティブと連結部分で最適化がとまるっていうのはCとアセンブラと同じ問題がでるぞ JNI全快のSWTは今となってはさほど早いものではないし、Swingとは 実装している機能が違いすぎるしな Eclipse3は2とは別次元でさらにヘビーに・・・ Cはアセンブラより遅いって15年位前に散々いわれまくったのと同じ話で笑える
java/.NETアプリの重さってコードの実行速度よりはバカ食いするメモリが原因じゃないか? しかもGCが走るせいでページファイル落ちが阻害されるとか
GCってのは遅くなる要因でもあるが、高速化に貢献もするわけだしな 動的コンパイラって作るのは大変だが楽しいかもしれん
キャッシュのヒット率が下がるのが問題なのよ。 同じようにC++で書いても、キャッシュからはみ出すようなサイズになると途端に遅くなるよ。
その点でも世代別 GC は結構優れてるよ。
まず、Edenでのメモリ確保が単純な足し算程度の処理で
済むおかげで、mallocやnewの際にメモリ上の領域管理用
データ構造を辿ったり書き換えたりしなきゃいけないCや
C++よりも、メモリアクセスが少なくて済むからキャッシュ
にやさしいし、計算量もずっと少なくて済む。
それから、最も頻繁にアクセスされるNew、From、To
あたりの領域はきっちり詰まって配置されるから、バラ
バラに配置されやすいCのmallocやC++のnewより、やはり
キャッシュにやさしい。
もちろんCでauto変数とstatic/externだけ使って書くよう
なスタイルが一番キャッシュにやさしいだろうけど、
ある程度動的メモリ確保を行なうスタイルのコードだと、
むしろJVMの方が速くなっても不思議はない。
実際
ttp://www-6.ibm.com/jp/developerworks/java/040312/j_j-jtp01274.html にも、そういう主張が載ってる。
世代別GCの短寿命オブジェクトが配置される領域=非GCにおけるスタックだろ。 利点としてはスコープ外れたから破棄されました、アクセスしたら鼻から悪魔が出ても知りません、がないだけ。
GC動くと綺麗に配置してるしね 関連性のある順序でオブジェクトを再配置するとはおもわんかった
>>465 なるほど、興味深い。
速度が許せば、より高級なレイヤーが求められているということか。
近い将来CPUの能力が1桁上がった頃には、中間言語系がもっと増えているかもな。
1次キャッシュだと、たいてい命令とデータが同量入っているが、
やはり必要だからそうしているんだよね。
何か32KB+32KBよりも16KB(命令)+48KB(データ)の方が性能いいように思えちゃうけど、
データキャッシュが増えればそれを使いこなすだけの命令の供給が必要になるのかね。
大きいコード書いたことないから実感がない。
関係ないけど、3GHzのCPUだと1clkの間に情報が10cmしか進めないんだよね。
CPUのサイズが1cm程度なのを考えると、けっこうキてるなあという感じ。
(1clk以下のレイテンシが必要なロジックは近くに配置されてるだろうけど)
データについては レイテンシという観点では、 プリフェッチを使えばキャッシュサイズを減らしてもいいよね。 どうせ大きなデータはキャッシュに入りきらないのだし。 コードについては、投機実行なんて高コストなことしないといけないので、 キャッシュのサイズを大きくしちゃったほうがいい、ということなんだろうね。 かなり再利用されるというか、ほとんど再利用されるわけだし。
>>457 の結果から、CPUのクロックを無限大にしたときのタイムを推定すると、13.5秒。
Dothan-1.1だと、15.9秒。(
>>446 に17秒と書いたのは凡ミス)
おそらくこれがPC2700とPC2100の差だと思われる。
Dothan-1.1GHz PC2100
L 11 10 10 11 58 60 60 60 58 60 356 393 421 407
S 12 11 11 12 143 170 183 190 194 200 943 1203 1369 1416
N 12 11 11 11 169 249 289 310 327 325 330 329 333 332
L 10 10 10 10 18 18 18 18 18 20 52 56 59 59
S 10 10 10 10 20 22 23 24 24 25 111 152 173 178
N 10 10 10 10 28 38 44 47 49 50 47 48 50 50
Dothan-600MHz PC2100
L 11 10 10 11 58 59 61 60 59 60 222 238 241 242
S 12 11 11 12 143 170 183 190 194 197 587 748 830 868
N 12 11 11 11 112 165 191 204 211 214 217 217 217 217
L 10 10 10 10 18 18 18 18 18 18 35 37 37 37
S 10 10 10 10 20 22 23 24 24 24 72 93 104 108
N 10 10 10 10 17 21 24 22 26 27 26 26 26 27
http://rerere.sytes.net/up/source/up6672.zip メモリベンチ作ってみました。SSE必須。
横軸がアクセス範囲で、4KBから32MBまで。
縦軸は、Load、Store、Non-Temporal Store。上は64byteおきのアクセス。下は普通の。
いずれもMMXで8byteのアクセスをしている。
数字は1アクセス当たりのクロック数の10倍。
32KB以下のメモリアクセスはみんな1clk。
1.1clkや1.2clkというのは、ループのオーバーヘッドだろう。
他、細かい考察は後で。
というわけで、結果貼り付けお願いします。(PenII、K6の人はゴメンナサイ)
CPUの名前、クロック、メモリは自分で書いてください。
Barton AthlonXP 2500+(ダウソクロック、130x11=1430。定格は、166x11=1833) ダウソのせいで、参考にならんと思う。スマソ PC3200メモリではあるが、動作クロックは195x2(133→130の比率) で、3.0-3-3-6 CMD2.0 4KB 8KB 16KB 32KB 64KB 128K 256K 512K 1MB 2MB 4MB 8MB 16MB 32MB L 13 11 10 10 10 200 200 200 501 500 501 503 506 507 S 12 11 10 10 10 199 199 199 854 1075 1201 1263 1287 1305 N 11 10 10 10 11 224 332 386 413 426 435 438 441 441 L 6 6 6 6 6 25 25 25 102 102 102 103 103 103 S 10 10 10 10 10 25 25 25 168 147 160 165 168 169 N 10 10 10 10 10 39 47 54 56 58 59 59 60 60
>>476 のベンチ頼む。意図がわからなかったかい。
64byteおきのアクセスは1キャッシュライン1アクセスという意味。ピーク帯域が見える。
movntqがどのように実装されているかも知りたかった。
普通のシーケンシャルアクセス(movq)と合わせて、L2の実効帯域が何で決まるかを見る。
レイテンシがどの程度効くのか。L2-L1間の帯域はどこまで生かされるか。
BaniasとDothanのL2レイテンシによる違い、Athlon64のメモリ性能、
Baniasより速いというCoppermineのL2、Celeron/Mはどこが弱いか、など。
Dothanの1.1GHzと600MHzを比べると、キャッシュの関係しないmovntqは絶対時間が同じだ。
純粋なメモリ性能を調べるときはmovntq系を使うのがいいだろう。
普通のメモリアクセスは、やはりクロックの高い方が有利。
>>478 ありがd。普通に2Laod/clkやってるのはさすがだ。
movntqに関しては、PenMもAthlonXPも「L1ヒットならL1へ、そうでなければL2を通さずメモリへ」
L2の64byteを見ると、1ライン20clkもかかっている。遅い。
ところがこれは2.5clkの8倍なわけで。ライン当たりの読み込み回数が所要クロックと関係ない。
L2帯域が64bit/clkとして、20=4(L1からVictimBuffer)+8(VictimBufferからL2)+8(L2からL1)
かな?L2のLoadとStoreで数字が変わらないのもこれで説明がつく。
こういうベンチマーク的アクセスは苦手みたい。
movntqのメモリ帯域は、絶対性能で
[email protected] を上回っている。
メモリが195MHzのDDRと高速だからだろう。FSBネックなのでレイテンシの影響だ。
それ以上に速いのがノーマルストア。これはPenMの方がどっか不器用なんだろう。
LoadはPenMが速いが、HWプリフェッチ性能の差だと思う。
>>479 対数グラフがいい場合もあるんだが、これはダメだな。
たまに間違った内容もある。まあ、役に立つページだからいいけど。
Dothan-1.1@L2 0MB
L11101011586060605860356393421407
S12111112143170183190194200943120313691416
N12111111169249289310327325330329333332
L1010101018181818182052565959
S10101010202223242425111152173178
N1010101028384447495047485050
L2を切ってみた。HWプリフェッチが効かないとかなり落ちるね。
以前ランダムアクセスで測ったときは逆転もあったが、このベンチでは勝ち目なし。
見づらいので表計算ソフトにでも食わせて読んでくれ。
ロードバッファの数を考えて、L2→L1帯域・レイテンシから見ると
それなりにわかるのだが、まだイマイチ。
ExcelからコピーしたからTab区切りだった・・・orz
手近にある P4 は全部 Linux なので、アセンブラの シンタックスを変えないと動かんが面倒だ… 誰か書き換えた人いない?
inline アセンブラ使ってるから、nasm にかけようとすると、 C の部分を全部アセンブラに書き直す必要があって余計面倒 なような。サブルーチンに直してからやる?
>>487 Macでさえx86路線に乗り換えなのに、CELLでアセンブラなど酔狂以外の
何物でもなかろうに。
いや、RISC系CPUって、実はアセンブラの手書きは結構楽よ。 レジスタが一杯ある分、むしろx86より楽とも言える。 例外はItanium。VLIWってだけで人手だと苦しいのに、性能 重視のせいで、これでもかってばかりに変態命令ばかり
VLIW自体はさほどむずかしくないよ EPICが難しいんだよ Cellは所詮DSP*7つきの石ですからねぇ
周りや漫画喫茶のPCを使って調べたよ。CPU-Zと
>>476 にプリフェッチ測定を追加したもので。
P6は256bit(32byteキャッシュライン)の転送が2clkでできると昔PC雑誌で見たが、
64byteおきのロードが2.8clkなのを見ると本当のようだ。
小さいラインサイズ、広帯域、小レイテンシ、この力はすごい。最強の小回りだ。
で、驚いたのがPen4のL2。64byteのキャッシュラインを2clkで転送している。
ストアはプリフェッチを使うと少し遅くなり、ロードは少し速くなる。
元々HWプリフェッチが効いている様子。メモリ帯域も広い。
movntqは、K8ではL1ヒットでもメモリに直接書き込む。
P4でもそうみたいだが、ストアバッファ(L1がライトスルーだから補助のために384byteある)
には書き込む感じだ。しかしL2の存在も少し見えている。何やってるんだろ。
L2に対してプリフェッチが有用なのはPeniumMだけみたい。P6もわずかには効く。
K7は、どのプリフェッチ命令でも同じ動作のようだ。
K8では、prefetchntaを使うと、L2より大きなメモリを扱うときにL2が邪魔にならない。
K8のメモリレイテンシは、さすがコントローラ内蔵。
メモリ側のクロック(200MHz)で11.5clkしかかかっていない。
PenM-1.1だと133MHzで20.5clk。P4の166MHzで17.5clk。K7の166MHzが21clk。
この辺はチップセット依存だけど、参考値に。
Athlon64-3000+が2種類試せたのだが、同じ2GHz、PC3200でも性能が違う。
それだけなら普通だが、片方はmovntqよりも普通のLoadの方が速い。
movntqでピーク帯域が測れると思っていたが、そうでもない場合もあるようだ。
プリフェッチありのLoad帯域が、ほぼ理論値を出していてすごい。
L2のバス幅がK7は64bit、K8は128bitということで、64byteおきLoadは倍の速さになっている。
排他の処理が大変なだけに、かなり効くと思われる。
K7ではL2の処理がネックになって、メモリ帯域ベンチでいい数字が出せない。
この辺、様々な転送(L1、L2、Victim、reg)がどの程度並列にできるのかも興味がある。
>>484 VCインラインの弊害か。。すまぬ。
>>488 Cellはコンパイラの吐いたコードを高速に実行できるようになってるらしいな。
cpu-zのも合わせて、測定結果をあげときます。
http://rerere.sytes.net/up/source/up7054.zip メモリアクセスって、何命令まで同時期にリクエストできるんだろう。
例えば、レイテンシ10・スループット1のとき、毎クロック命令を発行すれば
ピーク性能が出せる。
しかし、この場合リクエストが10個同時に存在し、並列実行できないといけない。
クロック数から単純計算すると、これの上限が3個程度に見える。
ロードバッファが16個あっても3個まで。
仮に無制限に並列実行できれば、PMならL2の帯域がL1と同じにまでなるはずだし。
何らかの制限があるのは確かだが、どこなのかが複雑でわからん。
メモリ自体は当然同時に1つしか実行できないからな。 (CPUがデータを取り出している間に次のアドレスを送る、 なんてことはできない) ・・・と書いて不安になってググったがそうでもないようだ。 DDR SDRAMやRDRAMはちょっとだけどパイプラインを持つらしい。 さらに、L2とメモリの間にあるだろうメモリコントローラが リクエストをキューしてるとすると、そこにも依存するのかな。
>L2に対してプリフェッチが有用なのはPeniumMだけみたい。P6もわずかには効く。 今度Pen4でプリフェッチ試してみようかと思ってたけど無駄なのね。
>>495 いや、試してくれ。効かないのは「movqでは」とうことだ。軽率なことを書いた。済まない。
でも元々のL2性能が普通のCPUの倍だから。movapsならL2で普通に8byte/clk出せるし。
P4は1Load/clkなのがAthlonと比べて弱いが、128bit/Loadが可能だ。
また、movによるプリフェッチの原理で、単純にアクセスの順番を変えただけで
L2Loadの性能がよくなることもある。
要するに、気づいていないアイデアがあるかも知れないということだ。
同じキャッシュラインのL1に対するLoadが1個増えると1clk遅くなると考えるのが普通だと思う。
しかし、試してみるとそれ以上に増えてしまう。
例えば、PenMでL2から1つ読むのに6clk。8つだと6+7=13clkと思いきや14.7clk。
L1もレイテンシは3あるわけで、その辺の負荷が大きいと思われる。
>>494 一般に「パイプラインがない=レイテンシとスループットが同じ」だと思うが正しい?
それで、パイプラインがないと毎回レイテンシをフルに食らうことになると思った。
でも順次アクセスなら大丈夫なのかな。
SDRはパイプライン持たないということだよね?
メモリの物理的なアドレス指定方法を知らないとダメか。
L2なら、64byte単位で記憶されているので、多分64byte単位のアクセスなら
ランダムでもシーケンシャルでもレイテンシ同じになるはず。
でもメモリは行と列なんかがあって、離れたところほどレイテンシが増えるはず。
Load命令は(Storeもそうだが)、CPU内のOoOユニットから発行されてしまったら最後、
基本的に先行するキャッシュミスしたLoad命令を追い越せない。
>>496 を見ると、PenIIでは4つまで追い越せるらしい。
L1ミスL2ヒットの場合も4つなんだろうか。
ただ、これは
>>497 で言われているOoOとは違う。
あちらはコントローラからメモリへの発行で、こちらはCPUからコントローラ(自信ない)。
>>494 のパイプラインもまた別で、メモリの中の話(かな?)。
>>496 それ知らなかった。測定結果に辻褄が合う構造を探しているだけだったので。
493で言ったのはOoOではなくパイプラインなので違うということになるのかな?
そのミスした4つって並列実行されてるのかね。
いくつまで追い越せるのかも気になる。
ちょっと過去のネタを。
>>132 lddquとmovdqu。
movdquは、キャッシュラインをまたぐとわかってから慌てて「2回のLoad」に切り替える。
またぐのがわかるのは、ロードアドレスを計算してからなので、かなり手遅れ。
パイプラインの最後の方まで来てから、別のμopを作って流さないといけない。
lddquは最初から「2回のLoad」にしておくのでペナルティがない。
当然ながら、命令をフェッチする前から「前後の16の倍数アドレスを両方読めば事足りる」
というのはわかっている。だからこそ可能になる芸当。
ただし、16byteのLoadが2回なので普段は倍遅い。
>>292 繰り返し回数が少ないときに「だんだん」現象が起こるのは、
メモリアクセスの範囲が広くても個数が少ないためキャッシュヒットしてしまうからだ。
>>293 L2は2MBなのに「1MB以上だと急に18clkになる」という現象。
これは別の要因によるものだった。
測定前にrdtsc / mov a,eax をしているが、このaがL2から追い出されてしまったのが原因。
rdtscの前にaをキャッシュに乗せるようにしたら普通の結果になった。
K8は排他式キャッシュだからLoadとStoreがあまり変わらないと思ったが、
結果をみると、そうでもない。
2Load/clkの力はあるにしても、Loadでもライトバックするので
Storeがそれほど不利になるとは思えないのだが。
DothanのL2(プリフェッチなし)は8*8byteLoadが14.7clk、Storeが19.9clk。
この差は64byteのライトバックにかかる手間によるものだと思われる。
64byteを4clkで転送ではないのかな。
そもそも、PentiumMのL2は省電力のために少し遅いものを使っていたはず。
BaniasのL2がレイテンシ9というのは、Tualatinの8と比べて、
キャッシュラインが大きいことを考慮に入れれば速いと言える。
何が遅いのかがわからない。
NoothwoodではL2に1個、8byte書くだけで12clkも食う。
読むのが2clkしかかからないので意味不明だ。L2への転送は遅いとか?
ここまで来ると、ハードの知識が必要になってくるな。
物理的な制約を知らないと、どこがネックか推測しにくい気がする。
>>501 読み書きのために、色々な技術が投入されてるんだな。
Prescottは、それを8に増やさないと同等の帯域が確保できなかったのかな。
ちっと閉塞感があるな。考えたパターンを全部測定しても規則性が見えない。 ここらでまた初心者の質問でもあるといいかも。 視点を変えるとわかるようになることもあるし。
んー、なんでP4ではPrefetch命令でL1 にロードしなくなったんだろう?
>>501 のところにはこう書いてある。
>データは L2 キャッシュに取り込まれ、 L1 キャッシュには取り込まれません。
>これは、L2 キャッシュよりも遙かに小さい L1 キャッシュを溢れさせないためです。
なんでだろうな。溢れさせたくなかったら、prefetcht0をやめてt1やntaを使えばいいだけなのに。
ただ、16byteLoadが一撃なので、L2実効帯域はプリフェッチ有りのPMやK8よりも素で速い。
L1は本当に小さいので、実装しても性能が上がらなかったという理由かな。
L2帯域だと、アクセス順を変えることによるプリフェッチが一番効くと思う。
これを試してみよう。
また、NetBurstのCeleronがないので、代わりにL2を切ったNoothwoodで実験する。
このスレ、普通にCeleron使い少なそうだよな。
P4って1次キャッシュっていいかたしてたっけ?
してるでしょ。 L1命令キャッシュがトレースキャッシュなだけで。
トレースキャッシュってNetBurst初期では1次キャッシュといういい方してないな。
安西先生…、128bit長のSSEレジスタを使ったEFLAGSに結果が反映される整数比較命令が欲しいです…。
>>506 データキャッシュのほうはL1と言ってるでしょ。
命令のほうは、トレースキャッシュがL1no代わりを務めているため、
命令L1が、無いわけだが。
512 :
509 :2005/06/17(金) 19:55:29
>>513 K8、cmovのレイテンシ1はすごいな。
64bit化では乗算が少し遅くなる程度の影響か。
P4のaddとかは、16bit*2はできても16bit*4を倍速で遅延なしに回すのは無理ってことだろうな。
スループットが正しい書き方(いつもは逆数)だから見辛い(w
>>509 が誘導先にいなくてガカーリ。
まあ、あれだ。分岐するよりマスク演算でゴリ押しの方が速いのだ。
でも、まれに分岐が必要なとき、すごく不便に感じるのは確か。
ポケコンで徹底的に分岐して処理を削っていたのが懐かすぃのう。
メモリベンチを改変。 SSE非対応と32byteキャッシュラインのCPUに対応し、アクセス順変えプリフェッチを追加。 アクセス順変えというのは、esi%64==16としてループに入る。 [esi+48]からのLoadがプリフェッチの役割を果たし、しかも命令数が増えないから速い。 ただ、遠くをプリフェッチするのは、不便とかいう以前になぜか効かない。 lp7: movaps xmm0,[esi+48] movaps xmm0,[esi] movaps xmm0,[esi+16] movaps xmm0,[esi+32] add esi,64 dec ecx jnz lp7 Noothwood、Banias、Coppermine-128kで試すことができた。 P4は、movaps*4がL2Loadで7.5clk。P6のL1帯域超えてますな。 prefetcht0は効かない。10clkに増える。仕様だから当然か。 アクセス順変えは効く。6clkにまでなる。これはすごい。 movq*8だと、15clk。movapsと比べて命令数が4増えただけで7.5clkも遅くなってる。 倍なので、movapsの方はL2へのリクエストを倍の頻度で出せたと予想。 >L1 データ・キャッシュでミスしながらもサービスされ得る処理中ロードの数を4から8に増やしました。 これかな。Noothwoodだから4。でもL2レイテンシは19で、たったの4では隠せないように思う。 何が4なんだろう。 アクセス順変えでは、9clkとかなりの高速化。 L1で8clk、L2→L1が2clkだから、L1→regとL2→L1が同時にできるのか!?
個人的に楽しみだったBaniasとDothanの比較。 L2のレイテンシが9か10かという違いがどう効くのか、対照実験ができる。 L2の64byteLoadは1clkに満たない違い。プリフェッチを使えば、全く差が出ない。 Storeで差が出る。4clk程度の差。Banias速いよ。 L1・L2間を往復するので倍の違いは出るだろうが、4clkは大きい。 上りと下りが競合するのかね。 プリフェッチしても少し差がある。 64byteおきLoadは6clkで同じ。64byteの転送にかかるのは6clkでいいようだ。 しかしハンパだな。どういうタイミングなんだ。 あとBaniasは、ハンパなmovntqが遅い。これはNoothwoodもそうだった。 Dothanでは64byteより8byteのmovntqが速いが、Baniasは8byteだと64byteの倍かかる。 どちらも64byteに収まるものはまとめて転送するが、穴があると困るようだ。 アクセス順変えメモリも遅い。 movntqでアクセス順を変えた場合、Dothanでは変わらないが、Baniasは8倍近く遅くなる。 movqのLoadでも、Dothanはプリフェッチとして64byteあたり3clk程度効くが、 Baniasでは全く効かない(遅くもならない)。 Noothwoodは、Dothanと同じ。 Banias→Dothanでは、この辺がかなり拡張されていたのだね。 Coppermine-128Kは、32byteのキャッシュラインを読むのに6clkかかる。 この前測ったTualatinのCeleronは2clkっぽかったのになあ。 そんな話は見たことあるので、「Celeronだから遅い」でいいと思う。 ただ、1個読むのに6clk強で、4個が7.5clk。 この「6clk」は遅くてもあまり性能に響かないように感じる。
忘れていたが、Coppermine-128KでL1をライトスルーにしたのもやってあった。
Load性能はほぼ変わらず、Storeが軒並み遅くなっている。
どうも、L2に対してだけでなくメモリに対してもライトスルーのようだ。
ただ、Storeで速くなっているのが32byteおきStore。
ライトスルーの性能的利点として、キャッシュミスしてもLoadせずにStoreできる
というのがある。(むしろライトバック式の欠点と言うべきだが)
これを考えれば、L2に対しては遅くなってもメモリに対するStoreは速くなるはずだが、
ライトスルーのモードでは「まとめて転送」が効かないらしく、遅くなっている。
32byteおきだと個数が少ないので何とか勝てたと。
movntqはそんなのお構いなしで同じ速さだった。L1無視の命令だからな。
P4のL2を切るのができなかった。どのキーでBIOS画面なんだorz
誰か機会があったらL2切ったP4で
>>446 の試してくれ。
元記事見たときには、さらっと読み飛ばしちゃったけど、4KB/1MBって メモリアクセスじゃなくて、キャッシュのアクセス速度かあ。BIOS関係 ないよね。
BIOSでロードされるマイクロコードのことなら完全に無関係とも言い切れないんじゃね?
キャッシュアクセスみたいな時間的にクリティカルなところに、 マイクロコードが関係するかな? 完全にハードワイヤードな 気がするんだけど。
x86系のCPUにおいてマイクロコードってエラッタの修正の為に使われるのであって、 そういうのには関係ないと思うが。
chipset叩いてRAMのアクセスタイミング変えるとかその程度だろ、BIOSでやるのって。
グラフ6の4KBの数字に注目してみた。 2.8GHzのFX-57では、21348MB/sなので、7.9946byte/clkとなる。 完全に8byte/clkと見ていい。 次に2.6GHzのFX-55は20643MB/s。明らかに8byte/clkを上回っている。 8byte/clkと仮定して逆算すると2.7GHzだが、これも考えにくい。 内部で違う測定ルーチンを使われているとか? 測定コードを知りたいな。 まあ、微妙なロジックの変更がたまたま悪く効いたのかもしれない。 ていうかメモリ性能ベンチって、数字が本当の理論帯域みたいな 印象を与えると思う。 測定ルーチンの書き方でいくらでも変わるのにな。
それはメモリに限ったことではないな ベンチ全般は逆アセ許可のバイナリかソースコードが無いと胡散臭い
>>525 というわけで、SuperPI(と同等のことをするベンチ)にも
ソース、キボンヌ
例えば、午後ベンチだったら、 午後のこ〜だでMP3を作るのにかかる時間がわかるわけだから、 ソースを見る必要はない。 たとえ特定のCPUにだけ最適化されていても、 そのソフトを使う限りにおいて、ベンチ結果は正義だ。 ただし、そこから他のエンコード系ソフトでの性能まで推測するのは、 場合によってはかなりの危険を含む。
あらゆるベンチマークソフトは性能の一端しかわからんけどな
正直、ベンチマークをするより、BIOSでL1やL2キャッシュを切ってみると、 キャッシュの有り難みがよくわかっていいかも。 L1切るといつまで待ってもWindowsが立ち上がらねえ('A`) L2切った場合はそんなにはっきりとは分からない。多少もっさりする程度。 しかしゲームなんかの3D計算を含むプログラムは、明らかにFPSが下がる。
従来の常識で考えれば、L2を大〜中粒度のバンクに分け 別々のバンクに各々のコアが独立アクセスできるようにしてあると思う。 L2が完全デュアルポートアクセスだとしたら、エレメントも配線も冗長になるため 面積がかなり膨れあがるんじゃないかな? ダイの写真見る限りじゃ、そういう類のものではなさげ。 ※K7/K8のL1D$は8バンク構成。バンクが衝突しない限りはLoadを2発行できる。
デスクトップもさっさとPentiumM系おりてきてほしいな 日本のマシンはTVパソコンとかがメインだから 結構PenM使うのもおおくなってきたけど 海外産のはコストのためにNetburstばかりだわ ストリーム処理が欠点だったけどマルチコアになれば大きく改善されるしね
Q:ところで本日公開されたBandwidth Adaptation Bufferについてもうすこし教えてください。 私が考えるに、通常のL2キャッシュは全体が1つのブロックとして動作するから、デュアルコアで 同時にアクセスすると帯域が減る事になります。そこでYonahでは複数のブロックに分けて 同時にアクセスできるようにした、という事でしょうか? A: そうではない。インタフェースは1つだけだ。例えばDothanの場合キャッシュラインにヒットして 読み出すまで4クロック掛かる。ところが、Yonah の場合、バスの幅が倍だ。このため、 2クロックで読み出しが可能になる。つまり、バンド幅自体は変わらない。 ただし、キャッシュをアクセスするのに必要な時間が半分に減ることになる。 従って、CPUコアから見れば倍の帯域として見える事になる。 Q:つまり資料(Photo08)には「倍の帯域」とありますが、正確には「半分のレイテンシ」という 理解でいいわけですか? A:その理解で正しい。
オフトピなツッコミだが、width って、ワイズじゃなくてウィドゥスだろ。 発音記号で書くと [widθ] だ。 よくある間違いではあるが、まさかインテルの人間までやるとは。
もうこれは昔からの誤用だからね 単体ではうぃどすといってもバンド幅はばんどわいずといったりしテルのよく聞く エネルギーとかミクロとかまぁいろいろとあるからかまわんけどね でもお願いですからHDDをハードっていうのは止めて下さい どこの会社いってもみんな略していってます ハードウェアと勘違いしますって orz
エネルギーはドイツ語かな。
まぁ、いきなりマッハのことをマークとかいわれても困る。
でもAthenaWidgetはアテナじゃなくてアシナなんだよね(謎
ratioをレートと書いてるのも結構あるぞ。
そ、それは余りにもあんまりだ……
キャッシュラインのバースト転送みたいなもんか
>>531 P6・PMもL1はバンクが違えばLoad・Storeが同時にできた。
(もっとも、実際にはmov系で1.5命令/clk出すのも難しい。何がネックなんだろ)
これなら、バッファがなくてもよさそうなもんだがな(見当外れ?)。
どの程度配線を増やせばいいのかとか全然わからん。
>>532 デュアルコアになるのは大きいよな。
SSEも多少強化されれば、現状のPentiumDと同等のベンチ結果は出せるだろう。
何より体感速度と発熱が抜群にいいから、高くても載せてほしいところ。
>>533 それって「倍の帯域」ということのような。
各コアから見た帯域が半分になるので帯域を倍にしました、というだけじゃない?
2clkで64byteのキャッシュラインをフィルできるという意味だと思うが、
L2が受けるリクエストの数も倍になるので、それをこなすだけの能力こそが問題。
あの、うんたらバッファというのはこのリクエストを溜めておくとこなのか?
あと、何のために「平均」と書いたのだろう。
[eax] から xmm0 と xmm1 両方に転送したいとします。 1: movaps xmm0,[eax] movaps xmm1,[eax] 2: movaps xmm0,[eax] movaps xmm1,xmm0 1と2のどちらを使うのが普通(速い)でしょうか? お詳しい方がいらっしゃいましたら、ぜひご教授下さい。 どうぞよろしくお願い致します。m(__)m
古いCPUだと2のほうが確実に速い。 現在のCPUの大多数は1のほうが速いはず キャッシュの構造によっては2が速い場合もあるかもしれないし、 パイプライン動作しない一部のCPUだったら今でも2が速いはず。 という感じかな?
いまやほとんどのハイエンドユーザーがPentiumMに傾いているのがわかったかも
549 :
545 :2005/07/16(土) 01:29:04
>546 どうもありがとうございます m(_ _)m 使用しているのはXeon 3.4GHz なので、1が速いという事になりそうですね。 勉強になりましたm(__)m m(__)m m(__)m
というかその後に続く命令によってあうとおぶおーだとか スレッドによってはHTによるパイプ補充とかあるから 単純にはいえないとしか 自分の環境で最速になっても他人の環境で最速にならないので注意 この点.NETやJavaは実行時にさしかえれるからいいわな
PenMって使ったこと無いけどPen4より速いの? 何が凄いのかよくわからん。
552 :
545 :2005/07/16(土) 01:58:57
>550 なるほど。 その後にもメモリアクセス命令がずっと連続します。 そういう場合は1より2の方が速いかもしれませんね。
>>551 大事なことかもしれないが、体感速度が速い
また、Javaや.NET、スクリプト系といった今の主流言語のダイナミックな動きに強い
元々モバイルように発熱が低いためオーバークロック耐性が高く
オーバークロックすれば86系最高性能が出る
オーバークロックしなくてもマルチコア時にちゃんと性能が出る、コア数を増やしやすいだろうと予想
PentiumDなんかが2個とも負荷かけるとクロックが下がるのとはわけが違うかと
所要クロックを測るようなロジカルなスレで 「体感速度が速い」とかいうエモーショナルなことを語られても 珍妙にしか見えませんな
「ダイナミックな動きに強い」というのも意味がサッパリ解らないのですが…
パイプラインが短いので、分岐予測がはずれた場合や インタラプトが入った場合に無駄にする時間が短い。 クロックあたりの性能(IPC)がPentium 4系よりも高い。 従って、低いクロックでも比較的高い性能が出る。 このため、同一性能を出すのに必要とする電力も少なく 結果として発熱も少ない。また今後の性能向上のための ヘッドルームも広い。(Pentium 4系シングルコア性能の 向上が止まったのは、発熱対策が限界に達し、これ以上 クロックを上げられなくなったから) とか言えばいいのにね。 ここら辺の特徴はAthlon/Athlon 64系とも共通している 話だけどね。
マルチコア性能は、インテル伝統のFSB方式がネックになりそうな Pentium-M 系より、point to point で HyperTransport を使う Athlon 64 系の方が良さそうな気がするね。
Yonah は L2 キャッシュ共有だから、FSB 接続じゃないのは 明らかですな。だから Pentium D よりはマシ。 L2 キャッシュが独立している Athlon 64 X2 とどちらがい いかは、アプリケーションに依存して、同一アプリがマルチ スレッドで走る場合には Yonah 有利で、異なるアプリが走 る場合は Athlon 64 X2 有利かな。 あと、Yonah は、Pentium 4 の HyperThreading の脆弱性と 同じセキュリティ問題がありそうね。モバイル用途なら問題 ないが、ブレードサーバ用途に転用すると、場合によっては 問題かな。
キャッシュ共有による脆弱性問題は L2共有程度なら問題ないレベルみたいだよ。 だから、この件はHTTやPower5系でなければ大丈夫。 もともと個人使用/非共用鯖には全く関係ないしね。
自作版に、PentiumMをOCして4GHzにして、SuperPI104万桁を19秒で 計算したスクリーンショットへのリンクが貼られていたが、あれが本物だと したらすごい。
つーか、ここでもそれはってあるから 3.5GHzを余裕で超えるというのはかなり前から言われてたよ 現在のハイエンドである2GHzちょいのPentiumMがPentium4の3.2GHzクラスの性能だから 3GHzいくというのがどいうことかわかるだろう ほぼ性能も同クロックのAthron64と同じだからねぇ
>>562 PenMの凄さがなんとなく分かった。ありがと。
>>545 lp:
movaps xmm0,[esi]
movaps xmm1,[esi]
mulps xmm0,xmm2
addps xmm1,xmm2
mulps xmm0,xmm1
movaps [esi],xmm0
add esi,16
dec ecx
jnz lp
メモリ操作が少ない例。1だと7020clk、2だと7304clk。
lp:
movdqa xmm0,[esi]
movdqa xmm1,xmm0
paddd xmm0,[esi+16]
psubd xmm1,[esi+32]
pxor xmm0,xmm1
movdqa [esi],xmm0
add esi,16
dec ecx
jnz lp
メモリ操作が多い例。1だと8056clk、2だと7134clk。
何の役に立つのかわからんコードですまん。いずれもPentiumMで1000回ループの数字。
俺は2の方が速いと思っていたのでちょっと意外だった。
PentiumMはP4やK8と違い、ピークでL1→xmmよりxmm→xmmのが倍速い。
だから1は不利なのだが、それでも上の例では1が速かった。
Pentium4ならL1→xmmが速くてxmm→xmmのレイテンシが長いため、1が有利と思われる。
まあ、メモリ命令と計算の命令の割合を見て、少ない種類の命令を選ぶといいだろう。
>>551 最近の速度が必要なアプリではP4向きのSIMDやマルチスレッドが多くなってきたので、
そういうのならPentium4は速い。K8でも勝てないくらいに。
ただ、動画でも変なフィルタかけたりすると古いx86命令が多くてPen4には辛い。
FPUは高レイテンシ。倍速ALUで1clk削ってもimulで10clk損すれば、計9clkの損。
実際に、非SIMDのプログラムだとIPCがPenMの半分近くまで落ちるのも珍しくない。
PentiumMの速さは、
・大きくて速いL1,L2。比較的低レイテンシで扱いやすい。L1も8wayだし32KBはP6の倍。
・分岐予測。強力なP4の機能をベースにループ検出器と間接分岐予測器を追加。
・μop-Fusion。少し複雑な命令のデコード・リタイヤが倍くらい速くなった。
・スタックエンジン。関数呼び出しのオーバーヘッドを低減。
Pentium4とは対極的なアーキテクチャ。ピーク性能はそこそこだが、
コンパイラが失敗したコード、キャッシュを考慮しない、関数を呼びまくる、
分岐を恐れず使う、命令のレイテンシをあまり考えてない、・・・etc
ある程度のダメコードならさほど遅くなく実行できる。
それが「体感速度」につながる。
世の中よくできたコードだらけじゃないしねぇ アセンブラによる最適化までやるのはもうほんの一握りのみ しかもそれがCより早くなるとは限らない それに最適化のターゲットとするCPUによって違う以上どうしようもない それに左右されにくいPenMは扱いやすい石と言える IntelとしてはNetburstアーキテクチャに最適化されたコードが 大量に出回ることを期待していたのかもね
でもさ、速度を必要とするアプリなんて数少ないわけで、 そのアプリの中でも速度を必要とする部分はごく一部なわけで、 そういう例外みたいなものは、 CPUに合わせてキッチリ最適化する手間をかける価値があるよね。 それで、ものすごく速くなるなら、いいんじゃないかな。 速度を必要としないアプリが速くても、 速度を必要とするアプリが速くできないよりはマシでしょう。
速度を欲しいとされるアプリってIDEかもね マシンパワーがいくら上がっても機能がどんどん増えて 快適になっていかないというか、これらはいわゆるPen4の体感速度は悪いほう 動画等のエンコードとかはまぁ問題なし マルチコアによる性能上昇が分かりやすいからYona以降で解決されるはず
動画のエンコードなんて、寝ている間にやりゃいいから、スピードはいらない。 IDEとかはマルチスレッド化しにくいので、マルチコアは解決策にならない。 やっぱりシングルスレッド性能が高いK8がウマーってことになるね。 そんな漏れは今だにVC6なので、古いPCで無問題。
CPU ぶん回していても、空いてる CPU でサクサク別の処理が出来る あの快適さを一度体験したらもう戻れないよ CPU 以外がネックだと意味ねーけど
バックグラウンドでCPUを食い続けるスレッドなんて、優先度をアイドルにしときゃいいじゃん。 んなことよりも、フォアグラウンドで人間が操作しているスレッドの速度が重要なんよ。
とりあえずあれだ、 PentiumPro 200MHzの4wayのPCと、 PentiumIII 800MHzシングルのPCで、 どっちが快適なのか考えたらわかるでしょうに。
>>544 Prescottって、倍速ALUを32bit*2に拡張したんだね(Noothwoodは16bit*2)。
それでレイテンシが0.5clkから1clkに伸びたと。
Yonahのトランジスタ数が少ないのは謎だ。
ていうか65nmプロセスなんだからもっとトランジスタ使えないのかね。
L2関係のトランジスタが意外に多いというオチを予想。
L2帯域は倍になり、共有での半減を打ち消したようだが、
このアーキテクチャは、2コア時の性能を(半減の)2倍にするというよりも、
そもそものL2性能を倍にしてしまうという贅沢な力技に見える。
シングルスレッド時の性能が高まるので、これができるならこれがいい。
こういう力技が使えなくなった後、バンク分けみたいな工夫で乗り切るのか?
>L2キャッシュは8レーン、4バンクで全部で32のブロックに分けられ、
>同時にこのうちの1つしかActiveにならないというメカニズム
Baniasの省電力の話。これが性能低下につながるのかを調べた。
DothanのL2レイテンシを、strideを変えて計測。
2MBのメモリを確保し、64byte〜128KB毎に依存関係のあるLoadをさせる。
(256KB以上のstrideだと、2MB中に8個以下なので8wayのL1にヒットしてしまう)
普通なら、1Loadあたり10clkとなるはず。
結果は64byte strideから順に、
10.7 11.2 11.5 11.8 12.6 13.9 17.2 19.6 19.9 15.9 16.5 16.3 (clk/load)
寝ているブロックを起こすレイテンシは見えない。
単純にメモリアクセスが入って遅くなっただけのような気がする。
消費電力の問題を無視するとして、 自分で最適化して走らせるならPentium4のが弄り甲斐がある。 実クロックが高い上にSSE/2が素直に回るから本当に速いだろうなあ。
とりあえずDothanを脇においてBaniasとYonahを比べると、 CPU Core + L1 +Bus I/F = 2038 (CPU Core + L1) × 2+Bus I/F = 3836 となり、CPU Core + L1が1798万トランジスタ、Bus I/Fが240万トランジスタという 遥かに現実的な数字が出てくる。勿論数字もラフなら計算の前提もラフすぎる わけであるが、YonahがDothanのDual CoreではなくBaniasのDual Coreだと考えれば、 トランジスタ数的にはわりと辻褄が合う感じだ。このあたりは、次に機会があったらまた (Eden氏に)確認してみたいと思うが、とりあえずそういうわけで、以前説明していた 数字は全部間違っていた事をお詫びしてレポートの締めとしたい。
http://pc.watch.impress.co.jp/docs/2003/0428/kaigai01.htm ●Jonahの開発スタートは2001年後半?
まず、Jonahについて整理すると、確実な情報は以下の2点となる。
・Dothanの後継となるモバイル専用CPU
・登場は遅くても2005年前半
BaniasはクオリティサンプルがOEM顧客に提供されたのが昨秋、エンジニアリングサンプルは
昨夏前だった言われている。その前にIntel社内のバリデーションを行っているはずなので、
Baniasのテープアウトは2002年前半ということになる。すると、Baniasの設計スタッフのうち一部は、
2001年中にはもう手が空いていたと考えられる。アーキテクチャ定義を行うアーキテクト達は
もっと前から空いていたはずだ。そのため、IntelはBanias/Dothanと平行してもう1ラインの設計を
並行して走らせることができたと考えられる。
●まだわからないプロセス技術
Jonahのプロセス技術についてはまだわからない。しかし、登場が2005年前半だとすると
まだ90nmである可能性が高い。
ヨナーはいろいろ言われているが、 その原因は「1年遅れた」ことにある。
マルチコア路線じゃないからまったく考え方がかわったのでは? まぁドタンもかなり遅れたしねぇ
さすがに「ドタンの前の世代のチップをデュアルにしますた!」とは言えないか・・・・
>>516 にあるようなドタンの改良点はどうなっているのかちょっと心配。
<a href=
581 :
↑リンク失敗 :2005/07/20(水) 20:40:24 BE:57581344-
>>564 546ですが...
[eax]から読み込んだデータが、
まだリネームレジスタかデータ転送用の一時レジスタ(アセンブラでは見えない)
あたりに残っているうちに、もういちど転送命令が来るため、
1を使うとデータ転送の後半部分を並列動作させる余地があるはずだが、
2を使う場合は、一つ目のムーブ命令が完了するまで
次の命令のソースとして使えないから、待ち合わせがおきる。
PenMでは、この待ち合わせを少なく抑える機能が付いたはずではあるけど、
まだ待ち合わせが起きることは事実、ということでは?
これが、下側のサンプル「メモリアクセスが多い例」だと、
二つ目のムーブが終わるまでロードストアユニットが
ふさがってしまうことになる1のほうが遅い。
ということは、ロードストアユニットが複数あるアスロン系では、
この例でも1が速い可能性があるのかな?
サンプルコードをPen4やAthlonXPやAthlon64で
所要クロック測定したら、いくらぐらいになるんだろう?
>>582 Loadが2回あっても、キャッシュから2回読まなくて済むケースか。気づかなかった。
1だと、(内部で並列動作していようと)Loadユニットを4回使う(と思う)ので、
それだとPenMでは確実に4clkを消費する(2だとベストケースで2clk)。
>>531 >K7/K8のL1D$は8バンク構成。バンクが衝突しない限りはLoadを2発行できる。
Athlonだと、同じ場所を読むとバンクが衝突するが、ひょっとしたら並列動作はできるかも。
物理的にはL1にアクセスせず、内部のレジスタから引っぱってこられれば。
この辺は知らない。中身はPenMと別物なCPUなので。
2を使うと、確かに待ち合わせがおきるが、レジスタ間movのレイテンシはPenMでは1clkなので
高々1clk遅れるにすぎない。OoOによりこの程度の遅れは隠蔽されるだろう。
待ち合わせを少なく抑える機能とは?できれば詳細。
movaps xmm0,[esi]
movaps xmm1,[esi]
movaps xmm2,[esi]
・・・
このように、ずらずらと並べた場合、PenMで2clk/命令。
物理的にL1から読んでいるかどうかはわからないが、クロック数は読んでいるのと同じ。
movaps [esi],xmm0
movaps xmm1,[esi]
Storeがリタイヤする前のLoadなら速い。これは2命令で2clk。
物理コピーじゃなくてリネームかな?
どちらにしろ、PenMではmovapsが2μopなので、更にmovaps xmm2,[esi]を
追加すると、1clkではなく2clk余計にかかる。
movdqu [esi],xmm0 を、手動でこのように分解したら速くなった。 movq [esi],xmm0 / punpckhqdq xmm0,xmm0 / movq [esi+8],xmm0 内部でmovq*2に分解してるだけちゃうんか。
>>585 デスクトップがNetBurstでなくなるのはめでたいが、
共通コアになるとデスクトップとノートの性能差が開くよな。
今で言えば、3GHz超にオーバークロックしたPentiumMが載るようなものだ。
ULV使いとしては置いていかれそうでコワヒ。
PentiumDだとチップ内で収まるはずの転送にも一旦バス経由でくるからかなり弱いよな とはいえこの値段差を考えれば無難というところか どちらにしろマルチスレッドにいかに対応するかで大きく性能が変わるから コンパイラオプションとかそういうレベルの話ではなくどうスライスさせるかとか 設計が重要になってくる
>>584 movlps, movhpsだとどんぐらい?
予想通りnetburst破棄が正式にきましたね
保守
●YonahのCPUコアの拡張 □命令デコーダの改良 ・uOPsフュージョンのSSE2命令への拡張 ・128bit SSE2命令を3個のデコーダでデコード可能に □SSE/SSE2命令最適化 ・SSE2 ShuffleとUnpack命令を30%高速化 ・整数除算(IDIV)の高速化 □SSE3命令サポート ・SSE3命令(10個)のサポート □浮動小数点演算性能の向上 ・FCW(FP precision/rounding control)レジスタのリネーミング ・データプリフェッチの拡張 ・ライトアウトプットバッファの追加 かなりいい感じだ
CPUごとに最適化を変えなきゃいけないから、 変えるならもっとドラスティックに変えて欲しい。
>>592 無難な改良ですな。
SSEばりばり使わないとあんまり恩恵なさそうですが。
>>593 それはx86互換を捨てない限り無理でないかい?
つまりはIntelのCPUを買ってIntelコンパイラを使ってIntel様の信者になれと言うわけだな。
597 :
593 :2005/09/07(水) 18:24:07
>>594 そこまでしなくてもいいけど、小出しにするのはやめて、と。
>>597 ドラスティックな変化はこの前あったじゃない。
ネ ッ ト バ ー ス ト
、、、改良とは思えないが。
NetBurstは名前のとおり、劇的に速くなったじゃないか。 ピーク性能を引き出してやれば、Athlon64をぶっちぎれる。
クロックだけは速くなったけど性能は出ず 発熱とか電力とかぶっちぎっただけじゃない PentiumM系の欠点ってSSE対応アプリだけだったんだし、 メインストリームに来て値段が下がるようだとかなりいいかもね 現状のハイエンドのPentiumMは恐ろしく早いし
性能を出せないのはヘタレプログラマですよ。
NetBurstはツンデレ
>>599 あの命令セットでパイプラインつまらせないのは至難の技じゃないか?
条件スキップ命令でもあればだいぶ楽になるが。
>>599 ピーク性能を引き出してやれば、Pentium Mをもぶっちぎれる。
つーか負荷かけるとクロック下がるんですが by PentiumD
それは空回りしまくりの時にブーストするための仕掛けだから。
609 :
デフォルトの名無しさん :2005/09/07(水) 23:06:40
お前ら試してから発言してるんだろうな?
>604 つ分岐予測
>>611 August 9, 2005
単なるエミュ。
後藤氏の記事(
>>592 )見たら、padd xmm,mem(現行PenMでは4μop)ですら1μop。
こりゃびっくりした。
ちょっと勘違いしていたが、μopsフュージョンというのは2μopのフュージョンに限らないんだな。
基本的にはいくつでもフュージョンできるはず(スケジュールの細かさは犠牲になるが)。
また、μopsフュージョンを使うのであれば、(原理的にはたぶん)
デコーダの負担はpadd xmm,mem もadd eax,ebx も違いはないはずだ。
ほんと、フュージョンというより「分解しない」だな。
デコーダにしてみれば、複雑デコーダの仕事が少し減って、
単純デコーダの仕事が少し増えただけ(仕事の質は大変になってない)。
強化されたのは、デコーダじゃなくてリオーダ・バッファ〜ディスパッチ周辺だろう。
(つまり、1つのROBから4つもの命令がOoOで発行され、全て完了したら一度にリタイヤする)
>>606 下がるらしいね。
3.2GHzと書いてあるのに、冷却の具合によっては常に3.2GHzを出せないとか。
俺はモバイル用ULVを使っているときに、似た機能が欲しいと思ったことがある。
ULV-1.1GHzなら、電圧をかければ、例えば1.4GHzなどは楽勝のはずなので、
PCが熱に耐えられる限界まで1.4GHzで回し、数秒の重い処理に対するレスポンスをよくする。
ただ、これを1.4GHzと称して売られたらヤだけど。
>>589 その命令の存在忘れてた。
そっちの方が少し速い場合が多いんじゃないかな。
実際に高速化するときは、最終段階で両方試して速い方にしますかね。
>>614 負荷かけると2.8GHzあたりで固定されたりするね
つまりPenDのローエンドと同じ性能になる
負荷かけないと3.2GHzでるけど、これはシングルスレッド性能を維持するため?
どっちにしろダメダメ>PenD
PenMの欠点だったSSEの改良+エンコード周りがYonaで一気に解決される見通しなので
PentiumM+マルチスレッドのお勉強をしてる人が今後は有利だな
やっぱり1GHz競争で負けたのがNetburstの無理な推進に踏み切ったのかな
TVショッピングではクロック数とHDDの容量だけアピールしてたしね
PenMはかなり不利だが、現在モデルナンバーなのでしのいでいるという感じ
>>615 なるほど!シングルスレッド性能の維持か。
デュアルコアならではだな。確かに
>>614 で言ったのよりは意味がある。
シングルスレッドならば、真の3.2GHzだからな。
連続ではなく、パルス的な負荷に対して、処理速度を改善するのなら、 3.2GHzなんてケチなことは言わず、4GHzくらいまでブーストして欲しいなぁ。 パイプラインがスカスカになるような処理なら、4GHzでブン回しても、 ほとんどの回路がお休み中になるでしょう。
ほんとのパルス的負荷に対してはクロックコントロールって使い物にならないんだよね。 負荷検知→(電源昇圧→)クロック変更のプロセスだからねー。
パルス的な負荷が発生するようなタスクは、多少クロックが上下した ところで総合的な処理能力は変わらないんじゃ?
スループットは同じでもレイテンシが短くなると思う。
>>618 負荷がかかったらクロックを上げるのではなく、
普段から一番速いクロックで回しておいて、
負荷がかかり続けたらクロックを下げればいいと思う。
>>620 負荷がゼロの時は最高クロックで回しておいて、負荷の量と逆比例
するようにクロックを下げるとかどう?w
プログラムを動かせば動かすほど遅くなる、不思議なCPUの出来上がり。ww
結局のところ、 パイプラインがスカスカならクロックがあがり、 パイプラインがみっちりならクロックがさがり、 トータルの仕事の量が同じになるようにすれば、 発熱も消費電力も一定になるわけで・・・。
クロック固定のファンつきPentiumM系でいいということになりそうだが。 ファンレスはクロック下げるからね。 そのへんが東芝あたりがXPSP2になってからの電力コントロールは便利。 SP2以前の東芝のはXP標準使ったほうがいいというくらいひどいのだったけど。
>>623 クロック2倍>>>消費電力2倍というところが動的クロック制御の前提だな。
俺が
>>614 みたいなことを考えたのは、
音をリアルタイムで処理するプログラムや、一時的に負荷の上がるゲームなんかで、
「10秒ぐらいなら1.4GHzを出せる潜在能力があるのになあ」と思ったから。
パルス的とまでなるとなあ。切り替えに0.29秒かかるわけだから。
実際、PenM@SpeedStepよりもCerelonMの方がレスポンスがいいくらいだし。
実際にやるとしたら
>>620 >>621 みたいな感じかなあ。
でもこれって、PentiumDそのまんまな気も・・・。
>>623 クロックが高いときは性能/電力がかなり落ちるぜ。
下手な切り替えをすると仕事にかかる時間がかえって増えてしまうことさえあるだろう。
総合的な電力量は、クロックが高いと電圧も高いので増える。
ただし、クロックが低すぎても時間がかかりCPU以外の電力消費が増える。
>>624 俺は東芝のXPProSP1だが、SP2だと何が変わったの?
SpeedStepオン、CPU速度低下優先、CPU使用率100%のとき、
俺のだと最高クロック固定のまま、熱ダレして遅くなる(
>>410 )。
>>625 モデルによって違うかもしれないけど、SpeedStepが常にきいていてBIOSで切らないと
体感速度がCeleronより低いとかでる
>>410 を見る限り比較的新しいモデルにみえて改善してきた・・・のかな?
今の東芝のは設定状態に応じてファンを優先か、自動かクロック低下を優先か、
可変クロックの場合クロックは600MHzから1.2GHzにするとか細かいことが可能
ファンを優先すれば常にフルスピードが可能だが、多少うるさくなるしバッテリで弱い
だから電源がつながっていればファン優先で常にTOPスピードでぶん回すけど、
バッテリ使用時はバッテリが80%くらいまでは600MHzから1.6GHzの可変で
ファンとクロック調整を自動で、50%きってきたら画面を少し暗めにして
600MHzから1.4GHzにしてファンはとめてクロック低下を優先にして・・・とか
そういう感じで設定しておいてあとは勝手にやってくれる
それ以来ファンレスのノートはもう買わなくなりました
ファンは使っても使わなくてもいいんだから問題ではない
実際去年の夏ULVPenMのファンレスレッツノート死んだし
通常電圧版でファンつきでもういいやと
>>627 それはSPのせいじゃなくて東芝がたまたま手を抜いたバージョンだったんじゃないかね。
確認したわけではないが、東芝の省電力ユーティリティは以前から評判がいいよ。
通常電圧版でもファンレスできるならいいね。
Dothan-ULV1.1でファンレスにすると、518MHz相当にまで落ちるのでややきつい。
ていうか、ファンレス動作はまさに
>>620 みたいな感じになるね。
Yonahについての予想(ていうか期待)。 共有L2は、バス幅がDothanの倍になるみたいなので、 64byteのキャッシュラインの読み出しが、Dothanの4clkからYonahでは2clkになる。 これは、単純に考えてスループット2倍、レイテンシ2clk減の効果がある。 ということは、共有のオーバーヘッドがあっても、レイテンシはさほど悪化しないと思う。 また、Banias→Dothanのときと違い、L2には大きな変更が加えられている。 なので、L2を多用するシングルスレッドアプリの性能向上を期待している。 FPの強化は、フラグレジスタのリネームとかしか聞かないので 演算ユニット自体は変わらないのかね。 それでもμopsフュージョンすればSSE*で1〜2割の改善はあると思う。
>>629 そのたまたまてをぬいたというやつが1年半ほど前の
大人気の東芝の1スピンドル軽量ノートだったもんだからたいへんなことに
あとXPSP2じゃないとESITのコントロールはうごかんよ
SP1だとダメ
上はEISTの入力ミス
>>631 え、S9ですか!?あれは欲しかったなあ(てそろそろスレ違い)。
EISTはPen4のじゃなくて?
PenMなら昔からできてたんじゃないかな。
ていうか俺のSP1でも省電力ユーティリティ使ってできるし。
あ、SP1だったかも まぁSP1単体ではPen4もまともにうごかんけどね でも東芝ならOSの省電力ユーティリティかくさない? 新しいやつは隠さないけどね
えと、Pen4のEISTはSP2が必要。 俺はPenMを東芝の省電力ユーティリティで使っている。 ということでありまつ。 Meromのパイプライン14段らしいが、デコードを含んでいるのかが気になる。
>>630 >共有L2は、バス幅がDothanの倍になるみたいなので、
>64byteのキャッシュラインの読み出しが、Dothanの4clkからYonahでは2clkになる。
ソースきぼん。
そこまで速いということになったら、L1キャッシュと変わんねーべ?
帯域が2倍になるというのはインテルがはっきりといってたが シングルコアがアクセスする速度が2倍になるとは書いてなかったはず レイテンシが長い以上L2が高速化したところでL1と同じにはならんよ
Pen4のSIMDユニットは何bitで周波数はコアクロックの何倍か。
http://pc7.2ch.net/test/read.cgi/jisaku/1125251094/ このスレから移動。俺は792,837,839,840。
俺は128bit半速だと思っていた。
>また、ファスト・クロックの1/4で動作するセクションもありますが、
>これも設計を容易にすることを目的としています。
ファスト・クロックってのは倍速のこと。半速の部分もあるとIntelは言っている。
また、所要クロックがほとんど偶数、SSE2整数のスループットとレイテンシが同じ、
一度Pen4でSSEを触ったときにクロック表通りに回ったのでPenMとは違うと思った。
ただ、これだとMMXのスループットが1であることに説明がつかない。
また、向こうのスレで言われて気づいたがpunpck系のLとHでクロックが違うのも64bitっぽい。
で、整数SIMDは64bitで2-1タイミングのユニットが1つあると考えると辻褄が合うような気がしてきた。 独立(上位64bitと下位64bitは独立)な2-1を2回やれば3-2になるが、 次のSIMD命令ともオーバーラップさせれば実質2-2で回る。 これはPenMの、4-2のaddpsが実質3-2で回るのと同じ原理。 ただ、これだと、PenMとPen4でIntelのドキュメントにあるクロック数の表記法が違うことになる。 Pen4の書き方は、64bit分解系のレイテンシが1少なく書いてあり、他の上位下位の順番と 合わせられないpunpck系のような命令は1多く書いてあるんじゃないかな(全くの予想)。 punpckは、Lの方が速いから、下位64bitを先にやるのかね。 でも実質演算量でもHよりLの方が実は少ないんだよな(64bitの場合)。 これは64bitっぽいニオイがする。 SSEのFPはどうなのかとか、気になる点はまだある。 64bitだとすると、Intelの言う半速ユニットはどこにあるのかがわからない。 128bitだとしても、MMXの命令を2つまとめてから半速128bitに送るのなら スループット1と言えなくもない。 パック・シャッフルなどのクロック数を実測してみたいところだ。 どっちだかわからなくなってきた。実機がないとキツイ。
純粋に内部データバスが64bitのままなんで2クロックだとか Yonaみてみたいなー
>>642 よくわからないということ。
どちらだと仮定しても気になる点が残るので。
誰か、気になる人はいないですか。
向こうのスレでも、128bit派の俺と64bit派の人たちがそれぞれ意見を言ってたけど、
相手がおかしいと言った点に対してどっちも反論できてないもんな。
大きな疑問点は、
64bitとすると、半速ユニットはどこにあるのか。
128bitとすると、punpck系のクロック数、MMXのスループットが変。
なんだこのスレの
>>1 が書いてたんだね。向こうに…。
NetBurstのFP系ユニットが半速っていうのを向こうで最初に言い出したのは漏れなんだけど、
ちゃんと海外の著名なアセンブラサイトでもそういう結論ででてたから、書いたんだよな。
漏れは完全なハード屋でプログラムはやらないから自分では確認してないけどね。
PrescottのFP系のレイテンシが2の倍数でないのは何故? PMUL**はFP_MUL
失敗した PrescottのFP系のレイテンシが2の倍数でないのは何故? PMUL**はFP_MULを使うけどスループットが1なのは何故?
64bitの半速ユニットが2つあると考えたらどうだろうか。
これなら何とか辻褄が合うんじゃないか。
俺は
>>152 でPen4を触ったとき、感触が128bitだと思ったが、
スケジューラの性能が良い、μopsフュージョン相当の技術が使われている、
などの理由でそう思ったのかもしれない。
>>644 邪魔したならごめんよ。
よければそのサイトを教えてくれ。
>>646 64bit半速と仮定しても矛盾か。
うーん。
浮動小数点演算を半分に分けて計算するのは困難だろ
>>397 の話題。
色々試してみたんだが、divとユニットが競合しているっぽいのはmulpsだけだった。
それも、397を見るに最大でも51-20*2=11clkしか競合してない。
mulpd(7-4と遅い)だとほとんど競合が見られない。
で、新しく作った測定ルーチンでmulpsの個数を色々変えてみると、
mulpsが7個で36clk、8個で50clk。8個でも、divの位置を変えると43clkになったり。
多分、mulpsを発行するタイミングを逃してるんじゃないかと思う。
そういやスケジューラの仕組みって全く知らないな・・・。
lp:
mov ebx,1000000
mov eax,ebx
mov edx,1
div ebx
mulps xmm0,xmm0
mulps xmm1,xmm1
・・・
dec ecx
jnz lp
>>29 のアンパックは3-2でなく1-1が正しい。
おそらく測定時にunpck(l/h)p「s」と間違えた。
Intelのpdfでandpsが2-2とあるのは、P6のクロックと間違えたのか?
で、確かにunpck(l/h)pdは1-1のタイミングだが、その割にはちょっと遅い。
実行ユニットを2つ使うのは当然として、2つのμopに依存性があるんだと思う。
packuswbはmul側のユニットでのみ実行できる。だからXMMだと2clkかかる。
addpd xmm0,xmm0 / unpck(l/h)pd xmm0,xmm0 がレイテンシ(4/5)。 Lの方が速い。 ここではxmm0の下位からaddしてるようだ。 下位の足し算のレイテンシが3で、その後下位を上位へ1clkで移動、計4clk。 ただ、Hの場合は、上位を下位に移動してからその上位に上位を移動する。 xmm0同士でも仕様通りくそ真面目にやる場合、上位からaddしても5clkは必ずかかる。 そもそもunpcklpdが演算器2つ食うのだが、これが変。 srcの下位からdstの上位に移動するだけなのに。unpckhpdと回路を共有する都合? addpd xmm0,xmm0 / shufpd xmm0,xmm0,hoge は、hogeに関係なくレイテンシ5。 シャッフルは2clk。足し算は上位からやってもいいみたいだな。 ↑これ、addpdのレイテンシが4になるケースを見つけようとしていたのだが、どうも難しい。 SSE*の設計が64bitなことがよくわかった。 128bitの演算器が必要な命令が全然ない。 pmovmskbは、MMXでもXMMでも同じ負荷に見える。 128bitかと驚いたが、XMMの上位64bitと下位64bitを入力としてeaxに出力すると考えれば 他の64bit演算と同じだ。明確に3オペランド。内部RISCだからOKでしょ。 addpd xmm0,xmm0 / pmovmskb eax,xmm0 / movd xmm0,eax これが、何と5clkちょい。 むむ、addpdの上位下位両方終わるのに4clk、その後1命令1clkでも6clkかかっちまう。 movdで上位が0になるからかと思ってpunpcklqdqを入れたが、それでも変わらず。 謎だ。 この命令は、XMMレジスタの上位と下位を必ず同時に使う貴重な命令だと思ったのに。
なんかわかりづらいな。 PentiumMで、divはほとんどの命令と並列実行できるということと、 addpdのレイテンシが4になるケースが見つからないという話。 基本的に、ジャンプがadd側、その他のある程度複雑な命令(lea,shrなど)はmul側を使う。 mov,addなどの単純な命令は両方で実行できる。
Pen4で測定。短時間で測るのはきついぜ。
addps xmm0,xmm0/ andps xmm0,xmm0 の繰り返しのレイテンシが8。
Intelのpdfを見ると、addpsは4-2、andpsも4-2と書いてある。
だからその通りのクロック数なのだが、andps単独で測ると2-2になる。
pandは公称2-2でandpsより速いが、実はandpsと交換してもクロック数は変わらない。
>>61 >K8でxmmレジスタに対するpandとandpdのクロックが違うのはなぜ?同じ動作なのに。
これも多分同じことで、pandとandpdのクロック数は、本当は全く同じだと思う。
同じ動作のアンパックがFPとintで違うように書いてあるのも、
測定してみたら同じクロック数だとわかった。
paddqは、MMXで2-1、XMMは6-2とある。XMMの方は単独での実測4-2。
paddq xmm0,xmm0 / pand xmm0,xmm0 の繰り返しレイテンシは8。
ここから俺の推測。 P4のandpsは64bitで4-2のユニットを2回稼動して実行している。 そしてその64bitのFP実行ユニットは2つある。 XMMを64bitずつ分けて実行すればレイテンシは隠蔽され、6-2でなく公称の4-2に見える。 ただしandpsは128bit揃わないと実行できないため、 6-2がもろに効いて、2-2のandpsと足して8レイテンシになるのだ。 andpsはpandと内部μopでは同じで、タイミング合わせをサボって 128bit終わってからなら確実だろとかになっちゃうのかな。 Pen4のSIMDユニットは64bit半速*2。 ユニットは2つあるのでMMXは2-1のタイミングになる。 Pen4でaddssとaddpsはどちらも4-2だが、これはユニットが128bitだからではなく、 addssは(下位用の)片方のユニットしか使っていないから。 本当は6-2だが、連続してやればレイテンシが隠蔽されて4-2になる。 しかし、隠蔽できない相手の命令(andpsなど)は、その命令のレイテンシが 実際より2だけ大きく表記されている。 XMMのpaddqは内部で何やってるのかな。MMXだと2-1、XMMだと6-2。 64bit加算だからレイテンシが大きくて自然だが、MMXならきれいにレイテンシ2で回る。 これは他のpaddと同じ。なのにXMMだと遅い。 わからないのがPrescottの奇数レイテンシ。 クロック表を見ると、FPとして扱うところだけレイテンシが1増えている。 FPだけ半速でないとすれば普通にわかるんだが。
勉強になるスレだ。 素朴な疑問として、何でいまだにx86系の浮動小数点レジスタはスタック式なんだろ。 単に互換性を保つようにしているからか?
「単に」と言うが それ(互換性を保ったこと)がx86が普及した最大の要因だとは思わないかい?
そういやWindows x64 edition は、浮動小数点演算はSSEのみじゃなかったっけ?
MMXはそろそろ普及した感じがするけど、 まだ、SSE必須のプログラムを無言で出せる時期じゃないと思う。 スタック式をやめるのにも相当な時間がかかるだろう。 で、64bitのWindowsでFPU(MMX)を使わなくなったのは スタック式脱却(将来のx86から従来のFPUを消す)のためだと思っていたが、 実際どうなんだろうね。 消すにしても、32bitアプリを使いたい間は消せないし。
X86-64に対応して且つSSE搭載してないCPUは存在しないからx86-64でFPU切り捨てても何の問題もない。 IA-32のほうはもうこのままのFPUだと思うが。今更手を入れる理由もないし。
しかし、1は演算器と実行ユニットが1対1だと勘違いしてるっぽいのがいただけないな。 実際には単にSSE/FPUといってもサブユニットがたくさん…。
サブユニットがたくさんあるとなんかあるのか?
単純にIntelのマニュアルのレイテンシ表みてもなかなかクロック数から 演算器の動作速度まで把握するのは難しいだろ。
基本的に
>>1 の勉強スレ
つーか
>>1 を肴にしてあれこれってスタンスで
>>659 確かにそうだな。すまん。ちょっと間違った書き方をしてしまった。
>スタック式をやめるのにも相当な時間がかかるだろう。
これは、ずっと以前からやめたいと思っていたけどやめられなかったんだ、と言いたかった。
実際はx64で完全にSSEへ移行できるから、この点は近い将来解決するね。
俺がもっと気にしているのは、64bitOSが一般化したときに、
「メインの64bit環境で使わない80bitのFPUを実装するのがもったいない」ということ。
64bitOSがソフトで切り捨てるのと、64bitCPUがハードで切り捨てるのは別の問題。
たとえWin64環境でも、32bitアプリも使えないと困る状況が非常に長く続くと思われる。
これでは、Windowsが全て64bitに移行したとしても、従来型FPU実装の負担が減らない。
(ハードを作るのが大変という意味で)
別の問題になるが、64bitアプリで80bit精度のFPUを使えないのも寂しい。
まあ、将来的に従来型FPU廃止という前提の話だけど。
そんなこと言ったらx86自体廃止か(AMD64のおかげで当面はないだろうけど)。
>>660 SSE用のFPユニットという1つの演算器でaddpsもmulpdもこなすような書き方だったな、俺。
まあ正直、演算器と実行ユニットという言葉を明確に区別して使ってなかった。
以後少しだけ気をつけると思う。
ALUユニット、FPユニット、MMXユニット、・・・このそれぞれが実行ユニットで、
ALUユニットの中でもaddする演算器とandする演算器と・・・てカンジ?
でもPen4の最適化マニュアルの図を見ると、
>Port1>FP Execute>FP_ADD>addps
たくさん階層があるな。
どれが実行ユニットでどれが演算器?ていうか区別がわからん・・・。
ディスパッチャがPortに発行して更に2回振り分けるのか?
詳しいことは何も知らんのだが、ユニット内の別演算器がロジックを共有してたりはするの?
ところで、半速で動いているのはFP Executeだろうな。
FP Moveは別ユニットだから、movapdのスループットが1なのもわかる。
ただ、faddもFP_ADDなんだよね。同じFP_ADD内で半速と等速が同居って変だよな。
じゃあfaddは5-2のユニット(?)が2つか?addssが4-1でなく4-2なのもわからんな。
Prescottでは、faddも6-1でレイテンシが1増えてるんだよね。
FPUは半速じゃないと思ってたけど、わかんなくなってきたな。
半速ユニットが、偶数クロックのみ動くのかとかも気になる。
内部レジスタが128bitだと、レジスタを部分的に書き換える命令は、特殊な制御が必要になる? もしくは特殊な制御をすれば4-1にできるが、シンプルにするために4-2になっている?
>レジスタを部分的に書き換える命令は、特殊な制御が必要になる? unpck(l/h)pdとか?Lが4-1と速いのは64bit動作だからだろう。 ただ、別に128bit化されても問題は起きないと思う。 xor eax,1 だって、eaxを部分的に書き換えるが、動作は遅くない。 問題なのは、32bitのレジスタの一部を「16bitとして」使うような場合。 内部で違う形式で扱うときに変換が必要になり、パーシャルレジスタストールが起こる。 これも、mov ax,[eax] を、dword ptr [eax] とマスクを使った32bit演算に変換すれば 前後のストールは起きないんじゃないかな。 (間違ってるかもしれないので補足訂正ぷりーず) そういえば、inc / dec ってフラグの中でキャリーフラグだけ変化させないから、 Pen4ではパーシャルレジスタストールが起きるんだよな。 クロックを上げるための変更だろうが、なぜこうなるんだ?
>>667 inc/decでパーシャルフラグストールが起こりうるのはP6系。
Netburstではincは加算μOPとフラグ合成μOPの2μOPで処理されるので、
パーシャルフラグストールは起こらないはず。
P6系は、ほとんどのケースでは、フラグ合成は必要ないだろうということで
フラグ合成μOPをはしょっているので、
フラグ合成が必要だと後から検出された場合、慌ててパイプラインをやり直す。
>>668 え、逆なの。
てことはP6系でincを使うと遅くなる場面がある?
レジスタは何となくわかるが、パーシャルフラグはイメージが難しいな。
P4ではその「慌ててやり直す」を実装すると倍速はキツイと思ったのかな。
addが0.5-0.5で、incが1-0.5だから大して遅くなってもいない。
確かにストールしてるクロック数じゃないかも。
http://pcweb.mycom.co.jp/special/2004/dothan/001.html >アクセス長が異なるデータのリードライトを効率的に管理できるようになったという
Dothanではパーシャルライトなどができるようになったらしい。
とりあえず感じをつかむために測定。
普通のdec ecx / jnz で1000回ループのクロック数を測定した(Dothan)。
2206clk mov eax,ebx / mov edx,eax
4346clk mov ax,bx / mov edx,eax
4346clk mov al,ah / mov edx,eax
2227clk mov eax,ebx / mov dx,ax
2206clk mov eax,ebx / mov al,ah
2227clk mov eax,ebx / mov ax,dx
後でパーシャルメモリとかも調べるつもり。
こんなケースも調べてはどうかというのがあったら書いてくれれば測定する。
パーシャルはNetBurstの方が早いってのは、 海外サイトで漏れもよんだよ。
>>1 は書き込みの時間帯からして学生だろう。
この手のハードウエアの本質に迫るような、本来のプログラミングの考え方は
海外のリソースの方がはるかに充実しているというか国内は話になってない。
今のうちから英語の資料に普段から慣れ親しんでおくことをお勧めする。
多分、にちゃんねるレベルでは
>>1 が一人で悩んでいるだけで、
まっとうなレスがつかないよ。
674 :
668 :2005/10/23(日) 05:53:03
>>668 「慌ててパイプラインをやり直す」ではなく、
「リタイアユニットでフラグが確定するまで待つ」でした。
>>671 サンクス。そのページを参考に色々測定してみた。
肝心のパーシャルフラグは、原理がわかったら書いてある他の内容に興味が
出てきてしまったのでまた今度測定。
lp:
mov ax,[esi]
add edx,eax ;←ここでストールするはずなのだが
add esi,2
dec ecx
jnz lp
何かこれ、movをmovzxにしても全く同じ1000回ループ4680clk。
これがDothanでの改良点なのか?
この場合movとmovzxは動作が違うからmovが使えるのは嬉しい。
ちなみにmov eax,[esi] とした場合は2109clk。movzxの内部処理はそれなりに重い。
ただ、alとahに依存性がないというのは変わっていない。
add al,al / add ah,ah を続けても、ちゃんと2命令1clkで並列実行されている。
さすがに、その直後にadd eax,eax を入れると遅くなる。とはいえ3135→6576clk程度。
パーシャルリードはOKだそうだが、これは、
mov bx,ax というのはaxから読んでもeaxから読んでも同じだからかな。
xor eax,eax / mov al,3 / mov ebx,eax は、xorによって速くなっている。
ただし、xorをなくしても2clkくらいしか遅くならない。
パーシャルメモリはさすがにまともに食らう。2clkちょいの処理が、ストールすると10clkになる。 ストールしたときに18個(9clk分)のnopを挿入しても同じクロック数だった。 mov [esi],eax / mov bh,[esi+1] はストールするが、 mov edx,eax / mov bh,dh はストールしないんだな。 mov [esi],al / mov ebx,[esi+4096] これ、ほんとにストールして驚いた。 違うcache banksでも同じset-valueのときにはストールするらしい。 PenMの場合、set-valueが同じとは、アドレス値を4096で割った余りが同じということ。 多分、[esi]も[esi+4096]も「このアドレスありますか?」とL1キャッシュの同じ部署に 問い合わせて競合するのだろう。 でも、このタイミングならキャッシュを通さずにCPU内でデータをやり取りしないのかな。 それとも、単に「パーシャルライトがあった」という情報をset-value毎にしか保存しない? よく考えると、この辺のやり取りを数clkで判断して回す今のCPUってすごいな。
>>672 そんな気はしてたけど、やっぱりそう?
まあ、がんがります。(最近やる気なくてすまん)
てか、こういうことに興味がある人って本当に少ないんだねえ。。
Pen4は、mov ax,bx のようなのもmovLowPart eax,ebx みたいに32bit処理なのかな。
mov ax,[mem] のときにメモリから何bit読んでるんだろう。
今までパーシャルレジスタストールというネタをやってこなかったのは、
ストールしなかったら嬉しいコードを書いたり使ったりの経験があまりなかったから。
実際、これで困ってる人って今は多くないんじゃないかな。
http://www.agner.org/assem/testp.zipを落としたら 、rdpmcが使えるようになった。
movをmovzxに変えてもクロック数が変わらなかったと書いたが、
パーシャルレジスタストールは1000回ループで2003回と、どちらも同じだった。
一応ストールしてる扱いなんだね。
面白いのは、ストールする命令数が1000*2==2000個なのに2003回ストールしていること。
ループの数が64回を超えると、少し余計にループを実行するらしい。
ここにループ検出器が見える。
BrMispred(分岐予測ミス)は64回以下のループならゼロ。それ以上だと1回。
つまり、64回以下のループを完全に予測する。
それ以上のループなら多少予測を外しても性能に影響が出ないということだろう。
5000命令、6000μops、2003ストール、5023デコード、1分岐予測ミスということだった。
movzx系は2μop。予測ミスで23回も余計にデコードしている。
その23命令の内、実行されてストールするステージまで進んだのは3つということか。
このμopの数は、フュージョンしたμopの数で、add eax,[ebx] などは1個のカウント。
そして、やっとパーシャルフラグストール。
lp:
cmovbe esi,edi
cmp eax,ebx
dec ecx
jnz lp
これが9clk/loopかかる。
ちなみに、cmovとcmpを入れ替えると2.8clk/loop程度になる。6clkの損だ。
パーシャルレジスタストールのカウンタは反応しない様子。
cmpがフラグをセットし、decがCFを変えずにZFを変える。
そしてcmovbeがCFとZFの両方を読むのでストールが起こる。
cmovcでもストールは起こる。decで変えられていないフラグを読むのがまずいらしい。 decのフラグがセットされてリタイヤできるまで待つということかな。 CFがまずいということは、adcもストールを起こすということだ。 多倍長データの加算でadcって実は遅いのだ。 lp: mov eax,[edi+ecx*4] mov ebx,[esi+ecx*4] adc eax,ebx mov [edi+ecx*4],eax dec ecx jnz lp これは10clk/loop。 dec ecx をsub ecx,1 に変えれば3clk/loop。でもこれじゃ加算にならない。 7clkも遅い。decを使うのはCFを保存するための工夫なので、かなりジレンマ。 add dl,0ffh ;ここをedxにするとパーシャルレジスタストール adc eax,ebx setc dl このようにしたら4clk/loopになった。setcでCFをdlに保存し、addでCFをセットする。 まあ、ループをアンロールすれば済む問題だがなw
movzxでストールしてしまうというのは驚き。 これ↓でストールが発生してしまうって事だよね? movzx eax,word ptr [esi] add edx,eax
>677 >てか、こういうことに興味がある人って本当に少ないんだねえ。。 興味はあるが、コアが変わると使い物にならなくなる最適化には時間を割けない。 特に業務だと移植性の低いものは絶望的。 でもこのスレは非常に面白い、というよりも興味深い。 こういうノウハウはコンパイラなんかに活かされると嬉しいなぁ。 チラシの裏でスマソ。
コンパイラを作ってるんでしょ? ちまちま人間が最適化するなんて無理だよ。 昔と違って今は、考慮すべきものが多くなりすぎて、とてもとても・・・。 前後20命令くらいにわたって、パイプラインがどう流れるか考えて、 確率的にベターなものを選ばないといけないんだよ? AMDが無償で配布しているCodeAnalystを使ってみるとわかるけどさ、 きっちり綺麗にパイプラインが流れるコードを書いたとしても、 すこし前にパイプラインが乱れると、その影響を引きずってしまうのよ。
今後はTLPが最適化のポイントになってくるから ひとつのコアの最適化に頼るのではなく、 2つのコアがどうすれば効率よく回るかってのが重要になってくるだろうね。 これはパイプラインがどうつまるかを検証するよりはるかに難しい。 バスの取り合いとか共有2次キャッシュの取り合いとかそのへんをチェックか。 そういやHTってある意味共有2次キャッシュなんだよね。
>>680 俺の考えだと、movの場合でもmovzxのような処理を取り入れて、
ストールは起きていないけれどもカウンタは回るということじゃないかと。
ストールしてないにしては若干遅い気もするが、以前のP6の結果待ちだな。
Intelのマニュアル3にrdpmcのことが書いてある。
>Number of cycles or event for partial stalls. This includes flag partial stalls.
フラグのパーシャルストールも含むらしいが、
>>678 ではカウントされなかった。
今試したら、パーシャルメモリアクセスにも反応しない。
P6とは仕様が変わったのかな。
>>682 パイプラインが乱れると言っても、そのせいで有意差をもって遅くはならないと思う。
20段なんてクソ長くなればそれなりに影響しそうな気がするが。
「パイプラインが乱れる」って、例えば20段のパイプラインの中に
泡(命令のない場所)がいくつかあるっていうことだよね。
普通に考えると泡の個数分だけのクロック遅れる。
ループの中で乱れて、乱れを引きずり、1ループ当たりのクロック数が
ループを出るまでずっと長いままってことはないと思う。
あるとすれば、命令のアラインが変なときで、これはループ前にalign 16とでも
書いておけば基本的に問題ないはず。
>>685 分岐予測ミスがなければパイプラインの長さは関係ないと思う。
分岐予測ミスがなくなるなんてありえねー
100%的中させる予測器か… 予知能力が必要ですな。
いや、完全なエミュレートをすれば100%的中も夢じゃない。 #完全なエミュレートをどうやって高速に実現するかは別の問題。
>>684 P6で計測してみました。
>>678 はお手軽に計測できて便利だね。
以下のループの場合、1ループ当たり
10clk,5命令,5μOPs,パーシャルレジスタストール7.67cycle
lp:
mov ax,[esi]
add edx,eax
add esi,2
dec ecx
jnz lp
以下のループの場合、1ループ当たり
2clk,5命令,5μOPs,パーシャルレジスタストール0
lp:
movzx eax,word ptr [esi]
add edx,eax
add esi,2
dec ecx
jnz lp
という結果でした。
P6ではmovzxはメモリオペランドでも1μOPなのが売りだった。
Dothanではmovzxは2μOPsになってしまい、
その代わり、パーシャルレジスタストールの時間が
かなり短くなったということかな?
あと、P6でもパーシャルフラグストールは
パフォーマンスカウンタのパーシャルストールには
カウントされないみたい。
>>684 の記述はマニュアルのミスっぽいね。
>#完全なエミュレートをどうやって高速に実現するかは別の問題 そういう問題じゃないんだよ 完全な予測器があれば,まず確実により高速で不完全な予測器が構成できて トータルではそっちの方が速い,ってことになるから 完全な予測器には工学的な意味があまりないんだ
>>675 (自己レス)
えーと、大変な間違いを犯していました。
"mov ax,[esi]" の "movをmovzxにしても全く同じ1000回ループ4680clk"とある。
馬鹿正直にmovをmovzxに変え、movzx ax,[esi] で測定していた。
本来はmovzx eax,word ptr [esi] と書くべきだった。
本当は、Dothanでmovzxは1μopでパーシャルストールのカウンタも反応しない。
movzxという命令に対する無知が原因です。
>>680 、
>>690 、申し訳ないです。
>>690 上のコードは、4.6clk、6μop、パーシャルレジスタストール2[clk?]。
下のコードはそのP6の結果と同じでした。
確かにDothanではパーシャルレジスタが改善されている。
それから、パーシャルストールの値を見ると、P6ではクロック数を返すのだね。
Dothanでも多分クロック数だな。偶数が出ることが多い。
実際にストールしているわけではないので、きれいなクロック数になるのだろう。
まとめ。
Dothanではmovzxの振る舞いはP6と同じ。1μopで速い。
パーシャルレジスタの動作はP6と違い、μopが1つ余計に発行されストールは起きない。
ただしrdpmcで見るとパーシャルストールとしてカウントはされている。
ループ当たりのクロック数が4.6clkとか半端なのは2μop命令でデコードがきついのだろう。
分岐予測なんてヒットしなくていいんですよ。 その間に他のスレッドを実行すりゃいいんですよ。 エロい人にはそれが、わからんのですよ。
Intelはエロすぎるな
>>693 やっぱりそうだと思った。
普段から*word ptrを省略して書いてると
movzxやx87命令でミスを犯すんだよね。
そういえば32bit-Pen4でもmov ax,[esi]は2μop。
>>682 > ちまちま人間が最適化するなんて無理だよ。
まぁ状況にもよるけど、アセンブラレベルの知識があるかないかで
C言語レベルでの最適化で随分差がつくよね。コンパイラは万能ではないよ。
> 昔と違って今は、考慮すべきものが多くなりすぎて、とてもとても・・・。
MMX/SSEになるとそうでもなくてむしろ時代に逆行してる。
普通の整数演算だけのコードでコンパイラに勝とうとするのは無謀だけど、
unpckhpsとかrsqrtpsとかshufpsとかを(普通にfloatで書いたコードに対して)
使いこなしてくれるコンパイラなんて無いなわけで(ほとんどパズル)。
> 前後20命令くらいにわたって、パイプラインがどう流れるか考えて、
> 確率的にベターなものを選ばないといけないんだよ?
> AMDが無償で配布しているCodeAnalystを使ってみるとわかるけどさ、
> きっちり綺麗にパイプラインが流れるコードを書いたとしても、
> すこし前にパイプラインが乱れると、その影響を引きずってしまうのよ。
経験的にいわしてもらえばあんましそうでもない気がする。
AMDの石にとっちゃぁx86というのはJAVAのように抽象化された命令らしく、
ちょっとやそっと命令の並べ方変えたぐらいじゃ性能はほとんど変わらない。
(スケジューラがそのへんのコンパイラより化け物)
結局将棋の場合と似てて、詰め将棋ならコンピュータのほうが圧倒的に強いけど
将棋では人間には勝てない。しかも特殊な動きをする駒(SIMD)がちょくちょく出現し
ルールもしょっちゅう変わってコンパイラは定石なかなかを含蓄できない。
当面は、人間様がアプリケーションの持つ並列性を抽出してコンパイラに教えて
あげたり(依存性、分岐のないCコードを書く)、SIMDでハンドコーディングする時代が
くると思う。
> 当面は、人間様がアプリケーションの持つ並列性を抽出してコンパイラに教えて > あげたり(依存性、分岐のないCコードを書く)、SIMDでハンドコーディングする時代が > くると思う。 まあもっかの答えはHPF。 SIMDでハンドコーディングする時代ってのはまさに今だろ。 かなりコンパイラの対応も進んできたし。
>>693 >パーシャルレジスタの動作はP6と違い、μopが1つ余計に発行されストールは起きない。
この、μopを1つ付け足すか否かの判断はいつしているんだろうね?
32bit-Pen4では mov ax,[esi] は前後の命令シーケンスによらず常に2μopのようだけど、
Dothanでも常に2μop?
それとも前後の命令シーケンスに応じて1μopになったり2μopになったりする?
>>700 > ちょっとやそっと命令の並べ方変えたぐらいじゃ性能はほとんど変わらない。
x86を内部命令に変換してOOOで実行する性能は、
インテルのP6とAMDのK7、K8で、それほどは変らなかったです。
インテルのNetBurstだと、命令の並び順によって性能が変わってきます。
OOO性能が落ちているのか、OOOしきれないのかは、わからないけどね。
既存のC/C++の文法では、コンパイラに分岐予測のヒントを与えられないですよね。
IA-64環境の場合、コンパイルした後に、プロファイラによって自動的にヒントを付加するらしい。
>703 初回通過時はif-then-elseのthenの方が実行されると予測する。
P4から分岐ヒントプリフィックスが追加されたけど、 AMDにはまだないんだっけ?
>>702 鋭いな。確かに、Dothanでは普段は1μopだ。
パーシャルレジスタストールが起きるようなコードでだけ2μopにカウントされている。
デコード段階で判断するのは難しそうだが、後でやるとストールするしなぁ。
そもそも、mov ax,[esi] とadd edx,eax のどちらが2μopなのだろうか。
それとも「どちらの」とは決められない場所で生まれるμopなのかね。
>>703 NetBurstは、俺がSIMD系命令を少し触った感じだとOoO性能は悪くなかった。
命令の並び順で性能が変わったのは、
レイテンシが長い命令などで高いOoO性能を要求されるようになったからかなあ。
分岐ヒントは、Pen4にはあるけどサポートしているコンパイラあるのかな。
使われているプログラムはどうやって作ったんだろう。
gcc 2.96 以降なら __builtin_expect() ってので指定できる。 NetBSD では、これを __predict_true()/__predict_false() って マクロでラップして使ってる。
>>707 i386だとヒント吐いてくれない。
iccあたりが対応してるんでないかい。
>>708 あれ、本当だ。
ただ、全然効いてないわけじゃなくて、ブロックの移動は
してくれるみたいよ。if 文なら、expect した方にはジャンプ
しないようにする (expect してない方にジャンプする) とか。
一応使えるんだね、分岐ヒント。
>>697 トレースキャッシュは遅いけど熱対策のために導入したとか
けっこう面白い話があるよな。
数字の見積もりには同意しかねるが、
この人がアセンブラいじり出したら面白そう。
>>706 やはり状況に応じてμopが追加されたり、されなかったりする訳だね。
途中で湧いてくるμopというのは興味深い。
たるさん・・・の記事は、 一見マニアックで詳しそうだけど、 実はトンデモな素人解説だったりするのよ。
>>712 同意。
だが、その色んな考え方を確かめる過程で、間接的には勉強になったということ。
ところで、Pen4がトレースキャッシュなのは実際なぜなんだろうね。
トレースキャッシュの利点は、(1)「(キャッシュヒットする限り)デコードを省略できる」こと。
トレースキャッシュの欠点は、(2)「命令長が長い」(3)「ミスヒット時のペナルティが大きい」。
(2)は、欠点というよりx86の利点だ(今では可変長が大きな欠点だが)。
(3)は、普通の命令キャッシュだと、L2からL1命令に転送するだけだが、
トレースキャッシュだとL2から読んで(おそらく)貧弱なデコーダでデコードする必要がある。
(1)は確かに発熱を抑える。デコーダを貧弱にすればピーク消費電力も抑えられる。
ただ、熱問題で破綻したNetBurstがそれを気にしていたとは考えにくい。
(1)は分岐予測ミスのペナルティが少なくなるという利点もあり、こちらが本音だろう。
デコード抜かしてパイプライン20段(31段)ということは、デコーダ入れたら・・・恐ろしい。
デコーダがクリティカルパスにならないからクロック向上にも寄与するかな?
(2)は命令キャッシュヒット率が減るということ。(3)と相まって、ペナルティは大きい。
中間言語に弱いのはこの辺かね。
SIMD系なら、Pen4向けに書けば問題にならないと思うので、
ピーキーなネトバとしては、この辺を無視してでもクロックを上げたいところだろう。
これ書いてからふと思い出したが、こんな記事があった。
http://pc.watch.impress.co.jp/docs/2004/0310/kaigai072.htm >NetBurstではデコーダ部分のトランスレーションを複雑化することが容易になった
なるほど、デコーダにリソースを割かないだけでなく、機能を複雑化することもできるね。
ていうかこのレスの内容、これ読んで考えたことばっかだった。
Meromはどうなんだろう。
パイプラインは14段らしいが、これは今のPentiumMとほぼ同じだ。
635でも少し言ったが、これはトレースキャッシュなせいじゃないかと思う。
それなりに強いデコーダを載せ、更に(2)をμopsフュージョンで解決するのではないか。
そうすれば、命令密度も上がるし、スケジュールもしやすい。
ALUが4個載るということなので、フュージョンなしでは演算器が遊んでしまう。
http://www.geocities.jp/andosprocinfo/wadai05/20050827.htm >MutiplyとAdd命令をくっつけてMultiply Accumulate命令にするMacro OP Fusion
なんじゃこりゃ。でも命令帯域、スケジュールを考えると有用かも。
多分、デコード段階でmov edx,[esi] / add eax,edx をAthlonのようにまとめてしまう
ということもできるのだろう。
フルスクラッチっぽいので、P6→PenMよりもP6→Pen4の変化に近いと思う。
一見Yonahと同じようなデュアルコアだが、別物の性能でデスクトップで大活躍しそう。
設計方針か結果論かは別として デコーダのスループットは劣悪な罠 クロックあたり最高1つのx86 opだな デコーダネックでクロックがageられないのを嫌ったものと思われ たるさんはプログラミングもマイクロアーキテクチャも素人だけど 読み物としてはそこそこオモロイので折れは好きだ
Pen4がトレースキャッシュ採用したのは、
長いパイプラインで分岐予測ミスのペナルティ低減と、
ハイパースレッディングのため。
それから、分岐予測機構を強化するためじゃないの?
>>1 よ、もっと勉強してくれ。
>>716 その、ハイパースレッディングと分岐予測機構強化というのは何故?
トレースキャッシュは分岐予測をもとに実行トレースを生成して、 それを保持しておくのが目的で、デコーダの後にあるのはもともとそのためだから。 単なるuops用の命令キャッシュではないぞ。
>>719 その説明だと単なるuops用の命令キャッシュに見える
いや、単なるuopsのキャッシュだったら、名前もuops-cacheでいいだろ。 トレースキャッシュはもっとインテリジェントで、分岐予測機能付きだから。 分岐予測に基づいて実行トレースを生成することによって、フェッチの効率 をあげているわけだから。それにトレースキャッシュ自体の分岐予測の おかげで、トレースキャッシュミスをしないこと前提で、後続の分岐予測器 の構造も簡素化できるわけで。
例えば、こんなコードの場合。 lp: sub ecx,1 jnz lp トレースキャッシュにはどういう風に入るのだ。 sub / jnz ←さすがにこれだよね? sub / jnz / sub / jnz / ・・・ sub / sub / sub / ・・・ >分岐予測をもとに実行トレースを生成 分岐する/しないを交互に繰り返すjccで、動的予測が完全ヒットのとき、 その「する/しない」を一塊としてキャッシュに乗せるとか?
(・∀・)アハハ えらそうなことをいって実は漏れも詳細までは把握していないんだけどね。 TraceCacheの最初の論文よみますか?英文読む気あるならリンクしてやるぞ。
で、ハイパースレッディングのためという部分に関しての説明は?
>>713 > 今回の「64-bit Extension Technology(通称IA-32e、コードネームClackamas:クラカマス)」も、
> 相当部分がMicrocodeで実装されていると見られる。
これが本命かと。
デコーダが疎結合なのは、設計変更が楽だということだよね。
>>730 AMD64互換にあんなに早く追随できたのもそのおかげだそうだし
てことは、NetBurst系が終わると、 IA-64対応なデコーダを持ったNetBurstという夢も潰えるのか。
なんでEPICなIA64がNetBurstの技術をいるんだ
IA-64とXeonのFSBやチップセットを共通化する構想がある XeonがIA-64に対応すればソフトウェアも共通化できる
バスインタフェースと内部アーキテクチャは 関係ないような気がするんだが。
関係ないな それに共通化構想はロードマップから消えた
ついでに、命令セットと内部アーキテクチャも関係ない。 IA-64命令を実行するからといって、中身までEPICである必要はないよ。
ああ、そういえば聞いたことあったな。 IA-64命令をデコードできるように NetBurstに拡張機能をつけるとかいうの。 NetBurstのCPUで、低速ながらも(?)IA-64アプリを 動作させれるようにして、 IA-64の普及を促進させようとねらってたんでしょ? PowerPC615と同じ運命をたどったな。 (x86命令をデコードできるPPC) 出る前に敗退・消滅って。
逆じゃなかったか?
逆ってぇと、 IA-64チップであるItaniumにx86命令を 実行できるようにってヤツか? そんなの、とっくにあるだろ?
Itaniumは初代からx86命令のデコーダを持ってますよ。 エミュレーションのほうが速くなったので、もう廃止しようという話だけど。 もしNetBurstが早々にIA-64命令をそれなりの速度で 実行することができていたら、 AMD64の出る幕はなかったかもしれない。
すでに出まわっている64ビット拡張と別の64ビット拡張は許さない というのがマイクロソフトのスタンスだったわけで、 すでに出まわっている64ビット拡張が、 もしIA-64だったら、 許されない別の64ビット拡張は、 AMD64になりますよ。
( ゚д゚)ポカーン
>744 IA-64は「x86の64ビット拡張」じゃなくて x86命令を実行するエミュを内部に(?)持つだけの、 全く別の(新規の)64ビットCPUだからな。 これを「64ビット拡張」と呼んでいいんなら、 AlphaAXPだって (WinNT上で、エミュを使ってx86アプリを実行していた実績があるんだから) 64ビット拡張と(強引に)呼んでもいいことになってしまわないか?
M$はIA-32との下位互換が無い拡張は認めなかったでFA
>>1 よ、そろそろ戻ってこい。
IA-64の話は詰まらん。
http://pcweb.mycom.co.jp/column/architecture/003/ >プロセサが計算処理を行うには回路のスイッチが必要であるが、
>例えば、Wordで文章を編集しているような処理では浮動小数点演算は不要であり、
>浮動小数点演算器は動作する必要はない。しかし、浮動小数点演算器にクロックが
>供給されているとスイッチが行われてしまい無駄な電力を消費してしまう。
>つまり、動作に必要ではない回路へのクロック供給を止めてしまえば、消費電力を
>減らすことが可能である。これがクロックゲーティングという手法であり、電力低減が
>必須の最近のプロセサでは広く用いられている。
これ気になるでしょ?
>>1 への宿題。
突発的にFPU命令を使用する整数/FP混在プログラム書いて、
レイテンシを測定してみてくれ。クロックゲーティングの影響が出るかもよ。
トレースキャッシュよくわからん。
気が向いたら調べるつもりだけど、ちょっと置いておく。
>>749 宿題って、自分でやれよ。最近のおまいらは自分の手で測定するというk(ry
(でも、そういう書き込み自体は、俺にとってはありがたいけど)
で、確かに気になるので実験しようと思う。
とりあえず、測定にかかるような遅延はないと予想しておく。
性能に影響が出ない実装だろうから。
測定方法が難しいんだよな。俺の常套手段であるループが使えないっぽい。
Yonah T1500(2GHz)のSuper PI 1Mのスコア
ttp://nueda.main.jp/blog/archives/001879.html ベンチに使われているCPUは、T1500という2GのYonahデュアルコア。
- T1500 : 2.00GHz(333x6)/FSB667/共有型L2 2MB:06年Q1:US$420
- Super PI 1M シングル起動時:30s
- Super PI 1M デュアル起動時:34s/35s
X2 4800+相当(2.4G)で34秒
SuperPIはディスクアクセスしてるから、 キャッシュの容量がものをいうよ。
それだと2MのPen4とかもかなり速いはずだが実際はあれだ
最新のプロセッサのL1キャッシュ性能を検索してこのスレの23が引っかかった俺がきましたよ 面白そうだったから最後まで読みふけってたらこんな時間になってしまった
よう、時間の無駄だったな
>>749 こんなコードでいいのかな。
数ミリ秒単位になってくるとOS上では正確に測れないね。
その範囲でecxに足す数字を変えて試すと、クロック数は常にその数+26or27。
5msの間FPUを使わなくても、FPUは寝ないのか、それとも寝てもすぐ起きるのか。
寝かせるのは1秒単位の粗い制御でも効果はあると思うけど、どうなんだろ。
まあ、実用的・ベンチ結果的に悪影響が出ることはないだろう。
そもそも、この技術が素直に使われているかわからんけど。
mov ecx,[esi]
add ecx,10000000
lp:
dec ecx
jnz lp
mov [esi],ecx
fild [esi]
fadd st,st
fistp [esi]
>>751 それはYonah速いってことか。
デュアル動作でも1個だけ起動なら30秒出せるんだよね?
俺のDothan-1.1GHzで68秒。
普通、クロックを倍にしても時間は半分にならないものだが、これは速いなあ。
考えられそうな原因は、FSBと使用メモリだな。
個人的にはL2キャッシュとHWプリフェッチの強化も効いたと思いたい。
また、FCWレジスタのリネーミングが効くようなプログラムではないだろう。
>>752 HDDアクセスを速くするのは、HDD内蔵キャッシュかOSのディスクキャッシュ(メインメモリ上)。
もちろん、そのディスクキャッシュ自体がCPUのキャッシュに乗れば言うことなしだが、
キャッシュはメモリを高速に扱うためのものなので、直接HDDアクセスに関係する話ではない。
SuperPIは要するにFFTベンチだろうから、FPUとメモリ・キャッシュがものをいうはず。
タスクマネージャで見ると、100万桁では8MBを使うようだ。
本来、多倍長数値の計算にFFTを使ってもランダムアクセスは回避できるのだが、
K6でライトアロケートをオンにすると遅くなったからSuperPIはランダムライトがあると
どっかで読んだことがある。
http://www.geocities.co.jp/SiliconValley-Bay/9439/negoto/ngt006.htm ここだった。
可能性としてはあると思う。
ライトアロケートがオフだと、L1ヒットしない書き込みのときに直接L2かメモリに書く。
L2に対するmovntqみたいな感じ。
L2→L1の余計なロードがないので再利用しないランダムライトには強い。
普通のライトバック式ならライトアロケートもオンだよな?
FFTの処理は、
>>186 で書いたマージソートみたいな流れで行う(メモリアクセスに関しては)。
再帰で局所的に処理するとキャッシュサイズが比較的リニアに効く。
そうでないときは一定量以下のキャッシュはほとんど効かない。
これはさすがに再帰のFFTだろう。
Pen4だと、FPUのレイテンシが長いのとL1キャッシュが小さいことで遅くなるだろう。
Athlonは、L1とメモリと特にFPUが良い。L2が排他でさえなければPenMよりずっと速いと思う。
PenMは、処理の多くを高速なL2で行えるため速い。その他のパワーは普通。
余談だが、Yonah、Meromと、K8には脅威となるCPUが出てくるとき、
K8の最後の切り札はL2キャッシュだと思う。排他処理やめてくれ。
何かやめない理由があるのだろうか?
1次キャッシュが大きいから2次キャッシュサイズが256Kとか512Kとか小さいときはそれがベストだったのでは 1Mくらいになってくると重なってもいいような気はするけどね それよりK8の厄介なところはモデルナンバーが交互にキャッシュサイズが半減するということ キャッシュサイズを見て最適化するというのは普通だと思うのだが、これによってかなり厄介に
Yonaの通常電圧版のローエンドでもPenD820は余裕で超えるっぽいな しかも値段はDothanとほぼかわらず、電力消費みたら涙が出る差に
う〜ん、低価格モデルであるSempronでの、 性能低下を最小限に抑えたいから? そのために上位モデルの性能を落とすのはバカすぎるけど。 ところで、 機会があったらK6-2(手持ちは400MHz)とか Cylix M2(166MHz)でもベンチとってみたいんだけど、 よさげな測定ファイルある? いや、不要ならいいんだが。 どっちも、MMXには対応してるがSSEは対応しない。 L1は内蔵するがL2は外付け66MHz(オンボード) あっと、ひょっとしたらママン死亡で動かないかも。
K8の排他キャッシュは、ベンチでは不利だけど、L2が512KB程度なら実性能で効果があり、
1MBになったらやめたくても単独の仕様変更は急には無理だった・・・てな感じかなぁ。
>>760 あれ、FSBは逆転してもYonahのが速いのか。
(俺がFSBと言ったのは軽率だったな。重要なのはメモリの速さ)
DothanのメモリはDDR400か。それだとオーバークロックでDDR600相当になる。
Yonahはどんなメモリだろう。いいチップセットは使ってそうだけど。
どちらにせよ、メモリ性能ではそんなに変わらないのにYonah速いということか。むう。
知らないうちにFPU強化してたりとかはしないだろうしなあ。
こりゃL2レイテンシにかなり期待できるってことか!?
SuperPIにランダムライトがあるとすれば、全体で数%の寄与はあるはず。
共有のオーバーヘッドがあるからダメかな。
自作板のSuperPIスレ見ると、同じDothanでもかなりバラつきがあるな。
でも、最近チップセット周辺に疎いので下手にコメントできない。
>>762 いいね。
cpu-zのレイテンシ測定や
>>47 のLoadBenchなど。
よければこれも。
>>491 のやつ。急遽3D Now!のプリフェッチにも対応(動くかな・・・)。
http://rerere.sytes.net/up/source/up10515.zip 32byte lineでSSE非対応だから1を入力して測ってくだされ。
K6-2では6の3D Now!でもおk(のはず)。
結果はresult.txt。
上からLc、Ln、Lm、とある意味は、
Lc:キャッシュラインから1つ読むのに必要なクロック数。
Ln:普通にキャッシュラインの全てのデータを読むのに必要なクロック数。
Lm:アクセス順変えプリフェッチを使ってキャッシュライン全てを読むクロック数。
Sはストア。SSE対応でのNはmovntq等を使ったストア。
横軸はアクセス範囲。
メモリベンチはちゃんとしたのを作ろうという思いはあるのだが、できてなかったな。
・Win+VC以外でも簡単にコンパイルできるソース
・結果を2chに貼り付けたとき見やすい
・CPU名やSSEの対応くらいは自動判別
面倒だな・・・。
PentiumMと一口に言っても 855GMはバスが400MHzのDDR266 855GMEはバスが400MHzのDDR333 915GMはバスが533MHzのデュアルチャネルDDR2/533 と大きく分けて3種類くらいあります ビデオチップの性能もそれぞれ大きく異なります メモリ性能で言えば915でいっきに跳ね上がりました UMAなビデオ性能ももちろんびっくりするくらい別物になりました YonaがDDR2/533から大きく変わるとは思えないのでバスクロックが多少上がった程度でしょう とはいえ533から666は25%も向上していますし、軽量系に多い400からは1.5倍以上になってます 元々PenM系はキャッシュ容量を増やしてUMAによるメモリアクセスのウエイトの 影響を隠していますので666でもなんとかデュアルコアでバス取り合うようなことは少ない ような気がします とはいえ、効率よく動けば動くほどもうぎりぎりでしょう
πもみみたいな古いコードを速く走らせる事ができても、 古いアプリしか恩恵がないような気もするが…
古いコードが速く動く=それはそれですばらしい 新しいコード=デュアルコアに最適化
最近のアプリは拡張命令だけで書かれてているのか? 知らなかった
>>765 どうもです。
DDR2/533デュアルはすごいな。ビデオに帯域を回しても全然OKそうだ。
その分だと、YonahもFSBを使い切るだけの帯域のメモリを載せてたっぽいな。
でも、SuperPIで重要なのがレイテンシだった場合、メモリモジュールは大して関係ないかも。
DDR2/533とDDR333のレイテンシって実時間でそんなに変わらないし。
シングル動作が30秒で、2個起動で34秒・35秒と遅くなる原因としては、
L2キャッシュの量・L2キャッシュの帯域・FSBを奪い合うことが主なものだろう。
使えるL2が減ってメモリアクセスが増えても、メモリアクセスの絶対量が少なければ競合しない。
多ければ競合して、メモリアクセスで遅くなった上、待たされて遅くなる。
http://hirobee.jp/archives/2005/08/07/ AthlonのX2だと、2つ起動しても1秒ちょいしか遅くなってない。
この1秒はFSBの取り合いだろう。
ということは、4〜5秒遅くなったYonahでL2を取り合うことでの性能低下は大きい。
使えるL2容量が半分になっても、FFT演算の1段分だけなのでガクッとは遅くならないはず。
帯域を取り合うのが効くのかな。
FSBで1〜2秒、L2容量で1秒、L2帯域で2秒、いや容量はもうちょっと効くか。
共有L2ゆえの要素が重なれば5秒の遅れは当然っぽい。
逆に言えば、共有用の強力なL2がシングルスレッドの性能にも生かせているとも言える。
(ひょっとしたら共有処理でモタついてるだけかもしれんけど)
Banias→DothanでもSuperPIはかなり速くなっているらしい。
これはキャッシュ量というよりメモリ周辺ではないだろうか。
>>766 それは忘れちゃいかんよね。
SuperPIの実験@Dothan-1.1(SuperPI 100万桁は68秒)
共有L2に近い状況として、シングルコアでSuperPIを2つ起動してみた。
100万桁は144秒で終了し、タスクマネージャで見るとCPU時間は72秒ずつ。
タスクスイッチのオーバーヘッドは1秒以下とすれば、4秒弱の遅れだ。
Yonahはコア毎にL2の割り当て量を決めるらしいが、その点はYonah有利。あとL1が個別。
Dothanは、時間的にFSBやL2帯域の競合が起こらない点が有利。
状況が違うので比較しにくいが、「L2を共有すると4秒程度遅れるっぽい」というのは
何となく納得できたようなできないような。
メモリ性能の寄与を確かめるため、600MHzにクロックダウンして測定。
1個起動だと115秒。2個だと237秒。
遅れは3.5秒。
メモリはDDR266のままのようなので、これを1.1GHz換算すると、DDR488相当。
単純計算では、488MHzの低レイテンシメモリを使えばDothan-1.1は63秒になる。5秒も速い。
そのときの2個起動の遅れは2秒弱。
メモリが速ければL2が少ない影響は少なくなる。当たり前か。
次に、VBでDo:LoopというCPU使用率100%のプログラムを作り、それと共にSuperPIを実行する。
135秒だったが、CPU時間は69秒。影響はほとんどないようだ。
そしてL2殺しのプログラム。ひたすら2MBの配列にストアし続けるプログラムで実験。
147秒で、CPU時間は73秒。
相手がSuperPIのときと、あまり変わらない。
VBでDoEventsを入れると他のスレッドに処理を渡すのだが、
2MBのストアをする度にDoEventsするようにすると、159秒/CPU時間106秒。
VB側のCPU使用率はむしろ下がるが、小まめにキャッシュをかきまわされ、撃沈。
>>332 でL2オフにしたときは138秒だったが、
これは、HWプリフェッチ無効、命令のL2キャッシュもゼロなので特別遅いのだろう。
共有2Mのために単純に2つに分ければ2次キャッシュが半分になるから それだけでは? メモリが少ないときはHDDの速度に大きく左右されてたのがSuperPI 2次キャッシュに左右されてもおかしくはないだろう そしてAthlon64X2はそれぞれのキャッシュを持っている さて、問題はこのTDP27Wな石がPenDは余裕で凌駕し、デスクトップ最強の AthlonX2並の性能を持ってるということ Netburst捨てたくなる気持ちがよく分かる
>>771 L2容量半減は明らかな要素だが、L2帯域やFSBの取り合いの寄与も知りたかったのよ。
俺がSuperPIの測定をした意図も、
PenM系においてSuperPIはどこがボトルネックになっているか調べるため。
結局よくわからなかったけど。
確かに容量半減は普通に考えて大きく効くよね。
Yonahは、シングルでDothanより高いIPC、しかもデュアルコア。
ただ、SuperPIはYonahのL2がはまっただけかもしれない。パワー自体はP6程度だし。
自作板の次世代AMDスレでレイテンシ15とあったのも気になる。
まあ、実際にSuperPIで悪いL2じゃないことは示されてるけど、
DothanとはL2の性格がかなり変わるような感じがする。
あっちで話題になってたビットカウント面白そう。
この前のインテルのお話だと2次キャッシュの大域を今までの2倍に引き上げて 2コアからのアクセスに耐えれるようにした、と書いてるよね そう考えるとシングルスレッドだと従来のコアに比べて単純な性能アップ、 2スレッドで従来どおりの性能+キャッシュ半減効果って考えれるんじゃないかな とりあえず、このすれとしてはPenM系が主流となることで 所要クロックの計測は比較的容易になるのではないかな
コアのキャッシュ奪い合いで問題になるのは帯域ではなくてエントリだろ。 使おうと思ってたものが、もう片方のコアによって、キャッシュ上から消えてたらダメじゃん。
エントリも帯域もどっちもだろ 4クロックだったのが2クロックになったとインテルの説明があったから それの影響は無視できないと思われ
>>774 SuperPIが、FPUよりもメモリを鬼のように使うものなら、帯域は大いに問題になる。
(だが、問題になるかどうかは俺にはわからなかった)
エントリの問題は容量の問題と同じことだよね?
ここは、コア毎にL2容量を分配するので、この仕組みがうまく働けば
奪い合って無駄に性能低下することなく、各コアが1MBのL2として使用できるはず。
>>767 ふるいにも限度があります。
486DX4が売れ線の時代にコンパイルされたソフトなんて…。
ループのアンロールすらされてね。
486時代のソフトなら本来の1/10の速度が出なくても 十分速すぎるんじゃね?
そういう問題ではなくて、この時代のソフトを動かして、 PenM, NetBurst, K8のどれが速いかってかなり運というか、かなり相性の問題がからむだろう。 せめてスーパーパイプラインで内部uOPs変換系のアーキテクチャに最適化してるものじゃないと つらい気が…。
それを考察するのは意味のあることなのか
このスレに来るたびにTCの件といい、
>>1 に文句ばっかたれてるきがするので、
ちょっとは資料提供することにしました。P5のFPU命令のレイテンシ表。
Instruction Operand Clock cycles
FLD r/m32/m64 1
FLD m80 3
FBLD m80 48-58
FST(P) r 1
FST(P) m32/m64 2
FST(P) m80 3
FBSTP m80 148-154
FILD m 3
FIST(P) m 6
FLDZ FLD1 2
FLDPI FLDL2E etc. 5
FNSTSW AX/m16 6
FLDCW m16 8
FNSTCW m16 2
FADD(P) r/m 3
FSUB(R)(P) r/m 3
FMUL(P) r/m 3
FDIV(R)(P) r/m 19/33/39
FCHS FABS 1
FCOM(P)(P) FUCOM r/m 1
FIADD FISUB(R) m 6
FIMUL m 6
FIDIV(R) m 22/36/42
FICOM m 4
FTST 1
FXAM 17-21
FPREM 16-64
FPREM1 20-70
FRNDINT 9-20 FSCALE 20-32 FXTRACT 12-66 FSQRT 70 FSIN FCOS 65-100 FSINCOS 89-112 F2XM1 53-59 FYL2X 103 FYL2XP1 105 FPTAN 120-147 FPATAN 112-134 FNOP 1 FXCH r 1 FINCSTP FDECSTP 2 FFREE r 2 FNCLEX 6-9 FNINIT 12-22 FNSAVE m 124-300 FRSTOR 70-95 WAIT m 1 パイプライン化されてないFPU萌え。
ちなみにTCとHTの関係についてはDynamicMTの論文を1998年にIntelがだしてて、 それが、TC前提のアプローチだったわけよ。
なんかしらない人がいるみたいだが、 SuperPIがコンパイルされたのは95年の6月ね。 日本語版Win95すらない。
どんなベンチでもCPUのタイプによって得意不得意が出るだけだろ Yona以降はデスクトップもやっとまともな路線に戻れるな
昔から中身の変わらない Super_PI だからこそベンチとして利用できているという側面もあろう。 benchmark はあくまでも基準点あってこそのベンチなので。 で、昨今の状況だとさすがに基準点が使い物にならなくなってきてるわけだが。
ベンチならdhrystoneとかでいいしー(おんぴ
>>779 SuperPIがそういう意味で古いプログラムだった場合、
ベンチ結果が実力というより「運」になってしまうという心配なら俺にもある。
ダメコードに強いPenM有利なベンチである可能性が高い。
>>781 俺も書き込むたびに相手の意見を否定してばかりな気がする。
まあ、「俺もmulpsはレイテンシ5だと思ってたよ( ´∀`)人(´∀` )ナカーマ」とか
レスしてもしょうがないけど。
でもfmulのレイテンシが3の昔CPU萌え。
>>784 P5のFPUは普通にパイプライン化されてると思う。
K6はパイプライン化されてなくて、多くのFPU命令が2clk。
http://homepage1.nifty.com/herumi/adv/adv01.html >>788 やはりまともに最適化すればSuperPIより速くなるか。
ソース付きは嬉しいが、現実問題読むのが大変だったりする。
ALU、FPU、メモリなどのエレメンタルなベンチなら大いに読みたいんだけどね。
ちなみに、拾い物のFFTで自前の計算ルーチンを作って円周率を計算したときは、
SuperPIより3倍遅い程度の速さだった。
昔の石は最適化のしがいは最高でしたよ
どういう動きしてるかわかりやすかったからね
でもキャッシュはどんどんのるしアウトオブオーダがきてかなりだめぽ
8bit,16bit時代さわってない
>>1 はある意味かわいそうだともいえるか
メモリアクセスのタイミングやIOのアクセスのタイミングの取り方ひとつで
大きく影響してきたからね
それだけに「腕」が大きく影響した
そんな時代だからこそスタープログラマーって単語があったのだがもう死語だよね
実効性能として当時P5より6x86はかなり高かったのを覚えてる
そりゃだって、6x86はアウトオブオーダーや分岐予測で重武装してますから。 Pentium100MHzと、6x86のサブセットの5x86の120MHzが同等の速度なんですし。
スタープログラマーなつかしす 俺はベーマガ世代だった(´・ω・`)
>>762 じゃないけど
>>764 のベンチをK6-2の400MHzでやってみたよ。
まあ、MMXPentium積んだメーカー製(NECのVS20CS5DA2)にIODATAの
アクセラレータで載せ代えたやつだからFSB66だしL2不明だから
余り参考にならないかも。
ライトアロケートON 4KB 8KB 16KB 32KB 64KB 128KB 256KB 512KB 1MB 2MB 4MB 8MB 16MB 32MB Lc 1.07 1.04 1.02 1.73 47.15 43.67 49.06 57.34 61.49 62.85 62.86 63.83 64.49 64.51 S 1.55 1.53 1.51 2.86 85.44 90.78 106.66 137.36 142.77 152.79 156.23 155.22 154.85 155.49 Ln 4.06 4.03 4.02 4.92 54.48 49.91 56.93 67.46 73.12 74.63 75.37 76.37 76.42 76.72 S 4.56 4.53 4.52 5.84 84.64 90.42 114.59 127.40 144.48 155.68 155.31 154.82 154.94 155.76 Lm 5.05 5.03 5.01 5.87 47.13 43.67 49.10 57.20 61.61 62.74 63.83 63.45 64.19 64.62 S 5.05 5.03 5.01 6.52 84.72 90.37 117.33 138.78 140.17 152.24 155.45 155.67 155.00 155.57 Lp 5.05 5.03 5.01 6.52 54.85 51.76 56.58 63.76 67.74 68.82 69.92 70.05 70.47 70.83 S 7.05 7.03 7.01 10.62 79.80 98.99 104.72 128.57 147.12 151.67 152.23 155.25 160.41 157.94
ライトアロケートOFF 4KB 8KB 16KB 32KB 64KB 128KB 256KB 512KB 1MB 2MB 4MB 8MB 16MB 32MB Lc 1.07 1.04 1.02 1.79 50.66 51.69 52.59 58.08 60.57 62.57 62.86 63.82 64.22 64.77 S 1.55 1.53 1.51 1.73 12.87 18.43 21.38 22.70 23.74 24.27 24.73 24.95 25.21 25.38 Ln 4.06 4.03 4.02 4.88 59.11 60.29 61.51 68.42 71.99 74.40 75.38 75.81 76.88 77.03 S 4.56 4.53 4.52 5.40 50.79 82.55 85.76 91.78 97.07 97.89 98.90 99.17 99.63 99.91 Lm 5.05 5.03 5.01 6.07 50.74 51.66 52.58 57.81 60.72 63.27 63.49 63.94 64.44 64.82 S 5.05 5.03 5.01 6.08 51.04 76.35 85.81 94.15 96.67 97.85 98.25 99.22 99.44 99.92 Lp 5.05 5.03 5.01 6.08 51.04 59.00 59.63 64.32 67.01 68.70 69.79 69.95 70.64 71.04 S 7.05 7.03 7.01 9.71 105.92 112.02 108.79 135.94 145.07 144.33 149.79 152.23 157.75 158.70
>>796 うお、ありがとう。
3D Now!のprefetch命令を使うと、L1の範囲では1clk遅くなる。これはPenM等と同じ傾向。
Lm(アクセス順変えによるプリフェッチ)でも、L1Loadでは同じ数字で、なぜか遅い。
命令数が少ないので遅くならないのが普通と思うが、
L1でも違うキャッシュラインにアクセスすると多少のペナルティがあるということか。
L1への32byteおき(Lc)ストアで1.5clkなことも、それをうかがわせる。
ライトアロケートがOFFだと、1個だけのストアはさすがに速い。25clkはFSBでの4clkだ。
(これが「
>>758 ランダムライトに強い」所以)
普通の連続ストアでも、99clk/4storeなので、25clk/storeと変わらない。
まとめて転送機能はなさそう。
ロードは1個だけでもL1キャッシュに入れてから読むね。
当然だが、ライトアロケートしないストアでは、アクセス順変えプリフェッチは効かない。
また、ストアでprefetch命令を使うと、余計なお世話なために遅くなる。
FSBの4clk(CPUの24clk)でキャッシュラインの32byteが理論値だが、ちょっと遅いね。
MMXPentium用マザーだから相性があまりよくないのかな。
アクセス順変えロードは速い。ロードが1個のときとほぼ同じ速度が出ている。
これは、メモリからL1への転送がこのくらいで律速されてるんだろう。
3D Now!のprefetchは、効いてはいるがそれほど速くない。
やはりK6-2では命令数が増えることが痛いか。
ストアはprefetchが効かないが、これはPenMのアクセス順変えと同じ傾向。
L2は存在しないということでいいかな。
128KB付近で、ライトアロケートONの方がロードで少し速いのはなぜだろう。
また、32KBのL1を外れた後、「だんだん」遅くなってくのはなぜか。
ロードの測定ルーチンでの唯一のストアは、rdtscの保存。
予め保存先にストアアクセスしてキャッシュに乗せているが、
それだとライトアロケートOFFではキャッシュに乗らない。
でも、10万clkの中の50clkとか関係ないや。
このベンチは、8回測定して一番速い数字を採用している。
本当は2番目に速い数字とかにすべきだとは思っていた。
規則的なアクセスだから測定結果に大差はないだろうが後で修正しよう。
キャッシュに新しくメモリを読み込むとき、どのキャッシュラインを捨てるかというのは
どうやって判断しているのだろう。
古いものから順に捨てるのだが、確か確実に最古のを捨てられるわけではなかった気がする。
この辺かなあ・・・。
http://www.sandpile.org/impl/k5.htm ここ見ると、K5のデコード性能ってすさまじいな。最大4命令ってマジかよ。
そのせいでクロックは低いが、IPCだけで言うとどの程度なんだろ。
この辺は、愛すべき低クロック高IPCのCPUが結局Intelに負けていくという時代か。
K5って初期型が性能がまったくでなかったから その後のPRがあがったK5はまったく売れてなかったはず なんせ、登場時期がK6とかぶるくらい遅かったのと悪いイメージのK5のままだったからね あと当時はFSBという言い方は普通はしない メモリコントローラの手前に2次キャッシュがあるわけでバスは1つ いまじゃ1チップに2次キャッシュがはいってるのでFSB,BSBなんて言い方は意味のないもの 当時インテルが営業上の文句で第6世代は2バス+RISC分解を指すといったからね このPentium133〜MMXPentium233あたりまでの時代は 自作PCの黄金時代といえる
>>800 最近のx86が3命令同時デコードに落ち着いたのは、結局のところx86命令で同時実行できるのがせいぜい3命令程度だってことじゃなかったか?
つーことでK5の4命令同時デコードって役に立たないオーバースペックな気がする。
手元にAMD5k86tm-P75 AMD-SSA/5-75ABRがあるな。 現在使ってないけど。
事実上K5はPR133どまりだったからね でたころはすでに166以上がターゲットになってきてたし
>>799 リファレンス見たらL2は256Kって載ってたんだけどこれかな?
CPUの欄に書かれてたけどMMXPentiumって
オンダイじゃないはずだよね。
>>805 さいですな。
K6あたりと間違えたんでないかい。
>>801 そういえば、FSBって、後ろ(メモリの反対)に接続されたL2に対しての言葉だったな。
もはやメモリバス=FSBという認識になっちゃってるね。
>>805 それですな。64〜256KBの数字があまり変化してないから間違いないだろう。
M/B上とはいえL2がバスの理論値の半分の帯域というのは、ゲタのせいだろうか。
それとも当時のボードはこのくらいの性能だったのかな。
>128KB付近で、ライトアロケートONの方がロードで少し速い
L2が256KBなら、これはL2キャッシュの範囲ということだろう。
でも、ライトアロケートとの関係は謎のまま。
あと、ライトアロケートOFFのストアの数字について。
「たまたま」直前に同じサイズのロードルーチンがあるので、ほぼ正しい測定ができている。
変数数個をロードしてるので、いくつかのキャッシュラインが汚染される(そしてされっぱなし)。
コンパイル結果を見ると、キャッシュライン1つの汚染で済む感じ。
キャッシュミスを64clkと仮定すると4KBの1.5clkがピッタリ説明が付く!んだけど違うっぽい。
汚染はロードでも同じだし、8KBも同じ1.5clkだし。
毎回ループ内でロードはあるので、汚染を放っておくことでむしろ速くなってるように思う。
ロードの4KBが1.07clkなのを見ると、0.07clk*(4KB/32byte)=9clk程度のオーバーヘッド。
1つのキャッシュミスも、隠蔽されればこの程度で済むということだと思う。
他のCPUで測定したときのも確かめると、同じような傾向だった。
>>808 128bit SSEのデコードって1clockで128bit幅の命令を発行できるってこと
じゃないよね?
Athlon64のように64bitずつに分けるってことか?
>>810 64bitずつ実行するのはDothanもYonahも同じだが、
内部で下位64bitと上位64bitの2つのμopをまとめて1つのμopとして扱う。
これによってデコード・スケジュール・リタイヤ等の処理が軽くなる。それがすごく嬉しい。
実質的には1clkで128bitの命令をデコードしているとも言える(ただし実行ユニットは64bit)。
ただ、今までも複雑命令デコーダが空いてれば1clkでデコードできたけどね。
実行ユニットへの発行は64bitずつなので、128bit分の発行には最低2clkかかる。
>>800 のキャッシュラインの捨て方について。
「擬似LRU(least recently used)置換アルゴリズム」ってのが使われているらしい。
例えばPenMのL2なら8Wayなので、あるアドレスのメモリが格納されうる場所が8つある。
その8つのキャッシュラインの中で一番長く使われていないものを探すわけだが、これのやり方。
昔どっかで読んだ気が・・・気のせいかなあ。
と思ってたら見つけた。
>>784 の「アセンブラでの高速化」。
ttp://hp.vector.co.jp/authors/VA003988/asm.htm >キャッシュの置換アルゴリズムは、次の通りである。
>各セットは、どのラインが新しいかを、3つのビットを使って記録している。
>4つのラインをA,B,C,Dとすると、一つはAまたはBとCまたはDのどちらが最近使われたかを、
>一つはAとBのどちらが最近使われたかを、一つはCとDのどちらが最近使われたかを記録している。
>キャッシュラインを置き換えるときには、この情報に基づいて古いほう捨てる。
>そのため、最も古いものではなく二番目に古いものを捨てることがある。
これは486の話だが、仮にDothanでも同じ方式だとすると、8Wayなだけにけっこう複雑。
シーケンシャルアクセスでもキャッシュされる場所がFFTのようにあっちゃこっちゃする。
でも、これだとメモリベンチに影響はなさそうだな。ちとがっかし。
>>800 の「だんだん」はL2が存在したから、ということで大体説明がつくが、
メインメモリもアクセス範囲でレイテンシが変わるとか、ロード時のライトバックとか、
細かい原因を詰めていきたいと思う。
キャッシュの動作見て最適化するのはいいけど 仮想記憶使ったOSでやるのはなしな 効果まったくなしだから
>>814 俺が今やっていたのは、キャッシュの動作を詳しく知ること。
具体的な最適化は、その基礎固めの後の話。
だから今後最適化の話するなよという話な
このスレを読めばわかると思うが、 俺が考えているのはライフゲームとかFFTとかそんな程度のエレメンタルな最適化で、 仮想記憶がどうのというレベルには達していない。 だから仮想記憶のあるOS(ていうかWindows)上でも最適化の効果はあるよ。
仮想記憶を使うということはメモリの配置が論理と物理で一致しないのでは?
俺はメモリベンチの結果について細かいクロック数まで予測できるようになったら嬉しい。 内部で何をやっているかがわかると、最適化のときに手の動きが違う。 なんつうか、本当に最適化の意味がないと思っているの? L2を少しはみ出す程度のメモリが物理的に細切れに置いてあるわけがないと思うけど。
長時間稼動し続けていれば断片化は考慮すべきポイントだろうに
そうか、そんなにムシキングの話をしなかったのはまずかったか。
ムシキング見たけどつまんなかった
>>820 仮想記憶とキャッシュは別次元の話。
ページ単位の断片化は、キャッシュには全く影響しない。
セットアソシエイティブなら影響するだろ
>>825 スマソ。了解した。
前提1: キャッシュが物理アドレスを使用している
前提2: ページサイズが1way分のキャッシュサイズより小さい
としたときに、確かにフラグメンテーションの影響を受ける。
物理的に連続する2つのページ(4KB×2)は、1way当たりの容量が8KB以上だと、
絶対に同じキャッシュラインに乗らない。
フラグメンテーションが起こったときは、論理的に連続するページが物理的に連続
しないから、隣のページとでも同じキャッシュラインにぶつかる可能性がある。
で、前提1って最近のCPUで成り立ってる?
仮想記憶を使っている場合に、最適化に効果がないなんて意見は、
半可通の証明だろ。
>>826 前提2が成り立つCPUなんてないのでは?
ページサイズは 4KB〜8KB 程度。(x86 は 4KB)
キャッシュのラインサイズは 8byte〜128byte 程度。
(
>>827 のリンク先の Xeon の場合、L1 のラインサイズが 64byte、
L2 と L3 のラインサイズは 128byte とある。)
register < L1 cache < L2 cache < RAM < backing store っていう
メモリ階層があるわけだから、cache←→RAM 間の入れ換え粒度 (ラインサイズ) は、
RAM←→backing store の入れ換え粒度 (ページサイズ) よりも、常に小さくすべき。
前提2が成り立つCPU設計って、正気の設計では、ありえない。
プログラムから見たら連続したアドレスをアクセスしてるつもりでも 物理アドレスは違うからキャッシュラインがクリアされてしまう ってだけの話なんじゃないの? ベンチとるにしろ通常のプロセスではなく物理アドレス使ってアクセスするような ものじゃないと正確なデータは取れないのは別に不思議なことではないと思うけど。
おっと、
>>826 の後半を読んでなかったので誤解した。
1way分っていう書き方に惑わされたけど、単に、キャッシュサイズ/way数
のことを言いたかったのか。
というわけで、
>>828 に書いた「前提2が成り立つCPUがない」というのは
誤りだった。失礼した。
でも、
> フラグメンテーションが起こったときは、論理的に連続するページが物理的に連
> 続しないから、隣のページとでも同じキャッシュラインにぶつかる可能性がある。
仮想記憶を使っているシステムでは、論理アドレスが連続するページであっても、
物理アドレスが連続していないのは当たり前。そういう状況の方がむしろ普通。
で、今どきの OS では、ページカラーリングというページ割り当てアルゴリズム
を使って、この問題を回避するのが常識になっている。この場合、物理アドレス
は連続していないが、キャッシュインデックスだけを見れば連続したページを
割り当てるので、
>>826 で気にしている問題は、結局発生しない。
今どきページカラーリングをしてない OS なんてほとんどない筈。
Windows は良く知らんのだけど、UNIX 系は Solaris, Linux, FreeBSD, NetBSD
みんなやってる。(実は OpenBSD だけ例外でやってないみたいだが)
でもpage coloringは万能ではないよ。 長時間運用していけば各OSの細かい動きに差が出てきて面白いとは思う。
まあ、万能じゃないのは確かにその通り。カラーリングアルゴリズム自体 いろいろあるし、アプリケーションが、自分に適したアルゴリズムを選択 できるOSもあったりするぐらいだし。 どうしても、この辺を気にする人は、メモリを沢山積んだマシンで、 リブート直後に計るって手も一応はある。ページの使い回しが必要に なるまでは、ほとんどのOSで、連続物理アドレスになると思う。
そういやNT4あたりだとJavaみたいに最初にヒープがばっととって プロセスがメモリ管理してるほうがパフォーマンス高かったのもなんかあるんかな。 freeBSDが採用早かったっけ。
834 :
826 :2005/11/27(日) 00:27:55
>>827 調べてくれてありがとです。でも、ちょっと考えたら当たり前ですね。
プロセス切り替えるたびにキャッシュをPurgeするのは現実的じゃないし、
IntelのHyperThreadingは2プロセスで同一のキャッシュを使うわけだし。
>>830 page coloringは知りませんでした。勉強になります。
結局、キャッシュカラーリングを実装している現代のOSでは、 キャッシュの入れ替えアルゴリズムを考慮した最適化に 大いに意味があるということですね。
キャッシュカラーリングじゃなくてページカラーリングです。
837 :
デフォルトの名無しさん :2005/11/27(日) 19:04:59
IA32 一般で、アラインメント違反は例外が発生するんですか? それとも実行時間のペナルティが与えられるんでしょうか? 昔 80486 を使っていたときアラインメント違反に遭遇したことが 有るのですが、Pentium になって以来アラインメント違反に 遭遇したことがありません。 いまの IA32 ではペナルティだけなのでしょうか? まだ、SIMD命令群ではどうなのでしょうか?
>>837 例外を起こすか起こさないかは設定で変更できる。
一部の命令は設定にかかわらず例外を起こす。
839 :
デフォルトの名無しさん :2005/11/28(月) 04:26:00
どうやって設定するのでしょうか?
EFLAGSのAC だっけ?
cr0のAMもセットしないと
842 :
837 :2005/11/28(月) 16:00:18
>>838-840 レスありがとうございます。
何もフラグをいじらずに Windows XP Home SP2 上で
いくつかの命令を実行してみたところ、
MMX 命令群ではアラインメント違反に対してペナルティが与えられ、
SSE, SSE2 命令群では prefetchnta を実行した時点で例外が発生しました。
843 :
837 :2005/11/28(月) 16:07:40
間違えました。 prefetchnta を実行した時点じゃなくて、 その直後で movdqa などを実行した時点で例外が発生しました。
844 :
デフォルトの名無しさん :2005/11/28(月) 17:14:54
実行時間を測る上で、キャッシュの影響を排除 したいので、最初にL1/L2をできるだけクリア(?) したいのですが、どのような方法があるでしょうか?
>>844 L1/L2にデータを埋めてから、全部CLFLUSHするなんてどう?
BIOSでCPUキャッシュをDisableすると阿鼻叫喚の世界が待ってます。 マジレスは他に任せた。
OS動かさない状態限定でならある程度コントロール可能だろう
>>846 BIOS設定でcache切れない環境ってのもある
wbinvd って、特権命令なのか。 じゃ、wbinvd するシステムコールかなにかを追加する。(ぉぃ フリーなOSの方が簡単だけど、Windowsでも、システムコールじゃなくて デバイスドライバとして実装すればできると思うよ。 欠点はやりたいことの割におおげさすぎるってことぐらい?
何を計測したいのかよく分からないけど、 Win32APIのVirtualAllocでPAGE_NOCACHEでメモリ確保して、 そこで計測するんじゃだめ?
851 :
850 :2005/11/29(火) 11:24:15
勘違いした。キャッシュオフで計測したいんじゃなくて、 キャッシュが空の状態から計測開始したいってことかな。
擬似LRUがどんなアルゴリズムか、
>>813 の以外に書いてあるところある?
Intelの最適化マニュアルにはこのようにある(PenProについて)。
>データ・キャッシュは、4バイト境界でインターリーブしている8つのバンクから構成されている。
Coppermineでは8byte境界で分かれていると思ったが、変わったのか、間違いか。
PentiumMで試してみると、ロードストア同時できるのは16byte境界だった。
時代が進むにつれ、メモリアクセスの幅が広がっているね。
小さいアクセスでもOoOが効くし、SIMDを使えば広いアクセスは必要だし。
Noothwoodで少し測定をした。
試した限りでは、パーシャルレジスタストールは起こらなかった。
パーシャルメモリは食らう。
おそらく全てを32bit演算としてやっているのではないかと思う。
P6と違いalとahには依存性があるが、それでもALUが倍速なので全く問題にならないと感じた。
つーか速杉。倍速ALUが2つというのは、等速4つよりも高性能だ。3μop/clkがピークのくせに。
853 :
デフォルトの名無しさん :2005/11/29(火) 20:32:54
prefetch* 命令でプリフェッチされるのは 何バイトと単位かって、全プロセッサ32バイト固定?
>>853 たいていはキャッシュと密接に絡んだ動作をするので
バイトオーダーで数えるのは無粋
>>852 あれの整数ALUは16ビットだろうという観測が大勢だったと思われ
>>852 >P6と違いalとahには依存性があるが、それでもALUが倍速なので全く問題にならないと感じた。
問題になるケースも結構出てくると思う。例えば、
mov bl,al
mov al,bl
は1クロックで実行できるが、
mov bh,al
mov al,bh
は8クロックもかかってしまう。
下位8ビット<->上位8ビット 間の演算や転送には
途中でシフタ(低速ALU)が使われていると思う。
>>853 そのアドレスを含むキャッシュライン1つ分をプリフェッチするんだと思う。
おおまかに言うと、PenM、Pen4、Athlonなら64byte。それ以前のCPUなら32byte。
Pen4のL2は64byte*2の128byteだったり、Efficeonはまた違ったりするけど。
だから、プリフェッチ命令はキャッシュラインのサイズ分処理する毎に入れる。
PenMだと、64byteを1ループとしてプリフェッチ命令をループ内に1個入れるとか。
ついでに言うと、eax%64==0 のとき、prefetch [eax] もprefetch [eax+hoge](0<=hoge<64) も
動作は同じはず。同じキャッシュラインに含まれる場所なので。
>>854 プリフェッチ命令なんざ、キャッシュ周りだから使い方が難しい部類に入るのに、
バイトオーダーで把握しなかったら効果的に使えないと思う。
(いや、俺も実戦で効果的に使う自信はないけどさ)
>>855 ALUのマイクロアーキテクチャのことではなく、スケジューラ周辺の話で32bitということっす。
スケジューラから見れば32bit演算を0.5clkでこなしているリアル32bitの倍速演算器なので、
内部で16bitずつ計算していようが、ここでは全く関係がない。
また、演算器が32bitでもパーシャルレジスタストールは起こる(P6みたいに)。
mov ax,bx をmovLowPart eax,ebx として処理する、つまりパーシャルレジスタの問題が
Pen4では根本的になくなっていると俺は測定を通して思った、ということ。
さすがにメモリだと、mov ax,word ptr [ebx] をmovLowPart eax,dword ptr [ebx] にしたら
アクセス範囲が面倒なのでダメだけど。
16bitで0.5clkレイテンシの処理ができるとき、32bit演算も0.5clkレイテンシでできるという
ところがすごい。ただしandやadd/subなどの単純な演算に限るが。
andやaddなら上位16bitと下位16bitを分けて計算できるというのがポイント。
ネトバALUは、たまに16bitだからと叩かれるが、的外れだよな。
>>857 8clk。シフト(4-1)の2回分っぽいね。
mov bh,al みたいなただのmovであってもシフトが必要だから倍速ALUは使えないのだな。
ていうか俺はbhとebxを別レジスタにマップすればmov bh,al が簡単にできることを
見逃していたということか。すまんかった。
>>853 P3 32
P4 128
PM 64
「IA-32 インテル アーキテクチャ最適化リファレンス・マニュアル」より。
Pen4ってprefetch*命令でL1にプリフェッチできないんだよね。 こういう手抜き実装はかんべんして欲しい。
863 :
デフォルトの名無しさん :2005/11/30(水) 01:52:02
>>861 なんのための prefetchnta かわからん・・
865 :
デフォルトの名無しさん :2005/11/30(水) 05:58:54
キャッシュラインのサイズって、 どうやって調べればいいんですか?
データシート見る
867 :
デフォルトの名無しさん :2005/11/30(水) 12:32:44
>>866 それしかないのか orz
SIMD命令の対応についてはCPU種別じゃなくて
フラグ見て判定しろっていってるのに、
キャッシュラインの大きさの判定が
フラグなどではできないだなんて・・・
cpuid使えるなら、キャッシュラインの大きさはわかるけど。
実測という手もある。 メモリアクセスして、どのくらい離れたところまで一緒にキャッシュに乗ったかを調べる。 ちょっと大変だけど。
パワレポのYonahベンチ見てきた。 PenDやAthlonX2に対してそれほど速いわけでもないと思ったら、 あそこに出ているベンチってPenMのスコアがすごく低いんだね。 やっぱり腕力はないんだなぁ。 同クロックのDothanに対しては2倍を大きく超える数値を出している。 SSEとL2だけでここまで速くなるんかね。 何にせよ、実機が出回るのが楽しみだ。
> 同クロックのDothanに対しては2倍を大きく超える数値を出している。 ヅアルコアだからでね?
>>870 あのベンチってマルチスレッドだから、コア数が多いほどよくなる。
エンコの方はDothan比2.4倍だからこれはすごいよね。
あの本に載っているYonahのシステムはメモリ1枚ざしなので、2枚にすればもう少し
性能は上がるかも。
ベンチでの力=体感速度じゃないからねぇ 2次キャッシュ1MのPen4と2Mとでベンチに差はなくても 体感速度が結構かわってくるとか そもそもTDP30W以下の製品でPenDを超える性能ってあたりが NetBurstおわっとるという結論だな
>>873 いや、TDP30W以下じゃないだろ、微妙に。
あの本Intelの未発表の石とAMDのハイエンドの石とYonahのハイエンドではない石との比較だったな 緊急だったようだから仕方ないけどやはり同クロックで並べて欲しかった 対抗のTurionX2はまだまだ先なのかな?
877 :
デフォルトの名無しさん :2005/11/30(水) 20:51:48 BE:134971878-#
うーん、キャッシュをクリアする方法、まだ悩んでます。 prefetcht0 を広範囲なメモリ空間にわたってぐるっと 回せば、キャッシュがクリアできたことになるんでしょうか?
OSに制御を渡さなければそれなりに
>>871 一般論で言えば、コア数がn倍になったときの性能向上はn倍以下なので。
それに、コア当たりのL2量は半分になってるし。
確かに誤解を招く表現だった。
同じコアを2個積んだ場合、1.8〜1.9倍の性能が出れば万々歳、2倍以上はありえないわけで、
それが2倍を大きく超えたということは、コアの性能がすごくアップしていると思ったわけです。
>>872 シングルコアでもマルチスレッドで処理するからオーバーヘッドがあるということ?
2コア用ルーチンの最適化の方が気合い入ってるという可能性もあるな。
どちらにしても、2.4倍はすごいね。
CPUの性能を知るという意味では、シングルコア用のタスクを2つ同時に走らせるベンチが
わかりやすくていいんだけどな。
メモリは、まだ謎ですな。チップセットが性能向上しているのかもしれないし、
Dothanの狭いFSBに対するデュアルチャネルの、非3D系ベンチでの効果も疑問だし。
>>873 ベンチ結果を元にYonahの内部を予想し、そこから体感速度を予想するって感じかね。
YonahはPenMベースとわかっているから比較的わかりやすい。
>>877 prefetcht0だと、CPUによって全てのキャッシュ階層に読んでくれないかも知れないので、
32byteおきに、mov eax,[esi] とかすればいいんじゃないかな。
;予めメモリを2MB確保しておいて、そこへのポインタをesiとする。
mov ecx,200000h
lp:
sub ecx,32
mov eax,[esi+ecx]
jnz lp
こんな風にすれば今まで使ってたキャッシュが全部追い出されると思う。
>>876 やっぱりレイテンシ14は本当だったってことか?まあ妥当っちゃ妥当だ。
Dothanと比べてかなり速くなっているが、それでもAthlon64X2に負けるというのは
今までDothan対K8って(同クロックの比較でも)かなりの負けっぷりだったんだね。
レイテンシが14とすると、転送時間を除くと、Yonahが12、Dothanが6。
共有に6clkとられたか。
X2/3800+とくらべて得意不得意がぱらぱらあるね すべて負けてるってわけじゃなくYonahんほうが速いものもあるし それは性格的なものかと あと重要なのが現状PenDとかPen4に最適化されたアプリやベンチはあるけど Yonahに最適化されたものがないってこと Intelということで今後加速する可能性はあるかもね Dothan vs Athron64ってそんなにたいした差があったわけじゃないよ Yonahのように同クロックでやや負けるかもといったところ そもそもAthron64って同じモデルナンバーでもコアやキャッシュ容量、クロックとか 違うんだからそれぞれで異なる結果が出る これ実は結構厄介でAthlon 64 3200+くださいといっても まったく性格が異なる3種類もあって・・・ソケットも違ったり・・・
>>883 パワレポは、SPECじゃないよね?
ベンチマークが違うんだから、結果が違ってもおかしくないよな。
2.2GHz の Opteron の場合、デュアルコア化でSPECint_rateは
1.93倍になるから、Yonah が1.8倍しかいかないというのは、
どこかにネックがあることを示しているね。
2倍以上いくベンチマークは、SPECint_rateとは特性が違うって
ことかな。
>>876 のYonahシステムのチップセットは945Gだからメモリ、FSBともに533MHz。
製品版では667MHzになるからもう少し性能が上がるかもしれん。
話の流れを読まずにカキコ。
なにやらベンチが置いてあった
>>764 のでやってみた。
K6-2+ 525MHz(105x5), FreeBSD 6.0-STABLE / wine 0.9.2, bench 6
Instruction TLB: 1-way associative. 64 entries.
Data TLB: 2-way associative. 128 entries.
L1 Data cache:
Size: 32Kb 2-way associative.
lines per tag=2 line size=32 bytes.
L1 Instruction cache:
Size: 32Kb 2-way associative.
lines per tag=2 line size=32 bytes.
L2 (on CPU) cache:
Size: 128Kb 4-way associative.
lines per tag=2 line size=32 bytes.
L3 (on MB) cache:
Size: 1Mb
4KB 8KB 16KB 32KB 64KB 128KB 256KB 512KB 1MB 2MB 4MB 8MB 16MB 32MB
Lc 1.07 1.04 1.02 1.11 8.60 7.51 41.93 43.00 43.34 44.36 45.42 46.89 47.38 47.52
S 1.55 1.53 1.51 1.64 12.00 11.95 71.17 88.14 95.27 101.42 104.68 109.32 111.80 113.04
Ln 4.06 4.03 4.02 4.12 12.00 11.95 41.92 42.91 43.32 44.12 45.42 47.03 47.48 47.50
S 4.56 4.53 4.52 4.62 11.99 12.09 73.58 86.14 95.54 99.26 106.78 108.29 110.92 112.11
Lm 5.05 5.03 5.01 5.11 12.00 11.78 41.79 43.01 43.40 44.04 45.42 46.98 47.36 47.49
S 5.05 5.03 5.01 5.15 12.01 12.18 72.12 89.32 95.02 98.85 104.41 108.33 110.97 112.24
Lp 5.05 5.03 5.01 5.15 9.68 8.22 42.02 43.01 43.29 44.10 45.44 46.95 47.48 47.49
S 5.05 5.03 5.01 5.40 11.59 12.48 70.62 88.92 95.92 98.57 105.36 109.13 111.54 112.39
Pentium3 733MHz(133x5.5), FreeBSD 6.0-STABLE / wine 0.9.1, bench 2 Instruction TLB: 4KB pages, 4-way associative. 32 entries. Instruction TLB: 4MB pages, fully associative. 2 entries. Data TLB: 4KB pages, 4-way associative. 64 entries. Data TLB: 4MB pages, 4-way associative. 8 entries. L1 Data cache: Size: 16KB 4-way associative. line size=32 bytes. L1 Instruction cache: Size: 16KB 4-way associative. line size=32 bytes. L2 (on CPU) cache: Size: 256KB 8-way associative. line size=32 bytes. 長すぎるので分割
4KB 8KB 16KB 32KB 64KB 128KB 256KB 512KB 1MB 2MB 4MB 8MB 16MB 32MB Lc 1.07 1.04 1.04 6.27 6.36 6.44 6.56 22.77 22.93 22.92 22.94 23.01 22.97. 22.99 S 1.21 1.17 1.21 10.05 11.75 11.91 12.28 56.12 77.09 87.73 99.66. 101.59 102.50 102.97 N 1.24 1.18 1.15 11.49 16.75 19.37 20.72 21.47 21.87 22.03 25.90 25.93 25.93. 25.94 Ln 4.13 4.09 4.10 7.51 7.50 7.50 7.88 24.27 24.50 24.50 24.50 24.61 24.60. 24.62 S 4.59 4.54 4.60 10.00 11.02 11.51 12.33 55.94 76.98 86.92 99.66. 101.51 102.48 102.91 N 4.59 4.55 4.52 13.18 17.65 20.04 21.38 21.98 22.21 22.40 101.85 101.94 101.94 101.98 Lm 4.09 4.07 4.13 7.99 8.00 8.00 8.36 22.48 22.71 22.72 22.73 22.80 22.80. 22.80 S 4.59 4.54 4.66 12.00 12.51 13.00 13.41 57.20 77.37 87.04 99.93. 101.65 102.54 102.96 N 4.59 4.54 4.52 46.88 66.54 77.87 83.15 86.00 86.33 85.77 103.59 103.62 103.69 103.75 L0 5.13 5.05 5.43 7.36 7.30 7.28 7.57 22.75 22.92 22.91 22.94 22.97 22.98. 22.99 S 6.06 6.03 6.10 9.11. 10.56 11.28 11.95 58.92 76.83 85.49 98.47. 101.03 102.25 102.88 N 5.58 5.54 5.87 11.96 11.98 12.00 12.17 67.88 82.38 84.71 103.17. 103.23 103.25 103.28 L1 5.11 5.10 5.16 10.67 10.67 10.67 10.88 23.31 23.48 23.47 23.47 23.53 23.55. 23.56 S 5.58 5.54 5.53 12.52 14.24 15.12 15.72 59.49 77.35 86.43 98.54. 100.92 102.18 102.87 N 6.06 6.03 6.02 31.26 48.20 54.61 55.27 54.27 54.78 102.26 102.54 102.64 102.67 102.72 La 5.13 5.07 5.17 14.43 22.00 22.14 20.18 22.52 22.66 22.68 22.71 22.73 22.75. 22.76 S 6.06 6.03 6.10 24.46 50.18 54.81 49.82 58.27 61.10 100.23 101.43 102.09 102.53 102.55 N 5.58 5.54 5.87 24.83 56.81 56.90 58.76 55.52 55.64 102.41 102.54 102.61 102.65 102.67
>>886 まだよく見てないが、PenIIIの結果がTualatinのCeleronと違うな。
32byteおきアクセスが6clkというのはCoppermineのCeleronと同じだ。
ということは、CeleronだからL2性能が低いんじゃなくてTualatinで改良されたのか。
これは帯域云々じゃなくて並列実行関係かな。
後でゆっくり解析しよう(うきうき)。
>>883 予想だが、SPECはメモリネックなんじゃないかな。
Dothan→Yonahで2.4倍なら、Dothan→Yonah(シングルコア)で1.2倍以上は確実。
マルチスレッドで1.8倍の性能を引き出すベンチだったと仮定すると1.33倍となる。
(このベンチに限っての話だが。2.4倍はTMPGEncだっけ?SSE3が効いただけかも)
Pen4でちょっと面白い事に気が付いた。
x86デコードされた段階でストア命令はストア・アドレスμOPとストア・データμOPの
2つに分解されてると思っていたが、必ずしもそうではないようだ。
>>678 のrdpmcで調べた所、
mov [esi+16],eax
は1μOPだった(P6ではもちろん2μOP)。
mov [esi+edx*4+16],eax
は2μOP。
ロードの場合
mov eax,[esi+edx*4+16]
は1μOP。
>>886 まず、K6-2+について。
L1の範囲では
>>797 のK6-2とピタリ一致。ただしprefetchありストアだけ速い。
内蔵L2は効いている。K6-2より体感速度が上がってそう。
ただ、アクセス順変えで速くならないのを見ると、L1ミスでパイプラインが止まってしまうのか。
L2ロードに対してprefetch命令が効いているのが嬉しい。
L3とメモリに対して、(
>>797 と違って)アクセス順変えが効かないのは、マザーの仕様?
256KB以上の数字を見ると、どのアクセス方法もほぼ同じ数字。どこかがネックになってる。
K6シリーズがP6に勝てなかったのは、普及しているマザーに対応させたために
古いマザーで使うことになり、メモリ性能が出せなかったからに思えてきたな。
>>887 次にPen3。733MHzでL2が256KBなのでCoppermineだろう。
Coppermine-128kと比べてみる。L1の範囲では同じ。
L2は微妙に違うが、L2サイズの違いと測定ルーチンによるわずかな汚染のせいか。
メモリは理論値の32byte/22clk(32/8*5.5=22)に迫る数字が出ていて優秀。
4MB以上のmovntqで遅い。ロードと同程度の速さのはずが、通常ストアの100clkになっている。
プリフェッチの効きも、ストアで微妙に悪い。
>>890 [esi+16]を、ストアアドレスユニットなしでアドレス計算できるってことになるのかな。
ロードだと1μopだし、興味深いところだな。
3μopがトレースキャッシュの限界だが、
もし、ストア・ロード・ALUの3命令を1clkでできる場合があるようだとすごいな。
前触った感じではできなさそうに思うのだが。
それは北森?プレスコ?
893 :
890 :2005/12/02(金) 20:09:54
>>892 ウィラです。
lp:
mov eax,[esi+4]
mov ebx,[esi+8]
lea edx,[eax+ebx]
mov [esi+8],edx
mov edx,[esi+12]
add eax,edx
mov edx,[esi+16]
add ebx,edx
sub eax,ebx
mov [esi+16],eax
sub ecx,1
jnz lp
このループだと、1ループ当たり12μOPで、4clkで回ります。
>>893 マジか。すごいなWillamette。
ロードユニットは1ループの4clkをフルに使っている。ロードストア同時もちゃんとできるんだな。
ここでアドレス指定を複雑にすると遅くなるわけだよね?
これは、ストアアドレスユニットを「使っていない」ということでいいのだろうか。
それとも、こっそり分離して使っている(長い[esi+edx*4+16]とかは別μopで送る)のか。
複雑なアドレス指定はトレースキャッシュの1μop分のスペースに入りきらなかった、
という説はどうだろう。
でも、それはロードも同じことか。ロードはどうやっても1μopだもんな。
そもそも、なぜロードとストアで負荷がこんなに違うのか。
ロードはアドレスを計算してそこからレジスタにデータを転送する。
ストアはアドレスを計算してそこにレジスタからデータを転送する。
うわ、自分で書いててわけわかんなくなった。
実際は、確か「ストアバッファに転送」がストアデータの仕事だったっけ。
つまり、転送すべきデータの準備、アドレス計算に必要なデータの準備、2つが必要だが、
この2つをアウト・オブ・オーダーで実行するわけだ。
Willametteの段階で実装されていたとは思いたくないが、μopsフュージョンみたいにして
1μopでストアデータとストアアドレスの両方に命令を発行とかしてるのかな。
やっぱり2μopになる場合がよくわからんが。
895 :
890 :2005/12/03(土) 15:25:18
>>894 ストアのアドレス指定を複雑にすると遅くなった。
ロードのアドレス指定を複雑にしても遅くならなかった。
Pen4のμOPは、入力レジスタ2,出力レジスタ1,即値 の
オペランド形式になっているんじゃないかと思う。
mov [esi+edx*4+16],eax は入力レジスタが3つあるので、
1μOPで処理できないって事じゃないかな。
>>895 なるほど。内部RISCというのを忘れていた。
ストアは出力レジスタがないところがロードと違うわけか。
正しいと確信はできないが、それで説明はつきそうだね。
しかし意外と難しい問題であった・・・。
897 :
890 :2005/12/03(土) 22:02:57
>>894 > Willametteの段階で実装されていたとは思いたくないが、μopsフュージョンみたいにして
> 1μopでストアデータとストアアドレスの両方に命令を発行とかしてるのかな。
俺もちょっとそう思った。
ストアアドレスとストアデータは別のタイミングで実行できる必要があるし、
実際に1μOPでも別のタイミングで実行できてるっぽいので。
http://ww1.tiki.ne.jp/~hino/ ここにあるマンデルブロ集合のプログラム、FPUバージョンがすごく速い。
以前自分が書いた本気のアンロールFPUコードがあっさり負けてしまった。
z←z^2+cの複素数演算の反復、絶対値が2を超えるか、反復が規定回数を超えたら終わり、
というのをやっている。純粋にFP性能が問われる処理だ。
SSEのやつは更新しない作業を外に追い出してやると高速化できた。
でも、この人一体どーゆーセンスをしているんだろう。命令の並べ方がうますぎる。
; xmm5=4.0, xmm0=xmm6=x, xmm1=xmm7=y, ecx=m lp: movapd xmm2, xmm0 ; xmm2=a mulpd xmm0, xmm0 ; xmm0=aa movapd xmm3, xmm1 ; xmm3=b mulpd xmm1, xmm2 ; xmm1=ab ,free xmm2 movapd xmm2, xmm0 ; xmm2=aa mulpd xmm3, xmm3 ; xmm3=bb addpd xmm0, xmm6 ; xmm0=aa+x addpd xmm1, xmm1 ; xmm1=2ab addpd xmm2, xmm3 ; xmm2=aa+bb=rr cmpnlepd xmm2, xmm5;xmm2=mask if(rr > 4) -1 else 0 subpd xmm0, xmm3 ; xmm0=aa-bb+x=a' ,free xmm3 movmskpd eax, xmm2 addpd xmm1, xmm7 ; xmm1=2ab+y=b' test eax, eax jnz exit dec ecx jnz lp exit: で、これがDothanで19clk/loop。速すぎw SSE命令のスループットを単純に足しただけで27clkにもなるのに。 仮にストールゼロとしても理論値は18clk。 分岐の判定とかに必要な計算は先延ばし、ひたすら投機実行がすごい。 実は、mulpd(5-4)をmulps(4-2)に変えても19clk/loopなんだけど。
900 :
デフォルトの名無しさん :2005/12/10(土) 07:11:24
>>899 たぶん Pentium の中の人と友達。
>>1 MeromはSpeculative Loadをサポートするようだが、
IA64みたいに、ld.sのようなロード開始命令を使って明示的に、メモリを先読みするやり方は
x86では互換性の問題からいって無理ですよね。
どういう感じで実現されると思いますか?(・∀・)
>>901 > MeromはSpeculative Loadをサポートするようだが、
それ、どこの情報?
903 :
901 :2005/12/10(土) 21:48:17
Fall IDF 2005 - Day 1: Intel's New Architecture Details Revealed
http://www.anandtech.com/tradeshows/showdoc.aspx?i=2504 >Intel is also introducing speculative data loads with the new architecture,
> loads to be executed ahead of stores if a dependency is predicted to not exist between the two.
今までのP6でも、ストアの後のロードはストアの前に実行することができる。 厳密には、P6ではストアの後のロードはストアデータの前に実行することができるが、 ストアアドレスの前に実行することはできない。 ストアアドレスとロードアドレスを実行しないとストア−ロードの依存性チェックができず、 うかつにロードを先に実行できないから。 Meromでは、この依存性チェックをアドレス計算ではなく予測で行い、 ストアアドレスがまだ計算できない状況でも、ロードアドレスが計算できれば ロードを先に実行できるようにしたものだと思う。 もしかすると、ストアをストアアドレスとストアデータに分割しない可能性もある (というか分割する必要性が薄れる)。 Meromがどのような予測方法をとるのかは分からないが、 AlphaのstWait tableをまねたものではないかと思う。
>>901 Speculative Loadというのは、こういうコードで、
if (A){
B;
} else {
C;
}
IA-64では、Aがわかる前にBとCを両方実行しておくなんてことができるらしいが、
PenMとかの投機実行と違って実際に実行してしまうため、結果的に破棄するパスで
例外が発生したりするとまずい。
で、例外があったらNaTビットというやつに記録しておいて後で例外発生させることで
この問題を回避している。
PenMでも、例外が発生した投機実行を破棄することはあるだろうけど、
多分うまく処理してくれてるんだろう。
そういう意味ではIA-64の方が機能が低いが(他にはOoOがないとかも)、
この辺のことはCPUではなくコンパイラがやってくれる。
PenMなら例外とかの問題は元々ないので(ていうかあったら投機実行できない)、
x86とは無縁の話じゃないかと思ったが、
>>903 を見ると
IA-64のSpeculative Loadと、x86のそれは違うものを指してるんだね?
>どういう感じで実現されると思いますか?
俺は全く見当が付かなかったけど、
>>904 を読んだら904の通り内容だと思った。
予測の具体的な仕組みは、コードを見て判断するのは難しそうだな。
単純に分岐予測と同じ感じでどうだろう。
依存関係ありと予測すればペナルティはないので、予測をそちらに振って、
何回も連続で依存関係がなかったストアに対しては投機ロードをする、みたいな。
それなりにハードの負担がありそうだが。
>>904 ロードが先行するストアを追い越すには、ストアアドレスが既に全て実行されていて、
その上でストアアドレスバッファを全てチェックしないといけないんだね。
ストアが混じったコードだと、全く依存関係がなくてもロードのOoOには限界があるわけだ。
考えてみれば当たり前だけど、こんなに大変だとは思っていなかった。
Alphaではどのように予測しているの?
904を読んで、ストア・フォワードのことかと勘違いして実験。
lp:
mov [esi],eax
mov bx,[esi+hoge]
dec ecx
jnz lp
hoge=0,4,5のとき、2.25clk/loop
hoge=1,2,3のとき、10.0clk/loop
本来ならhoge=1,2のときも高速に実行できそうだが、
「アドレスが一致しないけど含まれる」ものまでチェックしてるヒマがないのだろう。
hoge=3のときと同じクロック数ということは、ストアがリタイヤするまで待っているっぽい。
>>900 漏れもPentiumMの中に入りたいでつ。
組み込み系はスループットよりレスポンスが重要になることが多いから 分岐先2箇所とも実行するのも普通に多いね
Speculative LoadするMeromで速くなりそうなコードを作ってみた。
mov [esi],0
lp:
mov eax,[esi]
imul eax,eax
imul eax,eax
mov [esi+eax+16],eax ; ストアアドレスもストアデータもeaxを含むので依存関係がある
dec ecx
jnz lp
これはDothanで12clk/loop。
mov [esi+eax+16],eax をmov [esi+16],eax に変えると、なんと2clk/loopまで高速化する。
ストアするデータに関係なく、アドレスが違うから依存関係は無い、とCPUが考えるのだ。
ストアアドレスとストアデータのユニットが分かれているメリットは初めて測定したな。
んで、投機ロードがうまく働けば、このコードでは12clk→2clkの高速化が見込める。
とはいえ、実際にどういう処理で役に立つのかイマイチわからん。
>>908 さんくす。読んでみまつ。
>>905 それはプリディケーションという奴です。
IA-64はロード開始命令とロードした値を使用する命令とか分かれていて、
命令セットレベルでSpeculative Loadをサポートしている。
OOOプロセッサの場合は、これを動的にやる必要がある。
x86の場合は、専用のuOPsを発行して投げるだろうか…。
いずれにしろ、RAW, WAR, WAWの履歴からアドレスを予測する感じなのかな。
>>910 予測方法はともかく、投機実行の方法は分岐予測の場合と変わらないんじゃないの?
普通に投機ロードして、もしロードしたデータが間違いだとわかったらその時点で
投機ロード以降の依存した命令を破棄してやり直し。
P4のデータ・スペキュレーション&リプレイみたいな実装になるだろね。
慣れないIA-64のことなんか書いたから読み直すとボロが出てるな。
>>910 投機ロードはプレディケーションを使うときに限らないってことね。
905は例外処理ばかり書いていて、パイプラインを止めないという肝心なとこが抜けている。
というか完全手(コンパイラ)動なスケジュールだからx86のアーキと全然違うな。
ld.sを前の方に置くというのは、x86でmov eax,[esi]を前の方に置くのと同じことなのかな。
今のx86ならOoOできるから、ld.sと同じっぽい動作になる。
IA-64でただのldを前の方に置くと、In-Orderだから、そこでキャッシュミスした場合に
他の命令も巻き添えで遅くさせてしまうんだよね。
ぐむ、In-OrderのCPUを触ったことがないから全然IA-64の気持ちになれん・・・。
Intelさん、いつかx86にCellのSPEみたいなの付けたやつ売ってください。
>>908 [命令当たり1bit]*1024のstWaitテーブルがあって、
ロード命令がストアに依存したら、その命令のstWait bitをセット。16384clk毎に強制解除。
stWait bitがオンなロード命令では投機ロードはしない。オフならする。
てことで良い?
テーブルに入りきらなくなったら無視するのかな。どうせ16384clkの命だし。
1回でも失敗したらというのは妥当かも。16384clkもほどよい長さだ。
これって投機ロードするのがデフォルト?それだと、やや冒険な感じがするが。
>>913 なるほど、やってることが似てるね。
てか、P4のデータ・スペキュレーションて難しいな。何やってんだ。
>>914 > これって投機ロードするのがデフォルト?それだと、やや冒険な感じがするが。
レジスタがたくさんあるRISCプロセッサは、
ストアしたデータをすぐにまたロードするなんて事は
あまり想定してないのかも(?)。
Power4系のロードも基本的に投機ロードみたいだし。
そういえばPower4系のストアもストアアドレスとストアデータの2度発行なんだね。
OoOプロセッサでは、ld命令のデコード後にしか投機的な発行は出来ないけど、 IA64では、いくらでも先にld.sを置いて先読みできるのでは? だからキャッシュだけでなく、メインメモリのレイテンシのタイミングにも合わせられる。
プリフェッチ命令+ロード命令でいいんでは?
プリフェッチ命令を追加すると既存のx86コードと互換性がなくなってしまう。 IA64は、標準的な命令として、明示的な投機ロードが行えるところが強みの一つだね。 プリフェッチ+ロードだと、結局ロード時に、キャッシュのレイテンシが入っちゃうし。
キャッシュのレイテンシくらいだったら、 デコード後の投機ロードでも十分な気もする。
>>916 なるほど、レジスタ8個のx86とは事情が違うわけだ。
>>917 OoO付きx86でも、いくらでも先にmov(ld)を置ける。
IA-64ではOoOがないため、先にldを置くとまずいから、ldの代わりにld.sを入れる。
つまり、「ld.sを置く」というのはIA-64がOoOがないという点でOoO付きx86に劣っているから
仕方なく行っていることで、基本的にIA-64の有利な点ではない(と思う)。
x86だとprefetch命令が必要な場面で、IA-64ではld.sだけで済むことってある?
あるとすれば、ノンブロッキングキャッシュシステムみたいな機能の差によるものだと思う。
ところで、根元的なところだがldを先に置くとパイプラインが止まるってのは本当?
In-OrderのP5でも、順番通りにディスパッチするってだけで、レイテンシの隠蔽はできたのでは
ないかな。FPUもパイプライン化されてたし。
Loadだけでストールするというのは聞いたことがないね。 Loadスロットを浪費したり、待ちのためにRetirementが出来なくなって その結果としてストールという例ならたくさん目撃してるが。
じゃあld.sは、プレディケーションなど(先行するストアアドレス未確定も含むのかな) だけでしか使う意味がないということかな。
IA-64の話だったのか。それだったら
>>922 は筋違い。
922は、P5なら正しいけど、IA-64では間違いということか。 それならそれでいいです。
アセンブラスレの154へ。 話の腰を折るとか考えなくていいのに。本当に迷惑だったらスルーするだけだし。 むしろ初心者の質問は欲しい。それに答えられなかったら俺の理解が甘いということだから。 このスレが、「こういうことに興味はあるけど難しくてわかんない」ものだったら ログが残ってる意味が薄くなるので、「わからない人は何を知ればわかるようになるのか」が かなり知りたいわけです。
927 :
デフォルトの名無しさん :2005/12/14(水) 19:15:45
みんな2.5クロックとか、どうやって測ってるんだろ・・・ 専用のハードウェアでも使ってるの? 俺なんてRDTSCくらいしか思いつかない。
>>927 rdtsc以外にないでしょう。
2.5clkってのは1000回実行して2500clkだったということかと。
P4のデータ・スペキュレーション&リプレイについて。
Intelのページより。
>ロード・スケジューラから実行に至るまでのクロック数はロードを実行するレイテンシ
>そのものよりも長くなります。
>ロード実行が完了する前に、そのロードに依存した命令をディスパッチします。
P4では、L1ヒットするか不明な時点で発行する。
P6では、L1ヒットが確定してから(いつ利用可能になるか判明してから)発行する。
かなあ?
わかった気になっても、思考実験してみるとこんがらがってくる。むずい。
P4は、L2帯域が凄まじいが、ロードした結果をすぐ使うようなコードだと
リプレイのせいで遅くなったりするんだろうか。
安藤さんは専門家で実績のある方なんだけど 氏の書いた物は、読み物としていまいちなんだよな・・・ て感じてるのはおいらだけ?
本書く専門家じゃないから仕方ないべ
古い話題だが、Cレベルでダウンカウンタのループは本当に速いのか。 1から1000まで足して測ってみた。 コンパイラやCPUに依存する問題ではあるが。 for (i=1000 ;i>=0 ;i--) k+=i; //1549clk 確かに速い。cmp命令が省けるためだ。他のものより1命令少ない。 for (i=1000 ;i>0 ;i--) k+=i; //2012clk i>0の判定にjgを使っているが、なぜかsub eax,1の後にtestを使用。 for (i=1 ;i<=1000 ;i++) k+=i; //2013clk for (i=1 ;i<1001 ;i++) k+=i; //2013clk 即値cmpが使われている。 for (i=1 ;i<=1001 ;i++) k+=i; //2055clk前後 これは1001まで足してる 何か知らんけど、1増やしたら急に40clkも遅くなった。 まあ、1ループ0.5clk程度。 読みにくいし書きにくいので、速度重視の場合でもあまり意味がないね。
>932 ちょっと待った、コンパイラ依存とかの前に最適化オプションONにしてる? VC++6.0で/O2(デフォルトのRelease設定)で、 int main() { int i, k = 0; for (i=1000 ;i>=0 ;i--) k+=i; return 0; } をコンパイルすると事実上 >xor eax, eax >ret の2命令のみになる。(Cの呼び出し規約関連の初期化が別途入るが) int k; をグローバル変数にしてやると、 >mov eax, 3E8h という代入までは行われるが、上記程度のループは完全に展開されるよ。 この手の話題を扱うなら、せめて使用コンパイラとコンパイルオプションくらいは晒さないと。
>>932 じゃないけど俺はこんな風にして-Sでコンパイルしたけど
int aaa()
{
int i, k = 0;
for (i=1000 ;i>=0 ;i--) k+=i;
return k;
}
>>933 *ループの*速さの話をしてるんだから、
最適化してループがなくなっちゃうのは話違うっしょ。
ダウンループの利点は、速さもあるだろうけど、
ロジックそのものが単純化される*ケースがある*のが利点だと思う。
うまく使えると嬉しくなる小技の1つ。
漏れはダウンカウンタを意識するときは上の様には書かないな。 for(i = 1000; --i >= 0; ) k+=i; と for(i = 1000; --i > 0; ) k+=i; とを比べてみてくり。
ダウンカウンタの場合は、signedとunsignedでも結果が違った希ガス。 #今日は忙しいから実験はパス。 まぁ、アセンブリくらい読んでからレポートしてくれと。
Toolkit2003、/O2 /G7、PenMで測定でした。/G6でもsubがdecになるだけ。
kをprintfしている。結果埋め込みされるようだったら1000をnにするとかで対応。
>>935 >ロジックそのものが単純化される*ケースがある*
速度に振った最適化は、コードが汚くなるイメージもあるけど、
むしろきれいになるのが本来の姿だよな。
>>937 unsignedだと、
for (i=1000 ;i>0 ;i--) k+=i; //1552clk
判定はdecの後jneでしている。
符号なしの場合、i>0という条件が、i!=0と同じことになるんだね。
どういうことれすか? > 命令が一つreplayに入ると実行ユニットに1サイクルの待機状態が発生する。 > それだけでなく、一つの命令がreplayに入るとたいていの場合いくつかの命令を 道連れにする。 > 極めつけとしては、たった一回のキャッシュミスで長さ数千の命令列が数百回もreplayを回る例さえ作ることが出来た。 > 命令列が何回もreplayループを回るという状況について詳しく見てみよう。 > 不思議に思うかも知れないが、これが起きるのは仕事熱心なスケジューラのおかげなのだ。
rePlay : トレース最適化
942 :
デフォルトの名無しさん :2005/12/21(水) 07:50:12
もしほぼ同じ命令数になるなら、ブランチフリーにした方が実行速度の期待値はアップすると言えますか?
>>939 なるほど、こういうことが書いてあったわけね。
でも、キャッシュミスを起こす命令が1個なのに数百回もreplayを回るってのは
訳がわからないな。
>>941 トレースキャッシュにまで手を加えるの?
以前Noothwoodでメモリベンチをやったときは、
L2のシーケンシャルリードが8clk/64byteを切っていたぞ、って
「FPU,MMX,SSE命令は基本的にreplayを使わない」のか。
今度mov eax,[esi] とかで試してみよう。
>>942 普通分岐をなくしたら命令数増えない?それとも、分岐して実行されない命令数も含めてか。
分岐予測が当てにならない場合は、1回平均10clkくらい損するだろうから、
1回の処理が10clk増える程度で済めば分岐なしにしたらいいと思う。
どちらに分岐するかによって処理時間が変わるのが防げるのも嬉しいしね。
キャッシュの動作。ライトバック方式の場合。 L2のみへプリフェッチするときは、メモリから直接L2に行ったりもできるか? ロードありストアあり、キャッシュラインの追い出しもある実際のコードで プリフェッチ命令を使うのは難しい。 ストアでprefetchntaが効くのは、追い出し先のL2をもプリフェッチしておくからかな。 Load L1ヒットすればL1を読む L2ヒットならL1へ転送してそれを読む メモリからL1へ転送してそれを読む Store L1ヒットすればそこに書く L2ヒットならL1へ転送してそこへ書く メモリからL1へ転送してそこへ書く (L2かメモリから)L1へ転送 L1が満杯なら、L1の中で最も古いラインがL2にないか、あっても変更されているときL2へ転送 (L1から)L2へ転送 L2が満杯なら、L2の中で最も古いラインが変更されているときメモリへ転送
946 :
デフォルトの名無しさん :2005/12/21(水) 14:04:00
948 :
デフォルトの名無しさん :2006/01/03(火) 11:02:59
prefetch{nta|t0|t1|t2} でプリフェッチするにあたって、 キャッシュラインの幅ってどうやって見分ければいいんでしょうか? 32バイト、64バイト、128バイトのプロセッサがあるようなのですが。 また、そのとき必要なCPUサイクルってのはメモリのレイテンシに 影響されますよね?
久しぶりにCodeAnalyst動かしてみた。 結構リザベーション・ステーションが満杯になってストールする事が あるのね。逆にパイプラインがうまく働いてくれてると気持ちいい。
950 :
デフォルトの名無しさん :2006/01/04(水) 12:26:43
256ビット同士の排他的論理和をとって メモリにストアしたいとおもっています。 pxor xmm4, xmm0; movntdq [edi], xmm4; pxor xmm5, xmm1; movntdq [edi+16], xmm5; pxor xmm6, xmm2; movntdq [edi+32], xmm6; pxor xmm7, xmm3; movntdq [edi+48], xmm7; と交互に書くのと、 pxor xmm4, xmm0; pxor xmm5, xmm1; pxor xmm6, xmm2; pxor xmm7, xmm3; movntdq [edi], xmm4; movntdq [edi+16], xmm5; movntdq [edi+32], xmm6; movntdq [edi+48], xmm7; と分けて書くのとでは前者の方が早いのでしょうか?
951 :
デフォルトの名無しさん :2006/01/04(水) 12:27:18
すみません、256ビット同士の排他的論理和ではなく、 512ビット同士の排他的論理和でした。
実測してみては?
953 :
デフォルトの名無しさん :2006/01/04(水) 12:46:15
皆さんこういう場合の計測ってのは、 かなりの回数ループさせてRDTSC読んでって ことをやってらっしゃるんですか? 途中でコンテキストスイッチングが入ったりして、 うまく計測できないんですが・・・ つまり、計測しても分散が大きすぎて。 もしかして何らかの特別な計測用ツールを 使ってらっしゃいますか?
>>953 SetPriorityClass(handle, REALTIME_PRIORITY_CLASS);
を使うと、ほとんどコンテキスト・スイッチングを阻止出来る。
但し、これはデバイス・ドライバのCPU時間まで横取りしてしまう
ため、万が一暴走するとリセットするしかなくなる。
そこに気をつければ大丈夫。
このロード命令が16個あるループは、L1ヒットならPenMでもPen4でも16clk/loopで回る。 lp: ;prefetcht0 [esi+64] mov eax,[esi] ; アクセス順変えでは、ここをmov eax,[esi+64] に変更。 mov eax,[esi+4] ・・・ mov eax,[esi+60] add esi,64 dec ecx jnz lp L1ミスL2ヒットの場合だが、PenMでは25clk/loop。 プリフェッチを使うと20clk/loop、アクセス順変えで19clk/loopまで速くできる。 Pen4では、23clk/loop。 L2からL1へのプリフェッチは仕様上使えない。アクセス順変えで17clk/loopになる。 帯域の差でPen4が勝っている。てか、ロードに依存する命令がないからPen4でも速いのか。
そこで、movをaddに変更。これで、ロードに次の加算命令が依存するようになる。 lp: ;mov ebx,[esi+64] ; movによるL1へのプリフェッチ。prefetcht0 [esi+64] の代替として働く。 add eax,[esi] ; アクセス順変えでは、ここをadd eax,[esi+64] に変更。 add eax,[esi+4] ・・・ add eax,[esi+60] add esi,64 dec ecx jnz lp PenMでの結果は変化なし。 Pen4のL1ミスL2ヒットで、23clk/loop。これは変わってない。 アクセス順変えで22clk/loop。movをaddにすることで3clk遅くなっている。 movによるプリフェッチ(プリフェッチ結果に依存する命令がない点でアクセス順変えと異なる)を 使うと、18clk/loopになる。17load/loopなので満足できる速さだ。リプレイはしてないだろう。 プリフェッチなどを使わない通常のコードでは、ループ先頭でL1ミスするが、 そのときにOoOして代わりに実行できるロードは次のループ(64byte先)までやってこない。 なのでOoOが効果的にできなくてL2帯域が引き出せない。 これを解決するのがprefetcht0などのプリフェッチ命令。アクセス順変えも、この効果がある。 普通、アクセス順変えではループ先頭でL1ミスしても、L2からL1へ転送してる間に 前回のループ先頭でプリフェッチしてあるデータへのL1ヒットのロード命令を実行できるので L2レイテンシをゴッソリ隠蔽することができる。 ところがPen4の場合はL1ミスに気づくのが依存するadd命令を発行した後だったりするので、 投機実行を破棄してやり直しの手間がかかる。何と言うか、アクセス順を変えた意味がない。 L1ミスしてL2からL1へ転送している間に、依存していない命令をやってれば害はないのだが、 依存している命令をL1ヒットしたつもりで発行してしまうと、リプレイで遅くなる。 プリフェッチなしで23clkが変わらないのは、ロードに依存するadd eax,[esi+4] が、 [esi+4]もL1に乗ってないので投機実行できず、リプレイも起きないからだろう。
HTオンでSuperPI100万桁の2個起動やったら73秒と73秒だった。
1個起動だと53秒なので、L1L2共有にも関わらず1.45倍のユニット稼働率だ。
>>899 のコードは23clk/loop。psでもpdでも同じ。
#ここまでのPen4は、Noothwood-3.06GHz、PC1066 512MB。
>>948 >>858 ,
>>865-869 を参照。
ラインサイズをダイレクトに返してもらうのはPenMでも無理なので、eaxに2を入れてcpuidを使う。
そうすると、eax.ebx,ecx,edxの各バイト16個に情報が返り、
例えばその中に2ch(にちゃんねるじゃないよ)があったらL1のラインサイズは64byte、とか。
詳しくはIntelの命令セットリファレンスのCPUIDのところを見てくれ。
実測方法を考えるのも面白いよ。
(2^n)byte毎にメモリアクセスして、nと所要クロックの関係から推測するとか。
>>949 どういうコードでどうなったか詳細キボンヌ。
>>957 リザベーション・ステーションの件ですか?
CPUはAthlon64で、VS2003でコンパイルしたマージソートのプロジェクトを
食わせたら、所々で起きてました。
mov ecx, xxxxxxxxっていうメモリから即値を読み込む所で決まって起きて
いました。リザベーション・ステーションは、今からユニットにデコードしたmicro-OPS
(AMDではMacroOPS?)を溜めておく所ですが、あまりにも単調な命令ばかり
続くと、リタイヤメントの所で引っ掛かってしまい、溢れるようです。リタイヤメント
は実行ユニットと違い、インオーダーですからね。いろんな依存が絡んでくるん
でしょう。
x86の32bitモードでもワーキングレジスタ数は少ないですから、リネーミング をしても溢れてしまうんでしょうね。 x86-64になれば、レジスタ数がぐっと増えるので、リタイヤメントに伴うストール は減るのではないかと期待しています。その代わり、コンテクストスイッチング が重くなりますけど。
>>958 ありがとうです。
単純な命令が一気に流れ込むと3MacroOPS/clkのリタイヤ限界を超えるのかな。
>>959 はよくわからないけど、リネームするとリタイヤが重くなったりするの?
俺もAthlon機が1台欲しいな。。
>>950 xmm0やxmm1が計算済みなら前者が速そうだけど、実際はどうだろうね。
理論では簡単に判定できないタイプだと思うので、実測がおすすめ。
>>953 ループ回数を適度に減らし、1ms以下で完了するようにすればOKかと。
俺は1万clk程度で終わる測定ならPCで音楽を聴きながら測定したりもするが、全然平気。
961 :
948=950 :2006/01/04(水) 15:00:31
>>957 THX。
2ch(にちゃんねるじゃないよ)ってなんのことかと思いましたが、
Intel の命令リファレンスみて理解しました。 0x2c が
「L1キャッシュ 32K バイト、
8 ウェイ・セット・アソシアティブ、
64バイト・ライン・サイズ」
ってのを意味していたんですね。これで prefetchx命令の
配置を切り替えることができそうです。
といっても、ラインサイズが64バイトのプロセッサで
32バイトの処理ごとに(過剰に)プリフェッチした時の計測値と
64バイトの処理ごとにプリフェッチした時の計測値で
ほとんど差が出なかったので、切り替える意味があるのかどうか・・・
>>960 リネームしても、RAWハザード依存は消せないので、コンパイラの癖に
よってはストールを引き起こす場合がある、という事かもしれません。
実際、他のプロジェクトもいくつかCodeAnalystに食わせてみましたが、
長いストールはミスブランチとDATA TLB Missを除いてあまりありませ
んでした。たまたまそのマージソートのプロジェクトだけが癖を持っていた
ようです。
そうですね、Athlon64は、AMDサイトから落とせるCodeAnalyst
(無料、登録必要)が動かせるので、 一台あったら面白いと思いますよ。
>>962 いや、レジスタが少ないことによってストールしてるなら
リタイヤはネックにならないと思ったので。
リタイヤをボトルネックにするには、かなりの最適化が必要だよ。
ネックがリタイヤじゃないとすれば、ハザードで実行ユニットが遊んでしまい、
デコーダから流れてきた命令が溜まっているという状況ですね。
そういえば、Pen4-3.06で測定していて思ったが、
コンパイル速度がDothan-1.1よりずっと遅いのだ。
正確には測ってないけど、倍は違う。
他の要因があったのかな?
>>963 うーんそうかもしれません。コンパイラはVS2003のC++で、最適化をONに
した時とOFFにした時では、だいぶパイプラインの様子が違います。レジスタ
変数を使わなくなると、メモリのReadWrite命令が増えますね。
実際に実行時間を測定すると(QueryPerformanceCounter()等で)、
最適化ON/OFFで大きく変わるものと、あまり変わらないものがあります。
L1/L2キャッシュも関係してくるので、単純な事は言えないのでしょうが・・・・
Pentium4はトレースキャッシュの容量が割と小さく、しかもmicro-OPSの
サイズが大きいので、ただでさえ小さいL1キャッシュをさらに小さくしていると
聞きました。実際、セカンドマシンはPentium4 3.2GHzですが、Athlon64
に比べるとDivXのエンコードは結構健闘していますが、それ以外のすべて
のシチュエーションで遅いです。体感速度も”もっさり”しているのを感じます。
Athlon64は、L1コードキャッシュ・データキャッシュ共に64KBと、Athlon時代
からの伝統(?)で大きいせいか(Latencyは3ですけど)かなりキビキビ感じます。
元々PenMは得意だったのと バスクロック向上やFPUとかのチューニングはいっていると 明言されてるんだし当たり前では PenMって消費電力で圧倒、性能もバランスがよく 欠点はエンコ系だったのがそれがYonahで改善されて 現在最も全方位なバランスのいい石になったと思う マルチスレッドの最適化の場合アセンブリレベルでのチューニングより 動並列化させるかの設計のほうが重要だから 割と面白い
967 :
948=950 :2006/01/05(木) 18:49:34
>>954 >SetPriorityClass(handle, REALTIME_PRIORITY_CLASS);
>を使うと、ほとんどコンテキスト・スイッチングを阻止出来る。
これ、同様のことをLinuxでするには
プライオリティを一時的に挙げればよい、ということでしょうか?
Yonah発表でマイクロアーキテクチャ公開されないかな?
>>967 LinuxカーネルのスケジューラではCPU占有できなかったはず。
というわけでカーネルモジュール使えww
970 :
948=950 :2006/01/05(木) 20:24:45
>>969 が〜ん、カーネルスペースにまで手を出す
勇気と技量がないんで、やめときます(笑
RTカーネル使えばできなくもないが 俺の覚えてる限り、RTにロクな実装がない。 root で動かす限り、カーネルモードモジュールは難しくないべ。
>>969 Linuxは、ソフトウェアアフィニティだからな。
>>969 FreeBSDならrtprio(2)、Linuxだとsched_setscheduler(2)で
リアルタイム優先度に変更してやれば似たようなことできるっぽい。
さあて、そろそろスレのまとめ(
>>171 みたいなの)を作るか。
ログを保存してあるのはいいけど、自分でもどこに何書いたかわかんないし。
次スレは「x86命令の所要クロック計測スレPart2」でいいかな。
ってもうすぐ980か。次スレの1に何を書くかとか議論したかったのにできん(ニガワラ
>>975 ないと思うけど。
ていうかこの分じゃスレのまとめも貼れないまま埋まってしまうな。困った。
まとめ制作は長くて大変だし、いっそ今新スレを立ててしまおうか。
新スレで進行してれば旧スレが止まるからゆっくりまとめ貼れるし。
所要クロックでんでん(なぜか変換できない)は 実情に即さないスレタイなので もっとパイプラインとかスーパースカラ臭がする名前とか もっと厨臭いスレタイきぼん
アウトオブオーダーとかでもつければ良いんでね?
でも最終的には
>>1 が所要クロックを測定して確かめてるじゃん。
スレのまとめ。専用ブラウザ使えばポップアップできます。 >15-18 MMXとSSEのQ&A >22で組み込み関数の話は出てるよ。>137-148は気づいていたのかな。 >23 キャッシュの仕組み >27-31 PentiumMのSSE2のクロック数 >34 μopフュージョンについて >35 K7/K8のデコーダ >40 P4/PMのSSE/MMX比較 >41 P6のL2はエライ >43-44 CPUの内部構造 >47 P4とK7のキャッシュレイテンシ/LoadBench(リンク) >52 パイプラインの比喩(リンク)。>58はコンビニ。 >61-62 K8の128bit pandとandpdは違う?/K8のLoadは64bit*2/clk >65,67,69,75,77,85 SIMDとALUのQ&A。 >68 吉野家コピペ >73 mulpsを入れると速くなる謎。 >78-81 ロード・ストアする派とレジスタで何とかする派 >81-117 分岐。実験結果は>81,86,111,113 >84 初心者のためのアセンブラリンク >87-97 乱数について盛り上がった >99-110 内部構造を予測しつつ測定法を吟味 >114 RISCの分岐処理など >116-117 予測ミスのペナルティがパイプラインの段数より少ない理由を予想 >118 ライフゲームを作った感想 >123 Prescottの触り心地 >128-131 MMXの並列動作。よく考えたらMMX2はユニット限られてた。 >132,500 キャッシュラインをまたぐペナルティ >133-135,153,167 プリフェッチについて >149,154 lddquはps[lr]ldqで実装されてる。 >152 Pentium4の触り心地 >154-165 デュアルコアの話
メモリアクセスの季節。 >167,170 プリフェッチの実験@PenM >172 3つのDoublePath命令のデコードは2clk >182-186 Pentium4とCeleronとコンパイラの質問 >187-192,>196-199 自己書き換えアセンブラ、C、Java、色々な最適化 >200 Visual C++ Toolkit 2003はタダで使える >216-221,>228-229 for (i=0; i<1000; i++) q+=p[i];のコンパイル結果検証 >222 キャッシュのWay数の実験 >234-250 68kとかの昔話 >233,240 トリップ検索 >261-280 C#のトリップベンチ >292-293,>500 ランダムリードの実験(ロード命令同士の依存性なし) >301 Banias-1.5GHzのloadbench >308 新しいオモチャって何だったんだろう・・・ >314-317 複雑なソフト、進む仮想化、語り >332 BIOSでL2キャッシュを無効にしてみた >342-348,>362,>368-383 CPUとGPUの違い >364-366 メモリレイテンシの測定(依存チェーンあり) >397,398,649 divの実験 >400 Cの整数除算はコンパイラが乗算に最適化してしまうこともある >409-413 SpeedStepを試す >414 宇宙ヤバイのコピペ >415-424 x86に、CellのSPEみたいなのはどうか >425-434 ビッグエンディアンの利点/カコイイ >435 QueryPerformanceCounterとrdtscでSpeedStepの実験 >446-458 pcwebのメモリベンチ >457-473 中間言語、Java、GC >476,478,481,491 1がメモリベンチを作ってみました >493-497,499,501 メモリアクセスの並列実行って何よ? >503 閉塞感が漂ってくる。いわゆるネタ切れ。
雑談、パーシャル、トレース。 >513 x86CPUのレイテンシとスループットの表(リンク) >515-517 1がメモリベンチを改変 >518-529 pcwatchのベンチ記事に難癖をつける/ベンチとは何か >530-544 Yonahの情報。結局単純に帯域倍というだけだったかな >545-546,549-550,564,582-583 依存関係を避けたい派とメモリアクセスは極力減らす派 >547,553,556,562,565,575 PentiumMはこんなところが速い! >566-572 どんなアプリに対して最適化すべきか >584 movdquは分解した方が速い >592 YonahのCPUコアの拡張 >593-610 その後ちょい雑談 >613 μopsフュージョン >614-629 SpeedStep/EISTについての妄想たち >636-638 YonahのL2帯域が糞速いけど実際どーよ? >639-647,>653-654 Pen4のSIMDユニットは何bitで周波数はコアクロックの何倍か >650-651 addpdのレイテンシがどう工夫しても3にしか見えない(公称レイテンシは4) >655-665 やめたいスタック式FPUとやめられない互換性80bit/実行ユニットと演算器 >666-677 パーシャルストール >675,680,690,693 movzxに関する致命的な勘違い >678-679 パーシャルフラグストールの実験 >694-696 ワロタ >699,702,706,711 パーシャルアクセスに際しての追加μopは何者 >700,701 SIMDでハンドコーディングの時代です >703-709 分岐ヒントのプリフィックス >713,714,730 トレースキャッシュの功罪/Meromはトレースじゃないっぽ >716-729 トレースキャッシュってuops用の命令キャッシュと何が違うの? >733-747 IA-64とNetBurst/64bitの互換性
Yonah、Merom、色々なアーキ。 >749,750,756 クロックゲーティングを見ようとしたが見えず >751-763,965-966 YonahのSuperPIがやたら速い件/Athlonの排他キャッシュの是非 >764,>796-800,807,>886-889,891 1がメモリベンチを改変。K6-2/K6-2+/Pen3 >765 PenM用チップセットたち >766-780,786-791 AthlonX2も交えてSuperPI関連 >781-784,792 クロック数の表。有名どころへのリンクもあり >792-795 昔の石は最適化のしがいは最高でしたよ >800-804 あの時代のK5 >812 SSE命令がフュージョンするとどうなるか >813 キャッシュラインの捨て方、擬似LRU(least recently used)置換アルゴリズム >830-836 ページカラーリングについて >837-843 アラインメント違反は例外が発生するんですか? >844-851,877,880 L1/L2をできるだけクリアしたいのですが >852,>855-859 Pen4のパーシャルレジスタ >853,858,860,861,863 prefetch*命令でプリフェッチされるのは何バイト単位? >865-869,957 キャッシュラインのサイズってどうやって調べればいい? >870-875,879 パワレポのYonahベンチ >876,881-885 Yonahのベンチお届けです >890,>892-897 Pen4で、ストア命令は2つのμOPに分解されるとは限らない >898-900,957 マンデルブロ集合 >901-925,928 MeromのSpeculative Load/Pen4の投機ロード/IA-64のld.sとの違い >932-938 ダウンカウンタのループ >942,944 同じ命令数なら、ブランチフリーにした方が実行速度はアップする? >939-943,947,955-956 前に貼られてたxbitの記事/Pen4のreplayの実験 >945 キャッシュの動作 >949,958-960,962-964 リザベーション・ステーションの件 >953-954,960,967,969-973 コンテキストスイッチングが入って計測できない
OoO 2issue
われながら、よく連投規制にかからなかったものだ。 このスレでの積み残し。 キャッシュラインをまたいだときの挙動 movとprefetcht0の違い VBでnasm使って状況依存のコード生成 PenMでL2の寝ているブロックを起こす遅延 P4のL2を切る(BIOSで切れない)
次スレではYonahの結果がたのしみ うめ
(・∀・)
そういやMSRに関する詳細な公式の資料ってあったっけ? Appendix.H?
991 :
デフォルトの名無しさん :2006/01/08(日) 13:59:04
うめ
992 :
デフォルトの名無しさん :2006/01/08(日) 14:00:18
しっかりうめんかい
993 :
デフォルトの名無しさん :2006/01/08(日) 14:03:47
うめ
u m e
u m e
u m e
u m e
u m e
u m e
1000 :
デフォルトの名無しさん :2006/01/08(日) 14:20:32
このスレッドはHLTしました。 新しいスレッドをたててくさい。
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。