c++ - 从 C++ 中的参数复制本地数组比数组更快?

标签 c++ optimization

在优化一些代码时,我发现了一些我没有预料到的事情。 我写了一个简单的代码来说明我在下面发现的内容:

#include <string.h>
#include <chrono>
#include <iostream>

using namespace std;

int globalArr[1024][1024];

void initArr(int arr[1024][1024])
{
    memset(arr, 0, 1024 * 1024 * sizeof(int));
}


void run()
{
    int arr[1024][1024];
    initArr(arr);
    for(int i = 0; i < 1024; ++i)
    {
        for(int j = 0; j < 1024; ++j)
        {
            globalArr[i][j] = arr[i][j];
        }

    }
}

void run2(int arr[1024][1024])
{
    initArr(arr);
    for(int i = 0; i < 1024; ++i)
    {
        for(int j = 0; j < 1024; ++j)
        {
            globalArr[i][j] = arr[i][j];
        }

    }
}

int main()
{
    {
        auto start = chrono::high_resolution_clock::now();
        for(int i = 0; i < 256; ++i)
        {
            run();
        }
        auto duration = chrono::high_resolution_clock::now() - start;
        cout << "(run) Total time: " << chrono::duration_cast<chrono::microseconds>(duration).count() << " microseconds\n";
    }

    {
        auto start = chrono::high_resolution_clock::now();
        for(int i = 0; i < 256; ++i)
        {
            int arr[1024][1024];
            run2(arr);
        }
        auto duration = chrono::high_resolution_clock::now() - start;
        cout << "(run2) Total time: " << chrono::duration_cast<chrono::microseconds>(duration).count() << " microseconds\n";        
    }

    return 0;
}

我使用带有 -O3 标志的 g++ 版本 6.4.0 20180424 构建代码。 下面是在ryzen 1700上运行的结果。

(run) Total time: 43493 microseconds
(run2) Total time: 134740 microseconds

我试图通过 godbolt.org 查看程序集(代码分隔在 2 个 url 中)

https://godbolt.org/g/aKSHH6

https://godbolt.org/g/zfK14x

但我仍然不明白到底是什么造成了差异。

所以我的问题是: 1. 性能差异的原因是什么? 2. 是否有可能在参数中传递数组并具有与本地数组相同的性能?

编辑: 只是一些额外的信息,下面是使用 O2 构建的结果

(run) Total time: 94461 microseconds
(run2) Total time: 172352 microseconds

再次编辑: 从 xaxxon 的评论中,我尝试删除两个函数中的 initArr 调用。而且结果其实run2比run好

(run) Total time: 45151 microseconds
(run2) Total time: 35845 microseconds

但我还是不明白原因。

最佳答案

  1. What's causing the performance difference?

编译器必须为 run2 生成代码,如果您调用,该代码将继续正常工作

run2(globalArr);

或者(更糟),传入一些重叠但不相同的地址。

如果您允许您的 C++ 编译器内联调用,并且它选择这样做,它将能够生成内联代码,该代码知道该参数是否真的为您的全局别名。尽管如此,离线代码生成仍然必须是保守的。

  1. Is it possible passing array in argument with the same performance as local array?

您当然可以使用 restrict 修复 C 中的别名问题。关键字,例如

void run2(int (* restrict globalArr2)[256])
{
    int (* restrict g)[256] = globalArr1;
    for(int i = 0; i < 32; ++i)
    {
        for(int j = 0; j < 256; ++j)
        {
            g[i][j] = globalArr2[i][j];
        }
    }
}

(或者可能在 C++ 中使用非标准扩展 __restrict)。

这应该允许优化器像在您的原始运行 中一样自由 - 除非它足够聪明以完全省略局部并简单地将全局设置为零。

关于c++ - 从 C++ 中的参数复制本地数组比数组更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50523123/

相关文章:

c - 最后使用的缓存行与不同的缓存行

c++ - 散列中的单独链接

c++ - QTest 获取测试名称

c++ - 图片/"most resembling pixel"搜索优化?

c++ - 计算快速线终点

python - 尝试用 cvxpy 解决数独问题

mysql - 使用跨 3 个表的简单联接优化 MySQL 查询

c++ - 解析 xml 时无法获取属性的名称和值

c++ - FLTK显示图像

c++ - 编译器无法识别 Getline