Repository: JuliaGPU/KernelAbstractions.jl (julia)

Issue:
Can't allocate empty vector anymore with `KernelAbstractions.zeros`.
With `0.9.23` I get:
```julia
julia> KernelAbstractions.zeros(CPU(), Float32, 0)
ERROR: DivideError: integer division error
Stacktrace:
  [1] div
    @ ./int.jl:295 [inlined]
  [2] div
    @ ./div.jl:308 [inlined]
  [3] div
    @ ./div.jl:353 [inlined]
  [4] fld
    @ ./div.jl:319 [inlined]
  [5] mod
    @ ./int.jl:287 [inlined]
  [6] #4
    @ ~/.julia/packages/KernelAbstractions/QE5mt/src/nditeration.jl:121 [inlined]
  [7] ntuple
    @ ./ntuple.jl:48 [inlined]
  [8] partition
    @ ~/.julia/packages/KernelAbstractions/QE5mt/src/nditeration.jl:119 [inlined]
  [9] partition
    @ ~/.julia/packages/KernelAbstractions/QE5mt/src/KernelAbstractions.jl:644 [inlined]
 [10] launch_config
    @ ~/.julia/packages/KernelAbstractions/QE5mt/src/cpu.jl:83 [inlined]
 [11] (::KernelAbstractions.Kernel{…})(::Vector{…}, ::Vararg{…}; ndrange::Int64, workgroupsize::Nothing)
    @ KernelAbstractions ~/.julia/packages/KernelAbstractions/QE5mt/src/cpu.jl:40
 [12] Kernel
    @ KernelAbstractions ~/.julia/packages/KernelAbstractions/QE5mt/src/cpu.jl:39 [inlined]
 [13] zeros(backend::CPU, ::Type{Float32}, dims::Tuple{Int64})
    @ KernelAbstractions ~/.julia/packages/KernelAbstractions/QE5mt/src/cpu.jl:11
 [14] zeros(backend::CPU, T::Type, dims::Int64)
    @ KernelAbstractions ~/.julia/packages/KernelAbstractions/QE5mt/src/KernelAbstractions.jl:495
 [15] top-level scope
    @ REPL[3]:1
```

Pull request:
Fixes #504.

8b94cc693a970b3cd675f827c99b3311d06d0aec introduced this bug. I'm not sure of the best value to return in `default_cpu_workgroupsize` if `ndrange` is zero, but all ones seems to work. I might have not put the tests in the best place, too. Changes are welcome.

Patch:
diff --git a/src/cpu.jl b/src/cpu.jl
index c4afec5c..bae45a3a 100644
--- a/src/cpu.jl
+++ b/src/cpu.jl
@@ -49,7 +49,11 @@ end
 const CPU_GRAINSIZE = 1024 # Vectorization, 4x unrolling, minimal grain size
 function default_cpu_workgroupsize(ndrange)
     # if the total kernel is small, don't launch multiple tasks
-    if prod(ndrange) <= CPU_GRAINSIZE
+    n = prod(ndrange)
+    if iszero(n)
+        # If the ndrange is zero return a workgroupsize of (1, 1,...)
+        return map(one, ndrange)
+    elseif n <= CPU_GRAINSIZE
         return ndrange
     else
         available = Ref(CPU_GRAINSIZE)


Test patch:
diff --git a/test/test.jl b/test/test.jl
index 7269c297..c77d1f1c 100644
--- a/test/test.jl
+++ b/test/test.jl
@@ -296,4 +296,14 @@ function unittest_testsuite(Backend, backend_str, backend_mod, BackendArrayT; sk
         @test KernelAbstractions.default_cpu_workgroupsize((5, 7, 13, 17)) == (5, 7, 13, 2)
     end
 
+    @testset "empty arrays" begin
+        backend = Backend()
+        @test size(allocate(backend, Float32, 0)) == (0,)
+        @test size(allocate(backend, Float32, 3, 0)) == (3, 0)
+        @test size(allocate(backend, Float32, 0, 9)) == (0, 9)
+        @test size(KernelAbstractions.zeros(backend, Float32, 0)) == (0,)
+        @test size(KernelAbstractions.zeros(backend, Float32, 3, 0)) == (3, 0)
+        @test size(KernelAbstractions.zeros(backend, Float32, 0, 9)) == (0, 9)
+    end
+
 end