【发布时间】:2014-01-23 00:54:37
【问题描述】:
我正在将一些复杂的工程代码移植到 OpenCL,并且遇到了带有双精度数的 select() 三元函数的问题。我现在只使用标量,所以我可以使用简单的 C 三元运算符 ()?:但我计划很快转向向量类型。
我的问题是带有双精度的选择需要(长)类型作为比较,但标量关系函数(例如,isgreater)仅返回(int)双精度。这些函数的原型是...
int isgreater (double a, double b);
longn isgreater (doublen a, doublen b);
double select (double a, double b, long cmp);
doublen select (doublen a, doublen b, longn cmp);
只有当我将 isgreater() 的结果转换为 long 因为 select 需要相同大小的元素类型时,我才能让标量代码在标量模式下编译/运行。
double hi = ...;
double lo = ...;
double res = select (lo, hi, (long)isgreater(T, T_cutoff));
否则,我会收到编译器错误,因为 select 不明确。规范中关于标量和向量双精度的关系掩码类型似乎不匹配。
Q1:这是规范中的疏忽还是实现中的错误? Intel 和 AMD OpenCL 编译器都无法在 CPU 上构建,所以我猜是前者。
Q2:OpenCL 标量关系函数返回 0/1,向量关系函数返回 0/-1(即所有位都设置)。 (int)->(long) 转换似乎与此要求一致,但不是 (int)->(ulong),对吧? (int)->(long) 转换成本高吗?
Q3:当(如果)我切换到向量双精度时,编译器会丢弃不必要的显式转换吗?我想同时保留标量和矢量类型,这样我就可以针对 CUDA GPU 和 SIMD 设备(MIC、CPU)而不必保留两个庞大的代码集。
在这里感谢您的任何建议。
【问题讨论】:
-
在我看来
isgreater(T > T_cutoff)应该是isgreater(T, T_cutoff)。这是笔误吗? -
您可以使用一件事。如果您编写代码以便可以简单地将 double 替换为 double2 ,那么您可以将 long 替换为 long2 等。我忘了在我的回答中提及这一点。
-
谢谢Sharpneli。我现在使用 double2 到 double16(和 long2 到 long16)的向量案例。我最终不得不放置一个#ifdef 语句来处理标量情况(即,将 isgreater() 转换为 long),这非常烦人。我将请求 OpenCL 2.0 规范的功能更新,以支持在选择函数比较中支持对标量 isgreater
() 情况的隐式转换为 long 和/或支持 (int)。我更喜欢后者,因为它匹配常见的 c99 比较函数。