# What is the recommended type \<: Integer to use when doing index arithmetics?

**URL:** <https://discourse.julialang.org/t/what-is-the-recommended-type-integer-to-use-when-doing-index-arithmetics/12560>\
**Category:** GPU\
**Tags:** cudanative\
**Created:** [July 21, 2018, 2:33pm UTC](https://discourse.julialang.org/t/what-is-the-recommended-type-integer-to-use-when-doing-index-arithmetics/12560 "2018-07-21T14:33:31Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Lian\_Yunlong](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lian_yunlong/32/14437_2.png) [@Lian\_Yunlong](https://discourse.julialang.org/u/Lian_Yunlong)\
**Post date:** [July 21, 2018, 2:33pm UTC](https://discourse.julialang.org/t/what-is-the-recommended-type-integer-to-use-when-doing-index-arithmetics/12560/1 "2018-07-21T14:33:31Z")

</div>

Hi,

I have to compute the linear index in a CUDAnative kernel. I went to the source code `pointer.jl` in `CUDAnative.jl` but wasn’t able to get a clue. It seems to me that `unsafe_cached_load` deals with integers carefully, but it is a delicate issue.

My question is about the recommended type of integer to pass TO THE CUDANATIVE KERNEL for computation. For example, in the kernel I am currently optimizing, I pass the IJV-representation of a sparse matrix directly into the kernel to instruct the global memory access via the index list `I` and `J`, which are obtained from `findnz`. At first, I naively used `Int64`, but after profiling I found this was a bit stupid. According to `indexing.jl` line 41-61

```julia
for dim in (:x, :y, :z)
    # Thread index
    fn = Symbol("threadIdx_$dim")
    intr = Symbol("tid.$dim")
    @eval @inline $fn() = Int(_index($(Val(intr)), $(Val(0:max_block_size[dim]-1)))) + 1

    # Block size (#threads per block)
    fn = Symbol("blockDim_$dim")
    intr = Symbol("ntid.$dim")
    @eval @inline $fn() = Int(_index($(Val(intr)), $(Val(1:max_block_size[dim]))))

    # Block index
    fn = Symbol("blockIdx_$dim")
    intr = Symbol("ctaid.$dim")
    @eval @inline $fn() = Int(_index($(Val(intr)), $(Val(0:max_grid_size[dim]-1)))) + 1

    # Grid size (#blocks per grid)
    fn = Symbol("gridDim_$dim")
    intr = Symbol("nctaid.$dim")
    @eval @inline $fn() = Int(_index($(Val(intr)), $(Val(1:max_grid_size[dim]))))
end

```

I think it would better be `Int`. On the other hand, according to`unsafe_cached_load` in `pointer.jl` (which is traced back from `ldg()` ), I think I could use anything ☹ I am sure that when `@cuda` generates the kernel code, it won’t convert types as it thinks, it translate the code literally. So if I pass the `I`, `J`, `V` lists to the kernel, the actual type involved in the index arithmetics depends on `eltype(I)` and `eltype(J)`. Then what is the recommended type to choose for less type conversions and (probably) better performance?

Update 1:

By index arithmetics I mean something like

```julia
P_LIN = (iωP-1+(blockIdx().x-1)*dimΩP)*dimH*dimH
Q_LIN = (iωQ-1+(blockIdx().x-1)*dimΩQ)*dimH*dimH
X_LIN = (blockIdx().y-1)*dimX1
Y_LIN = (blockIdx().z-1)*dimY1

```

Update 2:

According to this post,

> **[How to tell if GPU cores are actually 32/64-bit processors](https://forums.developer.nvidia.com/t/how-to-tell-if-gpu-cores-are-actually-32-64-bit-processors/47889)**
>
> Is there a way to tell if the internal GPU core is a 32/64 bit processor? In my case, the GPU is Nvidia Tesla K80. But I am also interested to know that for other GPUs as well. Where to find such information? Is there a command or program to...

if I am sure about the actual range of `P_LIN`, `Q_LIN`, `X_LIN`, `Y_LIN` I’d better use `UInt32`, right? Can this actually invoke the correct “Integer Instructions” (I guess it is `IADD32I`) ?

---

<div class="post-metadata">

**Author:** ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)\
**Post date:** [July 21, 2018, 7:33pm UTC](https://discourse.julialang.org/t/what-is-the-recommended-type-integer-to-use-when-doing-index-arithmetics/12560/3 "2018-07-21T19:33:25Z")

</div>

For portability over distinct sorts of graphics processors and in service of performance, you want to use a 32-bit integer type. Whether or not that is better given as an UInt32 or an Int32 is going to be dependant on the way these things are handled from the gpu side rather than being something to optimize for Julia. We are very good about specializing on e.g. is it an Int32 or a UInt32 for purposes of dispatch. If the gpu is munching on unsigned indices, give it UInt32s and vice-versa.

Do not use an Int or a UInt for this purpose. They are both 32-bit and 64-bit types. You want more specificity when interacting with gpus (irrespective of the host processor’s bitwidth and also irrespective of the gpu’s nominal bitwidth for nonvectorized, nonsimd instructions).

---

<div class="post-metadata">

**Author:** ![Lian\_Yunlong](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lian_yunlong/32/14437_2.png) [@Lian\_Yunlong](https://discourse.julialang.org/u/Lian_Yunlong)\
**Post date:** [July 21, 2018, 9:02pm UTC](https://discourse.julialang.org/t/what-is-the-recommended-type-integer-to-use-when-doing-index-arithmetics/12560/4 "2018-07-21T21:02:42Z")

</div>

Thanks Jeffrey.  
I realized that `UInt` is tricky. `UInt32` makes the code portable, that’s what I want to use.

btw. the diplomatic language is quite Nvidian … 😃

---

<div class="post-metadata">

**Author:** ![maleadt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maleadt/32/10097_2.png) [@maleadt](https://discourse.julialang.org/u/maleadt)\
**Post date:** [July 24, 2018, 6:31am UTC](https://discourse.julialang.org/t/what-is-the-recommended-type-integer-to-use-when-doing-index-arithmetics/12560/5 "2018-07-24T06:31:10Z")

</div>

Generally, you use Int.

> [@Lian\_Yunlong](#):
>
> I have to compute the linear index in a CUDAnative kernel. I went to the source code `pointer.jl` in `CUDAnative.jl` but wasn’t able to get a clue. It seems to me that `unsafe_cached_load` deals with integers carefully, but it is a delicate issue.

`unsafe_cached_load` is a low-level function, but accepts all integers because of the conversion on the last line, `Int(i-one(i))`. In most cases however, these functions are called via indexing, eg. `getindex` → `unsafe_load`, but in the case of `ldg` that isn’t integrated yet. We probably need a separate device array type, a typevar, or a getindex kwarg.

Note that using plain Int’s might result in slightly lower performance, but I’ve decided to go down that road in anticipation of Cassette being able to rewrite Int to eg. Int32. See [Int64 literals vs Int32 constants: avoid conversions & checks · Issue #74 · JuliaGPU/CUDA.jl · GitHub](https://github.com/JuliaGPU/CUDAnative.jl/issues/25#issuecomment-359155011). At the same time, I’ve seen LLVM being better able to optimize redundant -1/+1 arithmetic away when everything is just an integer, so YMMV.
