我正在对C模拟进行编码,其中,给定一系列要验证的规则,我们将其分解为“切片”并验证每个切片。 (基本思想是顺序很重要,规则的实际含义受到上面某些规则的影响;我们可以为每个规则制作一个“切片”,只有与它重叠的那些规则。我们然后验证切片,通常比整个序列小得多。)
我的问题如下。
我有一个struct(policy),它包含一个struct(规则)数组和一个int(length)。 我最初的实现使用了malloc和realloc:
struct{
struct rule *rules;
int length;
}policy;
...
struct policy makePolicy(int length)
{
struct policy newPolicy;
newPolicy.rules = malloc(length * sizeof(struct rule));
newPolicy.length = length;
return newPolicy;
}
...
struct policy makeSlice(struct policy inPol, int rulePos)
{
if(rulePos > inPol.length - 1){
printf("Slice base outside policy \n");
exit(1);
}
struct slice = makePolicy(inPol.length);
//create slice, loop counter gets stored in sliceLength
slice.rules = realloc(slice.rules, sliceLength * sizeof(struct rule));
slice.length = sliceLength;
return slice;
}
由于这使用malloc的内存,我假设它大量使用堆。 现在我正在尝试移植到一个没有malloc的实验性并行机器。
我很遗憾地用固定大小的数组分配了所有内容。
现在这是令人震惊的。
新代码运行速度较慢。慢得多。
(原始代码用于在切片长度为200时结束等待分钟,也可能在300以上时等待一小时...现在当切片长度为70,80时已经这样做了...花费数小时说120.仍然不是200。)
唯一的问题是,现在切片被赋予与完整策略相同的内存(MAXBUFLEN为10000),但整体似乎没有内存耗尽。 'top'表示消耗的总内存非常适中,数十兆字节范围与以前一样。 (当然,当我存储长度时,我并没有遍历整个事物,只是具有真实规则的部分。)
有人可以帮忙解释为什么它突然变得如此之慢?
答案 0 :(得分:3)
似乎当你将结构的大小固定为更大的大小(例如10000个规则)时,你的缓存局部性可能会比原始局部性差得多。您可以使用分析器(Valgrind中的oprofile或cachegrind)来查看缓存是否有问题。
在原始程序中,一个缓存行最多可以容纳8 struct policy
(在具有64byte缓存行的32位机器上)。但是在修改后的版本中,它只能容纳一个,因为它现在比缓存行大小要大得多。
在这种情况下,向上移动length
字段可以提高性能,因为现在length
和前几个struct rule
可以放入单个缓存行中。
struct policy{
int length;
struct rule rules[10000];
};
要解决此问题,您需要编写自己的自定义分配器以确保缓存位置。如果您正在编写此程序的并行版本,还要记住将不同线程使用的内存隔离到不同的缓存行中,以避免缓存行争用。