__m128i 변수 인쇄
나는 고유성을 이용하여 코딩하는 것을 배우려고 노력하고 있고 아래는 추가를 하는 코드입니다.
compiler used: icc
#include<stdio.h>
#include<emmintrin.h>
int main()
{
__m128i a = _mm_set_epi32(1,2,3,4);
__m128i b = _mm_set_epi32(1,2,3,4);
__m128i c;
c = _mm_add_epi32(a,b);
printf("%d\n",c[2]);
return 0;
}
다음 오류가 발생합니다.
test.c(9): error: expression must have pointer-to-object type
printf("%d\n",c[2]);
변수의 값을 인쇄하려면 어떻게 해야 합니까?c
유형의__m128i
다음 기능을 사용하여 인쇄합니다.
#include <stdint.h>
#include <string.h>
void print128_num(__m128i var)
{
uint16_t val[8];
memcpy(val, &var, sizeof(val));
printf("Numerical: %i %i %i %i %i %i %i %i \n",
val[0], val[1], val[2], val[3], val[4], val[5],
val[6], val[7]);
}
128비트를 16비트(또는 32비트)로 나누어 인쇄합니다.
64비트 지원을 사용할 수 있는 경우 64비트를 분할하여 인쇄하는 방법입니다.
#include <inttypes.h>
void print128_num(__m128i var)
{
int64_t v64val[2];
memcpy(v64val, &var, sizeof(v64val));
printf("%.16llx %.16llx\n", v64val[1], v64val[0]);
}
참고: 캐스팅&var
직접적으로int*
아니면uint16_t*
MSVC도 작동하지만 이는 엄격한 앨리어싱을 위반하며 정의되지 않은 동작입니다.사용.memcpy
는 동일한 작업을 수행하는 표준 준수 방식이며 최소 최적화를 통해 컴파일러는 정확히 동일한 이진 코드를 생성합니다.
- gcc/clang/ICC/MSVC, C 및 C++에서 휴대 가능.
- 모든 최적화 수준에서 완벽하게 안전: 엄격한 앨리어싱 위반 UB 없음
- hexas u8, u16, u32 또는 u64 요소로 인쇄(@AG1의 답변 기준)
- 메모리 순서로 인쇄합니다(가장 중요하지 않은 요소 먼저).
_mm_setr_epiX
인텔의 매뉴얼이 사용하는 것과 같은 순서로 인쇄하고 싶다면 배열 인덱스를 반대로 합니다. 가장 중요한 요소는 왼쪽에 있습니다(예:_mm_set_epiX
) 관련:벡터 레지스터를 표시하는 규약
A를 사용.__m128i*
일련의 것에서 로드하다int
안전하기 때문에__m128
ISO C와 마찬가지로 앨리어싱을 허용하도록 유형이 정의됩니다.unsigned char*
. (예: gcc의 헤더에서, 그 정의는 다음을 포함합니다.__attribute__((may_alias))
.)
그 역은 안전하지 않습니다. (안을 가리키며)int*
의 일부에__m128i
목적어).MSVC는 그것이 안전하다고 보장하지만 GCC/clang은 그렇지 않습니다. (-fstrict-aliasing
는 기본적으로 켜져 있습니다.GCC/clang과 함께 작동하는 경우도 있지만, 왜 위험을 감수해야 합니까?때로는 최적화에 방해가 되기도 합니다. 이 Q&A를 참조하십시오.참고 항목 하드웨어 SIMD 벡터 포인터와 해당 유형 간의 'reinterpret_casting'이 정의되지 않은 동작입니까?
GCC AVX_m256i cast to int array는 다음을 가리키는 GCC breaking code의 실제 예에 대해 잘못된 값으로 이어집니다.int*
에__m256i
.
(uint32_t*) &my_vector
는 C 및 C++ 에일리어싱 규칙을 위반하며, 사용자가 기대하는 대로 작동할 것을 보장받지 못합니다.로컬 어레이에 저장한 다음 액세스하면 안전합니다.대부분의 컴파일러에서 최적화를 수행하기 때문에movq
/pextrq
예를 들어, 실제 저장소/reload 대신 xmm에서 정수 레지스터로 직접 이동합니다.
Godbolt 컴파일러 탐색기의 소스 + asm 출력: 증명 MSVC 등과 컴파일됩니다.
#include <immintrin.h>
#include <stdint.h>
#include <stdio.h>
#ifndef __cplusplus
#include <stdalign.h> // C11 defines _Alignas(). This header defines alignas()
#endif
void p128_hex_u8(__m128i in) {
alignas(16) uint8_t v[16];
_mm_store_si128((__m128i*)v, in);
printf("v16_u8: %x %x %x %x | %x %x %x %x | %x %x %x %x | %x %x %x %x\n",
v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7],
v[8], v[9], v[10], v[11], v[12], v[13], v[14], v[15]);
}
void p128_hex_u16(__m128i in) {
alignas(16) uint16_t v[8];
_mm_store_si128((__m128i*)v, in);
printf("v8_u16: %x %x %x %x, %x %x %x %x\n", v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
}
void p128_hex_u32(__m128i in) {
alignas(16) uint32_t v[4];
_mm_store_si128((__m128i*)v, in);
printf("v4_u32: %x %x %x %x\n", v[0], v[1], v[2], v[3]);
}
void p128_hex_u64(__m128i in) {
alignas(16) unsigned long long v[2]; // uint64_t might give format-string warnings with %llx; it's just long in some ABIs
_mm_store_si128((__m128i*)v, in);
printf("v2_u64: %llx %llx\n", v[0], v[1]);
}
C99 또는 C++03 또는 그 이전(예: C11 / C++11 없음)으로 휴대성이 필요한 경우 를 제거하고 사용합니다.storeu
대신에store
. 아니면 사용__attribute__((aligned(16)))
아니면__declspec( align(16) )
대신.
(만약 당신이 고유성을 가진 코드를 쓴다면, 당신은 최신 컴파일러 버전을 사용해야 합니다.최신 컴파일러는 SSE/AVX 고유의 경우를 포함하여 이전 컴파일러보다 더 나은 ASM을 만듭니다.은 gcc-6과 도 있습니다.3을 사용하고 싶을 것입니다.-std=gnu++03
C++11 같은 것을 위해 준비되지 않은 코드베이스를 위한 C++03 모드.)
4개의 기능을 모두 호출하여 출력한 샘플
// source used:
__m128i vec = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15, 16);
// output:
v2_u64: 0x807060504030201 0x100f0e0d0c0b0a09
v4_u32: 0x4030201 0x8070605 0xc0b0a09 0x100f0e0d
v8_u16: 0x201 0x403 0x605 0x807 | 0xa09 0xc0b 0xe0d 0x100f
v16_u8: 0x1 0x2 0x3 0x4 | 0x5 0x6 0x7 0x8 | 0x9 0xa 0xb 0xc | 0xd 0xe 0xf 0x10
일관된 출력 폭을 위해 선행 0으로 패딩하려면 형식 문자열을 조정합니다.보세요.
이 문제는 C라는 태그가 붙은 것으로 알고 있지만, 동일한 문제에 대한 C++ 솔루션을 찾을 때도 가장 좋은 검색 결과였습니다.
따라서 C++ 구현이 가능합니다.
#include <string>
#include <cstring>
#include <sstream>
#if defined(__SSE2__)
template <typename T>
std::string __m128i_toString(const __m128i var) {
std::stringstream sstr;
T values[16/sizeof(T)];
std::memcpy(values,&var,sizeof(values)); //See discussion below
if (sizeof(T) == 1) {
for (unsigned int i = 0; i < sizeof(__m128i); i++) { //C++11: Range for also possible
sstr << (int) values[i] << " ";
}
} else {
for (unsigned int i = 0; i < sizeof(__m128i) / sizeof(T); i++) { //C++11: Range for also possible
sstr << values[i] << " ";
}
}
return sstr.str();
}
#endif
용도:
#include <iostream>
[..]
__m128i x
[..]
std::cout << __m128i_toString<uint8_t>(x) << std::endl;
std::cout << __m128i_toString<uint16_t>(x) << std::endl;
std::cout << __m128i_toString<uint32_t>(x) << std::endl;
std::cout << __m128i_toString<uint64_t>(x) << std::endl;
결과:
141 114 0 0 0 0 0 0 151 104 0 0 0 0 0 0
29325 0 0 0 26775 0 0 0
29325 0 26775 0
29325 26775
참고: 다음을 방지할 수 있는 간단한 방법이 있습니다.if (size(T)==1)
, https://stackoverflow.com/a/28414758/2436175 를 참조하십시오.
#include<stdio.h>
#include<emmintrin.h>
int main()
{
__m128i a = _mm_set_epi32(1,2,3,4);
__m128i b = _mm_set_epi32(1,2,3,4);
__m128i c;
const int32_t* q;
//add a pointer
c = _mm_add_epi32(a,b);
q = (const int32_t*) &c;
printf("%d\n",q[2]);
//printf("%d\n",c[2]);
return 0;
}
이 코드를 사용해 보세요.
언급URL : https://stackoverflow.com/questions/13257166/print-a-m128i-variable
'programing' 카테고리의 다른 글
일반적으로 신뢰할 수 있다고 여겨지는 SHA-256 자바스크립트 구현이 있습니까? (0) | 2023.10.24 |
---|---|
SQL(MariaDB) NULL 값이 무시됩니다. (0) | 2023.10.24 |
브라우저에서 보류 중인 요청(Ajax 및 그 변형)이 있는지 확인하는 방법 (0) | 2023.10.24 |
오픈 스로우를 호출하기 전에 XMLHttpRequestresponseType을 설정하는 이유는 무엇입니까? (0) | 2023.10.24 |
HTML Tidy에서 메타 태그( 스키마 마크업)를 처리하지 못하도록 방지합니다. (0) | 2023.10.24 |