我写了一些代码来做一堆数学,它需要快速,所以我需要它来使用SSE和AVX指令.我相克编译它++和我使用的标志-O3和-march=native,所以我觉得它使用SSE和AVX指令,但我不知道.我的大多数代码看起来如下所示:
for(int i = 0;i<size;i++){
a[i] = b[i] * c[i];
}
Run Code Online (Sandbox Code Playgroud)
有什么方法可以判断我的代码(编译后)是否使用SSE和AVX指令?我想我可以看看程序集,但我不知道汇编,我不知道如何查看编译器输出的汇编.
是不是像
__m128 a = something;
__m128i b = reinterpret_cast<__m128i>(a);
Run Code Online (Sandbox Code Playgroud)
安全还是未定义?如果未定义,它是否至少适用于所有主要编译器(gcc、clang、msvc、icc)?我用 gcc 在我的电脑上测试过它,它可以工作,但我不确定它是否便携。我知道我可以使用_mm_castps_si128(),但是由于模板的原因,第一种方式恰好更方便。
假设我有一些类,其中唯一的成员是int.如果它不在类中,则int本身就是4个字节.该类是否占用超过4个字节的内存(在C++中)?
我想从simd寄存器访问任意浮点数。我知道我可以做以下事情:
float get(const __m128i& a, const int idx){
// editor's note: this type-puns the FP bit-pattern to int and converts to float
return _mm_extract_ps(a,idx);
}
Run Code Online (Sandbox Code Playgroud)
要么
float get(const __m128i& a, const int idx){
return _mm_cvtss_f32(_mm_shuffle_ps(a,_MM_SHUFFLE(0,0,0,idx));
}
Run Code Online (Sandbox Code Playgroud)
甚至使用轮换功能而不是随机播放。问题在于这些都需要在编译时知道idx(随机,移位和提取都需要8bit立即数)。
我也可以先使用_mm_store_ps()然后再使用结果数组来完成此操作,但这需要占用内存。有没有比这更快的方法了?
编辑:忽略第一个代码段,我希望浮点数在该位置,而不是像_mm_extract_ps返回一样的int 值。
我有以下代码(最小示例):
#include <iostream>
#include <immintrin.h>
using namespace std;
int main(){
__m128i a = _mm_set_epi32(rand(),rand(),rand(),rand());
__m128i b = _mm_set_epi32(rand(),rand(),rand(),rand());
__m128i c = _mm_add_epi32(a,b);
int d[4];
_mm_storeu_si128((__m128i*)d,c);
cout<<d[0]<<endl;
cout<<d[1]<<endl;
cout<<d[2]<<endl;
cout<<d[3]<<endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译时g++ -O3 -march=native,它会产生一些奇怪/坏/低效的程序集(https://godbolt.org/z/TQgbim).它存储c一次,然后它执行一个对齐的加载和一个提取来进行元素访问(每次).我可以看到它为什么需要将它存储到内存中,我可以看到对齐的加载和提取如何有效,但我不明白为什么它需要在提取后继续将相同的数据加载到xmm寄存器中.此外,当d更改它以便在堆上分配(https://godbolt.org/z/Pk7qP2)时,它甚至不再执行对齐的加载,它只是视为d普通数组并访问元素办法.有人可以解释为什么这样做以及它可能带来什么好处?谢谢.