2011-08-03 50 views
-1

有没有办法在使用单例对象时防止缓存未命中?这是我目前单身的实现:用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; 
} 

有没有更好的方式来做到这一点,以防止高速缓存未命中?这是不使用单身人士的另一个原因吗?


更新:原来这真的是无关的缓存为堆栈展开,并在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; 
} 
+3

你在哪里看到缓存未命中? –

+0

@Alenxandre C.你不在'GetSingleton()'方法中看到那个注释吗? – Tom

+0

@Tom:* cache miss *具有与问题无关的常见含义。这里的问题是这个问题不清楚,他想避免什么?在第一次调用时指针为空?它在被销毁之后为空?混合条款作为缓存未命中没有帮助。 –

回答

1

这是人到达后话了性能优化路一个非常具体的问题。你确定你一直在那里?我问的原因是,如果你足够频繁地访问你的Singleton,那么指向这个对象的指针将停留在缓存中。如果它不在缓存中,那么你没有足够频繁地访问这个对象,这意味着你并不需要它,所以预取缓存的指针(或对象)只会从你所拥有的东西中窃取宝贵的缓存空间在现实中更频繁地使用 - 这可能甚至会长期影响性能。 在我的理解到达你在目前这个问题你必须要经过以下步骤:

  1. 配置您的应用程序,找出static SingletonObject* SingletonObject();功能确实是一个热点(>整体的10%时间是花在执行这一功能上)
  2. 使用基于事件的采样采集器(如英特尔VTune)来分析您的应用程序,以发现缓存未命中对此函数的执行时间负责。它不一定是。它可能只是您对该功能进行的呼叫次数(进行呼叫计数)。
  3. 在确定指针不在高速缓存中后(L1或L2或LLC的哪个高速缓存?L1和L2非常小,并且访问L2的等待时间是〜10个周期,因此L1 miss不是一个巨大的问题)你会通过你的代码来弄清楚为什么它不是。这意味着您可以查看在static SingletonObject* SingletonObject();调用之间访问的数据量,并检查是否有必要访问所有这些访问。如果他们是,那么这是一个合理的缓存未命中,你不能做任何事情。如果不是,则尽可能减少工作集并重新运行探查器(步骤2)。
  4. 只有当您完成1-3并且您仍然在访问Singleton对象时看到缓存未命中,并且您看到这会损害性能,那么只有在访问Singleton对象之前将_mm_prefetch()调用放入代码中。
  5. 然后再次通过1-3(至少步骤1),以确保第4步改善了性能而不是伤害它,这可能会污染您选择的缓存级别。
1

不,不是没有,有一个即将到来的参考单的指针,它可能然后使用黄金在整个程序中的更多知识L1/L2与指针以及它将要引用的对象一起缓存。

这种技术被称为预取。


CF:http://portal.acm.org/citation.cfm?id=279529