Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Sorry, but, to be blunt: this is a horrid way of handling a 3D array: a double-nested loop with a bucketload of calls to <code>malloc()</code>, then triple-indirection to get a value at runtime. Yeuch! :o)</p> <p>The conventional way of doing this (in the HPC community) is to use a one-dimensional array and do the index computation yourself. Suppose index <code>i</code> iterates over <code>nx</code> <em>planes</em> in the <em>x</em> direction, <code>j</code> iterates over <code>ny</code> <em>pencils</em> in the <em>y</em> direction, and <code>k</code> iterates over <code>nz</code> cells in the <em>z</em> direction. Then a pencil has <code>nz</code> elements, a plane has <code>nz*ny</code> elements, and the whole “brick” has <code>nz*ny*nx</code> elements. Thus, you can iterate over the whole structure with:</p> <pre><code>for(i=0; i&lt;nx; i++) { for(j=0; j&lt;ny; j++) { for(k=0; k&lt;nz; k++) { printf("a(%d,%d,%d) = %d\n", i, j, k, a[(i*ny+j)*nz+k]); } } } </code></pre> <p>The advantage of this construction is that you can allocate it with a single call to <code>malloc()</code>, rather than a boatload of nested calls:</p> <pre><code>int *a; a = malloc(nx*ny*nz*sizeof(int)); </code></pre> <p>The construction <code>x=a[i][j][k]</code> has three levels of indirection: you have to fetch an address from memory, <code>a</code>, add an offset, <code>i</code>, fetch that address from memory, <code>a[i]</code>, add an offset, <code>j</code>, fetch that address from memory, <code>a[i][j]</code>, add an offset, <code>k</code>, and (finally) fetch the data, <code>a[i][j][k]</code>. All those intermediate pointers are wasting cache-lines and TLB entries.</p> <p>The construction <code>x=a[(i*ny+j)*nz+k]</code> has <em>one</em> level of indirection at the expense of two additional integer multiplications: compute the offset, fetch address, 'a', from memory, compute and add the offset, (i*ny+j)*nz+k, fetch the data.</p> <p>Furthermore, there is essentially no way <em>whatsoever</em> of improving the triple-indirection method's performance based on data-access patterns. If we were <em>actually</em> visiting every cell, we could do something like this to avoid some of the overhead of index computation.</p> <pre><code>ij = 0; for(i=0; i&lt;nx; i++) { ii=i*ny; for(j=0; j&lt;ny; j++) { ij=(ii+j)*nz; for(k=0; k&lt;nz; k++) { printf("a(%d,%d,%d) = %d\n", i, j, k, a[ij+k]); } } } </code></pre> <p>Depending on what you're doing, this may not be great either, and there all alternative layouts and indexing methods (such as Morton or Ahnenteufel indexing) that may be more suitable, depending on your access patterns. I'm not trying to give a complete treatise on 3D Cartesian grid representation or indexing, merely illustrate that a “three star” solution is very bad for numerous reasons. </p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload