我正在运行一个简单的二维数组读写访问基准测试练习.

我有const int XDim = 1000;const int YDim = 1000;,并创建了一个1000 x 1000矩阵.

在C风格中,我使用

double* doubleArray[XDim];
for (int i = 0; i < XDim; i++)
    doubleArray[i] = (double*)malloc(YDim * sizeof(double));
for (int i = 0; i < XDim; i++)
    for (int j = 0; j < YDim; j++)
        doubleArray[i][j] = 0.;

在C++std::vector<std::vector<double>>中,我使用:

std::vector<std::vector<double>> doubleArray;
std::vector<double> vecdbl;
for (int i = 0; i < XDim; i++)
    doubleArray.push_back(vecdbl);
for (int i = 0; i < XDim; i++)
    for (int j = 0; j < YDim; j++)
        doubleArray[i].push_back(0.);

在Boost风格中,我使用:

typedef boost::multi_array<double, 2> OuterArray;
typedef boost::array<OuterArray::index, 2> OuterArrayIndices;
OuterArray::index rows = XDim;
OuterArray::index cols = YDim;
OuterArrayIndices shape = { rows, cols };
OuterArray doubleArray(shape);
for (int i = 0; i < XDim; i++)
    for (int j = 0; j < YDim; j++)
        doubleArray[i][j] = 0.;

然后,我从doubleArray[][]中随机 Select 999999个元素,并将它们设置为[-5, 5]中 Select 的随机整数值.然后,我进一步随机挑选999999个元素,将它们相加,然后求出它们的平均值.找到平均值,并显示所有这些操作所用的时间.这个练习重复了很多次.

完成这一切的Godbolt链接有here多个

在上面的链接中,龙箭似乎只处理了const int total_iterations = 2;个.较大的值表示已超过时间的错误.在我的带有const int total_iterations = 100;的计算机上运行它时,我观察到一个一致的模式,即Boost方法无法匹配malloc的C方法或std::vector<std::vector<double>>的C++方法.在后两者之间,大多数情况下,C方法优于C++方法,但也有一些相反的实例.所有这些都是在使用默认设置的发布模式下在Visual Studio中编译和运行的.

相对于指针或std::vector<std::vector<double>>的原始C指针,我看不到boost::multi_array的值.有没有方法可以更快地制造boost::multi_array


102:根据 comments 、对数组元素的顺序访问以及在Godbolt上的发布模式设置,boost::multi_array在大多数情况下获胜.看10次中的here次9次.

由于对元素的非连续、随机访问,以及在Godbolt上的发布模式设置,它很接近,C风格略好于boost::multi_array.见here

多亏了tstanisl的 comments ,对于顺序访问,C风格似乎要快10倍.他的链接可访问here

用户n-m-can-be-an-ai指出了一个总体警告,即此剖析可能正在剖析随机数生成器.控制这一点似乎超出了这个问题的范围.然而,似乎无论如何,由于为每种情况生成相同数量的RNG,并且迭代次数也不是1或2,而是更大,这可能是一次洗牌.我可能错了.


101(2):根据chqrlie提供的答案,我修改了可用的代码here.我已经对它进行了充分的 comments ,希望能看到正在发生的事情.我仍然不完全清楚哪种方法更快,但也许其他人可以使用这段代码作为起点,更好地对这些不同的数据 struct 进行基准测试.

推荐答案

恐怕您的基准测试存在严重缺陷,使结果几乎没有意义:

  • 在没有进行优化的情况下编译C++代码.打开后,在编译窗口的命令选项字段中添加-O2-O3.
  • 您使用Godbolt的基础设施来运行基准测试:云中的CPU严重超载,这可能解释了运行之间甚至从一种方法到另一种方法结果不一致的原因.
  • 目前还不清楚随机数生成器与矩阵访问时间相比的效率:您应该使用单独的数组来预计算这些值,或者至少在没有数组访问的情况下测量时间,将所有此类计算相加以避免优化副作用.

以下是使用C99 VLA的附加矩阵实现的修改版本,GCC:https://godbolt.org/z/v5o8P5M6d支持C99 VLA

在一台独立的空闲计算机上try 它,以获得有意义的结果.

C++相关问答推荐

如何将一个integer与一个数组进行比较?

rSP堆栈指针在返回函数调用的值时有任何用途吗?

C语言中字符数组声明中的标准

ESP32在vTaskDelay上崩溃

如何在c++中包装返回空*的函数

每个 struct 变量在C中都有自己的命名空间吗?

用gcc-msse 2编译的C程序包含AVX 1指令

为什么指针运算会产生错误的结果?

在vfork()之后,链接器如何在不 destruct 父内存的情况下解析execve()?

不同原型的危险C函数是可能的

搜索使用int代替time_t的用法

我在C程序的Flex/Bison中遇到语法错误

正在try 理解C++中的`正在释放的指针未被分配‘错误

当我在34mb的.mp4文件中使用FREAD时,我得到了一个分段错误,我如何解决它?

C中的数组下标和指针算法给出了不同的结果

为什么GCC不能在 struct 初始值设定项中以sizeof作为条件的三进制中处理复合文字的编译时求值?

即使客户端不发送数据,也会发生UNIX套接字读取

C 语言中 CORDIC 对数的问题

C 中类型说明符的顺序重要吗?

我们可以在不违反标准的情况下向标准函数声明添加属性吗?