Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 面向对象、面向数据、缓存污染和缓存可见性_Performance_Oop_Caching_Memory Efficient_Data Oriented Design - Fatal编程技术网

Performance 面向对象、面向数据、缓存污染和缓存可见性

Performance 面向对象、面向数据、缓存污染和缓存可见性,performance,oop,caching,memory-efficient,data-oriented-design,Performance,Oop,Caching,Memory Efficient,Data Oriented Design,在常规的面向对象实践中,很少有对象具有多个不相关的成员属性。当处理对象时,在不同的过程中进行处理并不罕见,这些过程针对对象属性的不同部分 在这方面,创建对象集合的典型方法似乎不是一种非常有效的方法。考虑到计算机访问内存的方式和缓存线的平均大小,很有可能缓存内存中充满了不需要的内容,而恰好是相邻的内容,因此它最终会浪费缓存的容量,并增加执行的暂停和延迟 更糟糕的是,在没有内存池和自定义分配器的情况下,使用多态性并动态分配对象。在这种情况下,不仅缓存被不需要的数据填满,而且由于动态内存分配使用的任意

在常规的面向对象实践中,很少有对象具有多个不相关的成员属性。当处理对象时,在不同的过程中进行处理并不罕见,这些过程针对对象属性的不同部分

在这方面,创建对象集合的典型方法似乎不是一种非常有效的方法。考虑到计算机访问内存的方式和缓存线的平均大小,很有可能缓存内存中充满了不需要的内容,而恰好是相邻的内容,因此它最终会浪费缓存的容量,并增加执行的暂停和延迟

更糟糕的是,在没有内存池和自定义分配器的情况下,使用多态性并动态分配对象。在这种情况下,不仅缓存被不需要的数据填满,而且由于动态内存分配使用的任意地址,预取器也无法正常工作

拯救之道是回到OOP之前的时代,选择面向数据,这似乎是开发性能关键型应用程序、操作系统等的首选。但为什么不使用两者的混合版本呢?某种面向数据的对象编程

在那漫长的序曲之后,让我们开始讨论手头的问题。我没有一个足够大的项目来测试这个概念的效率,所以社区的理论知识是非常受欢迎的

与其对象存储自己的数据成员,不如对象只存储对集合的引用,其中数据成员顺序存储在自己的容器中,成员方法从这些容器返回数据,通过这种方式,不需要的数据到达CPU的几率应该降低,并且在不久的“将来”需要的数据的几率应该增加。合乎逻辑的假设是,这种方法将提高预取器效率、缓存命中率和使用效率,还将减少自动和手动并行化所涉及的延迟

你觉得怎么样


后期编辑:如果我们考虑到结构和类填充,应用“数据定向模式”可能会更加有益,如果“模型”有
char
int
数据成员,在OOP方式下,它将被填充,这只会进一步污染缓存,但是面向数据的存储模式可以按顺序存储所有的
char
s和所有的
int
s,而不会浪费任何空间和缓存。

首先,很好的幻灯片演示。嗯,我可以理解,你的问题与演讲中的问题大不相同。变量随机存储在主内存中,甚至对象属性也是如此。如果您试图将内存分配给连续的数据结构,那么您的数据结构的大小将受到主内存中最大的“气泡”的限制,否则它将不会完全连续。也许你是这样想的:

class MyClass
{
public:
    MyClass()
    {
        m_dataMembers = new GenericObject[DATA_MEMBERS_AMOUNT];

        //initialize array values...
    }

    int getMyVar()
    {
        return (int)m_dataMembers[MY_VAR_INDEX];
    }

    //others functions...

private:
    GenericObject* m_dataMembers;
}
for each creatures in creature_types:
     creatures.do_something();

这样,您将遇到一些问题。首先,您需要一个通用对象类来存储任何类型的变量。然后需要知道每个变量在数据结构中的位置,然后需要知道数据结构中每个变量的类型,以便在getter中正确转换。他在演示文稿中实际做的是减少类大小,使用引用,使其更好地适合缓存页面,并减少在缓存中而不是在主存中的使用。我希望我没有误解您的意思。

我的看法是,如果您在非常精细的细粒度对象级别(如抽象的
IPixel
接口)使用多态性,那么对象级别的多态性本质上是昂贵的。在这种情况下,围绕IPixel依赖关系运行的视频处理软件从效率的角度来看是非常糟糕的,因为它没有可优化的喘息空间。除了每像素动态调度的成本之外,这里所需的虚拟指针可能比整个像素本身还要大,内存使用量增加一倍或三倍。此外,我们不能再以超出单个像素的方式使用像素表示,最可怕的是,图像中的相邻像素甚至可能无法在内存中连续表示

同时,
IImage
可以提供大量的优化空间,因为图像为像素的集合/容器建模,并且仍然具有很大的灵活性(例如:每个像素格式都有不同的具体图像表示)。现在,每个映像的动态调度是廉价的,而虚拟指针的大小对于整个映像来说可以忽略不计。我们还可以探索如何将像素表示为我们内心的内容,使我们能够一次高效地处理多个像素。因此,我将其视为一个类似于您的问题,即以适当的粗糙度设计对象,这通常意味着事物的集合,以减少所有开销和优化的障碍

与其让对象存储自己的数据成员,不如让对象 仅存储对集合的引用,其中包含其数据成员 按顺序存储在其自己的容器中,以及其成员 方法从这些容器返回数据,这样可以降低 不需要的数据在传输到CPU的过程中应该被减少和删除 在不久的“未来”中需要的数据的几率增加了

我喜欢这个想法,但是如果你对多态上下文做得太过分的话,你可以回到定制内存分配器和排序基指针的方向。我经常发现这种设计的用途是,在需要聚合单个元素以提高效率的情况下(一种情况是使用SoA表示的容器,另一种情况我将在下面介绍),提高使用单个元素的便利性

多态性病例不一定对b有多大益处
for each orc in orcs:
     orc.do_something();
for each human in humans:
     humans.do_something();
for each elf in elves:
     elves.do_something();
for each creatures in creature_types:
     creatures.do_something();