从“int”类型分配给“__m256d”类型时不兼容的类型

Posted

技术标签:

【中文标题】从“int”类型分配给“__m256d”类型时不兼容的类型【英文标题】:incompatible types when assigning to type ‘__m256d’ from type ‘int’ 【发布时间】:2021-01-03 11:20:57 【问题描述】:

我正在做一个优化矩阵乘法的项目,我正在尝试使用内在函数。

这是我正在使用的一些代码:

#include <immintrin.h>

/* Vector tiling and loop unrolling */
static void do_block(int lda, int M, int N, int K, double* A, double* B, double* C) 
  /* For each row i of A */
  int i, j, k;
  for (i = 0; i < M / 4; ++i) 
    /* For each column j of B */
    for (j = 0; j < N / 12; ++j) 
      register __m256d c_00_03_0 = _mm256_loadu_pd(C + (4 * i) * lda + j * 12);
      register __m256d c_00_03_1 = _mm256_loadu_pd(C + (4 * i) * lda + j * 12 + 4);
      register __m256d c_00_03_2 = _mm256_loadu_pd(C + (4 * i) * lda + j * 12 + 8);
      register __m256d c_10_13_0 = _mm256_loadu_pd(C + (4 * i + 1) * lda + j * 12);
      register __m256d c_10_13_1 = _mm256_loadu_pd(C + (4 * i + 1) * lda + j * 12+4);
      register __m256d c_10_13_2 = _mm256_loadu_pd(C + (4 * i + 1) * lda + j * 12+8);
      register __m256d c_20_23_0 = _mm256_loadu_pd(C + (4 * i + 2) * lda + j * 12);
      register __m256d c_20_23_1 = _mm256_loadu_pd(C + (4 * i + 2) * lda + j * 12+4);
      register __m256d c_20_23_2 = _mm256_loadu_pd(C + (4 * i + 2) * lda + j * 12+8);
      register __m256d c_30_33_0 = _mm256_loadu_pd(C + (4 * i + 3) * lda + j * 12);
      register __m256d c_30_33_1 = _mm256_loadu_pd(C + (4 * i + 3) * lda + j * 12+4);
      register __m256d c_30_33_2 = _mm256_loadu_pd(C + (4 * i + 3) * lda + j * 12+8);

      /* Loop unrolling */
      for (k = 0; k < K; k += 1) 
    register __m256d b_00_03 = _mm256_loadu_pd(B + k * lda + j * 12);
    register __m256d b_10_03 = _mm256_loadu_pd(B + k * lda + j * 12+4);
    register __m256d b_20_03 = _mm256_loadu_pd(B + k * lda + j * 12+8);
    register __m256d a00 = _mm256_broadcast_sd(A + (4 * i) * lda + k);

    c_00_03_0 = _mm256_fmadd_pd(a00, b_00_03, c_00_03_0);
    c_00_03_1 = _mm256_fmadd_pd(a00, b_10_03, c_00_03_1);
    c_00_03_2 = _mm256_fmadd_pd(a00, b_20_03, c_00_03_2);

    a00 = _mm256_broadcast_sd(A + (4 * i + 1) * lda + k);
    c_10_13_0 = _mm256_fmadd_pd(a00, b_00_03, c_10_13_0);
    c_10_13_1 = _mm256_fmadd_pd(a00, b_10_03, c_10_13_1);
    c_10_13_2 = _mm256_fmadd_pd(a00, b_20_03, c_10_13_2);

    a00 = _mm256_broadcast_sd(A + (4 * i + 2) * lda + k);
    c_20_23_0 = _mm256_fmadd_pd(a00, b_00_03, c_20_23_0);
    c_20_23_1 = _mm256_fmadd_pd(a00, b_10_03, c_20_23_1);
    c_20_23_2 = _mm256_fmadd_pd(a00, b_20_03, c_20_23_2);

    a00 = _mm256_broadcast_sd(A + (4 * i + 3) * lda + k);
    c_30_33_0 = _mm256_fmadd_pd(a00, b_00_03, c_30_33_0);
    c_30_33_1 = _mm256_fmadd_pd(a00, b_10_03, c_30_33_1);
    c_30_33_2 = _mm256_fmadd_pd(a00, b_20_03, c_30_33_2);
      



所有使用函数 __mm256_fmadd_pd 的行都会抛出以下错误:

<b>incompatible types when assigning to type ‘__m256d’ from type ‘int’</b>

我不确定 int 来自哪里,因为__mm256_madd_pd 的所有参数都是“__m256d”,返回值也是“__m256d(__m256d _mm256_fmadd_pd (__m256d a, __m256d b, __m256d c))

【问题讨论】:

关闭一些 后,使用 gcc 可以正常编译:godbolt.org/z/s5has7。尽管如此,我还是建议去掉所有 register 关键字。编译器应该更好地知道将什么放入寄存器,什么不放入(无论如何,您需要检查实际发生了什么)。 在您的情况下,native 是什么? cat /proc/cpuinfo 是否包含 FMA? 这意味着你的 CPU 不支持 FMA。您可以使用-mfma 进行编译,但这会在运行时失败。 解决方法当然是调用_mm256_add_pd(_mm256_mul_pd(aXX, bYY), cZZ)(您可以将其放入内联函数中)。 除了“不兼容的类型”之外,是否还有更多错误或警告?如果您没有 FMA,那么我认为 -march=native 会设置 #defines 以便头文件不会声明 _mm256_fmadd_pd。你会得到一个“隐式声明”警告,它会被隐式声明为返回int,这将解释“不兼容的类型”错误。但这将是导致这一切的“隐含声明”。 【参考方案1】:

正如 chtz 所说,我使用的处理器不支持 _mm256_fmadd_pd 那样的 FMA 功能,所以我使用了他提出的解决方法,效果很好: _mm256_add_pd(_mm256_mul_pd(aXX, bYY), cZZ)

【讨论】:

以上是关于从“int”类型分配给“__m256d”类型时不兼容的类型的主要内容,如果未能解决你的问题,请参考以下文章

在 4 个 __m256d 寄存器中找到 4 个最小值

参数类型“Future<int>”不能分配给参数类型“int”

使用 AVX 功能时崩溃

如何修复 Flutter 中的“参数类型 'Future<int>' 无法分配给参数类型 'int'”

参数类型“int”不能分配给参数类型“double”

无法将“Int”类型的值分配给“String”类型?在 (cellForRowAt) 中使用 Tableview