【发布时间】:2015-10-03 19:32:05
【问题描述】:
背景/示例:
我目前有一个类似以下的课程:
class Element {
Large l1;
OtherLarge l2;
Small s1;
VerySmall s2;
};
其中Large 和OtherLarge 相对较大(约80 字节),而Small 和VerySmall 相对较小(约4 到16 字节)。
在这些元素上,我有两种操作方式:
- 以各种方式对它们进行排序。在此期间,只有成员
s1和s2可以访问/需要。 - 以各种方式组合大成员(例如矩阵-矩阵乘法)。
第二类操作已经相当快并且可以很容易地并行化,因此我想进一步加快第一类操作。与另一个类 Element2 相比,我用 8 字节整数替换了两个大数据成员,什么都不做告诉我,如果我能以某种方式将直接数据成员 l1 和 l2 替换为一种或另一种动态的指针- 在别处分配元素,我已经大获全胜了。
作为参考,所有成员类型都有复制和移动构造函数,并且可以复制和移动,但移动它们要便宜得多。 Large 和 OtherLarge 也会自己分配大量内存,所以分配多一点并不一定很糟糕。
具体问题
是否可以,如果可以,最好的方法是用指向其他地方动态分配对象的指针替换类的直接成员对象;尽可能地保留直接成员的行为 w.r.t 构造、销毁、成员变量访问等?如果我天真地使用std::unique_ptr<Large>,我想我将不得不取消对它的一半时间/特别注意复制?理想情况下,我希望新成员对象的行为就像旧的大成员对象仍然存在一样。
【问题讨论】:
-
所以基本上,你想减小
Element的大小? -
如果我是你,我会测试一下。您可能会对结果感到惊讶。缓存局部性会对性能造成巨大影响,160 字节并不是很大。如果元素数量不是很大,您可以使用不同的排序算法来减少元素移动而不是比较。
-
您是否考虑过使用 shared_ptr 代替?
-
是的,没错,我想减小元素本身的大小。 @CemKalyoncu 不幸的是,它确实有很大的效果,如果我用整数替换大元素(并且仍然不使用它们),事情会变得更快,因为我最多可以将 4 个
Elements 放入单个缓存行(而不是每个元素使用两个)。我不太确定为什么 shared_ptr 会有所帮助,据我所知,不需要引用计数。 -
关于算法的不同选择:每个单独的排序调用仅适用于 20 到 50 个元素,但这必须在代码的串行区域中经常发生。小尺寸意味着某种设置首先工作(我遍历元素并挑选所需的数据成员)或更智能的算法使用 O(log(n)n) 而不是当前的 O(n²)没有多大帮助。显然我想避免重做所有事情,因此是影响最小的问题。