# Memory Coalescing

**URL:** <https://forums.developer.nvidia.com/t/memory-coalescing/24606>\
**Category:** CUDA Programming and Performance\
**Created:** [October 12, 2011, 6:06pm UTC](https://forums.developer.nvidia.com/t/memory-coalescing/24606 "2011-10-12T18:06:33Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![danielz](https://developer.download.nvidia.com/images/forums/profile-default-devtalk-84.png) [@danielz](https://forums.developer.nvidia.com/u/danielz)\
**Post date:** [October 12, 2011, 6:06pm UTC](https://forums.developer.nvidia.com/t/memory-coalescing/24606/1 "2011-10-12T18:06:33Z")

</div>

I have a variation of the CUDA N-body example, instead of one sub-particle type (one atom), I have two sub-particle types (2 atoms) for each particle (molecule). I use the float3 type to store the x, y, z co-ordinates . I have stored the co-ordinates in memory as follows:

atom0\_mol0 x, atom0\_mol0 y, atom0\_mol0 z  
atom1\_mol0 x, atom1\_mol0 y, atom1\_mol0 z

atom0\_mol1 x, atom0\_mol1 y, atom0\_mol1 z  
atom1\_mol1 x, atom1\_mol1 y, atom1\_mol1 z

Similar to the N-body example, each thread uses its global thread ID to store the co-ordinates for the two atoms in a molecule. And then threads in a block share the task of copying a molecule’s co-ordinates to shared memory (which all the threads will access later) much like the N-body example. In spite of trying a few different access patterns for the loads from the global memory to retrieve the co-ordinates, I have not been able to achieve coalesced accesses in this case (as reported by the Compute Visual Profiler). Any hints on this will be appreciated.

---

<div class="post-metadata">

**Author:** ![tera](https://developer.download.nvidia.com/images/forums/profile-default-devtalk-84.png) [@tera](https://forums.developer.nvidia.com/u/tera)\
**Post date:** [October 12, 2011, 7:38pm UTC](https://forums.developer.nvidia.com/t/memory-coalescing/24606/2 "2011-10-12T19:38:58Z")

</div>

You will probably have to recast temporarily to a different type (float, float2 or float4) to achieve the necessary reshuffling.

---

<div class="post-metadata">

**Author:** ![danielz](https://developer.download.nvidia.com/images/forums/profile-default-devtalk-84.png) [@danielz](https://forums.developer.nvidia.com/u/danielz)\
**Post date:** [October 12, 2011, 8:30pm UTC](https://forums.developer.nvidia.com/t/memory-coalescing/24606/3 "2011-10-12T20:30:16Z")

</div>

> [@](#):
>
> You will probably have to recast temporarily to a different type (float, float2 or float4) to achieve the necessary reshuffling.

I replaced with float4 but that did not help alleviate the coalescing problem. I also tried the following storage pattern:

atom0\_mol0 x atom0\_mol0 y atom0\_mol0 z

atom0\_mol1 x atom0\_mol1 y atom0\_mol1 z

and so on

followed by

atom1\_mol0 x atom1\_mol0 y atom1\_mol0 z

atom1\_mol1 x atom1\_mol1 y atom1\_mol1 z

and so on

I was thinking that in the above case each thread will read the contiguous locations when retrieving the same atom type. I still see CVP reporting non-coalesced accesses.

---

<div class="post-metadata">

**Author:** ![tera](https://developer.download.nvidia.com/images/forums/profile-default-devtalk-84.png) [@tera](https://forums.developer.nvidia.com/u/tera)\
**Post date:** [October 12, 2011, 8:51pm UTC](https://forums.developer.nvidia.com/t/memory-coalescing/24606/4 "2011-10-12T20:51:46Z")

</div>

Casting to float4 alone does not solve the issue either. You also have to reassign the accesses to threads so that each thread reads 4 consecutive floats from memory, with the next thread reading the following 4 floats and so on. Then the optimizer will usually be clever enough to replace these by a single 128 bit/thread memory transaction.

If you are free to rearrange the data in memory, then the simplest thing probably is to just change the layout to this one:

atom0\_mol0 x atom0\_mol1 x atom0\_mol2 x …  
atom1\_mol0 x atom1\_mol1 x atom1\_mol2 x …  
…  
atom0\_mol0 y atom0\_mol1 y atom0\_mol2 y …  
atom1\_mol0 y atom1\_mol1 y atom1\_mol2 y …  
…  
atom0\_mol0 z atom0\_mol1 z atom0\_mol2 z …  
atom1\_mol0 z atom1\_mol1 z atom1\_mol2 z …  
…

It will not automatically lead you 64 bit/thread or 128 bit/thread transactions, but gives coalesced and bank conflict free memory accesses without further thought.

---

<div class="post-metadata">

**Author:** ![danielz](https://developer.download.nvidia.com/images/forums/profile-default-devtalk-84.png) [@danielz](https://forums.developer.nvidia.com/u/danielz)\
**Post date:** [October 14, 2011, 4:11pm UTC](https://forums.developer.nvidia.com/t/memory-coalescing/24606/5 "2011-10-14T16:11:50Z")

</div>

> [@](#):
>
> Casting to float4 alone does not solve the issue either. You also have to reassign the accesses to threads so that each thread reads 4 consecutive floats from memory, with the next thread reading the following 4 floats and so on. Then the optimizer will usually be clever enough to replace these by a single 128 bit/thread memory transaction.
> 
> If you are free to rearrange the data in memory, then the simplest thing probably is to just change the layout to this one:
> 
> atom0\_mol0 x atom0\_mol1 x atom0\_mol2 x …
> 
> atom1\_mol0 x atom1\_mol1 x atom1\_mol2 x …
> 
> …
> 
> atom0\_mol0 y atom0\_mol1 y atom0\_mol2 y …
> 
> atom1\_mol0 y atom1\_mol1 y atom1\_mol2 y …
> 
> …
> 
> atom0\_mol0 z atom0\_mol1 z atom0\_mol2 z …
> 
> atom1\_mol0 z atom1\_mol1 z atom1\_mol2 z …
> 
> …
> 
> It will not automatically lead you 64 bit/thread or 128 bit/thread transactions, but gives coalesced and bank conflict free memory accesses without further thought.

Thanks for the reply. Just to make sure I understand it right, for the NVIDIA Fermi architecture, a warp accesses the memory concurrently, hence, the following

atom0\_mol0 x atom0\_mol1 x atom0\_mol2 x … atom0\_mol31x

So if I have 32 or more threads in a block, in a warp, thread0 accesses atom0\_mol0 x, thread 1 accesses atom0\_mol1x and so on.

the above will be grouped into a (32\*32-bit)/8 = 128B transaction?

Similarly for the other atoms and co-ordinates?

---

<div class="post-metadata">

**Author:** ![tera](https://developer.download.nvidia.com/images/forums/profile-default-devtalk-84.png) [@tera](https://forums.developer.nvidia.com/u/tera)\
**Post date:** [October 15, 2011, 6:34pm UTC](https://forums.developer.nvidia.com/t/memory-coalescing/24606/6 "2011-10-15T18:34:39Z")

</div>

> [@](#):
>
> Thanks for the reply. Just to make sure I understand it right, for the NVIDIA Fermi architecture, a warp accesses the memory concurrently, hence, the following
> 
> atom0\_mol0 x atom0\_mol1 x atom0\_mol2 x … atom0\_mol31x
> 
> So if I have 32 or more threads in a block, in a warp, thread0 accesses atom0\_mol0 x, thread 1 accesses atom0\_mol1x and so on.
> 
> the above will be grouped into a (32\*32-bit)/8 = 128B transaction?
> 
> Similarly for the other atoms and co-ordinates?

Yes.
