目前,如果 p_N 被定义为 5,那么当内核被解析并输出时,p_N 的所有实例都被 5 替换。
添加解析器选项会很有用,以便#defines 包含在生成的源代码中,而编译器变量(如 p_N)留在生成的源代码中。
这将使生成的代码更易于阅读。
不幸的是,所有定义都需要扩展以应用代码转换
#define
值可以在两个地方找到
> head ~/.occa/cache/c8141715ac4e4272/raw_source.cpp
#define block 256
/* The MIT License (MIT)
*
> cat ~/.occa/cache/c8141715ac4e4272/build.json | jq .kernel.props.defines
{
"block": 256
}
我同意这样做对提取实际循环边界很有用,我想解析器就是为此而设计的。 但是,在代码中保留定义似乎不太可能。 跟踪值的计算方式将避免打印其数值的需要。
维护代码和转换它比看起来更难
定义可以是任何东西,甚至是部分代码
#define foo 3 +
for (int i = 0; i < foo 5; ++i) {}
保留#define
行也会导致问题,因为编译器仍将运行预处理器
...如果Define 只是一个数字常数...?
......为什么我们需要额外的逻辑......?
这是输出内核的示例
extern "C" __global__ void _occa_ellipticPreconCoarsenHex3D_0(const int Nelements,
const double * __restrict__ R,
const double * __restrict__ qf,
double * __restrict__ qc) {
{
int e = 0 + blockIdx.x;
__shared__ double s_qfff[8][8][8];
__shared__ double s_qcff[2][8][8];
__shared__ double s_qccf[2][2][8];
__shared__ double s_qccc[2][2][2];
__shared__ double s_R[2][8];
{
int k = 0 + threadIdx.z;
{
int j = 0 + threadIdx.y;
{
int i = 0 + threadIdx.x;
const int id = i + j * 8 + k * 8 * 8 + e * 512;
s_qfff[k][j][i] = qf[id];
if ((k == 0) && (j < 2)) {
s_R[j][i] = R[j * 8 + i];
}
}
}
}
内核正在失去翻译的可读性。 所有这些数字都是定义。
退后一步,功能请求的原因是
使生成的代码更易于阅读
生成的代码是供编译器使用的,而不是供用户使用的(类似于编译器的预处理输出)。 如果存在解析问题,特别是由于解析器尚未成熟,它可能有助于查看。 但是,这些问题应该随着时间的推移而得到解决。
如果目的是让调试更容易,我同意我们应该添加#line
以匹配原始源代码
我同意调试这将是一个真正的奖励 - 好主意!
我应该更清楚地了解这个请求背后的原因:我为 OCCA 1.0 中的新代码生成工具设想的一个重要用例是作为从 OKL 到非 OCCA 应用程序的本地线程语言的翻译器。 在这种情况下,保持可读性很重要,因为生成的 CUDA/OpenCL/HIP/OpenMP 代码将与 OKL 代码分开。
这听起来很合理
有一些功能需要首先添加
#define
传递的数字定义创建全局变量#defines
做到这一点太困难了,因为我们需要跟踪它们的定义位置以及它们在转换后触及的范围parser::getExpression
期间,将constexpr
替换为它们的值const
变量constexpr
函数#define
行添加到顶部感谢您考虑功能请求!
最有用的评论
这听起来很合理
有一些功能需要首先添加
#define
传递的数字定义创建全局变量#defines
做到这一点太困难了,因为我们需要跟踪它们的定义位置以及它们在转换后触及的范围parser::getExpression
期间,将constexpr
替换为它们的值const
变量constexpr
函数#define
行添加到顶部