防止c++中的单例缓存丢失
Preventing Singleton Cache Miss in C++
是否有办法防止使用单例对象时缓存丢失?下面是我当前的单例实现:
SingletonObject.h
#pragma once
class SingletonObject
{
public:
static SingletonObject* SingletonObject();
static void SingletonObject();
private:
static SingletonObject* sSingletonObject;
SingletonObject();
~SingletonObject();
};
SingletonObject.cpp
#include "SingletonObject.h"
SingletonObject* SingletonObject::sSingletonObject = NULL;
SingletonObject:: SingletonObject()
{
}
SingletonObject::~ SingletonObject()
{
}
SingletonObject* SingletonObject::GetSingleton()
{
if (sSingletonObject == NULL) // cache miss
{
sSingletonObject = new SingletonObject();
}
return sSingletonObject;
}
void SingletonObject::DestroySingleton()
{
delete sSingletonObject;
sSingletonObject = NULL;
}
是否有更好的方法来防止缓存丢失?这是不使用单例模式的另一个原因吗?
Update:事实证明,它实际上与缓存无关,而是为堆栈展开和GetSingleton()调用中的条件检查生成的代码。通过显式地创建和销毁单例(而不是按需创建),并为静态实例创建一个访问器,我能够避免大量的开销,并注意到分析中的显著加速。
SingletonObject.h
#pragma once
class SingletonObject {
public:
static void CreateSingleton();
static void DestroySingleton();
static inline SingletonObject* GetSingleton() { return sInstance; }
private:
static SingletonObject* sInstance;
SingletonObject();
}
SingletonObject.cpp
#include "SingletonObject.h"
void SingletonObject::CreateSingleton() {
if (sInstance == NULL)
sInstance = new SingletonObject();`
}
void SingletonObject::DestroySingleton() {
delete(sInstance);
sInstance = NULL;
}
这是人们在性能优化道路上遇到的一个非常具体的问题。你确定一路都到了吗?我问的原因是,如果你访问你的单例足够频繁,对象的指针将留在缓存中。如果它不在缓存中,那么您访问对象的频率就不够高,这意味着您并不真正需要它,因此,将指针(或对象)预取到缓存中只会从您在现实中更经常使用的对象中窃取宝贵的缓存空间——从长远来看,这甚至可能会损害性能。根据我的理解,要解决您目前遇到的问题,您必须经过以下步骤:
- 配置你的应用程序,找出
static SingletonObject* SingletonObject();
函数真的是一个热点(>10%的总时间花在执行这个函数上) - 使用基于事件的采样收集器(如Intel VTune)对应用程序进行配置,以找出缓存丢失对该函数的执行时间负责。这是可以避免的。它可能只是你对函数的调用次数(做一个调用计数)。
- 并指出,指针不在缓存(哪缓存的方式?L1, L2还是LLC?L1和L2非常小,访问L2的延迟约为10个周期,因此L1丢失不是一个大问题),您需要检查代码以找出原因。这意味着您将查看在调用
static SingletonObject* SingletonObject();
之间访问的数据量,并检查是否所有这些访问都是必要的。如果是,那么这就是合理的缓存丢失,您对此无能为力。如果不是,那么尽可能减少你的工作集,然后重新运行分析器(步骤2)。 - 只有当你完成了1-3,你仍然看到访问Singleton对象的缓存丢失,你看到这会损害性能,只有那时你把
_mm_prefetch()
调用在你的代码之前访问Singleton对象。 然后再次执行1-3(至少是第1步),以确保第4步提高了性能,而不是损害它,这可能会污染您选择的缓存级别。
不,在你的整个程序中,如果没有更多的知识,就不会有一个对单例指针的引用,然后它可以使用该指针和它将要引用的对象来启动L1/L2缓存。
这种技术叫做预取。
cf: http://portal.acm.org/citation.cfm?id=279529
相关文章:
- 为什么在单例中,检查类==空?
- C++ 实现模板单例类时出现链接错误
- 在类中存储单例的指针
- C++中的单例实现在调用 getInstance 函数时不会产生相同的类实例
- 具有非默认构造函数的单例类
- 使用 std::call_once 实现类似单例的功能
- 为什么单例使用指针而不是引用?
- 提升单例池release_memory vs purge_memory
- 具有 QObject 继承的单例 - Qt
- 单例类析构函数无法清理 (SDL_Quit) MinGW
- C++单例,不会为此文档加载任何符号
- 使用 CRTP 实现单例
- C++单例模板类使我的程序崩溃
- 初学者C++线程安全单例设计
- 派生类是单例是否是一种好的做法
- _CrtIsValidHeapPointer(块)错误在应用单例-帕特恩后退出主窗口时引发
- 在这种单例实施中,是否可以对两个商店重新排序?
- 这是MSVC 2013中具有共享PTR的单例的正确实现吗?
- C++ 单例实现 迈耶与call_once
- 防止c++中的单例缓存丢失