我正在使用 C# 3.5 和 VS 2010 终极版。
我正在优化(以提高速度)具有四个嵌套 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)
我已经对这两种方法进行了概要分析,“之前”版本的速度相当快,大约 18% 的时间用于 GC,而“之后”版本的时间大约为 88%。很明显,添加此缓存使 GC 活动增加,但我看不出这是怎么可能的。
我在应用程序中使用了许多长寿对象。在进行分析时,我的机器没有承受重负载。张量是使用多维数组(不是锯齿状数组)实现的。上述两种方法中最内层的循环都是使用Parallel.For
构造实现的,在循环之前,我正在分配一个小double
数组。
如何减少花费在 GC 上的时间?
编辑#1:结果确实来自发布模式。
编辑#2:after方法的四个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;
}
}
}