我正在处理存储在数组中的大量数据,并且正在尝试优化访问和修改它所花费的时间。我使用的是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++;
}
以&lt; 1ms。
返回我想也许改变整数的数量是问题,但是下面的代码仍然需要250毫秒,所以我不认为它是这样的:
for (int i = 0; i < count; i++)
{
fooArr[0]->inc(); //only increment first element
}
我认为数组索引访问本身可能是瓶颈,但以下代码需要<1ms才能完成:
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++;
}
所以我被困在这里? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~还是我错过了一些明显的事情?我尝试了多线程(给每个线程一个不同的数组块来增加),一旦我开始使用足够的线程,实际上需要更长的时间。也许这是由于我忽略了一些其他显而易见的事情,所以现在我想远离多线程来保持简单。
我也开放尝试除了矢量之外的容器,如果它加快了速度,但无论我最终使用什么容器,我都需要能够轻松调整它,删除元素等。
我对c ++很新,所以任何帮助都会受到赞赏!
答案 0 :(得分:1)
让我们从CPU的角度来看。
递增一个整数意味着我将它放在CPU寄存器中,然后递增它。这是最快的选择。
我给了一个地址(vector-&gt;成员),我必须将它复制到寄存器,递增,并将结果复制回地址。最糟糕的是:我的CPU缓存填充了向量指针,而不是向量成员指针。点击量太少,缓存太多,加油#34;
如果我能够将所有成员放在一个向量中,那么CPU缓存命中会更频繁。
答案 1 :(得分:0)
尝试以下方法:
int count = 10000000;
std::vector<foo> fooArr;
fooArr.resize(count, foo());
for (auto it= fooArr.begin(); it != fooArr.end(); ++it) {
it->inc();
}
new
正在杀死你,实际上你并不需要它,因为resize
如果大小更大,则会在末尾插入元素(查看文档:{{3}})
另一件事是关于使用指针恕我直言应该避免直到最后一刻,在这种情况下它是不必要的。在这种情况下,性能应该快一点,因为您获得了更好的引用局部性(请参阅缓存局部性)。如果它们是多态的或更复杂的东西,它可能会有所不同。