Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
8 years ago

Parallel accesses to banked local memory

I've been attempting to bank local memory so that I can perform parallel access. I can't seem to get it to work. The compiler always either replicates the memory or generates the memory bank with stalls. I don't understand why the code snippet below doesn't generate a number of parallel BRAMs capable of being accessed concurrently.

# define L 64

__kernel __attribute__((task))

void test(

__global char * restrict message,

__global char * restrict decodedData

)

{

local char __attribute__((numbanks(L),

bankwidth(1))) msgMem[L][256];

int __attribute((register)) Lrji_row_sum[L];

//store data across L memory banks

for(uint k=0; k<256; k++)

{

for(uint r=0; r<L; r++)

{

msgMem[r][k]=message[(k*L)+r];

}

}

mem_fence(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE);

//accumulator for each memory bank

for(uint i=0; i<256; i++)

{

# pragma unroll

for(uint r=0; r<L; r++)

{

Lrji_row_sum[r]=msgMem[r][i];

}

}

for(uint r=0; r<L; r++)

{

decodedData[r] = Lrji_row_sum[r];

}

}

I'm using Quartus 17.0.1

Appreciate the help,

Jason

2 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    You are unrolling the loop that reads from the local memory buffer, but the unrolling is done on the first dimension of the local buffer rather than the second one. Because of this, the accesses to the local buffer cannot be coalesced and the compiler instantiates 64 reads from that buffer which results in a very high replication factor. If you swap the dimensions of this buffer, your problem will be solved:

    msgMem[r][k]=message[(k*L)+r]; --> msgMem[k][r]=message[(k*L)+r];

    Lrji_row_sum[r]=msgMem[r]; --> lrji_row_sum[r]=msgmem[r];

    This way, you can also unroll the write loop to get large coalesced accesses to both global and local memory which allows you to better use the global memory bandwidth without any extra local memory replication.

    P.S. Barrier are not needed in task kernels since there is no threading/scheduling in this kernel type.