如何在避免溢出的同时将 abs2 应用于 CuArray{Complex{Int8}}

How to apply `abs2` to a `CuArray{Complex{Int8}}` while avoiding overflow

这个问题出现在 julialang Slack 服务台频道


如何计算 Complex{Int8} 数组的 abs2 且元素不超过 Int8 的最大值且不增加 CPU->GPU 传输时间?我有两个预分配的 CuArrays eltype Complex{Int8}Int32。复数数组abs2的结果应该存放在Int32CuArray.

由于 julia 的通用接口,答案与 CPU 上的答案基本相同。

using CUDA

let v = CUDA.rand(Complex{Int8}, 10)
    u = CUDA.zeros(Int32, length(v))
    u .= abs2.(Complex{Int32}.(v))
end
10-element CuArray{Int32,1}:
   424
 16201
 18253
  1305
 19109
 13322
  8948
 18401
  8840
   628

在此代码段中,我使用 broadcastingu 的每个元素转换为 Complex{Int32},然后对其应用 abs2 并将结果存储在 u.多亏了广播语义,上面的所有循环都被融合了,所以没有创建临时循环。

另外,这可以通过就地映射来实现,


let v = CUDA.rand(Complex{Int8}, 10)
    u = CUDA.zeros(Int32, length(v))
    map!(x -> abs2(Complex{Int32}(x)), u, v)
end
10-element CuArray{Int32,1}:
 12682
  5821
 12676
 19061
  6025
   433
  8609
   205
  2125
 11169