C# 3.5 と VS 2010 Ultimate を使用しています。
ネストされた 4 つの for ループを持つ機械学習アルゴリズムを (速度のために) 最適化しています。同じオブジェクトの再割り当てが多数あるため、単純なキャッシュ (オブジェクトのテンソル) によってパフォーマンスが大幅に向上する可能性があることがわかりました。
導入前と導入後はこちら。
前:
four nested for-loops:
var object = new object(3 parameters);
Calculate(object, other params)
後:
var cache = new object[count1,count2,count3];
three nested for-loops:
cache[param1, param2, param3] = new object(3 params);
four nested for-loops:
var object = cache[3 parameters];
Calculate(object, other params)
私は両方の方法をプロファイリングしましたが、「前」のバージョンは GC に約 18% の時間が費やされてかなり高速でしたが、「後」のバージョンは GC に約 88% の時間が費やされました。このキャッシュの追加によって GC アクティビティが増加したことは明らかですが、これがどのように可能であるかはわかりません。
アプリケーションで多くの寿命の長いオブジェクトを使用しています。プロファイリングの時点で、私のマシンには大きな負荷がかかっていませんでした。テンソルは、多次元配列 (ギザギザ配列ではない) を使用して実装されました。上記の両方の方法の最も内側のループは、Parallel.For
構造体を使用して実装されています。ここでは、ループの直前に小さなdouble
配列を割り当てています。
GC に費やす時間を短縮するにはどうすればよいですか?
編集 #1: 結果は確かにリリース モードからのものです。
編集 #2: after メソッドの 4 つの for ループの実際のコード:
List<int> labels = // count = 80
List<int> tokens = // count = 35
var table = new double[tokens.Count, labels.Count, labels.Count];
var cachedObjects = new CachedObject[tokens.Count, labels.Count, labels.Count];
for (int k = 0; k < tokens.Count; k++)
{
foreach (var tagCurrent in labels)
{
foreach (var labelBack in labels)
{
double[] value = new double[labels.Count];
Parallel.For(0, labels.Count, (i) =>
{
CachedObject CachedObject = cachedObjects[k, labelsBackFurther[i], labelBack];
var me = ModelEstimate(vOptimal, CachedObject, tagCurrent, labels);
value[i] = table[k - 1, labels[i], labelBack] * me;
});
var maxValue = 0;
var maxTagIdx = 0;
for (int j = 0; j < value.Length; j++)
{
var item = value[j];
if (item > maxValue)
{
maxValue = item;
maxTagIdx = j;
}
}
table[k, labelBack, tagCurrent] = maxValue;
}
}
}