# Fast tile search

**URL:** https://discourse.julialang.org/t/fast-tile-search/89821
**Category:** GPU
**Created:** [November 5, 2022, 7:19pm UTC](https://discourse.julialang.org/t/fast-tile-search/89821 "2022-11-05T19:19:53Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![00shiv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/00shiv/32/8903_2.png) [@00shiv](https://discourse.julialang.org/u/00shiv)
#### Post date: [November 5, 2022, 7:19pm UTC](https://discourse.julialang.org/t/fast-tile-search/89821/1 "2022-11-05T19:19:53Z")

</div>

The following code (using Tullio.jl):

```julia
@tullio dists[u,v,n] := abs( query[i, j, ch] - images[u+i-1, v+j-1, ch, n] )

```

is very fast on my AVX512 capable 4-core CPU.

I would like to run this even faster on my CUDA capable GPU. However all my naive attempts:

- using Tullio itself
- using `mapreduce` in various ways
- kernel code with `images[:,:,:,n]` being treated on thread `n`

all gave essentially a 10x **slower** code.

For reference query is typically around 10x10x3 and images is around 32x32x3x20000.

Before I dig further into GPU programming I am wondering if I can get some sage advice on this forum.

Thanks.  
–shiv–

---

<div class="post-metadata">

### Author: ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)
#### Post date: [November 7, 2022, 9:39am UTC](https://discourse.julialang.org/t/fast-tile-search/89821/2 "2022-11-07T09:39:37Z")

</div>

I have zero experience with GPU programming in Julia. However, generally, if the computation is very simple, it can be more expensive to _transfer the data to the GPU memory_ and perform the computation on GPU than to perform the computation on CPU directly. I am not sure this is the case though.

---

<div class="post-metadata">

### Author: ![00shiv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/00shiv/32/8903_2.png) [@00shiv](https://discourse.julialang.org/u/00shiv)
#### Post date: [November 7, 2022, 2:50pm UTC](https://discourse.julialang.org/t/fast-tile-search/89821/3 "2022-11-07T14:50:36Z")

</div>

Thanks for the suggestion. I timed the code for multiple runs after all the memory was copied over. I still had a 10x slow down over the CPU. I did notice that in the kernel code if I deliberately introduce a bug and replace images[i+p-1,j+q-1,ch,n] by images[i+p-1,j+q-1,ch] (notice lack of 4th index), then the GPU code is indeed faster than the CPU code. My guess was that this indicates that the memory access pattern inside my kernel code was probably not done the right way. But I have no idea what the right way is!

---

<div class="post-metadata">

### Author: ![00shiv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/00shiv/32/8903_2.png) [@00shiv](https://discourse.julialang.org/u/00shiv)
#### Post date: [November 11, 2022, 6:29pm UTC](https://discourse.julialang.org/t/fast-tile-search/89821/4 "2022-11-11T18:29:10Z")

</div>

I browsed through some other posts here and guessed that much of the slow down could be because the `query` tile is shared among all threads. So I thought I should put it in dynamic (as I don’t have a static size) shared memory. The documentation in CUDA.jl was not very clear about how to do this, but I tried something and got the following error:

error: :1:16: invalid register name  
mov.u32 %edx, %dynamic\_smem\_size;

I can clean up and post my code if needed, but does anyone have any advice before I do that?  
Thanks.  
–shiv–

---

<div class="post-metadata">

### Author: ![00shiv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/00shiv/32/8903_2.png) [@00shiv](https://discourse.julialang.org/u/00shiv)
#### Post date: [November 11, 2022, 7:23pm UTC](https://discourse.julialang.org/t/fast-tile-search/89821/5 "2022-11-11T19:23:01Z")

</div>

Does anyone know if the techniques on dynamic shared memory from this old thread:

> [@Thinking through distance matrix calculation](https://discourse.julialang.org/t/thinking-through-distance-matrix-calculation/3725/6):
>
> Note that GPU arrays are tied to the Julia GC, and are freed after they go out of scope on the host, so that might be your problem. That means you need to keep data that is alive on the GPU, alive on the CPU as well. Lastly, because there’s no way for us to indicate GPU memory pressure to the Julia GC, you might need to manually finalize(arr) at some points. I played some more with the example, now also mapping the outer loop into the GPU’s execution model (makes the code cleaner) and introduc…

are still valid in 1.8.2?  
Thanks.  
–shiv–

---

<div class="post-metadata">

### Author: ![00shiv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/00shiv/32/8903_2.png) [@00shiv](https://discourse.julialang.org/u/00shiv)
#### Post date: [November 11, 2022, 7:46pm UTC](https://discourse.julialang.org/t/fast-tile-search/89821/6 "2022-11-11T19:46:07Z")

</div>

I realized my mistake and fixed the crash. CuDynamicSharedArray has to be called from inside the device code. The examples helped me.  
However the code is still 10x slower. Maybe this is a case where AVX512 is just better?  
–shiv–

---

<div class="post-metadata">

### Author: ![roflmaostc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roflmaostc/32/30123_2.png) [@roflmaostc](https://discourse.julialang.org/u/roflmaostc)
#### Post date: [November 11, 2022, 10:56pm UTC](https://discourse.julialang.org/t/fast-tile-search/89821/7 "2022-11-11T22:56:49Z")

</div>

Just a few hints, since I had similar tasks in the past:

- Tullio is crazily fast and speedup can be for those array sizes sometimes only a factor of 10 with CUDA. (what is your GPU btw?)
- did you use Float32?
- can you post a full MWE? Then we could run your code directly. That’s probably one reason why we don’t see many replies.
