2

このサイトでこの解決策 (元の問題を含む) が見つかるまで、私は K&R 問題 7-8 の解決策に頭を悩ませようとし続けました。答えについてコメントすることはできません (おそらく年齢のため)。その質問に実際に入力できる唯一の方法は、回答を投稿することですが、これは不適切だと感じました。だから私は、このポイントに到達するまで(関数をマクロとして実装することに関して)、論理的に思えた選択された「答え」に基づいて、この非常に関連性の高い質問を作成することにしました:

「それをマクロとして非常に頻繁に繰り返すと、ビットマスキングのサイズが固定されるため、「スペースの節約」が急速にコストになります。」

唯一の問題は、関数呼び出しにも時間がかかることです。関数の場所に「ジャンプ」し、ローカル変数用にストレージを確保し、実際に比較を計算するには、すべて時間がかかります。

では、文字の ASCII 値をテストするマクロの実装は、(これを念頭に置いて) table-lookup を組み込んだ最初の関数よりも正確にどのように実行されるのでしょうか?

2 つの整数を比較するよりも、関数呼び出しにかかる時間が短くなる可能性があるのはなぜですか。そのうちの 1 つは既にメモリ内にあり、もう 1 つは定数です。関数とマクロを繰り返し呼び出すと、時間の経過とともにマクロが高速になるように思えます。

私の考え方は間違っていますか?元の質問では取り上げられていなかったので、そうでなければならないと思います。

誰かがこれに光を当ててくれたらうれしいです。

4

1 に答える 1

3

まず第一に、彼らが言及しているコストは速度ではなくサイズであることに注意してください。たとえば、マクロが 16 バイトのコードに展開されるとします。さらに、関数が 32 バイトのコードにコンパイルされ、関数の呼び出しに 6 バイトのコードが必要であると仮定しましょう (もちろん、これらのいずれも保証されていませんが、少なくとも 32 ビットの正しい一般的な範囲内にあると思われます)。コード)。

この場合、関数を使用しても、それを 1 か所からのみ呼び出すと、38 バイトのコードになります。代わりにマクロを使用すると、16 バイトのコードしか得られず、22 バイト節約できます。マクロを 2 か所で使用すると、32 バイトのコードが得られますが、関数を使用した場合は 44 バイトになります。少し先に進んで、コード内の 10 か所で使用したと仮定しましょう。この場合、マクロは 160 バイトを使用しますが、関数は 92 バイトしか使用しません。

最新のプロセッサでは、関数も同様に高速になる可能性があるというかなり合理的な議論も見られます。最新のプロセッサのほとんどはキャッシュを使用しています。通常、関数を呼び出したときにキャッシュにあるように関数を十分に使用すると、コードを使用するたびに (より) フェッチする必要があるマクロを使用するよりもはるかに高速になります。再びメモリからコード。その理由は非常に単純です。最新のプロセッサはメモリよりもはるかに高速に動作します。

せいぜい、メモリから一部のデータをフェッチするために少なくとも 50 ns のレイテンシを計画できます (75 ~ 100 ns はかなり一般的です)。平均として 75 ns と仮定しましょう。典型的な最新の CPU は、1 クロックあたり約 1.8 命令を実行し、(たとえば) 2.5 GHz で、0.4 ns のクロック サイクル タイムを持ちます。つまり、75 ns で (平均して) 75/0.4*1.8 = 337.5 命令を実行できます。ここで話しているような関数の呼び出し、実行、および関数からの復帰は、半ダースの命令のオーダーのどこかです。約 56 回キャッシュから関数を実行できます。

もちろん、タイトなループでそれだけを実行している場合、マクロもほとんどの場合キャッシュ内にあります。関数の利点は、コード内の十分に異なる場所からその関数を呼び出して、通常はループの最初の繰り返しでもキャッシュ内にある場合に発生しますが、これは通常、マクロには当てはまりません。

于 2010-11-04T07:00:12.903 に答える