小编Amo*_*ati的帖子

如何实现高效的_mm256_madd_epi8?

英特尔提供了一个名为_mm256_madd_epi16的C风格函数,基本上就是这样

__m256i _mm256_madd_epi16(__ m256i a,__ m256i b)

在a和b中多次打包有符号的16位整数,产生中间带符号的32位整数.水平添加相邻的中间32位整数对,并将结果打包为dst.

现在我有两个__m256i变量,每个变量都有32个8位int.

我想实现_mm256_madd_epi16与之相同的功能,但结果__m256i中的每个int32_t元素是四个signed char产品总和,而不是两对signed int16_t.

我可以在标量循环中做到这一点:

  alignas(32) uint32_t res[8];
  for (int i = 0; i < 32; ++i)
      res[i / 4] += _mm256_extract_epi8(a, i) * _mm256_extract_epi8(b, i);
  return _mm256_load_si256((__m256i*)res);
Run Code Online (Sandbox Code Playgroud)

请注意,乘法结果在添加之前是符号扩展的int,并且_mm256_extract_epi8辅助函数1 返回signed__int8.没关系总数uint32_t而不是int32_t; 无论如何它只能添加四个8x8 => 16位数字才能溢出.

它看起来非常难看,并且不能高效运行,除非编译器使用SIMD做一些魔术,而不是编写为标量提取.


脚注1: _mm256_extract_epi8不是内在的. vpextrb仅适用于256位向量的低通道,此辅助函数可能允许索引不是编译时常量.

c++ x86 simd intrinsics avx2

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

为什么“native_write_msr”主导我的分析结果?

我有一个在 Linux 内核 4.18 和 Intel CPU 的多线程框架上运行的程序。我跑去perf record -p pid -g -e cycles:u --call-graph lbr -F 99 -- sleep 20收集堆栈跟踪并生成火焰图。

在此输入图像描述

我的程序在低工作负载下运行,因此所花费的时间futex_wait是预期的。但栈顶是一个内核函数native_write_msr。根据内核中的native_write_msr 做什么?https://elixir.bootlin.com/linux/v4.18/source/arch/x86/include/asm/msr.h#L103,该函数用于性能计数器。我已禁用 中的跟踪点native_write_msr

pidstat -p pid 1告诉我系统CPU使用率相当低。

05:44:34 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
05:44:35 PM  1001     67441   60.00    4.00    0.00   64.00    11  my_profram
05:44:36 PM  1001     67441   58.00    7.00    0.00   65.00    11  my_profram
05:44:37 PM  1001     67441   61.00    3.00    0.00   64.00 …
Run Code Online (Sandbox Code Playgroud)

x86 profiling linux-kernel perf

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

如何将32位浮点数转换为8位有符号字符?

我想做的是:

  1. 将输入浮点数乘以固定因子.
  2. 将它们转换为8位有符号字符.

请注意,大多数输入具有较小的绝对值范围,如[-6,6],因此固定因子可以将它们映射到[-127,127].

我只使用avx2指令集,所以内在函数就像_mm256_cvtepi32_epi8不能使用一样.我想使用,_mm256_packs_epi16但它将两个输入混合在一起.:(

我还编写了一些将32位浮点数转换为16位int的代码,它正如我想要的那样工作.

void Quantize(const float* input, __m256i* output, float quant_mult, int num_rows, int width) {
  // input is a matrix actuaaly, num_rows and width represent the number of rows and columns of the matrix
  assert(width % 16 == 0);

  int num_input_chunks = width / 16;

  __m256 avx2_quant_mult = _mm256_set_ps(quant_mult, quant_mult, quant_mult, quant_mult,
                                     quant_mult, quant_mult, quant_mult, quant_mult);

  for (int i = 0; i < num_rows; ++i) {
    const float* input_row = input + …
Run Code Online (Sandbox Code Playgroud)

c x86 simd intrinsics avx2

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

标签 统计

x86 ×3

avx2 ×2

intrinsics ×2

simd ×2

c ×1

c++ ×1

linux-kernel ×1

perf ×1

profiling ×1