c++ - 随着计算的进行,我的 C++ 程序变慢
问题描述
我用 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];
为了解决这个问题,我尽了最大努力找到并排除了原因,但我失败了……下面是简单的代码结构。对于这不是与本地语句相关的问题的情况,我将我的代码上传到了谷歌驱动器。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
解决方案
我不确定为什么它变得越来越慢,但我确实知道你可以在哪里获得一些性能。
二维和更高维数组仍然存储在一维内存中。这意味着(对于 C/C++ 数组)
array[i][j]
和array[i][j+1]
彼此相邻,而array[i][j]
和array[i+1][j]
可能相距任意远。
以或多或少的顺序方式访问存储在物理内存中的数据,可以显着加快您的代码速度(有时提高一个数量级或更多)!
当现代 CPU 将数据从主内存加载到处理器缓存中时,它们会获取多个值。相反,它们获取包含请求数据和相邻数据的内存块(高速缓存行)。这意味着 after
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
作为表达式结果。当该值未使用时,编译器可能会对其进行优化,但不要指望它。
推荐阅读
- java - JUnit 端到端集成测试
- sh - Cloudflare DDNS 使用 API v4 重复 sh 脚本,在单个 sh 脚本中有多个 A 记录,但失败
- gradle - 在 gradle 6.0.1 中找不到参数的方法 compileOnly()
- amazon-web-services - 如何使用 Elastic Beanstalk 和 django-cms 上传图像
- python - cv2.findContours 找不到轮廓
- python-3.x - 当没有其他python进程同时写入sqlite db数据库时,为什么会锁定它?
- c++ - 将 PrimitiveBatch::DrawIndexed 与 ID3D11DeviceContext::DrawIndexed 一起使用?
- python - 如何在 PyQt5 中创建浏览器?
- flutter - 在用户点击(平面按钮)上创建一个新的小部件
- javascript - javascript将我所有解密的html列表放入HTML