2011-08-03 23 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:*キャッシュミス*には、質問とは無関係の共通の意味があります。ここでの問題は、質問が不明であることです。彼は避けたいのは何ですか?ポインタを最初の呼び出しでnullにする?それは破壊された後、それはヌルですか?そして、キャッシュミスとしての用語の混在は助けになりません。 –

答えて

1

これは、人々は、パフォーマンス最適化の道道に到着した非常に具体的な質問です。あなたはそこにいると確信していますか?あなたがシングルトンに頻繁にアクセスすれば、オブジェクトへのポインタはキャッシュに残ります。キャッシュにない場合は、頻繁にオブジェクトにアクセスしていないため、実際には必要ないので、ポインタ(またはオブジェクト)をキャッシュに先読みするだけで、貴重なキャッシュ領域を盗むことになります実際にはより頻繁に使用しています - これは長期的に性能を損なうかもしれません。私の理解で 次の手順を実行する必要があると思いますが、現在でいる質問到着:static SingletonObject* SingletonObject();機能は本当に全体的のホットスポット(> 10%であることを見つけるためにあなたのアプリケーションのプロファイリング

  1. を時間はこの1つの関数を実行するのに費やされます)。
  2. イベント・ベースのサンプリング・コレクター(インテルVTuneなど)を使用してアプリケーションをプロファイリングすると、キャッシュ・ミスがこの関数の実行時間の原因です。それは必ずしもそうである必要はありません。それはあなたが関数に行う呼び出しの数(呼び出し回数を行う)にすぎません。
  3. そして、ポインタがキャッシュにないことを知った後(L1 L1またはL2またはLLC?L1とL2はかなり小さく、L2にアクセスするまでの待ち時間は〜10サイクルなので、L1ミスは巨大ではありません)問題)、あなたはあなたのコードを調べて、それがなぜではないのかを理解するでしょう。つまり、static SingletonObject* SingletonObject();の呼び出しの間にアクセスされているデータの量を調べ、それらのアクセスがすべて必要であるかどうかを調べることを意味します。もしそうであれば、正当なキャッシュミスであり、あなたはそれについて何もできません。そうでない場合は、できるだけ作業セットを減らし、プロファイラを再実行してください(ステップ2)。
  4. シングルトンオブジェクトへのアクセス時に1-3の処理が完了してもキャッシュミスが発生し、パフォーマンスが低下することがわかった場合にのみ、_mm_prefetch()コールをシングルトンオブジェクトにアクセスする前にコードに挿入します。
  5. そして、ステップ1から3をもう一度行って、ステップ4がパフォーマンスを向上させることを確認してください。これは、選択したレベルのキャッシュを汚染する可能性があります。
1

いいえ、それはその後、首相に使用することができシングルトンのポインタへの今後の参照があることを、あなたのプログラム全体で大きな知識がなくてもL1/L2キャッシュは、ポインタとそれが参照しようとしているオブジェクトの両方をキャッシュします。

このテクニックはプリフェッチと呼ばれます。


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