小编Ral*_*alf的帖子

使用AVX/AVX2内在函数对齐和未对齐的内存访问

根据英特尔软件开发人员手册(第14.9节),AVX放宽了内存访问的对齐要求.如果数据直接加载到处理指令中,例如

vaddps ymm0,ymm0,YMMWORD PTR [rax]
Run Code Online (Sandbox Code Playgroud)

加载地址不必对齐.但是,如果使用专用的对齐加载指令,例如

vmovaps ymm0,YMMWORD PTR [rax]
Run Code Online (Sandbox Code Playgroud)

必须对齐加载地址(为32的倍数),否则会引发异常.

令我困惑的是内在函数的自动代码生成,在我的例子中是gcc/g ++(4.6.3,Linux).请查看以下测试代码:

#include <x86intrin.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#define SIZE (1L << 26)
#define OFFSET 1

int main() {
  float *data;
  assert(!posix_memalign((void**)&data, 32, SIZE*sizeof(float)));
  for (unsigned i = 0; i < SIZE; i++) data[i] = drand48();
  float res[8]  __attribute__ ((aligned(32)));
  __m256 sum = _mm256_setzero_ps(), elem;
  for (float *d = data + OFFSET; d < data + SIZE - 8; d += 8) {
    elem = _mm256_load_ps(d);
    // …
Run Code Online (Sandbox Code Playgroud)

gcc avx avx2

12
推荐指数
1
解决办法
6959
查看次数

什么gcc选项为具有立即操作数的SSE内在函数启用循环展开?

这个问题与gcc(4.6.3 Ubuntu)及其在为具有即时操作数的SSE内在函数的展开循环中的行为有关.

具有立即操作数的内在函数的示例是_mm_blend_ps.它期望一个4位立即数整数,它只能是一个常数.但是,使用-O3选项,编译器显然会自动展开循环(如果循环计数器值可以在编译时确定)并生成具有不同立即值的相应混合指令的多个实例.

这是一个简单的测试代码(blendsimple.c),它贯穿了blend的立即操作数的16个可能值:

#include <stdio.h>
#include <x86intrin.h>

#define PRINT(V)                \
  printf("%s: ", #V);               \
  for (i = 3; i >= 0; i--) printf("%3g ", V[i]);    \
  printf("\n");

int
main()
{
  __m128 a = _mm_set_ps(1, 2, 3, 4);
  __m128 b = _mm_set_ps(5, 6, 7, 8);
  int i;
  PRINT(a);
  PRINT(b);
  unsigned mask;
  __m128 r;
  for (mask = 0; mask < 16; mask++) {
    r = _mm_blend_ps(a, b, mask);
    PRINT(r);
  }
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

可以使用编译此代码

gcc -Wall -march=native -O3 -o blendsimple blendsimple.c …
Run Code Online (Sandbox Code Playgroud)

c gcc sse

7
推荐指数
1
解决办法
598
查看次数

是静态/静态本地SSE/AVX变量阻塞xmm/ymm寄存器?

使用SSE内在函数时,通常需要零向量.无论何时调用函数(每次有效调用某些xor向量指令),避免在函数内部创建零变量的一种方法是使用静态局部变量,如

static inline __m128i negate(__m128i a)
{
   static __m128i zero = __mm_setzero_si128();
   return _mm_sub_epi16(zero, a);
}
Run Code Online (Sandbox Code Playgroud)

似乎只在第一次调用函数时才初始化变量.(我通过调用一个真正的函数而不是_mm_setzero_si128()内在函数来检查这个.顺便说一句,它似乎只能在C++中,而不是在C中.)

(1)但是,一旦发生这种初始化:这是否阻止了xmm寄存器用于程序的其余部分?

(2)更糟糕的是:如果在多个函数中使用这样的静态局部变量,它会阻塞多个xmm寄存器吗?

(3)反过来说:如果它没有阻塞xmm寄存器,那么在调用函数时,零变量是否总是从内存中重新加载?那么静态局部变量将毫无意义,因为使用_mm_setzero_si128()会更快.

作为替代方案,我考虑将零置于一个全局静态变量中,该变量将在程序启动时初始化:

static __m128i zero = _mm_setzero_si128();
Run Code Online (Sandbox Code Playgroud)

(4)程序运行时,全局变量是否会保留在xmm寄存器中?

非常感谢你的帮助!

(由于这也适用于AVX内在函数,我还添加了AVX标记.)

c++ sse avx

6
推荐指数
2
解决办法
1048
查看次数

C++ 编译器支持 std::execution(并行 STL 算法)

我想使用并行版本,std::sort我可以在其中指定执行策略,例如std::execution::par_unseq.

我目前正在 Ubuntu Linux 下使用clang++-10g++ 7.5.0,但是两者都没有找到所需的包含文件execution,因此显然这些编译器版本尚不支持并行算法。

有人可以告诉我哪个版本clang支持gcc此功能吗?

c++ std c++17

6
推荐指数
1
解决办法
3070
查看次数

_mm256_slli_si256:错误"最后一个参数必须是一个8位中间"

我有以下问题(g ++(Ubuntu 4.8.4-2ubuntu1~14.04)4.8.4):

当我_mm256_slli_si256()直接使用时,例如:

__m256i x = _mm256_set1_epi8(0xff);
x = _mm256_slli_si256(x, 3);
Run Code Online (Sandbox Code Playgroud)

代码编译没有问题(g++ -Wall -march=native -O3 -o shifttest shifttest.C).

但是,如果我将它包装成一个函数

__m256i doit(__m256i x, const int imm)
{
  return _mm256_slli_si256(x, imm);
}
Run Code Online (Sandbox Code Playgroud)

编译器抱怨说

/usr/lib/gcc/x86_64-linux-gnu/4.8/include/avx2intrin.h: In function '__m256i doit(__m256i, int)':
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/avx2intrin.h:651:58: error: the last argument must be an 8-bit immediate
   return (__m256i)__builtin_ia32_pslldqi256 (__A, __N * 8);
Run Code Online (Sandbox Code Playgroud)

无论是否使用该功能.

这对于立即操作数来说不是问题,因为如果我使用eg _mm256_slli_si32(x, imm)而不是函数doit()编译,并且_mm256_slli_si32()还需要立即操作数.

有一个相关的错误报告

https://gcc.gnu.org/bugzilla/show_bug.cgi?format=multiple&id=54825

但它已经很老了(2012)并且与gcc 4.8.0有关,所以我认为这个补丁已经被整合到g ++ 4.8.4中了.

这个问题有解决方法吗?

c gcc simd avx avx2

5
推荐指数
1
解决办法
2188
查看次数

sse/avx相当于霓虹灯vuzp

英特尔的矢量扩展SSE,AVX等为每个元素大小提供了两个解包操作,例如SSE内在函数是_mm_unpacklo_*_mm_unpackhi_*.对于向量中的4个元素,它执行此操作:

inputs:      (A0 A1 A2 A3) (B0 B1 B2 B3)
unpacklo/hi: (A0 B0 A1 B1) (A2 B2 A3 B3)
Run Code Online (Sandbox Code Playgroud)

解压缩的等价物vzip在ARM的NEON指令集中.但是,NEON指令集也提供了与之vuzp相反的操作vzip.对于向量中的4个元素,它执行此操作:

inputs: (A0 A1 A2 A3) (B0 B1 B2 B3)
vuzp:   (A0 A2 B0 B2) (A1 A3 B1 B3)
Run Code Online (Sandbox Code Playgroud)

如何vuzp使用SSE或AVX内在函数有效实现?似乎没有针对它的指示.对于4个元素,我假设它可以使用shuffle和随后的unpack移动2个元素来完成:

inputs:        (A0 A1 A2 A3) (B0 B1 B2 B3)
shuffle:       (A0 A2 A1 A3) (B0 B2 B1 B3)
unpacklo/hi 2: (A0 A2 B0 B2) (A1 A3 B1 B3)
Run Code Online (Sandbox Code Playgroud)

使用单个指令是否有更高效的解决方案?(也许对于SSE优先 …

sse simd avx neon

5
推荐指数
1
解决办法
709
查看次数

NASM Intel 64位模式:为什么32位常量0xffffffff会导致“警告:有符号双字值超出界限”

在 NASM (2.14.02) 中,指令add rbx, 0xffffffff导致

警告:有符号双字值超出界限 [-w+number-overflow]

我知道 64 位模式下的算术逻辑运算仅接受 32 位常量,但 0xffffffff 仍然是 32 位宽。

为什么 NASM 发出警告,为什么它假设一个有符号常量?它是否将 32 位符号扩展-1为 64 位-1(0xffffffffffffffff)并因此出现溢出?0x7fffffff 工作时不会发出警告。

我能以某种方式说服 NASM 这不是一个有符号常量,而是一个无符号常量吗?

assembly x86-64 nasm immediate-operand

4
推荐指数
1
解决办法
510
查看次数

为什么 Tigerlake 的 gcc 自动矢量化使用 ymm 而不是 zmm 寄存器

我想探索 gcc (10.3) 的自动矢量化。我有以下简短的程序(请参阅https://godbolt.org/z/5v9a53aj6),它计算向量所有元素的总和:

#include <stdio.h>
#define LEN 1024

// -ffast-math -march=tigerlake -O3 -fno-unroll-loops
  
int
main()
{
  float v[LEN] __attribute__ ((aligned(64)));
  float s = 0;
  for (unsigned int i = 0; i < LEN; i++) s += v[i];
  printf("%g\n", s);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我用选项编译-ffast-math -march=tigerlake -O3 -fno-unroll-loops。由于 Tigerlake 处理器具有 avx512,我希望 gcc 自动向量化使用 zmm 寄存器,但它实际上在最内层循环中使用 ymm 寄存器(avx/avx2):

vaddps  ymm0, ymm0, YMMWORD PTR [rax]
Run Code Online (Sandbox Code Playgroud)

如果我替换-march=tigerlake-mavx512f,则使用 zmm 寄存器:

vaddps  zmm0, zmm0, ZMMWORD PTR [rax]
Run Code Online (Sandbox Code Playgroud)

如果我只是指定,为什么不使用 …

c gcc avx auto-vectorization avx512

3
推荐指数
1
解决办法
531
查看次数

Tcl:检查数组元素是否存在的最快方法

Tcl 中测试数组元素是否存在的最快方法是什么?

  1. 目前我用的info exists ::myArray($myKey)是,效率高吗?
  2. 我可以使用llength [array names ::myArray -exact $myKey],这样会更快吗?

这些也是 Nadkarni 在 Tcl 书中列出的可能性。还有其他更有效的想法吗?

感谢您的帮助!

tcl

1
推荐指数
1
解决办法
2054
查看次数

标签 统计

avx ×5

gcc ×4

c ×3

sse ×3

avx2 ×2

c++ ×2

simd ×2

assembly ×1

auto-vectorization ×1

avx512 ×1

c++17 ×1

immediate-operand ×1

nasm ×1

neon ×1

std ×1

tcl ×1

x86-64 ×1