修改指针中的值非常慢?

时间:2017-03-28 16:06:57

标签: c++ arrays pointers optimization

我正在处理存储在数组中的大量数据,并且正在尝试优化访问和修改它所花费的时间。我使用的是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 ++很新,所以任何帮助都会受到赞赏!

2 个答案:

答案 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}})

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