Tag: sse

获得对齐内存的最佳跨平台方法

这是我通常使用的代码,用于获取与Visual Studio和GCC对齐的内存 inline void* aligned_malloc(size_t size, size_t align) { void *result; #ifdef _MSC_VER result = _aligned_malloc(size, align); #else if(posix_memalign(&result, align, size)) result = 0; #endif return result; } inline void aligned_free(void *ptr) { #ifdef _MSC_VER _aligned_free(ptr); #else free(ptr); #endif } 这个代码一般都没问题吗? 我也看到人们使用_mm_malloc , _mm_free 。 在大多数情况下,我想要对齐内存,使用SSE / AVX。 我可以一般使用这些function吗? 它会使我的代码更简单。 最后,创建我自己的函数来对齐内存很容易(见下文)。 那么为什么有这么多不同的常用函数来获得对齐的内存(其中许多只能在一个平台上运行)? 此代码执行16字节对齐。 float* array […]

SSE寄存器返回SSE禁用

我遇到以下情况: 我正在为不允许SSE指令的内核编写代码 我需要做浮点运算 我正在为x86_64平台编译 这是一个代码示例,说明了问题: int main(int argc, char** argv) { double d = 0.0, dbase; uint64_t base_value = 300; d = (2200.0 – 1000.0)/(1000.0); dbase = d * base_value; printf(“d = %f, dbase = %f\n”, d, dbase); base_value = dbase; printf(“base_value = %llu\n”, (long long unsigned)base_value); return 0; } 这是makefile中的相关行: CFLAGS += -mcmodel=kernel -mno-red-zone […]

使用SSE最快地实现指数函数

我正在寻找在SSE元素上运行的指数函数的近似值。 即 – __m128 exp( __m128 x ) 。 我有一个快速但实际上准确度非常低的实现: static inline __m128 FastExpSse(__m128 x) { __m128 a = _mm_set1_ps(12102203.2f); // (1 << 23) / ln(2) __m128i b = _mm_set1_epi32(127 * (1 << 23) – 486411); __m128 m87 = _mm_set1_ps(-87); // fast exponential function, x should be in [-87, 87] __m128 mask = _mm_cmpge_ps(x, m87); […]

如果它们是16字节对齐,是否可以直接将浮点数转换为__m128?

如果它们是16字节对齐的话,将浮点数直接转换为__m128是否安全/可行/可取? 我注意到使用_mm_load_ps和_mm_store_ps来“包装”原始数组会增加很大的开销。 我应该注意哪些潜在的陷阱? 编辑: 使用加载和存储指令实际上没有开销,我得到了一些数字混合,这就是为什么我有更好的性能。 即使你能够在__m128实例中使用原始内存地址进行一些HORRENDOUS修改,当我运行测试时,如果没有_mm_load_ps指令则需要TWICE AS LONG完成,可能会回退到一些故障安全代码路径。

在GNU C inline asm中,对于单个操作数,xmm / ymm / zmm的修饰符是什么?

在尝试使用内在函数和汇编来回答嵌入式广播时 ,我试图做这样的事情: __m512 mul_broad(__m512 a, float b) { int scratch = 0; asm( “vbroadcastss %k[scalar], %q[scalar]\n\t” // want vbr.. %xmm0, %zmm0 “vmulps %q[scalar], %[vec], %[vec]\n\t” // how it’s done for integer registers “movw symbol(%q[inttmp]), %w[inttmp]\n\t” // movw symbol(%rax), %ax “movsbl %h[inttmp], %k[inttmp]\n\t” // movsx %ah, %eax : [vec] “+x” (a), [scalar] “+x” (b), [inttmp] “=r” […]

AVX标量操作要快得多

我测试了以下简单的function void mul(double *a, double *b) { for (int i = 0; i<N; i++) a[i] *= b[i]; } 具有非常大的数组,因此它是内存带宽限制。 我使用的测试代码如下。 当我用-O2编译时需要1.7秒。 当我用-O2 -mavx编译时,它只需要1.0秒。 非vex编码的标量操作慢了70%! 为什么是这样? 这是-O2和-O2 -mavx的程序集。 <img src="http://sofzh.miximages.com/c/otliN.png" alt=" -O2 和 -O2 -mavx 的vimddif”> https://godbolt.org/g/w4p60f 系统:i7-6700HQ@2.60GHz(Skylake)32 GB内存,Ubuntu 16.10,GCC 6.3 测试代码 //gcc -O2 -fopenmp test.c //or //gcc -O2 -mavx -fopenmp test.c #include #include #include #include […]

如何确定内存是否对齐?

我是使用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 } } } […]

高效的4×4矩阵乘法(C vs汇编)

我正在寻找一种更快,更棘手的方法来将C中的两个4×4矩阵相乘。我目前的研究主要集中在具有SIMD扩展的x86-64汇编上。 到目前为止,我已经创建了一个函数,比一个简单的C实现快了大约6倍,这超出了我对性能改进的期望。 不幸的是,只有在没有使用优化标志进行编译时(GCC 4.7),这种情况才会成立。 随着-O2 ,C变得更快,我的努力变得毫无意义。 我知道现代编译器利用复杂的优化技术来实现几乎完美的代码,通常比巧妙的手工assembly更快。 但在少数性能关键的情况下,人类可能会尝试使用编译器争取时钟周期。 特别是,当一些支持现代ISA的数学可以被探索时(就像我的情况一样)。 我的函数如下(AT&T语法,GNU汇编程序): .text .globl matrixMultiplyASM .type matrixMultiplyASM, @function matrixMultiplyASM: movaps (%rdi), %xmm0 # fetch the first matrix (use four registers) movaps 16(%rdi), %xmm1 movaps 32(%rdi), %xmm2 movaps 48(%rdi), %xmm3 xorq %rcx, %rcx # reset (forward) loop iterator .ROW: movss (%rsi), %xmm4 # Compute four values (one row) […]

使用SSE获取__m128i向量中的最大值?

我刚开始使用SSE,我很困惑如何获得__m128i的最大整数值( max )。 例如: __m128i t = _mm_setr_ps(0,1,2,3); // max(t) = 3; 搜索引导我到MAXPS指令,但我似乎无法找到如何使用”xmmintrin.h” 。 另外,您是否会建议使用”xmmintrin.h”文档,而不是查看头文件本身?

逻辑SSE内在函数之间有什么区别?

不同类型的逻辑SSE内在函数之间有什么区别吗? 例如,如果我们采用OR运算,有三个内在函数:_mm_or_ps,_mm_or_pd和_mm_or_si128所有这些都做同样的事情:计算其操作数的按位 OR。 我的问题: 使用一个或另一个内在(使用适当的类型转换)之间是否有任何区别。 在某些特定情况下,是否会有更长的执行等隐藏成本? 这些内在函数映射到三个不同的x86指令(por,orps,orpd)。 有没有人有任何想法为什么英特尔浪费宝贵的操作码空间的几个指令做同样的事情?