NVIDIA / NVIDIA/CUDALibrarySamples
cuFFTDx 2d FFT explanation of logical remapping for shared memory based global memory to register memory IO
@mferreravila is already working on this.
Since Mar 3, 2026.
- Dominant language
- Cuda
- Stars
- 2.5k
- Forks
- 478
- PR merge metrics
- No merged PRs in 30d
Description
Hi,
I am trying to understand the thread remapping logic in the shared memory variants of load_strided / store_strided in block_io_generic_strided.hpp of mathdx\25.12\example\cufftdx\05_fft_Xd folder.
My current understanding of the natural thread assignment (used in the non-shared-memory variants and during FFT computation for 1D FFT in introduction_example.cu) is:
threadIdx.x→ thread's position within its FFTthreadIdx.y→local_fft_idblockIdx.x→ block's batch offset
However, in the shared memory variants, the code performs the following remapping before doing the global memory I/O:
const unsigned int tid = threadIdx.x + FFT::working_group::block_dim().x * threadIdx.y;
const unsigned int tidx = tid / FFT::working_group::block_dim().y;
const unsigned int tidy = tid % FFT::working_group::block_dim().y;
unsigned int smem_index = tidx + tidy * FFT::working_group::block_dim().x;
I tried to understand it through with AI, however, I yet to succeed with a clear explanation of this logical mapping.
What I still don't fully understand is:
- What is the concrete motivation for performing this logical mapping at all? In other words, what problem does it solve compared to just using
threadIdx.x / threadIdx.ydirectly for global memory indexing as in the non-smem variants? - After the transpose, the smem index is computed as
tidx + tidy * block_dim().x. Then after__syncthreads(), the read phase usesthreadIdx.x + threadIdx.y * block_dim().xwith the same formula. Could you walk through concretely what data each thread writes vs. reads, and why those two different identities (tidx/tidy vs threadIdx.x/threadIdx.y) indexing the same smem layout performs the intended transpose? - Is my understanding of
blockIdx.ycorrect — is it unused / always 0 in this kernel launch configuration, or does it carry meaning?
Thanks in advance for your time!
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.