修改指针中的值非常慢?

modifying values in pointers is very slow?

本文关键字:非常 指针 修改      更新时间:2023-10-16

我正在处理存储在数组中的大量数据,并试图优化访问和修改它所需的时间。我正在使用Window,c ++和VS2015(发布模式)。

我运行了一些测试,但并不真正了解我得到的结果,所以我希望得到一些帮助来优化我的代码。

首先,假设我有以下类:

class foo
{
public:
int x;
foo() 
{
x = 0;
}
void inc()
{
x++;
}
int X()
{
return x;
}
void addX(int &_x)
{
_x++;
}
};

我首先将指向该类实例的 1000 万个指针初始化为相同大小的 std::vector。

#include <vector>
int count = 10000000;
std::vector<foo*> fooArr;
fooArr.resize(count);
for (int i = 0; i < count; i++)
{
fooArr[i] = new foo();
}

当我运行以下代码并分析完成所需的时间时,大约需要 350 毫秒(就我而言,这太慢了):

for (int i = 0; i < count; i++)
{
fooArr[i]->inc(); //increment all elements
}

为了测试多次增加整数需要多长时间,我尝试了:

int x = 0;
for (int i = 0; i < count; i++)
{
x++;
}

在 <1 毫秒内返回。

我想也许是要更改的整数数量是问题所在,但是以下代码仍然需要250ms,所以我认为不是这样:

for (int i = 0; i < count; i++)
{
fooArr[0]->inc(); //only increment first element
}

我想也许数组索引访问本身就是瓶颈,但以下代码需要 <1 毫秒才能完成:

int x;
for (int i = 0; i < count; i++)
{
x = fooArr[i]->X(); //set x
}

我想也许编译器正在对最后一个示例的循环本身进行一些隐藏的优化(因为 x 的值在循环的每次迭代中都是相同的,所以编译器可能会跳过不必要的迭代?所以我尝试了以下内容,需要 350 毫秒才能完成:

int x;
for (int i = 0; i < count; i++)
{
fooArr[i]->addX(x); //increment x inside foo function
}

所以那个又慢了,但也许只是因为我再次用指针递增整数。

我也尝试了以下内容,它也在 350 毫秒内返回:

for (int i = 0; i < count; i++)
{
fooArr[i]->x++;
}

所以我被困在这里了吗?~350ms 是我可以在向量中的 1000 万个指针内递增整数的绝对最快吗?还是我错过了一些明显的东西?我尝试了多线程(给每个线程一个不同的数组块来递增),一旦我开始使用足够的线程,这实际上需要更长的时间。也许这是由于我缺少其他一些明显的东西,所以现在我想远离多线程以保持简单。

我也愿意尝试矢量以外的容器,如果它加快速度,但无论我最终使用什么容器,我都需要能够轻松调整它的大小、删除元素等。

我对 c++ 相当陌生,所以任何帮助将不胜感激!

让我们从CPU的角度来看。

递增一个整数意味着我把它放在 CPU 寄存器中,并且只是递增它。这是最快的选择。

我得到一个地址(vector->member),我必须将其复制到寄存器,递增,然后将结果复制回地址。最差:我的 CPU 缓存充满了矢量指针,而不是矢量成员指针。命中太少,缓存"加油"太多。

如果我能设法将所有这些成员都放在一个向量中,CPU 缓存命中会更加频繁。

尝试以下操作:

int count = 10000000;
std::vector<foo> fooArr;
fooArr.resize(count, foo());
for (auto it= fooArr.begin(); it != fooArr.end(); ++it) {
it->inc();
} 

new正在杀死你,实际上你不需要它,因为如果大小更大,resize最后插入元素(检查文档:std::vector::resize)

另一件事是关于使用指针,恕我直言,直到最后一刻都应该避免,在这种情况下这是不明智的。在这种情况下,性能应该快一点,因为您可以获得更好的引用局部性(请参阅缓存局部性)。如果它们是多态的或更复杂的东西,它可能会有所不同。