代码之家  ›  专栏  ›  技术社区  ›  Tryer

数据对齐以实现矢量化/高效缓存访问

  •  0
  • Tryer  · 技术社区  · 6 年前

    This 书上说:

    对于骑士登陆,当数据开始时记忆移动是最佳的 地址位于64字节边界上。

    Q1。是否有一种方法可以动态地查询C++代码中的处理器以知道这是什么 n -字节边界将用于当前运行应用程序的处理器?这样,代码将是可移植的。

    这本书进一步指出:

    作为程序员,我们最终有两个工作:(1)调整数据,(2)制作 当然,编译器知道它是对齐的。

    (假设对于下面的问题,我们知道对于我们的处理器来说,数据从64字节边界开始是最佳的。)

    不过,这究竟是什么“数据”?

    假设我有这样一个班:

    class Class1_{
        private: 
        int a;//4 bytes
        double b;//8 bytes
        std::vector<int> potentially_longish_vector_int;
        std::vector<double> potentially_longish_vector_double;
        double * potentially_longish_heap_array_double;
        public:
        //--stuff---//
        double * return_heap_array_address() {return potentially_longish_heap_array_double;}
    }
    

    假设我也有这样原型化的函数:

    void func1(Class1_& obj_class1);
    
    void func2(double* array);
    

    也就是说, func1 接受的对象 Class1_ 通过引用,以及 func2 称为 func2(obj_class1.return_heap_array_address());

    为了与建议一致,数据应适当地边界对齐,应 obj_class1 它本身是64字节边界对齐的,以便 func1() ?应该 potentially_longish_heap_array_double 64字节边界对齐,以便 func2() ?

    对于作为STL容器的类的其他数据成员的对齐,线程 here 建议如何完成所需的对齐。

    问题2。那么,对象本身是否需要适当地对齐,以及其中的所有数据成员呢?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Maxim Egorushkin    6 年前

    一般来说,当您在缓存线边界上对齐阵列时,可以最大限度地提高缓存利用率,同时使阵列适合于任何SIMD指令。这是因为RAM和CPU缓存之间的传输单元是一条缓存线,在现代Intel CPU上是64字节。

    但是,增加的对齐也可能浪费内存并降低缓存利用率。通常,只有应用程序关键快速路径上的数据结构可能需要指定更大的对齐方式。

    按热度、大小顺序排列类成员是有意义的,这样,最经常访问的成员或一起访问的成员就位于同一缓存线上。

    这里的优化目标是减少缓存和TLB未命中(或者,减少每个指令的周期/增加每个周期的指令)。使用大页面可以减少TLB遗漏。