cuda - 任何人都可以帮助我了解 cuda 的 atomicmin 函数语法吗?
问题描述
我无法获得正确的语法来使用atomicMin
. 我想用这个函数对双精度而不是整数进行操作。
__global__ void npd(int *a, int *g)
{
int index = threadIdx.x;
__shared__ int d[N];
d[threadIdx.x]=a[index];
__syncthreads();
int dd;
int inn;
int u;
if( 0==threadIdx.x )
{
for( int u = 0; u<16; u++ )
{
atomicMin( g, d ) ;
}
}
}
解决方案
CUDA 定义的atomicMin
函数不支持使用浮点数。参考文档,我们看到唯一可用的原型是、和(最后一个需要在计算能力为 3.5 或更高的 GPU 上编译和运行)。int
unsigned int
unsigned long long int
至少有2个选项。
这是一种可能的实现,对于double
:
__device__ double atomicMin_double(double* address, double val)
{
unsigned long long int* address_as_ull = (unsigned long long int*) address;
unsigned long long int old = *address_as_ull, assumed;
do {
assumed = old;
old = atomicCAS(address_as_ull, assumed,
__double_as_longlong(fmin(val, __longlong_as_double(assumed))));
} while (assumed != old);
return __longlong_as_double(old);
}
这个相关的问题和答案也可能很有趣,尽管它主要是float
考虑到的。
其他一些评论:
通过切换到
float
而不是double
我相信可以简化atomicMin
(或atomicMax
)操作,如我在上面链接的答案中所示,可能有一些警告(例如,没有 NaN、INF 数据)。我相信 iee754float
遵循两个数量的排序规则A
,B
如果A > B
, then*reinterpret_cast<int*>(&A) > *reinterpret_cast<int*>(&B)
。我不确定是否double
遵循类似的规则long long
(可能其他人会说)。在您的代码中,此循环可以首先对本地数量进行操作,然后在最后执行单个原子操作,如下所示:
double v = *g; for( int u = 0; u<16; u++ ) { v = min(v,d); } atomicMin_double(g, v);
我认为应该更快
推荐阅读
- java - Spring Boot oath2 访问令牌无效
- html - 子菜单文本和背景 css 不同步
- shopware - 如何在插件中要求作曲家包?
- c# - Entity Framework Core:通过导航属性组合主键
- node.js - 错误 400:invalid_request 缺少必需参数:范围
- ios - “日期”类型的值没有成员“格式”和“日期”类型的值没有成员“小时”
- c# - 如何在一个表单中打开多个表单
- elasticsearch - 如何在弹性搜索中获得可能的关键字组合
- amazon-web-services - Terraform 从非对称 KMS 密钥对获取公钥
- flutter - 颤振:抛出另一个异常:RenderPointerListener 对象在布局期间被赋予了无限大小