使用placement new可以更快地运行代码

时间:2012-07-24 18:19:46

标签: c++ performance gcc compiler-optimization

我上了这堂课,

方法1:

typedef float v4sf __attribute__ (vector_size(16))

class Unit
{
    public:
    Unit(int num)
    {
        u = new float[num];
        v = new float[num];
    }
    void update()
    {
        for(int i =0 ; i < num; i+=4)
        {
            *(v4sf*)&u[i] = *(v4sf*)&v[i] + *(v4sf*)&t[i];
            //many other equations
        }
    }
    float*u,*v,*t; //and many other variables
}

方法2:

与方法1相同。除了在方法2中,vu和所有其他变量都使用展示位置new分配在堆上预先分配的大块上。

typedef float v4sf __attribute__ (vector_size(16))

class Unit
{
    public:
    Unit(int num)
    {
        buffer = new char[num*sizeof(*u) + sizeof(*v)  /*..and so on for other variables..*/]
        u = new(buffer) float[num];
        v = new(buffer+sizeof(float)*num) float[num];
        //And so on for other variables
    }
    void update()
    {
        for(int i =0 ; i < num; i+=4)
        {
            *(v4sf*)&u[i] = *(v4sf*)&v[i] + *(v4sf*)&t[i];
            //many other equations
        }
    }
    char* buffer;
    float*u,*v,*t; //and many other variables
}

然而,方法2快2倍。那是为什么?

大约有12个浮点变量,num是500K。 update()被称为1k次。速度不会影响内存分配。我像这样测量速度:

double start = getTime();
for( int i = 0; i < 1000; i++)
{
   unit->update();
}
double end = getTime();
cout<<end - start;

这在方法2中快了约2倍。

编译器选项:gcc -msse4 -o3 -ftree-vectorize.

L1缓存为256K,Ram为8GB,页面大小为4K。

编辑:更正了在方法2中分配变量时的错误。所有变量都在不同的部分中正确分配。 处理器是Intel(R)Core(TM)i7-2600 CPU @ 3.40GHz

修改:在此处添加了来源 - Source。方法1)给出69.58s,方法2)给出46.74s。虽然速度不快2倍,但仍然很快。

4 个答案:

答案 0 :(得分:4)

可能是因为“方法2”存在错误 - 所有变量uvt都位于内存中完全相同的位置(您将相同的地址传递给展示位置)新)。

修改:现在你没有......;)

如果没有分析,很难猜测,但它可能与默认分配器有关。如果在第一种方法中,您为每个变量单独调用new,则无法保证将为这些变量分配彼此接近的地址。另一方面,在第二种方法中,您确保它们彼此尽可能接近。这将最大化缓存利用率并限制缓存未命中。

答案 1 :(得分:1)

分解时间并查看构造函数中的哪个部分与update中的哪个部分有用将是有用的。

由于update没有改变,唯一会影响其时间的是缓存对数据的影响。这超过了2倍的差异。

答案 2 :(得分:0)

普通新实际上是分配+建设,而新安置只是建设 因此,分配+2构造自然比分配+构造+分配+构造更快 而且,整数类型的构造是nop,所以在你的情况下它是2个分配对1个分配。

答案 3 :(得分:0)

我假设在方法2中,编译器能够识别出u和v的地址在调用之间不会改变,因此将for循环中的一些指针用于寄存器中的for循环。