アカウント名:
パスワード:
うしろから羽交い絞めにして、「やめろ、やめるんだ!!」「はなせっ離してくれっっ、ここを最適化しないと…ここを最適化しないとっっ」「ばかっ、そこで苦労してどうする。今じゃもう、gcc とかの最適化がそんな事は全部やってくれるんだっっ」「な…なんだって… じゃぁ、俺の今までの苦労は…」
うん。もう同情に涙が止まりませんよ。gccの最適化の強靭さを見た瞬間の感動を君にも分けてあげたい。
.
ただ、そのためにコードを読みにくくするのは昔のコードであってもお勧めできません。
「アセンブラで組め」「インライン アセンブリコードで組め」
で、コメントにCの読みやすいコードを書くんだ。「いつか、良いコンパイラが出てきたら、このアセンブリコードは破棄するように」というコメントをつけて。
コンパイラは「共通部分式の削除」だといった「小手先の最適化」はできますけど、アルゴリズムレベルでの最適化は無理ですね。計算量のオーダーは変わらない。計算量そのものが変わってくるような、例えば
int sum(int n) { int i, accum = 0; for (i = 1; i <= n; i++) accum += i; return accum;}
を
int sum(int n) { return (n+1)*n/2; }
に書き換えるような最適化はコンパイラには無理で、そういうの手で書くしかないし、それを突き進めていくと、どうしても可読性は悪くなるんですよね。
昔の自分が書いたコードで、
アルゴリズムレベルでの最適化は無理ですね。
そんな事はありません。Tail-Recursionコードをジャンプに変更する等は今でもやってくれて、スタック消費量などを大幅に削減してくれます。単に「あまりにも優先度の低いレアパターン」だから標準で組み込まれていないだけです。
ようするに「無理」なんじゃなくて「無駄」なんですよ。
一方で、sprintf( dst, "%s", src ) とかは gcc-4 でコードを吐けばわかりますが、strcpy( dst, src )に勝手に書き換えてくれます。
末尾再帰のループ化は、「計算量そのものが変わってくるようなアルゴリズムレベルの最適化」とはあまり認めたくないですねぇ…確かに、空間計算量はO(n)からO(1)に減ってるんですけど、「再帰呼び出し」自体は「ループの表現」方法にすぎず、それ単体では「アルゴリズム」とは呼べないというか…
> 単に「あまりにも優先度の低いレアパターン」だから標準で組み込まれていないだけです。> ようするに「無理」なんじゃなくて「無駄」なんですよ。
それはその通りだと思います。私が言いたかったのは、「コンパイラがある特定のアルゴリズムを検出して書き換えるのは無理」だって話ではなく一般論として「アルゴリズムレベル最適化をコンパイラに期待する」のは「無理」だろうってことでした。そういうレベルでは「コンパイラに期待せずに、自前でゴリゴリ書くしかないだろう」と。
特定状況でのアルゴリズムレベル最適化なら、「dhrystone ベンチマークを書き換える」ようなコンパイラも現実にありましたしねぇ…
#それでもまあ、gccの最適化がすごいのは私も認めてます。
前述のsum関数なんかを使ってる> int n=sum(10);といったコードがあったら、gccは> int n=55;に書き換えてくれますからねぇ。
単に「関数のインライン展開」と「定数ループの展開」なだけってタネが分かれば納得なんですが、初めて見たときは何事かと思いましたね。
定数を下手に前計算してマジックナンバーを埋め込むよりは、複雑な式でもをそのまま書いてもいいってことで。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
ソースを見ろ -- ある4桁UID
良い言い訳 (スコア:1)
出来る限りの最適化を加えてた結果としてどうしょうもなく読みにくくなって、それを緩和すべくくどい説明を添えることぐらいは許してください。
単純なところでは、
strcpy(dst + a + b + c, src); // 意図はstrcat(dst, src); ここまでの処理でstrlen(dst) == a + b + cなので
みたいな、(この例だと変数名が最悪なのは置いといて)分かってる値を使い回してステップ数を減らすところから、もっと凝りに凝った最適化まで。
ぱっと見て何が書いてあるのか分からない、
Re: (スコア:2, 参考になる)
うしろから羽交い絞めにして、
「やめろ、やめるんだ!!」
「はなせっ離してくれっっ、ここを最適化しないと…ここを最適化しないとっっ」
「ばかっ、そこで苦労してどうする。今じゃもう、gcc とかの最適化がそんな事は全部やってくれるんだっっ」
「な…なんだって… じゃぁ、俺の今までの苦労は…」
うん。もう同情に涙が止まりませんよ。gccの最適化の強靭さを見た瞬間の感動を君にも分けてあげたい。
.
ただ、そのためにコードを読みにくくするのは昔のコードであってもお勧めできません。
「アセンブラで組め」
「インライン アセンブリコードで組め」
で、コメントにCの読みやすいコードを書くんだ。
「いつか、良いコンパイラが出てきたら、このアセンブリコードは破棄するように」
というコメントをつけて。
fjの教祖様
Re: (スコア:1, 興味深い)
コンパイラは「共通部分式の削除」だといった「小手先の最適化」はできますけど、
アルゴリズムレベルでの最適化は無理ですね。計算量のオーダーは変わらない。
計算量そのものが変わってくるような、例えば
を
に書き換えるような最適化はコンパイラには無理で、そういうの手で書くしかないし、それを突き進めていくと、どうしても可読性は悪くなるんですよね。
昔の自分が書いたコードで、
Re:良い言い訳 (スコア:2, 参考になる)
そんな事はありません。Tail-Recursionコードをジャンプに変更する等は今でもやってくれて、スタック消費量などを大幅に削減してくれます。単に「あまりにも優先度の低いレアパターン」だから標準で組み込まれていないだけです。
ようするに「無理」なんじゃなくて「無駄」なんですよ。
一方で、sprintf( dst, "%s", src ) とかは gcc-4 でコードを吐けばわかりますが、
strcpy( dst, src )
に勝手に書き換えてくれます。
fjの教祖様
Re:良い言い訳 (スコア:1)
末尾再帰のループ化は、「計算量そのものが変わってくるようなアルゴリズムレベルの最適化」とはあまり認めたくないですねぇ…
確かに、空間計算量はO(n)からO(1)に減ってるんですけど、「再帰呼び出し」自体は「ループの表現」方法にすぎず、それ単体では「アルゴリズム」とは呼べないというか…
> 単に「あまりにも優先度の低いレアパターン」だから標準で組み込まれていないだけです。
> ようするに「無理」なんじゃなくて「無駄」なんですよ。
それはその通りだと思います。
私が言いたかったのは、「コンパイラがある特定のアルゴリズムを検出して書き換えるのは無理」だって話ではなく
一般論として「アルゴリズムレベル最適化をコンパイラに期待する」のは「無理」だろうってことでした。
そういうレベルでは「コンパイラに期待せずに、自前でゴリゴリ書くしかないだろう」と。
特定状況でのアルゴリズムレベル最適化なら、「dhrystone ベンチマークを書き換える」ようなコンパイラも現実にありましたしねぇ…
#それでもまあ、gccの最適化がすごいのは私も認めてます。
前述のsum関数なんかを使ってる
> int n=sum(10);
といったコードがあったら、gccは
> int n=55;
に書き換えてくれますからねぇ。
単に「関数のインライン展開」と「定数ループの展開」なだけってタネが分かれば納得なんですが、初めて見たときは何事かと思いましたね。
定数を下手に前計算してマジックナンバーを埋め込むよりは、複雑な式でもをそのまま書いてもいいってことで。