【问题标题】:How do you vectorise a loop?你如何矢量化一个循环?
【发布时间】:2021-01-18 01:07:56
【问题描述】:

我在矢量化循环时遇到了麻烦。我希望重写下面的代码,使其矢量化。我已经运行了 Complete Banerjee 的测试,发现所有依赖项都已损坏,但我不知道从哪里开始。 编译器是 gcc。架构是 x86,数组是整数数组。

for (int i = 0; i < 100; i++) { 
     x[20 + i] = y[i] * z[i];
     p[i] = x[21 + i] + q[i];
}

【问题讨论】:

  • 矢量化通常是一种优化,您依赖编译器为您执行。 C 语言没有表达“这个循环应该被矢量化”的方法,尽管您的特定实现可能提供了一个扩展来服务于该目的。
  • 例如:gcc -ftree-vectorize ...
  • 你能澄清你的意思吗?您是否在询问使用哪些编译器开关来要求编译器进行矢量化(您没有说您正在使用什么编译器),或者对您的代码进行哪些更改以鼓励编译器有效地这样做(仍然依赖于编译器),或者如何使用向量指令用汇编语言自己重写代码(你没有说什么CPU)?无论如何,需要更多信息。
  • @NateEldredge 我很抱歉。我的意思是如何在 C 中重写,使其矢量化。我现在就来编辑!
  • 另外,为什么要使用parallel-processingcluster-computing 标签?这些通常是指在多个线程/进程/作业之间划分计算,然后可以在多个内核/CPU/计算机上并行运行。但是向量化将计算保持在单个内核上的单个线程中,只要求该内核使用一次处理多个数据元素的指令。

标签: c optimization parallel-processing vectorization cluster-computing


【解决方案1】:

两个一般提示:

  • 将数组作为参数传递给您的函数,使用 restrict 关键字通知编译器它们不能相互别名(这会阻止任何矢量化)。

  • 虽然循环第二行从x 读取的内容不依赖于第一行的写入内容,但编译器可能不够聪明,无法检测到这一点。通过交换这两行来帮助它,或者在写入之前将读取移动到它自己的循环。

以下版本已通过 gcc 10.2 成功矢量化 -O3 -march-skylake (try on Godbolt),每次迭代使用 ymm 寄存器处理 8 个 ints。它还完全展开循环,因为迭代计数是恒定的并且不会太大。

void foo(
            int *restrict x,
            const int *restrict y,
            const int *restrict z,
            int *restrict p,
            const int *restrict q
        ) {
    for (int i = 0; i < 100; i++) { 
        p[i] = x[21 + i] + q[i];
        x[20 + i] = y[i] * z[i];
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-21
    • 2012-09-24
    • 2018-12-08
    相关资源
    最近更新 更多