This is the second in a series of posts looking at our current ArrayFire <a href="http://www.accelereyes.com/arrayfire/c/examples.htm" target="_blank">examples</a>. The code can be compiled and run from <code>arrayfire/examples/</code> when you <a href="http://www.accelereyes.com/download_arrayfire">download</a> and install the ArrayFire library. Today we will discuss the examples found in the <code>benchmarks/</code> directory.

In these examples, my machine has the following configuration:
<pre class="lang:default highlight:0 decode:true">ArrayFire v1.9 (build XXXXXXX) by AccelerEyes (64-bit Linux)
License: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
CUDA toolkit 5.0, driver 304.54
GPU0 Quadro 6000, 6144 MB, Compute 2.0 (single,double)
Display Device: GPU0 Quadro 6000
Memory Usage: 5549 MB free (6144 MB total)...</pre>
<a href="http://www.accelereyes.com/arrayfire/c/examples_2benchmarks_2blas_8cpp-example.htm"><strong>Blas</strong></a>

This example shows a simple bench-marking process using ArrayFire's matrix multiply routine. For more information on <em>Blas</em>, click <a href="http://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms">here</a>. The data measured in this example is the Giga-Flop (GFLOP <em>Floating Point Operations Per Second</em>). I got the following results using the example code on my machine:
<pre class="lang:default highlight:0 decode:true">GPU0 Quadro 6000, 6144 MB, Compute 2.0 (single,double)
Display Device: GPU0 Quadro 6000
Memory Usage: 5543 MB free (6144 MB total)
128 x 128: 124 Gflops
256 x 256: 283 Gflops
384 x 384: 478 Gflops
512 x 512: 483 Gflops
640 x 640: 583 Gflops
768 x 768: 628 Gflops
896 x 896: 646 Gflops
1024 x 1024: 647 Gflops
1152 x 1152: 648 Gflops
1280 x 1280: 658 Gflops
1408 x 1408: 659 Gflops
1536 x 1536: 668 Gflops
1664 x 1664: 673 Gflops
1792 x 1792: 674 Gflops
1920 x 1920: 677 Gflops
2048 x 2048: 676 Gflops</pre>
Just for fun, I wrote a small program to perform a simple matrix multiply using the CPU in a triple-for loop (a pretty standard, but non-optimized solution). This basic algorithm has a run-time of O(n^3). Here is what I got measuring the same benchmark using my simple algorithm:
<pre class="lang:default highlight:0 decode:true">128 x 128: 1 Mflops
256 x 256: 1 Mflops
...</pre>
As you can see, I got bored fast waiting for my CPU to do what my GPU did in a matter of seconds! I would have ended up spending a long time waiting for this program to finish running on the CPU. Also notice that I measured the CPU computation in terms of Mega-Flops instead of Giga-Flops. Of course, a real linear algebra library would do much better than my simple routine, but using ArrayFire takes the next step beyond smart algorithms, by taking full advantage of the GPU and parallelism.

<a href="http://www.accelereyes.com/arrayfire/c/examples_2benchmarks_2pi_8cpp-example.htm"><strong>Pi</strong></a>

Pi is a fun little example we use to make comparisons between regular programming, and GPU programming. We use a <a href="http://en.wikipedia.org/wiki/Monte_Carlo_method">Monte-Carlo</a> simulation to estimate Pi - the idea is to take a bunch of random points in the Cartesian plane unit-square, and then count the ratio of points that lie within the unit circle to the points in the square. The process of generating millions of random points, then using the Pythagorean theorem to calculate the hypotenuse is fairly simple math, and can be done in a for loop that counts the number of times the resulting hypotenuse has a length of less than 1 (and therefore lies in the unit circle) and compares it to the total number of points generated:
<pre class="lang:default decode:true">    int count = 0;
    for (int i = 0; i &lt; samples; ++i) {
        float x = float(rand()) / RAND_MAX;
        float y = float(rand()) / RAND_MAX;
        if (sqrt(x*x + y*y) &lt; 1)
            count++;
    }
    return (4.0 * count / samples);</pre>
The ArrayFire version is of course, much simpler:
<pre class="lang:default decode:true">    array x = randu(samples,f32);
    array y = randu(samples,f32);
    return (4.0 * sum&lt;float&gt;(sqrt(x*x + y*y) &lt; 1) / samples);</pre>
The speed difference is huge, here are some of the results I get on my machine:
<pre class="lang:default highlight:0 decode:true">gpu: 0.00635 seconds to estimate pi = 3.1417060
cpu: 1.89067 seconds to estimate pi = 3.1418986
speedup: 297.7433

gpu: 0.00639 seconds to estimate pi = 3.1421003
cpu: 1.84324 seconds to estimate pi = 3.1417162
speedup: 288.457

gpu: 0.00635 seconds to estimate pi = 3.1417060
cpu: 1.83939 seconds to estimate pi = 3.1420715
speedup: 289.6677</pre>
<a href="http://www.accelereyes.com/arrayfire/c/examples_2benchmarks_2pi_cuda_8cu-example.htm"><strong>Pi Cuda</strong></a>

The reason this code example exists is to show you the synthesis between CUDA programming and the ArrayFire library. Of course, we just saw how ArrayFire could calculate Pi just fine all by itself, but in some cases, you will have more complex CUDA routines and need more control. You can still facilitate pieces of your program with the ArrayFire constructs.

For example, although we are using CUDA vectors instead of ArrayFire arrays, we can still take advantage of the ArrayFire library to <a href="http://www.accelereyes.com/arrayfire/c/group__random__ptr.htm#ga30f0770ad54d1439191ce6057c49cc43">populate</a> these vectors with random numbers:
<pre class="lang:default mark:5-6 decode:true">float *d_x = NULL, *d_y = NULL;
unsigned bytes = sizeof(float) * n;
CUDA(cudaMalloc(&amp;d_x, bytes));
CUDA(cudaMalloc(&amp;d_y, bytes));
AF(af_randu_S(d_x, n));
AF(af_randu_S(d_y, n));</pre>
... and take the <a href="http://www.accelereyes.com/arrayfire/c/group__summul__ptr.htm#gaefb2415d321af39e1bbbd8eeb4cd6e3c">sum of the elements</a> of a vector:
<pre class="lang:default mark:2 decode:true">    float h_result;
    AF(af_sum_vector_S(&amp;h_result, n, d_inside));</pre>
One last insight that we can gain from this example is just how much simpler ArrayFire makes GPU programming. Compare this example, to the regular Pi example above, and you can see that ArrayFire abstracts away a lot of initialization/boilerplate coding. There are a lot of lines of code required to set-up devices, allocate memory, manage memory, and handle errors that you don't have to worry about when you are using the ArrayFire library.

So go for it, <a href="http://www.accelereyes.com/download_arrayfire">download</a> the ArrayFire library and see how fast your computer can go!

---

<strong>Posts in this series:</strong>
<ol>
	<li><a href="http://blog.accelereyes.com/blog/2013/03/04/arrayfire-examples-part-1-of-8-getting-started/">ArrayFire Examples (Part 1 of 8) – Getting Started</a></li>
	<li><a href="http://blog.accelereyes.com/blog/2013/03/06/arrayfire-examples-part-2-of-8-benchmarks/">ArrayFire Examples (Part 2 of 8) – Benchmarks</a></li>
	<li><a href="http://blog.accelereyes.com/blog/2013/03/25/arrayfire-examples-part-3-of-8-financial/">ArrayFire Examples (Part 3 of 8) – Financial</a></li>
	<li><a href="http://blog.accelereyes.com/blog/2013/04/16/arrayfire-examples-part-4-of-8-image-processing">ArrayFire Examples (Part 4 of 8) - Image Processing</a></li>
	<li><a href="http://blog.accelereyes.com/blog/2013/06/05/arrayfire-examples-part-5-of-8-machine-learning/">ArrayFire Examples (Part 5 of 8) - Machine Learning</a></li>
	<li><a href="http://blog.accelereyes.com/blog/2013/06/12/arrayfire-examples-part-6-of-8-multiple-gpus/">ArrayFire Examples (Part 6 of 8) - Multiple GPU</a></li>
	<li><a href="http://blog.accelereyes.com/blog/2013/07/03/arrayfire-examples-part-7-of-8-pde/">ArrayFire Examples (Part 7 of 8) - PDE</a></li>
</ol>
&nbsp;
<h6 class="zemanta-related-title" style="font-size: 1em;">Related articles</h6>
<ul class="zemanta-article-ul zemanta-article-ul-image" style="margin: 0; padding: 0; overflow: hidden;">
	<li class="zemanta-article-ul-li-image zemanta-article-ul-li" style="padding: 0; background: none; list-style: none; display: block; float: left; vertical-align: top; text-align: left; width: 84px; font-size: 11px; margin: 2px 10px 10px 2px;"><a style="box-shadow: 0px 0px 4px #999; padding: 2px; display: block; border-radius: 2px; text-decoration: none;" href="http://blog.accelereyes.com/blog/2013/03/04/arrayfire-examples-part-1-of-8-getting-started/" target="_blank"><img style="padding: 0; margin: 0; border: 0; display: block; width: 80px; max-width: 100%;" alt="" src="http://i.zemanta.com/149709769_80_80.jpg" /></a><a style="display: block; overflow: hidden; text-decoration: none; line-height: 12pt; height: 80px; padding: 5px 2px 0 2px;" href="http://blog.accelereyes.com/blog/2013/03/04/arrayfire-examples-part-1-of-8-getting-started/" target="_blank">ArrayFire Examples (Part 1 of 8) - Getting Started</a></li>
	<li class="zemanta-article-ul-li-image zemanta-article-ul-li" style="padding: 0; background: none; list-style: none; display: block; float: left; vertical-align: top; text-align: left; width: 84px; font-size: 11px; margin: 2px 10px 10px 2px;"><a style="box-shadow: 0px 0px 4px #999; padding: 2px; display: block; border-radius: 2px; text-decoration: none;" href="http://www.tomshardware.com/news/Kepler-Quadro-geforce-gpu-nvidia,21352.html" target="_blank"><img style="padding: 0; margin: 0; border: 0; display: block; width: 80px; max-width: 100%;" alt="" src="http://i.zemanta.com/149939798_80_80.jpg" /></a><a style="display: block; overflow: hidden; text-decoration: none; line-height: 12pt; height: 80px; padding: 5px 2px 0 2px;" href="http://www.tomshardware.com/news/Kepler-Quadro-geforce-gpu-nvidia,21352.html" target="_blank">Kepler in the Workstation: Nvidia Rolls Out New Quadros</a></li>
	<li class="zemanta-article-ul-li-image zemanta-article-ul-li" style="padding: 0; background: none; list-style: none; display: block; float: left; vertical-align: top; text-align: left; width: 84px; font-size: 11px; margin: 2px 10px 10px 2px;"><a style="box-shadow: 0px 0px 4px #999; padding: 2px; display: block; border-radius: 2px; text-decoration: none;" href="http://hemprasad.wordpress.com/2013/03/04/getting-started-with-cuda/" target="_blank"><img style="padding: 0; margin: 0; border: 0; display: block; width: 80px; max-width: 100%;" alt="" src="http://i.zemanta.com/149542002_80_80.jpg" /></a><a style="display: block; overflow: hidden; text-decoration: none; line-height: 12pt; height: 80px; padding: 5px 2px 0 2px;" href="http://hemprasad.wordpress.com/2013/03/04/getting-started-with-cuda/" target="_blank">Getting Started with CUDA</a></li>
	<li class="zemanta-article-ul-li-image zemanta-article-ul-li" style="padding: 0; background: none; list-style: none; display: block; float: left; vertical-align: top; text-align: left; width: 84px; font-size: 11px; margin: 2px 10px 10px 2px;"><a style="box-shadow: 0px 0px 4px #999; padding: 2px; display: block; border-radius: 2px; text-decoration: none;" href="http://openclnews.com/blog/amd_strengthens_opencl_ecosystem_with_new_tools_for_hpc_that_take_advantage" target="_blank"><img style="padding: 0; margin: 0; border: 0; display: block; width: 80px; max-width: 100%;" alt="" src="http://i.zemanta.com/noimg_9_80_80.jpg" /></a><a style="display: block; overflow: hidden; text-decoration: none; line-height: 12pt; height: 80px; padding: 5px 2px 0 2px;" href="http://openclnews.com/blog/amd_strengthens_opencl_ecosystem_with_new_tools_for_hpc_that_take_advantage" target="_blank">AMD strengthens OpenCL ecosystem with new tools for HPC that take advantage of GPU</a></li>
	<li class="zemanta-article-ul-li-image zemanta-article-ul-li" style="padding: 0; background: none; list-style: none; display: block; float: left; vertical-align: top; text-align: left; width: 84px; font-size: 11px; margin: 2px 10px 10px 2px;"><a style="box-shadow: 0px 0px 4px #999; padding: 2px; display: block; border-radius: 2px; text-decoration: none;" href="http://streamcomputing.eu/blog/2013-01-06/x86-workstation-buying-guide-for-opencl-developers-q1-2013/" target="_blank"><img style="padding: 0; margin: 0; border: 0; display: block; width: 80px; max-width: 100%;" alt="" src="http://i.zemanta.com/138441733_80_80.jpg" /></a><a style="display: block; overflow: hidden; text-decoration: none; line-height: 12pt; height: 80px; padding: 5px 2px 0 2px;" href="http://streamcomputing.eu/blog/2013-01-06/x86-workstation-buying-guide-for-opencl-developers-q1-2013/" target="_blank">X86-workstation buying guide for OpenCL developers, Q1 2013</a></li>
</ul>
<div class="zemanta-pixie" style="margin-top: 10px; height: 15px;"><img class="zemanta-pixie-img" style="border: none; float: right;" alt="" src="http://img.zemanta.com/pixy.gif?x-id=5a61e66e-7eda-4e65-9677-5f1dfe15c63c" /></div>