title: offset parameter of curand_init
body: <p>I have a problem in understanding the offset parameter of <code>curand_init</code>.</p>
  
  <p>The <code>cuRAND</code> guide says:</p>
  
  <blockquote>
    <p>The offset parameter is used to skip ahead in the sequence. If offset = 100, the
    first random number generated will be the 100th in the sequence. This allows
    multiple runs of the same program to continue generating results from the same
    sequence without overlap.</p>
  </blockquote>
  
  <p>This seems to be the skipahead concept illustrated in</p>
  
  <pre><code>T. Bradley, J. du Toit, R. Tong, M. Giles, P. Woodhams, "Parallelization Techniques for Random Number Generators", GPU Computing Gems, Emerald Edition.
  </code></pre>
  
  <p>Consider the following code:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;curand.h&gt;
  #include &lt;curand_kernel.h&gt;
  
  #define BLOCKSIZE 256
  
  /**********/
  /* iDivUp */
  /**********/
  int iDivUp(int a, int b){ return ((a % b) != 0) ? (a / b + 1) : (a / b); }
  
  /***********************/
  /* CUDA ERROR CHECKING */
  /***********************/
  #define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
  inline void gpuAssert(cudaError_t code, char *file, int line, bool abort=true)
  {
      if (code != cudaSuccess) 
      {
          fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line); 
          if (abort) exit(code);
      }
  }
  
  /********************************************************/
  /* KERNEL FUNCTION FOR TESTING RANDOM NUMBER GENERATION */
  /********************************************************/
  __global__ void testrand1(unsigned long seed, float *a, int N){
      int idx = threadIdx.x + blockIdx.x * blockDim.x;
      curandState state;
      if (idx &lt; N) {
          curand_init(seed, idx, 0, &amp;state);
          a[idx] = curand_uniform(&amp;state);
      }
  }
  
  /********/
  /* MAIN */
  /********/
  int main() {
  
      const int N = 10;
  
      float *h_a  = (float*)malloc(N*sizeof(float));
      float *d_a; gpuErrchk(cudaMalloc((void**)&amp;d_a, N*sizeof(float)));
  
      testrand1&lt;&lt;&lt;iDivUp(N, BLOCKSIZE), BLOCKSIZE&gt;&gt;&gt;(1234, d_a, N);
      gpuErrchk(cudaPeekAtLastError());
      gpuErrchk(cudaDeviceSynchronize());
  
      gpuErrchk(cudaMemcpy(h_a, d_a, N*sizeof(float), cudaMemcpyDeviceToHost));
  
      for (int i=0; i&lt;N; i++) printf("%i %f\n", i, h_a[i]);
  
      getchar();
  }
  </code></pre>
  
  <p>A run to this code generates:</p>
  
  <pre><code>0 0.145468
  1 0.820181
  2 0.550399
  3 0.294830
  4 0.914733
  5 0.868979
  6 0.321921
  7 0.782857
  8 0.011302
  9 0.285450
  </code></pre>
  
  <p>Now, if I use </p>
  
  <pre><code>curand_init(seed, idx+2, 0, &amp;state);
  </code></pre>
  
  <p>I receive:</p>
  
  <pre><code>0 0.550399
  1 0.294830
  2 0.914733
  3 0.868979
  4 0.321921
  5 0.782857
  6 0.011302
  7 0.285450
  8 0.781606
  9 0.233840
  </code></pre>
  
  <p>which means that the generated sequence starts from the third element of the Random Number Generator (RNG) sequence associated to <code>seed = 1234</code>. According to the definition in the <code>cuRAND</code> guide, I would then say that</p>
  
  <pre><code>curand_init(seed, idx+2, 0, &amp;state);
  </code></pre>
  
  <p>should be equivalent to</p>
  
  <pre><code>curand_init(seed, idx, 2, &amp;state);
  </code></pre>
  
  <p>Unfortunately, if I use the above line, I receive:</p>
  
  <pre><code>0 0.870710
  1 0.511765
  2 0.782640
  3 0.620706
  4 0.554513
  5 0.214082
  6 0.118647
  7 0.993959
  8 0.104572
  9 0.231619
  </code></pre>
  
  <p>different from the above one.</p>
  
  <p>On page <code>11</code> of the same guide, when discussing <code>curand_init()</code>, it is written:</p>
  
  <blockquote>
    <p>The state set up will be the state after <code>2^67 # sequence + offset</code> calls to <code>curand()</code> from the seed state.</p>
  </blockquote>
  
  <p>which I interpret as <code>offset</code> offsets within one of <code>2^67</code> available sequences associated to a specific seed.</p>
  
  <p>Anyone helps me understanding the usage of the <code>offset</code> parameter in <code>curand_init</code>?</p>