アカウント名:
パスワード:
> パフォーマンスを重視すると、 > ある程度汚く読みにくくなるのは、 > 仕方がないと思われますが。
これって昔から言われることですが, 本当にこれが当てはまるケースって今ではごく稀になっているのではないかと. おそらくは
程度か, その類似の場合だけで, 多くの場合はむしろコンパイラが最適化しやすいように明瞭なプログラムの流れにした方が良いでしょう. それに手による最適化が必要な局面っ
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
Stableって古いって意味だっけ? -- Debian初級
どの言語でも (スコア:3, 参考になる)
ある程度汚く読みにくくなるのは、
仕方がないと思われますが。
うちの仕事ものんびりした仕事は少ないので、
とりあえず動くものということだと、
金余分に貰ってそれをOSとDBにつぎ込んで
VBできる人を集めて、ASPで作っちゃいます。
Javaの「使える」エンジニアは常に不足気味ですから、
なかなか現場の要求に迅
Re:どの言語でも (スコア:5, 参考になる)
> パフォーマンスを重視すると、
> ある程度汚く読みにくくなるのは、
> 仕方がないと思われますが。
これって昔から言われることですが, 本当にこれが当てはまるケースって今ではごく稀になっているのではないかと. おそらくは
程度か, その類似の場合だけで, 多くの場合はむしろコンパイラが最適化しやすいように明瞭なプログラムの流れにした方が良いでしょう. それに手による最適化が必要な局面っ
Re:どの言語でも (スコア:1)
> 直接アセンブラを使ってディレイスロット等を入れる場合
delay slot を手で埋めて最適化というのは、ちょっと古い気がします。
命令スケジューラを完備した最適化コンパイラの場合、コンパイラに埋めさせた方が高速だと思います。
p.s.
delay slot に似たような話だと、プレディケイト命令があります。
プレディケイト命令は使い所が難しくて静的なコンパイラだけでは痛し痒しなコードを出力しますが、
(C言語の)処理系によっては、条件分岐を 3項演算子で書くと積極的にプレディケイト命令を使ってくれてハッピーな場合があります。
特に EPIC の Itanium になると同時実行される命令スロットを埋めるために、
プレディケイト命令を積極的に使う必要がありますから、高速化のために
コーディングスタイルの変更を求められるかもしれません。
p.p.s.
コンパイラが最適化しやすいコードって、プログラマにとって明瞭な流れになるかなぁ?
例えば「A と B の 2 つの処理を定数回繰り返す返すループ。ただし、cond1 が成立する場合には初回の A 処理を省略する」というルーチンの場合、どれが読みやすいですか?
# コンパイラが最適化しやすいのは例 3。
● 例1
if( cond1 )
goto label;
for( i=0 ; i<N ; i++ ){
// A
lable:
// B
}
● 例2
if( !cond1 ){
// A
}
// B
for( i=1 ; i<N ; i++){
// A -> B
}
● 例3
if( cond1 ){
// B
for( i=1 ; i<N ; i++){
// A -> B
}
} else {
for( i=0 ; i<N ; i++ ){
// A → B
}
}
● 例4
tmp = cond1;
for( i=0 ; i<N ; i++ ){
if( tmp )
tmp = 0;
else{
// A
}
// B
}
コンタミは発見の母
訂正 (スコア:1)
● 例1
i=0;
if( cond1 )
goto label;
for( ; i<N ; i++ ){
// A
lable:
// B
}
コンタミは発見の母
Re:訂正 (スコア:0)
Re:どの言語でも (スコア:1)
i=0;
if( cond1 ){
// B
i++;
}
for( ; i<N ; i++ ){
// A -> B
}
はどうでしょう?例2よりはちょっぴりましになるかも。
保守性を考えると例1が好きですね。
同じ処理を複数箇所に書くと、片方だけ修正して気づかないことがよくあるので。
うじゃうじゃ
Re:どの言語でも (スコア:1)
> 同じ処理を複数箇所に書くと、片方だけ修正して気づかないことがよくあるので。
ですね。私も普通に書くときは例1のように書くと思います。
goto はスパゲッティーコードの素と言われますが、使い方によってはプログラムを読みやすくしてくれます。
p.s.
例1は goto の代わりに switch を使うこともできます。
コンタミは発見の母
Re:どの言語でも (スコア:1)
switch (!cond) {
case 0: for (i=0; i<N; i++) {
// A
default:
// B
}
}
# 先生! 合ってますか?
あぁ、「ン」が消えてるんですよ。「ビーフン・カレー」ね。
Re:どの言語でも (スコア:1)
i=0;
switch (cond) {
case 0: for (; i<N; i++) {
// A
default:
// B
}
}
ですね。
# 薀蓄をたれると Duff's device といいます。
あぁ、「ン」が消えてるんですよ。「ビーフン・カレー」ね。
Re:どの言語でも (スコア:1)
でも、この手の怪しい記述のコードは薀蓄を語る時か、コンパイラ
のデバッグをするときにしか使いませんよね。
実際のプログラムでこういうコーディングをする人がいて、
その人の書いたコードをデバッグすることになったら嫌だろうなぁ。
コンタミは発見の母
Re:どの言語でも (スコア:1)
例3が例2より最適化しやすい理由がわかりません。よろしかったら教えてください。
# 個人的には私なら2を選ぶだろうなと思います。
あぁ、「ン」が消えてるんですよ。「ビーフン・カレー」ね。
Re:どの言語でも (スコア:1)
このままではほとんどの最適化手法が使えないので、最適化コンパイラはコードを複製して例3 に近い形に変形します。
# irreducible loop が多段に入ると、びっくりするほど大きなオブジェクトコードが生成される
# ことがあります。
例3 はループ本体をコピーしているため、例2 よりループを周る回数を判断しやすいです。ループ系の最適化が効き易くなります。
コンタミは発見の母
Re:どの言語でも (スコア:1)
この説明は嘘ですね。例2、3ともループの回数を判断できますから。
ただ、ループに入る前の変数の状態の曖昧さ 例3 の方が少ないので、最適化は効き易いです。
A が S++、B が空だとすると、以下のように最適化される可能性があります。
● 例2
if(!cond1){
S++;
}
S += N-1;
● 例3
if(cond1){
S += N-1;
} else {
S += N;
}
# 例のコードの外側にさらにループがある場合には、例2 の方が有利かもしれません。
コンタミは発見の母
Re:どの言語でも (スコア:1)
> この説明は嘘ですね。例2、3ともループの回数を判断できますから。
ああ、そうでしたか。Nがcondに依存する変数のつもりで書かれたのかと思いました。
> ただ、ループに入る前の変数の状態の曖昧さ 例3 の方が少ないので、最適化は効き易いです。
なるほど、そのとおりですね。ご説明ありがとうございました。
あぁ、「ン」が消えてるんですよ。「ビーフン・カレー」ね。