パスワードを忘れた? アカウント作成
この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。

コメントはソースコードを表す?」記事へのコメント

  • > コメントに言い訳まがいのくどい説明

    出来る限りの最適化を加えてた結果としてどうしょうもなく読みにくくなって、それを緩和すべくくどい説明を添えることぐらいは許してください。

    単純なところでは、

    strcpy(dst + a + b + c, src); // 意図はstrcat(dst, src); ここまでの処理でstrlen(dst) == a + b + cなので

    みたいな、(この例だと変数名が最悪なのは置いといて)分かってる値を使い回してステップ数を減らすところから、もっと凝りに凝った最適化まで。

    ぱっと見て何が書いてあるのか分からない、
    • Re: (スコア:2, 参考になる)

      うしろから羽交い絞めにして、
      「やめろ、やめるんだ!!」
      「はなせっ離してくれっっ、ここを最適化しないと…ここを最適化しないとっっ」
      「ばかっ、そこで苦労してどうする。今じゃもう、gcc とかの最適化がそんな事は全部やってくれるんだっっ」
      「な…なんだって… じゃぁ、俺の今までの苦労は…」

      うん。もう同情に涙が止まりませんよ。gccの最適化の強靭さを見た瞬間の感動を君にも分けてあげたい。

      .

      ただ、そのためにコードを読みにくくするのは昔のコードであってもお勧めできません。

      「アセンブラで組め」
      「インライン アセンブリコードで組め」

      で、コメントにCの読みやすいコードを書くんだ。
      「いつか、良いコンパイラが出てきたら、このアセンブリコードは破棄するように」
      というコメントをつけて。

      --
      fjの教祖様
      • by taka2 (14791) on 2009年11月19日 17時22分 (#1675293) ホームページ 日記

        コンパイラは「共通部分式の削除」だといった「小手先の最適化」はできますけど、
        アルゴリズムレベルでの最適化は無理ですね。計算量のオーダーは変わらない。
        計算量そのものが変わってくるような、例えば

        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; }

        に書き換えるような最適化はコンパイラには無理で、そういうの手で書くしかないし、それを突き進めていくと、どうしても可読性は悪くなるんですよね。

        昔の自分が書いたコードで、「何を計算したいのか」「どういう式で算出しているのか」は一目瞭然なんだけど、
        「なぜその式で答えが出るのか」がさっぱり分からないという羽目になったことがあります。
        仕方ないので、ムダにもう一度悩んで悩んで、なんとかその通りに式変形できることを確認しました。

        それ以来、私はそういう処理をした時は、コメントに式変形過程を残したりしてますけど、そもそもテキストベースで「数式を書く」こと自体が難しいという問題があるんですよね。
        TeXスタイルは厳密な数式表現はできるけど可読性悪いし。
        結局、アスキーアート駆使して書いてます。

        親コメント
        • Re:良い言い訳 (スコア:2, 参考になる)

          by okky (2487) on 2009年11月20日 10時59分 (#1675799) ホームページ 日記

          アルゴリズムレベルでの最適化は無理ですね。

          そんな事はありません。Tail-Recursionコードをジャンプに変更する等は今でもやってくれて、スタック消費量などを大幅に削減してくれます。単に「あまりにも優先度の低いレアパターン」だから標準で組み込まれていないだけです。

          ようするに「無理」なんじゃなくて「無駄」なんですよ。

          一方で、sprintf( dst, "%s", src ) とかは gcc-4 でコードを吐けばわかりますが、
          strcpy( dst, src )
          に勝手に書き換えてくれます。

          --
          fjの教祖様
          親コメント
          • 末尾再帰のループ化は、「計算量そのものが変わってくるようなアルゴリズムレベルの最適化」とはあまり認めたくないですねぇ…
            確かに、空間計算量はO(n)からO(1)に減ってるんですけど、「再帰呼び出し」自体は「ループの表現」方法にすぎず、それ単体では「アルゴリズム」とは呼べないというか…

            > 単に「あまりにも優先度の低いレアパターン」だから標準で組み込まれていないだけです。
            > ようするに「無理」なんじゃなくて「無駄」なんですよ。

            それはその通りだと思います。
            私が言いたかったのは、「コンパイラがある特定のアルゴリズムを検出して書き換えるのは無理」だって話ではなく
            一般論として「アルゴリズムレベル最適化をコンパイラに期待する」のは「無理」だろうってことでした。
            そういうレベルでは「コンパイラに期待せずに、自前でゴリゴリ書くしかないだろう」と。

            特定状況でのアルゴリズムレベル最適化なら、「dhrystone ベンチマークを書き換える」ようなコンパイラも現実にありましたしねぇ…

            #それでもまあ、gccの最適化がすごいのは私も認めてます。

            前述のsum関数なんかを使ってる
            > int n=sum(10);
            といったコードがあったら、gccは
            > int n=55;
            に書き換えてくれますからねぇ。

            単に「関数のインライン展開」と「定数ループの展開」なだけってタネが分かれば納得なんですが、初めて見たときは何事かと思いましたね。

            定数を下手に前計算してマジックナンバーを埋め込むよりは、複雑な式でもをそのまま書いてもいいってことで。

            親コメント
        • Re:良い言い訳 (スコア:1, すばらしい洞察)

          by Anonymous Coward on 2009年11月19日 21時09分 (#1675483)

          蛇足ですが、上の関数と、下の関数は同じじゃないですよ。だからコンパイラ
          がどんなに賢くなってもその最適化は出来ない。

          > (n+1)*n

          で、n >= sqrt(2^31) になった場合、オーバーフローが起きて計算結果が負に
          なります。(32bit CPUの場合) ですがfor-loopの場合、accum >= 2^31 になる
          までオーバーフローしません。

          親コメント
          • by Anonymous Coward

            > オーバーフローが起きて計算結果が負になります。(32bit CPUの場合)
            いえ、結果は未定義です。ゼロ除算のように、例外が発生してプログラムが強制終了したっていっこうにかまいません。インテルのCPUにもそのための命令(INTO)があるのですが、アライメントチェックと同様まったくと言っていいほど使われていませんね。

            • by Anonymous Coward

              さらに言うなら
              mov eax,[n]
              mov edx,eax
              inc eax
              mov ecx, 2
              imul edx
              idiv ecx
              みたいなコードを生成するコンパイラがあったってかまわない。そういう環境ではn >= sqrt(2^31)でも(たまたま)「正しい」結果が得られるけど、移植性がない(ほかの環境に持って行くと黙って間違った答えを返すようになったり不正終了したりその他あらゆることが起きうる)プログラムになる。
              オーバーフローしなかった場合の結果さえ規格通りなら、オーバーフローが起きた場合は文字通りどんな動作をしてもかまわない。C言語っておそろしいね。INTOやBOUNDの1つ実行するコストさえもったいなかった時代には妥当な設計だったんだろうけど、今やセキュリティホールの温床。

        • by Anonymous Coward

          > に書き換えるような最適化はコンパイラには無理で、そういうの手で書くしかないし、それを突き進めていくと、どうしても可読性は悪くなるんですよね。

          あなたの挙げた例の通り、多くの場合可読性は向上します

コンピュータは旧約聖書の神に似ている、規則は多く、慈悲は無い -- Joseph Campbell

処理中...