前几天我偶然看到这个非常有趣的演示 http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/STL11-Magic-Secrets作者:Stephan T. Lavavej,其中提到“我们知道你住哪里“优化(很抱歉在问题标题中使用了缩写词,所以警告我,否则问题可能已被关闭),并且作者:赫伯·萨特(Herb Sutter)关于机器架构的文章。
简而言之,“我们知道你住哪里“优化在于将引用计数器放置在与对象相同的内存块上make_shared
正在创建,从而导致一个内存分配而不是两个并且使得shared_ptr
更紧凑。
然而,在总结了我从上面两个演示中学到的知识后,我开始怀疑 WKWYL 优化是否不能降低性能以防万一shared_ptr
被多个线程访问运行在不同的核心上.
如果参考计数器是close到内存中的实际对象,事实上,它们应该更有可能被提取到相同的缓存行作为对象本身。反过来,如果我正确地吸取了教训,那么线程在竞争同一缓存行时更有可能减慢速度,即使它们不需要这样做。
Suppose one线程数需要更新参考计数器多次(例如,复制时shared_ptr
周围),同时其他的只需要访问指向的对象: 这不会减慢执行速度吗all线程通过让它们竞争相同的缓存线?
如果引用计数位于内存中的其他位置,我会说争用不太可能出现.
这是否是反对使用的一个很好的论据make_shared()
在类似的情况下(当然,只要它实现了 WKWYL 优化)?还是我的推理有错误?
If这就是你的使用模式,那么当然,make_shared
将导致“错误共享”,这是我所知道的使用相同缓存行的不同线程的名称,即使它们没有访问相同的字节。
对于其附近部分被不同线程(其中之一正在写入)使用的任何对象来说也是如此。在这种情况下,“对象”是由以下命令创建的组合块make_shared
。你也可以问是否any如果不同线程或多或少同时使用邻近数据,则尝试从数据局部性中受益可能会适得其反。是的,它可以。
可以得出结论,如果每个对象的每个可写部分都分配在较远的位置,则不太可能出现争用。因此,通常修复错误共享的方法是将内容分散开(在这种情况下,您可以停止使用make_shared
或者您可以将填充放入对象中,以将其各部分分隔到不同的缓存行中)。
与此相反,当不同的部件用于same线程,如果您将它们分散到内存中,那么就会产生成本,因为有更多内容需要提取到缓存中。由于分散事物有其自身的成本,因此这实际上可能不会像您首先想到的那样对很多应用程序有帮助。但毫无疑问,编写有帮助的代码是可能的。
有时的好处是make_shared
与缓存行和局部性无关,只是它进行了一次动态分配而不是两次。它的值取决于您分配和释放的对象数量:它可能可以忽略不计;这可能是你的应用程序适合 RAM 与疯狂交换之间的区别;在某些情况下,您的应用程序可能需要进行所需的所有分配。
仅供参考,还有另一种情况可能不使用make_shared
,那就是当对象不小并且弱指针的寿命明显超过shared_ptr
。原因是控制块在弱指针消失之前不会被释放,因此如果您使用make_shared
那么直到弱指针消失后,对象占用的全部内存才会被释放。当然,一旦共享指针被破坏,对象就会被破坏,所以重要的只是类的大小,而不是关联的资源。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)