首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >加法操作如何加速此内存访问?

加法操作如何加速此内存访问?
EN

Stack Overflow用户
提问于 2015-04-06 22:49:09
回答 1查看 141关注 0票数 2

我正在看下面的代码,在计时它的性能时,我注意到了一些奇怪的东西。

为了记录在案,我是在Visual 2010、Windows7 x64、-O2优化on和发布模式中这样做的。我的处理器是英特尔的i5。

在代码中有一个部分,可以将内存写入其中。我以前是这样做的:

代码语言:javascript
复制
d_res_matrix[x][y] = a;

在这种情况下,执行整个程序大约需要2.3秒。我在胡闹代码,试图让它更快,然后我做了以下工作:

代码语言:javascript
复制
d_res_matrix[x][y] = a + 0.00000001;

在0.4s内执行!这是一个巨大的差异,但我不知道为什么会发生这种情况。

对我来说,如果速度慢一点的话,这将是有意义的,因为额外的加法操作需要时间。我想我的另一种假设是,做加法会以某种方式迫使编译器执行SIMD操作(获取、添加和写入?)。也许写会拖住管道,但这能阻止这种情况吗?有什么主意吗?

编辑(4月6日,6:19):此问题在我的家用计算机上是相同的(Visual 2012)。

编辑(4月6日,6:38):Visual 2008 (-O2,Release)中也存在这个问题。在调试中,它们都很慢,但速度却是一样的。

编辑(4月8日,1:28):我安装了Intel并行Studio XE (我是一名学生),它给我展示了很多好东西--其中之一,我从未真正删除过我声明的数组(我现在没有修复它,但请注意)。然而,释放内存并没有解决任何问题。正如理查德在答案中所概述的那样,整个问题是由密度浮点值引起的(参见更多信息这里)。FP单元不能正确地处理异常值,而启动微码序列的速度非常慢。

代码语言:javascript
复制
#include <time.h>
#include <stdio.h>
#include <cstdlib>
#include <stdlib.h>

#define DIM 1000
#define ITERATIONS 100

#define CPU_START clock_t t1; t1=clock();
#define CPU_END {long int final=clock()-t1; printf("CPU took %li ticks (%f seconds) \n", final, ((float)final)/CLOCKS_PER_SEC);}

int main(void)
{
    double ** d_matrix, ** d_res_matrix;

    d_res_matrix = new double * [DIM];
    d_matrix = new double * [DIM];

    for (int i = 0; i < DIM; i++)
    {
        d_matrix[i] = new double [DIM];
        d_res_matrix[i] = new double[DIM];
    }

    d_matrix[20][45] = 1; // start somewhere

    double f0, f1, f2, f3, f4;

    CPU_START;

    for (int iter = 0; iter < ITERATIONS; iter++)
    {
        for (int x = 1; x < DIM-1; x++) // avoid boundary cases for this example
        {
            for (int y = 1; y < DIM-1; y++)
            {
                f0 = d_matrix[x][y];
                f1 = d_matrix[x-1][y];
                f2 = d_matrix[x+1][y];
                f3 = d_matrix[x][y-1];
                f4 = d_matrix[x][y+1];

                double a = f0*0.6 + f1*0.1 + f2*0.1 + f3*0.1 + f4*0.1;

                // THIS PART IS INTERESTING:
                //d_res_matrix[x][y] = a;
                d_res_matrix[x][y] = a + 0.000000001;

            }
        }
        for (int x = 1; x < DIM-1; x++)
        {
            for (int y = 1; y < DIM-1; y++)
            {
                d_matrix[x][y] = d_res_matrix[x][y];
            }
        }
    }
    CPU_END; 

    return 0;
}

这里是一些截图的输出,以表明这不是一次发生:,不再截图:D :D,,这里是一些文本!

no添加:

代码语言:javascript
复制
CPU took 3585 ticks <3.585000 seconds>
CPU took 3592 ticks <3.592000 seconds>
CPU took 3430 ticks <3.430000 seconds>
CPU took 2032 ticks <2.032000 seconds>
CPU took 3117 ticks <3.117000 seconds>
CPU took 2050 ticks <2.050000 seconds>
CPU took 3266 ticks <3.266000 seconds>
CPU took 3394 ticks <3.394000 seconds>
CPU took 3446 ticks <3.446000 seconds>
CPU took 3131 ticks <3.131000 seconds>

加法:

代码语言:javascript
复制
CPU took 430 ticks <0.430000 seconds>
CPU took 428 ticks <0.428000 seconds>
CPU took 470 ticks <0.470000 seconds>
CPU took 470 ticks <0.470000 seconds>
CPU took 470 ticks <0.470000 seconds>
CPU took 470 ticks <0.470000 seconds>
CPU took 460 ticks <0.460000 seconds>
CPU took 471 ticks <0.471000 seconds>
CPU took 471 ticks <0.471000 seconds>
CPU took 460 ticks <0.460000 seconds>
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-04-08 18:52:30

您可能在第一次运行时生成非正态,这将避免添加。随后对这些非正常值的操作可能会非常昂贵。在调试模式下,您的数据将初始化为0,但在发布时不会发生这种情况,因此您所操作的值可能是任何值。如果在分配memset d_matrix到0之后仍然显式地看到这种行为,我会感到惊讶。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29480944

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档