[解決済み】スタックサイズがデフォルトの50倍のスレッドを作成した場合の危険性とは?
質問
私は現在、非常にパフォーマンスが重要なプログラムに取り組んでおり、リソースの消費を減らすのに役立つかもしれない1つの道を探ることにしたのは、ワーカスレッドのスタックサイズを増やして、ほとんどのデータを移動できるようにすることです (
float[]
を使用して)スタックにアクセスすることになります。
stackalloc
).
私は
読む
スレッドのデフォルトのスタックサイズは 1 MB であるため、私のすべての
float[]
のスタックを約50倍(50MB~)に拡張する必要があります。
これは一般的に "unsafe" と考えられており、推奨されないことは理解していますが、この方法に対して現在のコードをベンチマークした結果、私は 530% 処理速度が向上しました スタックを大きくすることの危険性(何が問題なのか)と、その危険性を最小化するための予防策を教えてください。
私のテストコード
public static unsafe void TestMethod1()
{
float* samples = stackalloc float[12500000];
for (var ii = 0; ii < 12500000; ii++)
{
samples[ii] = 32768;
}
}
public static void TestMethod2()
{
var samples = new float[12500000];
for (var i = 0; i < 12500000; i++)
{
samples[i] = 32768;
}
}
解決方法は?
テストコードをSamと比較したところ、どちらも正しいことが判明しました。
しかし、異なる点についてです。
- メモリへのアクセス(読み出しと書き込み)は 同じ速さ スタック、グローバル、ヒープなど、どこであろうと。
- アロケート しかし、スタック上では最も速く、ヒープ上では最も遅いです。
こんな感じです。
stack
<です。
global
<
heap
. (割り当て時間)
技術的には、スタックの割り当ては実際には割り当てではなく、ランタイムはスタックの一部(フレーム?)が配列用に予約されていることを確認するだけです。
これには気をつけることを強く勧めますが。
をお勧めします。
- のない配列を頻繁に作成する必要がある場合。 出る を使用することで、大幅に改善されます。
- 配列を再利用できるのであれば、できる限りそうしてください。ヒープはオブジェクトの長期保存に最適な場所です。(グローバルメモリを汚染するのは良いことではありません。スタックフレームが消える可能性があります)
( ノート : 1. 値の型にのみ適用されます。参照型はヒープに割り当てられ、その恩恵は0になります)
質問そのものにお答えします。私は、どの大容量スタックテストでも、全く問題に遭遇していません。
考えられる問題は、関数呼び出しに注意しないとスタックオーバーフローが発生することと、システムが低レベルで動作している場合にスレッドを作成する際にメモリ不足になることくらいだと考えています。
下のセクションは、私の最初の回答です。間違いっぽいし、テストも正しくない。参考程度にとどめておきます。
私のテストでは、スタックに割り当てられたメモリとグローバルメモリは、配列で使用する場合、ヒープに割り当てられたメモリよりも少なくとも15%遅い(120%の時間がかかる)ことが示されました!このような場合、スタックに割り当てられたメモリとグローバルメモリは、配列で使用する場合、ヒープに割り当てられたメモリよりも少なくとも15%遅い(120%の時間がかかる)。
これは私のテストコードです。 そして、これが出力例です。
Stack-allocated array time: 00:00:00.2224429
Globally-allocated array time: 00:00:00.2206767
Heap-allocated array time: 00:00:00.1842670
------------------------------------------
Fastest: Heap.
| S | G | H |
--+---------+---------+---------+
S | - | 100.80 %| 120.72 %|
--+---------+---------+---------+
G | 99.21 %| - | 119.76 %|
--+---------+---------+---------+
H | 82.84 %| 83.50 %| - |
--+---------+---------+---------+
Rates are calculated by dividing the row's value to the column's.
Windows 8.1 Pro (Update 1)、i7 4700 MQ、.NET 4.5.1上でテストしました。
x86とx64の両方でテストしましたが、結果は同じです。
編集
: 全スレッドのスタックサイズを201MBに、サンプルサイズを5000万に、反復回数を5回にしました。
結果は以下の通りです。
上記と同じ
:
Stack-allocated array time: 00:00:00.4504903
Globally-allocated array time: 00:00:00.4020328
Heap-allocated array time: 00:00:00.3439016
------------------------------------------
Fastest: Heap.
| S | G | H |
--+---------+---------+---------+
S | - | 112.05 %| 130.99 %|
--+---------+---------+---------+
G | 89.24 %| - | 116.90 %|
--+---------+---------+---------+
H | 76.34 %| 85.54 %| - |
--+---------+---------+---------+
Rates are calculated by dividing the row's value to the column's.
とはいえ、実際にはスタックは 遅くなる .
関連
-
[解決済み】プラットフォームが同じでも「不正なフォーマットでプログラムを読み込もうとしました。
-
[解決済み] C#の正しいバージョン番号を教えてください。
-
[解決済み] Javaで、オブジェクトの大きさを決定する最も良い方法は何ですか?
-
[解決済み] WPFの場合、x:Name属性とName属性の違いは何ですか?
-
[解決済み] C#のデフォルトのアクセス修飾子は何ですか?
-
[解決済み] タスクとスレッドの違いは何ですか?
-
[解決済み] LINQは結果が空の場合、何を返すのですか?
-
[解決済み】ExpandoObjectの本当のメリットは何ですか?
-
[解決済み】スタックの目的は何ですか?なぜそれが必要なのですか?
-
[解決済み】enum変数のデフォルト値は何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] [Entity Framework 4.1でエンティティに関連オブジェクトを追加する際に、エンティティオブジェクトをIEntityChangeTracker.の複数のインスタンスから参照できない。
-
[解決済み】「namespace x already contains a definition for x」エラーの修正方法は?VS2010にコンバートした後に発生しました。
-
[解決済み】Socket.Selectがエラー "An operation was attempted on something that is not a socket" を返す。
-
[解決済み】MetadataException: 指定されたメタデータ・リソースをロードできない
-
[解決済み】Swashbuckle/Swagger + ASP.Net Core: "Failed to load API definition" (API定義の読み込みに失敗しました
-
[解決済み】値をNULLにすることはできません。パラメータ名:source
-
[解決済み] [Solved] .NETでスレッドの終了を待つには?
-
[解決済み】URLから画像をダウンロードする方法
-
[解決済み】別のスレッドがこのオブジェクトを所有しているため、呼び出し側のスレッドはこのオブジェクトにアクセスできない
-
[解決済み] Javaで正しいマイクロベンチマークを書くには?