我正在構建一個使用SSE內在函數的類層次結構,因此該類的某些成員需要16字節對齊。對於棧實例,我可以使用__declspec(align(#))
,像這樣:防止在堆上未對齊的數據
typedef __declspec(align(16)) float Vector[4];
class MyClass{
...
private:
Vector v;
};
現在,由於__declspec(align(#))
是一個編譯指令,下面的代碼可能會導致矢量堆上未對齊的實例:
MyClass *myclass = new MyClass;
這我知道我可以很容易地通過超載新和刪除運營商相應地使用_aligned_malloc
和_aligned_free
。像這樣:
//inside MyClass:
public:
void* operator new (size_t size) throw (std::bad_alloc){
void * p = _aligned_malloc(size, 16);
if (p == 0) throw std::bad_alloc()
return p;
}
void operator delete (void *p){
MyClass* pc = static_cast<MyClass*>(p);
_aligned_free(p);
}
...
到目前爲止好..但這裏是我的問題。請看下面的代碼:
class NotMyClass{ //Not my code, which I have little or no influence over
...
MyClass myclass;
...
};
int main(){
...
NotMyClass *nmc = new NotMyClass;
...
}
由於MyClass
的MyClass的實例靜態創建於NotMyClass的動態實例,MyClass的會比較一致,因爲Vector的__declspec(align(16))
指令NMC的開始16字節。但是這是毫無價值的,因爲nmc是通過NotMyClass的新運算符在堆上動態分配的,這不會確保(肯定可能不是)16字節對齊。
到目前爲止,我只能想到2點的方法對如何處理這個問題:
防止MyClass的用戶能夠編譯下面的代碼:
MyClass myclass;
意義, MyClass的實例只能使用new運算符動態創建,從而確保MyClass的所有實例都是使用MyClass的重載新實例動態分配的。我諮詢關於如何做到這一點的另一個線程,並得到了一些偉大的答案:不必在我的課矢量成員 C++, preventing class instance from being created on the stack (during compiltaion)
還原並只有指針向量作爲成員,我會分配和使用
_aligned_malloc
解除分配並分別在ctor和dtor中輸入_aligned_free
。這種方法看起來很粗糙,容易出錯,因爲我不是編寫這些類的唯一程序員(MyClass派生自基類,許多這些類使用SSE)。
但是,既然這兩個解決方案都在我的團隊中被淹沒了,我會向您尋求不同解決方案的建議。
使用未對齊的SSE加載/存儲說明不是一個選項? (如果計算不加載/存儲性能的影響占主導地位應該是微乎其微。) – 2010-06-22 18:16:26
如果您的團隊使用調試版本,你可以嘗試添加斷言強制理智^ Walignment。 – ninjalj 2010-06-22 18:30:56
@ inflagranti:不是。首先,在一些(很少見的情況下)加載/存儲操作是我們最關心的問題。但是這些通常在具有大數據尺度的動態分配向量上執行。這些成員通常是傳遞給該類的單個參數。考慮到程序員必須在一個128字節的向量上執行一個簡單的設置函數。 SSE設置功能僅適用於對齊的數據。不,我們不能使用這些向量作爲靜態成員 – eladidan 2010-06-22 18:31:35