【问题标题】:OpenCL select() function with double具有双精度的 OpenCL select() 函数
【发布时间】: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 比较函数。

标签: double opencl simd


【解决方案1】:

第一季度: 我想说的是,没有将 isgreater 的结果隐式转换为 long 是规范中的疏忽。

在单元素情况下,选择应该与三元运算符完全一样。这也是 isgreater 在标量情况下返回 1 的原因。基本上 isgreater 应该与使用标量运算符时的 > 完全一样。

在矢量化的情况下,select 查看 MSB,这就是 isgreater 返回 -1 的原因(所有位为 1,因此 MSB 自然也是 1)。

Q2:Int long 转换根本不应该是昂贵的。最多只需要 1 条额外的指令。

第三季度: 它不是。

这个问题令人讨厌地阻止了编写从 1 到 n 个元素向量化的代码,它需要对标量情况进行特殊处理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-17
    • 1970-01-01
    • 2015-05-17
    • 1970-01-01
    • 2016-04-18
    • 2011-04-06
    • 1970-01-01
    • 2019-12-02
    相关资源
    最近更新 更多