title: Is the C++ AMP library useful from F#?
body: <p>I'm experimenting with the C++ AMP library in F# as a way of using the GPU to do work in parallel. However, the results I'm getting don't seem intuitive.</p>
  
  <p>In C++, I made a library with one function that squares all the numbers in an array, using AMP:</p>
  
  <pre><code>extern "C" __declspec ( dllexport ) void _stdcall square_array(double* arr, int n)
  {
  // Create a view over the data on the CPU
      array_view&lt;double,1&gt; dataView(n, &amp;arr[0]);
  
  // Run code on the GPU
      parallel_for_each(dataView.extent, [=] (index&lt;1&gt; idx) restrict(amp)
      {
          dataView[idx] = dataView[idx] * dataView[idx];
      });
  
  // Copy data from GPU to CPU
      dataView.synchronize();
  }
  </code></pre>
  
  <p>(Code adapted from Igor Ostrovsky's <a href="https://blogs.msdn.com/b/pfxteam/archive/2011/09/21/10214538.aspx?Redirected=true" rel="nofollow">blog</a> on MSDN.)</p>
  
  <p>I then wrote the following F# to compare the Task Parallel Library (TPL) to AMP:</p>
  
  <pre><code>// Print the time needed to run the given function
  let time f =
      let s = new Stopwatch()
      s.Start()
      f ()
      s.Stop()
      printfn "elapsed: %d" s.ElapsedTicks
  
  module CInterop =
      [&lt;DllImport("CPlus", CallingConvention = CallingConvention.StdCall)&gt;]
      extern void square_array(float[] array, int length)
  
  let options = new ParallelOptions()
  let size = 1000.0
  let arr = [|1.0 .. size|]
  // Square the number at the given index of the array
  let sq i =
      do arr.[i] &lt;- arr.[i] * arr.[i]
      ()
  // Square every number in the array using TPL
  time (fun() -&gt; Parallel.For(0, arr.Length - 1, options, new Action&lt;int&gt;(sq)) |&gt; ignore)
  
  let arr2 = [|1.0 .. size|]
  // Square every number in the array using AMP
  time (fun() -&gt; CInterop.square_array(arr2, arr2.Length))
  </code></pre>
  
  <p>If I set the array size to a trivial number like 10, it takes the TPL ~22K ticks to finish, and AMP ~10K ticks. That's what I expect. As I understand it, a GPU (hence AMP) should be better suited to this situation, where the work is broken into very small pieces, than the TPL.</p>
  
  <p>However, if I increase the array size to 1000, the TPL now takes ~30K ticks and AMP takes ~70K ticks. And it just gets worse from there. For an array of size 1 million, AMP takes nearly 1000x as long as the TPL.</p>
  
  <p>Since I expect the GPU (i.e. AMP) to be better at this kind of task, I'm wondering what I'm missing here.</p>
  
  <p>My graphics card is a GeForce 550 Ti with 1GB, not a slouch as far as I know. I know there's overhead in using PInvoke to call into the AMP code, but I expect that to be a flat cost that is amortized over larger array sizes. I believe the array is passed by reference (though I could be wrong), so I don't expect any cost associated with copying that.</p>
  
  <p>Thank you to everyone for your advice.</p>