我用C ++编写了一个神经网络程序来测试某些东西,结果发现我的程序随着计算的进行变得越来越慢。由于这种现象是我以前从未见过的,因此我检查了可能的原因。程序使用的内存变慢时不会改变。运行程序时,RAM和CPU的状态很好。
幸运的是,该程序的先前版本没有这样的问题。因此,我终于找到一条使程序运行缓慢的语句。当我使用以下语句时,程序不会变慢:
dw[k][i][j] = hidden[k-1][i].y * hidden[k][j].phi;
但是,一旦我将上面的语句替换为:
,程序就会变得越来越慢dw[k][i][j] = hidden[k-1][i].y * hidden[k][j].phi - lambda*w[k][i][j];
为解决此问题,我尽力查找并消除了原因,但失败了...以下是简单的代码结构。对于这不是与本地语句相关的问题,我将代码上传到了Google驱动器。 URL位于此问题的末尾。
MLP.h
class MLP
{
private:
...
double lambda;
double ***w;
double ***dw;
neuron **hidden;
...
MLP.cpp
...
for(k = n_depth - 1; k > 0; k--)
{
if(k == n_depth - 1)
...
else
{
...
for(j = 1; n_neuron > j; j++)
{
for(i = 0; n_neuron > i; i++)
{
//dw[k][i][j] = hidden[k-1][i].y * hidden[k][j].phi;
dw[k][i][j] = hidden[k-1][i].y * hidden[k][j].phi - lambda*w[k][i][j];
}
}
}
}
...
完整的源代码:https://drive.google.com/open?id=1A8Uw0hNDADp3-3VWAgO4eTtj4sVk_LZh
答案 0 :(得分:3)
我不确定为什么它变得越来越慢,但我确实看到了可以在其中获得一些性能的地方。
二维和更高维数组仍存储在一维中 记忆。这意味着(对于C / C ++数组)
array[i][j]
和array[i][j+1]
彼此相邻,而array[i][j]
和array[i+1][j]
可以 任意分开。
以或多或少的顺序访问数据,如 物理内存可以极大地加快您的代码的速度(有时 数量级,甚至更多)!
当现代CPU将数据从主内存加载到处理器缓存中时, 他们获取的不仅仅是单个值。取而代之的是 包含请求的数据和相邻数据的内存(高速缓存行 )。这意味着
array[i][j]
在CPU缓存中后,array[i][j+1]
已经在缓存中的可能性很大,而array[i+1][j]
是 可能仍在主内存中。
来源:https://people.cs.clemson.edu/~dhouse/courses/405/papers/optimize.pdf
使用您当前的代码,将读取w[k][i][j]
,在下一次迭代中,将读取w[k][i+1][j]
。您应该反转i和j,以便按顺序读取w
:
for(j = 1; n_neuron > j; ++j)
{
for(i = 0; n_neuron > i; ++i)
{
dw[k][j][i] = hidden[k-1][j].y * hidden[k][i].phi - lambda*w[k][j][i];
}
}
还要注意,++x
应该比x++
快一点,因为x++
必须创建一个包含旧值x
的临时表达式作为表达式结果。不过,当未使用该值时,编译器可能会对其进行优化,但不要依靠它。