programing

메모리가 정렬되어 있는지 확인하는 방법

minecode 2022. 8. 11. 21:25
반응형

메모리가 정렬되어 있는지 확인하는 방법

SSE/SSE2 명령으로 코드를 최적화하는 것은 처음이며, 지금까지도 별로 진척되지 않았습니다.SSE에 최적화된 일반적인 함수는 다음과 같습니다.

void sse_func(const float* const ptr, int len){
    if( ptr is aligned )
    {
        for( ... ){
            // unroll loop by 4 or 2 elements
        }
        for( ....){
            // handle the rest
            // (non-optimized code)
        }
    } else {
        for( ....){
            // regular C code to handle non-aligned memory
        }
    }
}

다만, 메모리가 올바르게 동작하고 있는지 어떤지를 확인하는 방법.ptr바바바바바 16 바바바바바바바?이 함수에 전달된 모든 메모리가 정렬되는지 확인할 수 없기 때문에 비정렬 메모리의 일반 C 코드 경로를 포함해야 한다고 생각합니다.또한 이 기능을 사용하여 정렬되지 않은 메모리에서 SSE 레지스터로 데이터를 로드하는 것은 매우 느린 것처럼 보입니다(일반 C 코드보다 느린 경우도 있습니다).

잘 부탁드립니다.

#define is_aligned(POINTER, BYTE_COUNT) \
    (((uintptr_t)(const void *)(POINTER)) % (BYTE_COUNT) == 0)

★★★★★★★★★★★★★★의 출연자:void *char *에서는 로의 되기 때문에 uintptr_t★★★★★★에void *.

타입의 안전성을 필요로 하는 경우는, 인라인 함수의 사용을 검토해 주세요.

static inline _Bool is_aligned(const void *restrict pointer, size_t byte_count)
{ return (uintptr_t)pointer % byte_count == 0; }

합니다.byte_count는 컴파일 시간 상수입니다.

왜 변환이 필요한가? void * ?

타입에 다른 을 할 수 를 들어 C를 할 수 .void *공간 ) 및 "32" 를 입력합니다.foo *을 사용하다

★★foo *->void *는 실제 계산을 수반할 수 있습니다(예를 들어 오프셋 추가).이 규격은 (임의) 포인터를 정수로 변환했을 때의 실장에 의해서도 좌우되지만, 종종 noop으로서 실장되는 것은 아닐까 생각합니다.

에서는, 「」를 참조해 주세요.foo *->uintptr_t->foo *foo *->uintptr_t->void * ★★★★★★★★★★★★★★★★★」void *->uintptr_t->foo * 정렬 오프셋에 또는 않을 수 .또한 세그먼트 간격띄우기에 상대적인 선형만 선택하므로 선형 계산이 안정적으로 작동하지 않습니다.

★★★★★★★★★★★★★★★★★★★★★★★★★★void *구현에 의존하지 않는 동작을 얻을 수 있습니다.

대상: 캐스팅 대상:long오늘날 int와 포인터의 크기가 다를 수 있는 가능성으로부터 자신을 보호하는 저렴한 방법입니다.

아래 코멘트에서 지적한 바와 같이, 헤더를 포함할 의향이 있다면 더 나은 솔루션이 있습니다.

★★★p 경계 16바이트 .((unsigned long)p & 15) == 0.

다른 답변에서는 낮은 비트가 설정된 AND 연산을 제안하며 0과 비교합니다.

그러나 보다 간단한 테스트는 원하는 정렬 값을 사용하여 MOD를 수행하고 0과 비교하는 것입니다.

#define ALIGNMENT_VALUE     16u

if (((uintptr_t)ptr % ALIGNMENT_VALUE) == 0)
{
    // ptr is aligned
}

다음과 같은 기능 템플릿을 사용하여

#include <type_traits>

template< typename T >
bool is_aligned(T* p){
    return !(reinterpret_cast<uintptr_t>(p) % std::alignment_of<T>::value);
}

실행 시 다음과 같은 것을 호출하여 정렬을 기동할 수 있습니다.

struct foo_type{ int bar; }foo;
assert(is_aligned(&foo)); // passes

잘못된 정렬이 실패하는지 확인하려면 다음을 수행할 수 있습니다.

// would almost certainly fail
assert(is_aligned((foo_type*)(1 + (uintptr_t)(&foo)));

이게 기본적으로 제가 쓰고 있는 거예요.이 정수를 템플릿으로 함으로써 컴파일 시간을 연장할 수 있기 때문에, 무엇을 해도 모듈로의 동작이 늦어지는 일은 없습니다.

저는 항상 제 입력을 체크하는 것을 좋아하기 때문에 컴파일 타임 어설션을 합니다.얼라인먼트 값이 틀리면 컴파일되지 않습니다.

template <unsigned int alignment>
struct IsAligned
{
    static_assert((alignment & (alignment - 1)) == 0, "Alignment must be a power of 2");

    static inline bool Value(const void * ptr)
    {
        return (((uintptr_t)ptr) & (alignment - 1)) == 0;
    }
};

상황을 확인하려면 다음을 사용합니다.

// 1 of them is aligned...
int* ptr = new int[8];
for (int i = 0; i < 8; ++i)
    std::cout << IsAligned<32>::Value(ptr + i) << std::endl;

// Should give '1'
int* ptr2 = (int*)_aligned_malloc(32, 32);
std::cout << IsAligned<32>::Value(ptr2) << std::endl;

그건 전문가에게 맡기세요

https://www.boost.org/doc/libs/1_65_1/doc/html/align/reference.html#align.reference.functions.is_aligned

bool is_aligned(const void* ptr, std::size_t alignment) noexcept; 

예:

        char D[1];
        assert( boost::alignment::is_aligned(&D[0], alignof(double)) ); //  might fail, sometimes

ptr을 0x03(4초에서 정렬), 0x07(8초에서 정렬) 또는 0x0f(16초에서 정렬)로 '및'하여 가장 낮은 비트가 설정되어 있는지 확인할 수 있습니까?

그럼 어떻게 해?

void *mem = malloc(1024+15); 
void *ptr =( (*(char*)mem) - (*(char *)mem % 16) );

언급URL : https://stackoverflow.com/questions/1898153/how-to-determine-if-memory-is-aligned

반응형