【发布时间】:2020-08-13 23:29:11
【问题描述】:
我正在开发一个high-performance parallel computational fluid dynamics code,它涉及很多轻量级循环,因此如果所有重要循环都完全展开,性能会提高大约 30%。
这可以通过使用编译器指令轻松地为固定数量的循环完成:#pragma GCC unroll (16) 被我的目标编译器识别,英特尔 C++ 编译器 ICC 和 GCC,而 @987654323 @ 遗憾地被 GCC 忽略了。例如,我还可以将 模板参数或预处理器指令作为限制与 ICC (similar to what you can do with nvcc) 一起使用
template <int N>
// ...
#pragma unroll (N)
for (int i = 0; i < N; ++i) {
// ...
}
或
#define N 16
#pragma unroll (N)
for (int i = 0; i < N; ++i) {
// ...
}
使用 ICC 编译时使用 -Wall -w2 -w3 不会引发错误或警告,而使用 GCC (-Wall -pedantic) 的补充语法 #pragma GCC unroll (N) 在 Ubuntu 18.04 中的 GCC 9.2.1 20191102 中会引发错误:
error: ‘#pragma GCC unroll’ requires an assignment-expression that evaluates to a non-negative integral constant less than 65535
#pragma GCC unroll (N)
有人知道基于模板参数和编译器指令的循环展开以可移植的方式工作(至少与 GCC 和 ICC 一起工作)的方法吗?我实际上只需要完全展开整个循环,所以像#pragma GCC unroll (all) 这样的东西已经对我有很大帮助了。
我知道unroll loops with template meta-programming 存在或多或少复杂的策略,但在我的应用程序中,循环可能是嵌套的并且可以包含更复杂的循环体,我觉得这样的策略会使我的代码过于复杂并减少可读性。
【问题讨论】:
-
用于完全展开给定循环的惯用 GCC 方法,不幸的是,afaik 是一种推送/弹出选项方法,
#pragma GCC push_options,#pragma GCC optimize ("unroll-loops"),for ...,#pragma GCC pop_options,这将但是,不能与 ICC 一起移植。
标签: c++ gcc hpc icc loop-unrolling