我正在4个线程中运行while循环,在循环中评估函数并逐步增加计数器。
while(1) {
int fitness = EnergyFunction::evaluate(sequence);
mutex.lock();
counter++;
mutex.unlock();
}
当我运行这个循环时,如我在4个运行线程中所说的那样,我每秒得到大约20,000,000次的评估。
while(1) {
if (dist(mt) == 0) {
sequence[distDim(mt)] = -1;
} else {
sequence[distDim(mt)] = 1;
}
int fitness = EnergyFunction::evaluate(sequence);
mainMTX.lock();
overallGeneration++;
mainMTX.unlock();
}
如果我为这个序列添加一些随机突变,我可以获得每秒约13,000,000次的评估。
while(1) {
if (dist(mt) == 0) {
sequence[distDim(mt)] = -1;
} else {
sequence[distDim(mt)] = 1;
}
int fitness = EnergyFunction::evaluate(sequence);
mainMTX.lock();
if(fitness < overallFitness)
overallFitness = fitness;
overallGeneration++;
mainMTX.unlock();
}
但是,当我添加一个简单的if语句去检查新的适应度是否比旧的适应度更小,如果是,则用新的适应度替换旧的适应度。
但是性能损失非常大!现在我每秒只能得到约20,000次评估。如果我删除随机变异部分,那么我也可以得到约20,000次评估每秒。
变量overallFitness被声明为
extern int overallFitness;
我遇到了麻烦,无法弄清楚导致性能大幅度下降的问题是什么。比较两个int是否会花费很长时间?
此外,我不认为这与互斥锁有关。
更新
这个性能问题不是因为分支预测,而是编译器忽略了这个调用int fitness = EnergyFunction::evaluate(sequence);
。
现在我添加了volatile
,编译器不再忽略该调用。
同时感谢您指出了分支误判和atomic<int>
,我之前不知道它们!
由于使用了原子性,我也删除了互斥部分,所以最终代码如下:
while(1) {
sequence[distDim(mt)] = lookup_Table[dist(mt)];
fitness = EnergyFunction::evaluate(sequence);
if(fitness < overallFitness)
overallFitness = fitness;
++overallGeneration;
}
现在我每秒获得约25,000个评估。
atomic<int>
可能会有帮助。 - Jarod42.lock()
和.unlock()
是一种反模式 - 使用lock_guard
。 - Barry