gpt4 book ai didi

C++ 性能 std::array 与 std::vector

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:06:29 40 4
gpt4 key购买 nike

晚上好。

我知道 C 风格数组或 std::array 并不比 vector 快。我一直使用 vector (而且我用得很好)。但是,在某些情况下,使用 std::array 比使用 std::vector 性能更好,我不知道为什么(使用 clang 7.0 和 gcc 8.2 测试)。

让我分享一个简单的代码:

#include <vector>
#include <array>

// some size constant
const size_t N = 100;

// some vectors and arrays
using vec = std::vector<double>;
using arr = std::array<double,3>;
// arrays are constructed faster here due to known size, but it is irrelevant
const vec v1 {1.0,-1.0,1.0};
const vec v2 {1.0,2.0,1.0};
const arr a1 {1.0,-1.0,1.0};
const arr a2 {1.0,2.0,1.0};

// vector to store combinations of vectors or arrays
std::vector<double> glob(N,0.0);

到目前为止,还不错。上面初始化变量的代码不包含在基准测试中。现在,让我们编写一个函数来组合 double 的元素 ( v1 )和 v2 , 或 a1a2 :

// some combination
auto comb(const double m, const double f)
{
return m + f;
}

基准函数:

void assemble_vec()
{
for (size_t i=0; i<N-2; ++i)
{
glob[i] += comb(v1[0],v2[0]);
glob[i+1] += comb(v1[1],v2[1]);
glob[i+2] += comb(v1[2],v2[2]);
}
}

void assemble_arr()
{
for (size_t i=0; i<N-2; ++i)
{
glob[i] += comb(a1[0],a2[0]);
glob[i+1] += comb(a1[1],a2[1]);
glob[i+2] += comb(a1[2],a2[2]);
}
}

我已经用 clang 7.0 和 gcc 8.2 试过了。在这两种情况下,阵列版本的运行速度几乎是 vector 版本的两倍。

有人知道为什么吗?谢谢!

最佳答案

GCC(可能还有 Clang)正在优化数组,而不是 vector

您关于数组必然比 vector 慢的基本假设是不正确的。因为 vector 需要将它们的数据存储在分配的内存中(默认分配器使用动态内存),所以需要使用的值必须存储在堆内存中,并在该程序的执行期间重复访问。相反,数组使用的值可以完全优化掉,并在程序的汇编中直接引用。

下面是打开优化后 GCC 为 assemble_vecassemble_arr 函数吐出的汇编:

[-snip-]
//==============
//Vector Version
//==============
assemble_vec():
mov rax, QWORD PTR glob[rip]
mov rcx, QWORD PTR v2[rip]
mov rdx, QWORD PTR v1[rip]
movsd xmm1, QWORD PTR [rax+8]
movsd xmm0, QWORD PTR [rax]
lea rsi, [rax+784]
.L23:
movsd xmm2, QWORD PTR [rcx]
addsd xmm2, QWORD PTR [rdx]
add rax, 8
addsd xmm0, xmm2
movsd QWORD PTR [rax-8], xmm0
movsd xmm0, QWORD PTR [rcx+8]
addsd xmm0, QWORD PTR [rdx+8]
addsd xmm0, xmm1
movsd QWORD PTR [rax], xmm0
movsd xmm1, QWORD PTR [rcx+16]
addsd xmm1, QWORD PTR [rdx+16]
addsd xmm1, QWORD PTR [rax+8]
movsd QWORD PTR [rax+8], xmm1
cmp rax, rsi
jne .L23
ret

//=============
//Array Version
//=============
assemble_arr():
mov rax, QWORD PTR glob[rip]
movsd xmm2, QWORD PTR .LC1[rip]
movsd xmm3, QWORD PTR .LC2[rip]
movsd xmm1, QWORD PTR [rax+8]
movsd xmm0, QWORD PTR [rax]
lea rdx, [rax+784]
.L26:
addsd xmm1, xmm3
addsd xmm0, xmm2
add rax, 8
movsd QWORD PTR [rax-8], xmm0
movapd xmm0, xmm1
movsd QWORD PTR [rax], xmm1
movsd xmm1, QWORD PTR [rax+8]
addsd xmm1, xmm2
movsd QWORD PTR [rax+8], xmm1
cmp rax, rdx
jne .L26
ret
[-snip-]

这几段代码之间有几处不同,但关键的区别分别在.L23.L26标签之后,对于 vector 版本,数字与使用(更多)SSE 指令的数组版本相比,它们通过效率较低的操作码加在一起。与数组版本相比, vector 版本还涉及更多的内存查找。这些因素相互结合将导致 std::array 版本的代码比 std::vector 版本的代码执行得更快.

关于C++ 性能 std::array 与 std::vector,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54542867/

40 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com