c++ - 如何减少 constexpr 函数的编译时间?
问题描述
假设我们想在编译时构建一个非平凡的表
template<int N, int M>
constexpr auto foo()
{
std::array<std::array<int, N>, M> a = {};
for(int m = 1; m < M; m++)
for(int n = 1; n < N; n++)
{
// For exposition only
auto x = (m ^ 42) + (n << 3) - m;
auto y = (n ^ 420) + (m % 420);
a[m][n] = (a[(x + m) % m][(y + n) % n] + (x ^ y)) % 0xFACADE;
}
return a;
}
constexpr auto bar(int n, int m)
{
constexpr auto dim = /* something */;
constexpr auto table = foo<dim, dim>();
return table[n][m];
}
将编译时间推到最高点并不需要太多。另一种方法是通过脚本将表格生成为源代码,这显然不太好。
如何减少此类函数的编译时间?
一些动机
constexpr
函数与常规函数有很大不同,与常规函数相比极其缓慢。除了由编译器执行之外,它们还有边界检查、溢出检查和几乎所有防止 UB 的检查。我怀疑这会使从常规函数中收集的大多数直觉变得毫无用处。
解决方案
我想编译器只是优化了以下几点,所以你可能没有任何优势,但是:
1)m ^ 42
并且m % 420
不依赖于n
,因此您可以在内部循环之外计算它们
2)如果我没记错的话,
(x + m) % m == x % m + m % m
== x % m + 0
== x % m
和
(y + n) % n == y % n + n % n
== y % n + 0
== y % n
3)您可以尝试将一些添加const
到auto
变量中。
所以你可以试试
template <int N, int M>
constexpr auto foo ()
{
std::array<std::array<int, N>, M> a = {};
for(int m = 1; m < M; m++)
{
auto const m42 = m ^ 42;
auto const m420 = m % 420;
for(int n = 1; n < N; n++)
{
// For exposition only
auto const x = m42 + (n << 3) - m;
auto const y = (n ^ 420) + m420;
a[m][n] = (a[x % m][y % n] + (x ^ y)) % 0xFACADE;
}
}
return a;
}
如果这可行,您可以尝试重新处理x % m
,拆分x
不依赖于n
( m42 - m
) 的组件和依赖的组件 ( n << 3
),这样您就可以计算x % m
内部循环外部的一部分。
推荐阅读
- javascript - “动态”加载带有 html5 视频的 Flickity corousel
- datatables - 数据表只显示表头,但不显示 SQL 表中的数据
- javascript - 有问题确定表之间的关系(多对多或一对一)
- python - Count Name 列表(与 Number 混合)
- android - 滚动进出视图时,TextureView isAvailable 偶尔为假
- php - 在 FormRequest 和验证中被认为是空的字段
- c# - 在实体框架核心中执行业务规则
- php - 设置一个 cronjob 来运行一个 php 文件并更改我的 sql 数据库
- ms-access - VBA 无法从查询中找到日期字段
- mysql - 如何让 SQL SELECT 仅显示在 WHERE 子句中触发结果的列