首页 > 解决方案 > 在 for 循环中使用变量作为数组的索引而不是在每次迭代时计算它们真的更快吗?

问题描述

在我的实习期间,我必须使用嵌套的 for 循环,我写了这样的东西(在 C 中):

        for (int N_dt0_s_dt = 0; N_dt0_s_dt < N_dt; N_dt0_s_dt++)
        {
            for (int j = 0; j < N; j++)
            {
                for (int i = 0; i < N0; i++)
                {
                    Matrix_t0[i + N0 * j] += M_t_t0_loc[i + N0 *(N_dt0_s_dt + j)];
                }
            }
        }

这里,N 和 N0 是表示矩阵维数的整数。N 和 N0 介于 200 和 500 之间,具体取决于输入矩阵。在审查代码期间,一些同事建议进行以下更改:

        int dec,dec1;//to compute index
        for (int N_dt0_s_dt = 0; N_dt0_s_dt < N_dt; N_dt0_s_dt++)
        {
            for (int j = 0; j < N; j++)
            {
                dec = N0 * j;
                dec1 = N0 *(N_dt0_s_dt + j);
                for (int i = 0; i < N0; i++)
                {
                    Matrix_t0[i + dec] += M_t_t0_loc[i + dec1];
                }
            }
        }
    }

同事告诉我,后者应该运行得更快,因为我们没有计算每次迭代时得出 N0 *(N_dt0_s_dt + j) 所需的操作。

我认为这是非常合理的,但我在问自己编译器(Visual Studio)是否已经在进行优化,这会使这些更改变得无用。

对此的一些想法将不胜感激。

标签: cfor-loopoptimization

解决方案


您需要查看生成的组件以确定。也就是说,通用子表达式消除是一种非常容易理解的优化技术,据我所知,现在大多数常用的编译器都会使用合适的优化选项来实现。

有趣的是,优化人员如今的工作越来越好。过去,如果您写下以下内容,您会得到一记耳光:

for (auto it = container.begin(); it != container.end(); it++)

但是,我通过编写两个等效函数来测试 MSVC,其中一个使用上述函数,而另一个使用“已批准”:

for (auto it = container.begin(); it != container.end(); ++it)

没有其他区别。

MSVC 不仅正确地意识到它可以替换it++为,++it因为我实际上并没有使用该值,然后它在链接过程中注意到这两个例程现在是相同的,所以它完全省略了其中一个,并使用了目标代码另一个用于两个调用。


推荐阅读