インライン機能をクライアントまで、フルのC#?
-
19-08-2019 - |
質問
ごきげんよう"インライン機能"クライアントまで、フルのC#?とは思わないか、コンセプトです。みたいな感じですかね匿名の方法を教えてください。のようにラムダ)
注意:の回答がほぼ完全に対応する機能を インライン機能, ("マニュアル又はコンパイラの最適化を置き換え機能通話サイトのボディに相手先." ご興味のある方に 匿名(a.k.a.ラムダ)の機能を, 参照 @jalfの回答 または この'ラムダ"皆保といえば?.
解決
最後に.NET 4.5で、CLRは MethodImplOptions.AggressiveInlining
値。また、Monoのトランクでも利用可能です(今日コミットされています)。
// The full attribute usage is in mscorlib.dll,
// so should not need to include extra references
using System.Runtime.CompilerServices;
...
[MethodImpl(MethodImplOptions.AggressiveInlining)]
void MyMethod(...)
1 。以前は<!> quot; force <!> quot;ここで使用されました。いくつかのダウン票があったので、この用語を明確にしようとします。コメントとドキュメントのように、The method should be inlined if possible.
特にMono(オープン)を考慮すると、インライン化またはより一般的なもの(仮想関数など)を考慮するモノ固有の技術的な制限があります。全体的に、はい、これはコンパイラーへのヒントですが、それが求められたものだと思います。
他のヒント
インラインメソッドは、関数のコードが呼び出し元にロールされる単純なコンパイラ最適化です。
C#でこれを行うメカニズムはなく、サポートされている言語では控えめに使用する必要があります-どこで使用する必要があるかわからない場合は、使用しないでください/ p>
編集:明確にするために、控えめに使用する必要がある2つの主な理由があります:
- 不要な場合にインラインを使用すると、大量のバイナリを簡単に作成できます
- パフォーマンスの観点から何かをインライン化する必要がある場合、コンパイラはあなたよりもよく知っている傾向があります
物事を放置し、コンパイラに作業を任せてから、インラインが最適なソリューションであるかどうかをプロファイルし、把握するのが最善です。もちろん、インライン化するのが理にかなっているものもあります(特に数学演算子)が、通常はコンパイラーに処理させることがベストプラクティスです。
更新: konrad.kruczynskiの回答により、次のバージョンの場合に当てはまります。 4.0までのNET。
MethodImplAttributeクラスを使用できますメソッドがインライン化されるのを防ぐ ...
[MethodImpl(MethodImplOptions.NoInlining)]
void SomeMethod()
{
// ...
}
...しかし、反対のことを行う方法はなく、強制的にインライン化する。
2つの異なる概念を混ぜています。関数のインライン化は、セマンティクスに影響を与えないコンパイラーの最適化です。関数は、インライン化されているかどうかにかかわらず同じように動作します。
一方、ラムダ関数は純粋にセマンティックな概念です。言語仕様で定められた動作に従う限り、それらの実装または実行方法に関する要件はありません。 JITコンパイラーが気に入ればインライン化できますが、そうでない場合はインライン化できません。
C#にはインラインキーワードはありません。これは、特にJIT言語でコンパイラに任せることができる最適化であるためです。 JITコンパイラーはランタイム統計にアクセスできるため、コードを作成するときよりもはるかに効率的にインライン化するものを決定できます。コンパイラーが決定した場合、関数はインライン化され、どちらの方法でも実行できることはありません。 :)
C ++の意味でのインライン関数を意味しますか?通常の関数の内容は、自動的にコールサイトにインラインでコピーされますか?最終的な効果は、関数を呼び出すときに関数呼び出しが実際に発生しないことです。
例:
inline int Add(int left, int right) { return left + right; }
もしそうなら、いいえ、これに相当するC#はありません。
または、別の関数内で宣言されている関数を意味しますか?そうであれば、C#は匿名メソッドまたはラムダ式を介してこれをサポートします。
例:
static void Example() {
Func<int,int,int> add = (x,y) => x + y;
var result = add(4,6); // 10
}
Codyはそれを正しく持っていますが、インライン関数とは何かの例を示したいと思います。
このコードがあるとしましょう:
private void OutputItem(string x)
{
Console.WriteLine(x);
//maybe encapsulate additional logic to decide
// whether to also write the message to Trace or a log file
}
public IList<string> BuildListAndOutput(IEnumerable<string> x)
{ // let's pretend IEnumerable<T>.ToList() doesn't exist for the moment
IList<string> result = new List<string>();
foreach(string y in x)
{
result.Add(y);
OutputItem(y);
}
return result;
}
コンパイラ Just-In-Timeオプティマイザは、スタック上でOutputItem()の呼び出しを繰り返し配置しないようにコードを変更することを選択できます。これにより、コードを記述したかのようになります。代わりに次のようにします。
public IList<string> BuildListAndOutput(IEnumerable<string> x)
{
IList<string> result = new List<string>();
foreach(string y in x)
{
result.Add(y);
// full OutputItem() implementation is placed here
Console.WriteLine(y);
}
return result;
}
この場合、OutputItem()関数はインライン化されたと言えます。 OutputItem()が他の場所からも呼び出された場合でも、これを行う可能性があることに注意してください。
インライン化される可能性が高いシナリオを表示するように編集。
はいはい、唯一の違いは値を返すという事実です。
単純化(式を使用しない):
List<T>.ForEach
アクションを実行しますが、結果を返すことはありません。
したがって、Action<T>
デリゲートで十分です..:
List<T>.ForEach(param => Console.WriteLine(param));
は次のことと同じです:
List<T>.ForEach(delegate(T param) { Console.WriteLine(param); });
違いは、paramタイプとデリゲートの宣言が使用法によって推論されることであり、単純なインラインメソッドでは中括弧は必要ありません。
Where as
List<T>.Where
関数を受け取り、結果を期待します。
したがって、Function<T, bool>
が期待されます。
List<T>.Where(param => param.Value == SomeExpectedComparison);
これは次と同じです:
List<T>.Where(delegate(T param) { return param.Value == SomeExpectedComparison; });
これらのメソッドをインラインで宣言し、変数IEに割り当てることもできます。
Action myAction = () => Console.WriteLine("I'm doing something Nifty!");
myAction();
または
Function<object, string> myFunction = theObject => theObject.ToString();
string myString = myFunction(someObject);
これが役立つことを願っています。
コードを強制的にインライン化したい場合があります。
たとえば、非常に反復的なブロック内で多数の決定が行われる複雑なルーチンがあり、それらの決定の結果、実行されるアクションが類似しているがわずかに異なる場合。例えば、複雑な(DB駆動ではない)ソート比較器を考えてみましょう。ソートアルゴリズムは、高速言語の文法的基準と意味的基準に従って単語をソートする場合のように、さまざまな無関係な基準に従って要素をソートします。認識システム。ソースコードの可読性とモジュール性を維持するために、これらのアクションを処理するヘルパー関数を作成する傾向があります。
これらのヘルパー関数はインライン化する必要があることを知っています。これは、人間が決して理解する必要がない場合にコードを記述する方法だからです。この場合、関数呼び出しのオーバーヘッドがないことを確実に確認したいと思います。
計算書に"最高の離れで、コンパイラを組み合わせて形を作る.."(Cody Brociousが完了しているrubish.いにおいて高性能-ゲームコードでは、20年間やっていくコンパイラが十分にスマート'を知るコードinlined(機能)です。いて"インライン"の声にスレッドセーフで、c#、このコンパイラで作って全ての情報が必要かを決定する機能は常にinlinedはなく、"インライン"のヒント.さらにその機能は小さなアクセス用メソッド)でも自動的にinlinedんだ数行のコードについて教えてください。Nonesense、コンパイラがないのを知りながらお客さんをお持ちいただくだける、コンパイラの最適コードを超えalgorithims).
いいえ、C#にはそのような構造はありませんが、.NET JITコンパイラーはJIT時にインライン関数呼び出しを行うことを決定できます。しかし、実際にそのような最適化を行っているかどうかはわかりません。
(そうすべきだと思う:-))
アセンブリが生成される場合、TargetedPatchingOptOutをご覧ください。これは、ngenがメソッドをインライン化するかどうかを決定するのに役立ちます。 MSDNリファレンス
それでも、命令型コマンドではなく、最適化するための宣言的なヒントにすぎません。
この質問はC#に関するものであることは知っています。ただし、F#を使用して.NETでインライン関数を作成できます。参照: F#での `inline`の使用
ラムダ式はインライン関数です!私は、C#にはインラインなどの余分な属性がないと思います!
C#は、Pythonのような動的言語のようにインラインメソッド(または関数)をサポートしません。ただし、以下の例のように、包含メソッドの変数にアクセスする必要がある場合など、匿名メソッドとラムダを同様の目的に使用できます。
static void Main(string[] args)
{
int a = 1;
Action inline = () => a++;
inline();
//here a = 2
}