例としてUnityのShader風に記載します。
float a = "変数" + 0.5;
return a * a;
のようなものがあった場合、以下と結果は変わらないと思いますが、
return ("変数"+0.5) * ("変数"+0.5);
負荷的には、前者のほうが軽いのでしょうか。わからないでいるのは、"a"には計算結果だけが格納されるのか、計算式そのものが格納されているのか、です。
「計算結果」だけが格納されているのであれば前者のほうが軽いと思いますし、「計算式」が格納されていてaを使うと中身が展開されるような形なら両者とも負荷は変わらないと思うんです。どっちなのでしょうか
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答6件
0
解決済みですが、質問文に「(どの言語にもいえる)」と書いてあるので、C#以外の言語について補足しておきたいと思います。
この回答には、参照透過など関数型プログラミングの用語や最適化にまつわる定数式などの用語が含まれているため、理解にはある程度の知識が必要なことをあらかじめご了承ください。
まず、言語によって式の評価の仕方、および、最適化の仕方はかなり異なります。ですので、C#での動作がどの言語でも同じとは言えません。
まず、Haskellのような純粋関数型言語の場合、遅延評価という動作になります。
Haskell
1a = x + 0.5 2b = a * a 3x = 0.1 4 5main = print b
a = x + 0.5
の時点でa
がどんな式の結果なのかが定義されるだけで、評価されません。そもそもx
が不明なので評価できません。続くb
でも評価はされません。最後のmain
でb
の評価値が必要となって、b
の定義の式を評価しようとします。さらにa
の評価値が必要となって、a
の定義の式を評価しようとします。a
ではx
がちゃんと定義されていますので、0.6が評価値になるでしょう。最初のa
はこれで定まったのでb
の定義の評価の続きをしようと2盤面のa
を評価しようとします。このとき、a
の定義の式を再度評価するのかというと、a
は参照透過であるため、再度評価しても結果は同じなので、ほとんどの場合はキャッシュが使われます(キャッシュが使われるかどうかは実行環境の実装次第なので、必ず使われるわけはありません)。
つまり、遅延評価が前提のような場合は、a
の結果ではなくa
の式がそこに置かれているとみなすことができます。言わば、質問の前者と後者はあまり違いが無いと言うことです。これは、C#のような正格評価の言語とは全く異なることに注意してください。
次に最適化についてです。
先程のHaskellの例ではa
は参照透過と言いましたが、このように参照透過であることが保証されていれば、キャシュを使う、または、2回計算しないような処理に最適化される場合があります。これは変数に入れた場合に限りません。質問の後者の場合であっても、("変数"+0.5)
が参照透過であれば、二つ目の式は一つ目の式の結果を使う場合があると言うことです。
この、参照透過であるというのはかなり複雑です。"変数"がどうなっているかによって違います。例えばobj.name
と言ったプロパティアクセスの場合、C#では参照透過ではない可能性がある(プロパティの読み込みアクセスは副作用ありにできる)ため、処理のキャッシュを使うと言うことができません。優秀なコンパイラやJITエンジンはこれらを自動的に判別して、「どちらであっても確実に結果がわからない」場合のみキャッシュを使用するような動作になります。
最適化はまだあります。前者で使われた変数a
ですが、その変数が他の場所で使われていない場合は、変数がなかったかのように処理される場合があります。つまり、変数ようにメモリが確保されるわけではなく、a
を計算した結果がレジスタにあるうちにそのままa * a
を求めると言うことです。C/C++での最適化では度々この処理が行われます。(他で使われた瞬間に最適化から外れるので、確認するのは難しいです。)
最適化についてもう一つです。それは定数式です。もし、"変数"部分が定数式なら、a
は定数式でしょう。そうなるとa * a
も定数式です。言語やコンパイラによって異なりますが、定数式の場合、コンパイル時にその値に置き換わります。実行時に計算しても常に結果が同じだから、コンパイル時に計算して置き換えておこうという物です。この場合、前者も後者もコンパイル後は一つの「値」に置き換わっているため、全く同じ動作になるでしょう。
プログラミング言語は似たような言語では同じような動作をすることも多いですが、細部を見ると千差万別です。他の方はC#を念頭に回答していると思われますが、C#以外の言語でも全く同じになるとは限らないと言うことだけが、伝わっていれば幸いです。
投稿2020/08/14 02:46
編集2020/08/14 02:47総合スコア21739
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
"変数" とはなんでしょうか? メソッド内での変数? それとも外部定義? それによっても(若干)異なると思いますが、、
a
は、floatとして宣言されているので、式ではなく、値(計算結果)が格納されます。(少なくとも、C#とかでは)
ただ、どちらが実際の処理として軽い(速い)かは、単純には分かりません。最近のコンパイラは、最適化が行われるので、コンパイルした結果で見る必要があります。
(まあ、一旦、 aに結果を格納した方が速いとは思いますが)
なお、"変数"が外部定義で、マルチタスクとかで参照されている場合、結果が異なる事があるので注意が必要。
投稿2020/08/13 12:32
総合スコア6385
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
この程度の違いならばコンパイル時に自動修正されるでしょう。
インタプリタ言語だとすればケースバイケースです。
投稿2020/08/13 12:40
総合スコア4830
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/08/13 12:42
2020/08/14 12:06
0
ベストアンサー
a には計算結果が格納されます
最初の例では、足し算一回と、掛け算一回(と変数の代入一回)の動作ですが、
あとの例では、足し算2回と掛け算一回の動作となります
まあ、最近のCPUでは、計算1回より、メモリ(変数)のアクセスのほうが実行時間がかかる事が多いため、どちらかと言うとあとのほうが軽くなったりしますね
投稿2020/08/13 12:28
総合スコア88042
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。