2010-12-01 2 views
3

이 코드는 작동하지만 InterlockedIncrement 함수를 올바르게 사용 했습니까? m_count의 올바른 메모리 정렬이 가장 중요한 문제입니다. 우리가 x86-64 시스템에 있고 64 비트 응용 프로그램을 컴파일한다고 가정합니다 (중요한 경우). 그건 그렇고, 내 실제 목적을 위해 나는 m_count를 휘발성 long으로 선언 할 수 없으며, InterlockedIncrement (& m_count)를 사용한다. 그러나 힙의 데이터에 대한 포인터 여야합니다.InterlockedIncrement 함수에 대해 올바른 메모리 정렬로 힙에서 할당하는 방법은 무엇입니까?

#include <Windows.h> 
#include <malloc.h> 

class ThreadSafeCounter { 
public: 
    ThreadSafeCounter() 
    { 
     // Are those arguments for size and alignment correct? 
     void* placement = _aligned_malloc(sizeof(long), sizeof(long)); 
     m_count = new (placement) long(0); 
    } 
    ~ThreadSafeCounter() 
    { 
     _aligned_free(const_cast<long*>(m_count)); 
    } 

    void AddOne() 
    { 
     InterlockedIncrement(m_count); 
    } 

    long GetCount() 
    { 
     return *m_count; 
    } 

private: 
    volatile long* m_count; 
}; 
+2

왜 힙에 있어야합니까? _aligned_malloc을 사용하고 싶습니까? 어쨌든 _aligned_malloc은 컴파일러 확장입니다. 따라서 정렬 요구 사항을 충족 할 수있는 GCC 및 MSVC 컴파일러에서 사용할 수있는 #pragma pack 지시문을 사용할 수도 있습니다. 그리고 GCC와 MSVC의 기본 프라 그마 패킹은 인터 로킹 된 작업의 기본 정렬 요구 사항을 이미 충족시킵니다. 그래서 당신은 정말로이 문제에 대해 과도하게 생각한 것 같습니다. –

+0

이 ThreadSafeCounter 클래스는 간단한 예입니다. 내가 실제로하고있는 일은 std :: shared_ptr와 같은 것이지만, 몇 가지 추가 기능이 있습니다. 그리고 그 때문에 힙에 카운터가 있어야합니다. – zeroes00

+0

카운터가 힙에있을 수 있지만 그것을 수행하는 방법을 할당 할 필요가 없으며 std :: shared_ptr과 같은 클래스의 경우 클래스에서 인라인 될 수 있고 정렬로 장식 될 수 있으므로 _align_malloc이 수행됩니다) a) 성능을 떨어 뜨리고 b) 자물쇠가없는 환경에서 문제를 일으킬 수있는 자체 자물쇠 섹션에 붙이십시오. – Necrolis

답변

5

힙 할당자는 이미 반환 된 주소를 기본 플랫폼 단어 크기에 맞 춥니 다. x86의 경우 4 바이트, x64의 경우 8 바이트 길이가이고 MSVC의 경우 32 비트입니다. _aligned_malloc() 후프를 뛰어 넘을 필요가 없습니다.

3

플랫폼 아키텍처 세부 사항이지만 정렬보다는 원자 연산이 많다는 것을 명심해야합니다. 플랫폼 ABI는 일반적으로 기본적으로 원시 데이터 형식 정렬이 어떤 작업 (원자어 포함)도 작동 할 수 있도록합니다. malloc()은 비록 당신이 1 바이트를 요구하더라도 당신에게 잘못 정렬 된 포인터를 반환해서는 안된다.

http://en.wikipedia.org/wiki/False_sharing - 정렬 필요성 (일반적으로 sizeof(long))을 의미한다는 점을 제외하면 동일한 캐시 라인 내에서 원자 적으로 액세스되는 변수 하나만 호스트해야합니다.

이러한 카운터의 배열을 사용하거나 허용하려는 경우 특히 중요합니다.

Microsoft의 컴파일러는 특정 구조체 정렬을 보장하도록 컴파일러에 지시 할 때 __declspec(align(value))을 사용합니다. 다른 언급했듯이, 힙 할당을위한 데이터 구조/클래스에 대한 구체적인 필요성은없는 것 같지만, 당신이 뭔가 다른 것을 필요로하는지 알 수 없습니다.

1

유스 케이스에서 가장 쉬운 방법은 상속을 통한 간섭 적 참조 계산을 사용하여이 필요성을 제거하는 것입니다.

그러나 필사적 인 경우 MSVC의 shared_ptr 구현을 확인하십시오.

typename aligned_storage<sizeof(_Ty), 
     alignment_of<_Ty>::value>::type _Storage; 
    }; 
    _Ty *_Getptr() const { // get pointer 
     return ((_Ty *)&_Storage); 
    } 

그 C 캐스트는 상당히 심해요. 그러나 이것은이 개체가 유형 특성을 활용하여 올바른 정렬을 가장 확실하게 갖게된다는 것을 나에게 암시합니다.

관련 문제