메모리가 정렬되어 있는지 확인하는 방법
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;
그건 전문가에게 맡기세요
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
'programing' 카테고리의 다른 글
타입 세이프 에넘을 작성하는 방법 (0) | 2022.08.11 |
---|---|
vue.material에서의 vue.modial2 라우팅 (0) | 2022.08.11 |
Base64 Java 인코딩 및 문자열 디코딩 (0) | 2022.08.11 |
이중이 정수인지 검사하는 방법 (0) | 2022.08.11 |
어레이가 늘인지 비어 있는지 확인하려면 어떻게 해야 합니까? (0) | 2022.08.11 |