(8834,18528,'2016-05-11 11:29:58','2016-05-11 15:29:58','Continuing our blog series \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" today we will provide an introduction to the core data structure in ArrayFire: the af::array. We describe how to construct arrays, what datatypes arrays support, how to query an array for various properties (content, dimensions), how to write mathematical expressions on arrays.\r\n\r\n<!--more-->\r\n\r\nArrayFire abstracts away much of the details of programming parallel architectures by providing a high-level container object, the <a class=\"el\" href=\"classaf_1_1array.htm\">array</a>, that represents data stored on a CPU, GPU, FPGA, or other type of accelerator. This abstraction permits developers to write massively parallel applications in a high-level language where they need not be concerned about low-level optimizations that are frequently required to achieve high throughput on most parallel architectures.\r\n<h3>Creating ArrayFire Arrays</h3>\r\nArrays represent memory on a supported device. You can create arrays of uninitialized memory using the array constructor:\r\n<pre class=\"lang:c++ decode:true\">// Arrays may be created using the af::array constructor and dimensioned\r\n// as 1D, 2D, 3D; however, the values in these arrays will be undefined\r\narray undefined_1D = array(100);        // 1D array with 100 elements\r\narray undefined_2D = array(10, 100);    // 2D array of size 10 x 100\r\narray undefined_3D = array(10, 10, 10); // 3D array of size 10 x 10 x 10</pre>\r\nOr using one of many constructors that initialize memory:\r\n<pre class=\"lang:default decode:true\">// Create an array of zeros of length three:\r\narray zeros      = constant(0, 3);\r\n\r\n// Generate a 1x4 array of uniformly distributed [0,1] random numbe// using af::randu():\r\narray rand1      = randu(1, 4);\r\n    \r\n// Make a 2x2 array (or matrix, if you prefer) of random numbers\r\n// sampled from a normal distribution using af::randn():\r\narray rand2      = randn(2, 2);\r\n\r\n// Construct a 3x3 identity matrix. \r\narray iden       = af::identity(3, 3);</pre>\r\nLastly, arrays may be populated with data from the host using our copy constructor:\r\n<pre class=\"lang:default decode:true\">// Create a six-element array on the host\r\nfloat hA[] = {0, 1, 2, 3, 4, 5};\r\n    \r\n// Using the array copy constructor, we can create a 2x3\r\n// matrix from this data:\r\narray A(2, 3, hA);</pre>\r\nArrays can also be created from CUDA device pointers or OpenCL memory buffers. Please consult the <a href=\"http://arrayfire.org/docs/gettingstarted.htm\">documentation</a> on these aspects.\r\n<h3>Supported data types</h3>\r\nArrayFire arrays support standard integral and complex data types found in C/C++. The data type for an array is specified by providing an (optional) final parameter to any of the array constructors. The type field and supported types are as follows:\r\n<ul>\r\n 	<li>b8 8-bit boolean values (bool)</li>\r\n 	<li>f32 real single-precision (float)</li>\r\n 	<li>c32 complex single-precision (cfloat)</li>\r\n 	<li>s32 32-bit signed integer (int)</li>\r\n 	<li>u32 32-bit unsigned integer (unsigned)</li>\r\n 	<li>f64 real double-precision (double)</li>\r\n 	<li>c64 complex double-precision (cdouble)</li>\r\n 	<li>s64 64-bit signed integer (intl)</li>\r\n 	<li>u64 64-bit unsigned integer (uintl)</li>\r\n 	<li>s16 16-bit signed integer (short)</li>\r\n 	<li>u16 16-bit unsigned integer (unsigned short)</li>\r\n</ul>\r\nFor example, if you wanted to construct a 2x1 (column vector) of uniformly distributed 32-bit complex numbers (c32 data type), you would use the following code:\r\n<pre class=\"lang:default decode:true\">// Create a 2x1 column vector of uniformly distributed\r\n// 32-bit complex values:\r\narray randcplx   = randu(2, 1, c32);</pre>\r\n&nbsp;','Introduction to the ArrayFire array','','inherit','closed','closed','','8831-revision-v1','','','2016-05-11 11:29:58','2016-05-11 15:29:58','',8831,'http://sandbox.arrayfire.com/8831-revision-v1/',0,'revision','',0),(8835,18528,'2016-05-11 12:28:08','2016-05-11 16:28:08','Continuing our blog series \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" today we will provide an introduction to the core data structure in ArrayFire: the af::array. We describe how to construct arrays, what datatypes arrays support, indexing, how to query an array for various properties (content, dimensions), how to write mathematical expressions on arrays.\r\n\r\n<!--more-->\r\n\r\nArrayFire abstracts away much of the details of programming parallel architectures by providing a high-level container object, the <a class=\"el\" href=\"classaf_1_1array.htm\">array</a>, that represents data stored on a CPU, GPU, FPGA, or other type of accelerator. This abstraction permits developers to write massively parallel applications in a high-level language where they need not be concerned about low-level optimizations that are frequently required to achieve high throughput on most parallel architectures.\r\n<h3>Creating ArrayFire Arrays</h3>\r\nArrays represent memory on a supported device. You can create arrays of uninitialized memory using the array constructor:\r\n<pre class=\"lang:c++ decode:true\">// Arrays may be created using the af::array constructor and dimensioned\r\n// as 1D, 2D, 3D; however, the values in these arrays will be undefined\r\narray undefined_1D = array(100);        // 1D array with 100 elements\r\narray undefined_2D = array(10, 100);    // 2D array of size 10 x 100\r\narray undefined_3D = array(10, 10, 10); // 3D array of size 10 x 10 x 10</pre>\r\nOr using one of many constructors that initialize memory:\r\n<pre class=\"lang:default decode:true\">// Create an array of zeros of length three:\r\narray zeros      = constant(0, 3);\r\n\r\n// Generate a 1x4 array of uniformly distributed [0,1] random numbe// using af::randu():\r\narray rand1      = randu(1, 4);\r\n    \r\n// Make a 2x2 array (or matrix, if you prefer) of random numbers\r\n// sampled from a normal distribution using af::randn():\r\narray rand2      = randn(2, 2);\r\n\r\n// Construct a 3x3 identity matrix. \r\narray iden       = af::identity(3, 3);</pre>\r\nLastly, arrays may be populated with data from the host using our copy constructor:\r\n<pre class=\"lang:default decode:true\">// Create a six-element array on the host\r\nfloat hA[] = {0, 1, 2, 3, 4, 5};\r\n    \r\n// Using the array copy constructor, we can create a 2x3\r\n// matrix from this data:\r\narray A(2, 3, hA);</pre>\r\nArrays can also be created from CUDA device pointers or OpenCL memory buffers. Please consult the <a href=\"http://arrayfire.org/docs/gettingstarted.htm\">documentation</a> on these aspects.\r\n<h3>Supported data types</h3>\r\nArrayFire arrays support standard integral and complex data types found in C/C++. The data type for an array is specified by providing an (optional) final parameter to any of the array constructors. The type field and supported types are as follows:\r\n<ul>\r\n 	<li>b8 8-bit boolean values (bool)</li>\r\n 	<li>f32 real single-precision (float)</li>\r\n 	<li>c32 complex single-precision (cfloat)</li>\r\n 	<li>s32 32-bit signed integer (int)</li>\r\n 	<li>u32 32-bit unsigned integer (unsigned)</li>\r\n 	<li>f64 real double-precision (double)</li>\r\n 	<li>c64 complex double-precision (cdouble)</li>\r\n 	<li>s64 64-bit signed integer (intl)</li>\r\n 	<li>u64 64-bit unsigned integer (uintl)</li>\r\n 	<li>s16 16-bit signed integer (short)</li>\r\n 	<li>u16 16-bit unsigned integer (unsigned short)</li>\r\n</ul>\r\nFor example, if you wanted to construct a 2x1 (column vector) of uniformly distributed 32-bit complex numbers (c32 data type), you would use the following code:\r\n<pre class=\"lang:default decode:true\">// Create a 2x1 column vector of uniformly distributed\r\n// 32-bit complex values:\r\narray randcplx   = randu(2, 1, c32);</pre>\r\n<h3>Indexing</h3>\r\nLike all functions in ArrayFire, indexing is also executed in parallel on the OpenCL/CUDA device. Because of this, indexing becomes part of a JIT operation and is accomplished using parentheses instead of square brackets (i.e. as A(0) instead of A[0]). To index af::arrays you may use one or a combination of the following functions:\r\n<ul>\r\n 	<li>integer scalars</li>\r\n 	<li>seq() representing a linear sequence</li>\r\n 	<li>end representing the last element of a dimension</li>\r\n 	<li>span representing the entire dimension</li>\r\n 	<li>row(i) or col(i) specifying a single row/column</li>\r\n 	<li>rows(first,last) or cols(first,last) specifying a span of rows or columns</li>\r\n</ul>\r\nHere are a few examples of these indexing functions in operation:\r\n<pre class=\"lang:default decode:true\">// Make an 3x3 array containing numbers 1-9:\r\narray A = array(seq(1,9), 3, 3);\r\n\r\nA(0);            // first element\r\nA(0,1);          // first row, second column\r\nA(end);          // last element\r\nA(-1);           // also last element\r\nA(end-1);        // second-to-last element\r\nA(1,span);       // second row\r\nA.row(end);      // last row\r\nA.cols(1,end);   // all but first column</pre>\r\nFor further examples, see the <a href=\"http://arrayfire.org/docs/indexing.htm\">documentation on indexing</a>.\r\n<h3>Querying existing arrays for their properties</h3>\r\nArrayFire array objects carry some ancillary information which can be quite useful when developing applications. For example, once you have an array <span class=\"lang:default decode:true  crayon-inline \">A</span> , you can query for:\r\n<ul>\r\n 	<li>Number and size of dimensions via. <span class=\"lang:default decode:true  crayon-inline \">A.numdims()</span>  and <span class=\"lang:default decode:true  crayon-inline \">A.dims(int)</span>  functions.</li>\r\n 	<li>The size of the array in bytes with <span class=\"lang:default decode:true  crayon-inline \">A.bytes()</span></li>\r\n 	<li>The underlying data type using <span class=\"lang:default decode:true  crayon-inline \">A.type()</span> or one of many type-specific queries.</li>\r\n 	<li>Whether or not the array is complex or real using <span class=\"lang:default decode:true  crayon-inline \">A.iscomplex()</span>  or <span class=\"lang:default decode:true  crayon-inline \">A.isreal()</span></li>\r\n 	<li>If the data is scalar, <span class=\"lang:default decode:true  crayon-inline \">A.isscalar()</span> , a vector, <span class=\"lang:default decode:true  crayon-inline \">A.isvector()</span> , a row, <span class=\"lang:default decode:true  crayon-inline \">A.isrow()</span> , or a column, <span class=\"lang:default decode:true  crayon-inline \">A.iscolumn()</span> .</li>\r\n</ul>\r\n<h3>Writing mathematical expressions</h3>\r\nArrayFire features an intelligent Just-In-Time (JIT) compilation engine that converts expressions using arrays into the smallest number of CUDA/OpenCL kernels. For most operations on arrays, ArrayFire functions like a vector library. That means that an element-wise operation, like <span class=\"lang:default decode:true  crayon-inline \">c[i] = a[i] + b[i]</span>  in C, would be written more concisely without indexing, like <span class=\"lang:default decode:true  crayon-inline \">c = a + b</span> . When there are multiple expressions involving arrays, ArrayFire\'s JIT engine will merge them together. This \"kernel fusion\" technology not only decreases the number of kernel calls, but, more importantly, avoids extraneous global memory operations. Our JIT functionality extends across C/C++ function boundaries and only ends when a non-JIT function is encountered or a synchronization operation is explicitly called by the code. Thus writing mathematical functions in ArrayFire is as simple as writing the equations themselves!\r\n\r\nArrayFire provides <a class=\"el\" href=\"http://arrayfire.org/docs/group__arith__mat.htm\">hundreds of functions</a> for element-wise operations. All of the standard operators (e.g. +,-,*,/) are supported as are most transcendental functions (sin, cos, log, sqrt, etc.).\r\n\r\nIn addition to mathematical functions, ArrayFire also includes frequently used computer vision functions (FAST, ORB, SIFT), and image processing functions (colorspace conversion, filters, histograms, transformations, and morphological operations).\r\n\r\n&nbsp;','Introduction to the ArrayFire array','','inherit','closed','closed','','8831-revision-v1','','','2016-05-11 12:28:08','2016-05-11 16:28:08','',8831,'http://sandbox.arrayfire.com/8831-revision-v1/',0,'revision','',0),(8836,18528,'2016-05-11 12:31:05','2016-05-11 16:31:05','Continuing our blog series \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" today we will provide an introduction to the core data structure in ArrayFire: the af::array. We describe how to construct arrays, what datatypes arrays support, indexing, how to query an array for various properties (content, dimensions), how to write mathematical expressions on arrays.\r\n\r\n<!--more-->\r\n\r\nArrayFire abstracts away much of the details of programming parallel architectures by providing a high-level container object, the <a class=\"el\" href=\"classaf_1_1array.htm\">array</a>, that represents data stored on a CPU, GPU, FPGA, or other type of accelerator. This abstraction permits developers to write massively parallel applications in a high-level language where they need not be concerned about low-level optimizations that are frequently required to achieve high throughput on most parallel architectures.\r\n<h4>Creating ArrayFire Arrays</h4>\r\nArrays represent memory on a supported device. You can create arrays of uninitialized memory using the array constructor:\r\n<pre class=\"lang:c++ decode:true\">// Arrays may be created using the af::array constructor and dimensioned\r\n// as 1D, 2D, 3D; however, the values in these arrays will be undefined\r\narray undefined_1D = array(100);        // 1D array with 100 elements\r\narray undefined_2D = array(10, 100);    // 2D array of size 10 x 100\r\narray undefined_3D = array(10, 10, 10); // 3D array of size 10 x 10 x 10</pre>\r\nOr using one of many constructors that initialize memory:\r\n<pre class=\"lang:default decode:true\">// Create an array of zeros of length three:\r\narray zeros      = constant(0, 3);\r\n\r\n// Generate a 1x4 array of uniformly distributed [0,1] random numbe// using af::randu():\r\narray rand1      = randu(1, 4);\r\n    \r\n// Make a 2x2 array (or matrix, if you prefer) of random numbers\r\n// sampled from a normal distribution using af::randn():\r\narray rand2      = randn(2, 2);\r\n\r\n// Construct a 3x3 identity matrix. \r\narray iden       = af::identity(3, 3);</pre>\r\nLastly, arrays may be populated with data from the host using our copy constructor:\r\n<pre class=\"lang:default decode:true\">// Create a six-element array on the host\r\nfloat hA[] = {0, 1, 2, 3, 4, 5};\r\n    \r\n// Using the array copy constructor, we can create a 2x3\r\n// matrix from this data:\r\narray A(2, 3, hA);</pre>\r\nArrays can also be created from CUDA device pointers or OpenCL memory buffers. Please consult the <a href=\"http://arrayfire.org/docs/gettingstarted.htm\">documentation</a> on these aspects.\r\n<h4>Supported data types</h4>\r\nArrayFire arrays support standard integral and complex data types found in C/C++. The data type for an array is specified by providing an (optional) final parameter to any of the array constructors. The type field and supported types are as follows:\r\n<ul>\r\n 	<li>b8 8-bit boolean values (bool)</li>\r\n 	<li>f32 real single-precision (float)</li>\r\n 	<li>c32 complex single-precision (cfloat)</li>\r\n 	<li>s32 32-bit signed integer (int)</li>\r\n 	<li>u32 32-bit unsigned integer (unsigned)</li>\r\n 	<li>f64 real double-precision (double)</li>\r\n 	<li>c64 complex double-precision (cdouble)</li>\r\n 	<li>s64 64-bit signed integer (intl)</li>\r\n 	<li>u64 64-bit unsigned integer (uintl)</li>\r\n 	<li>s16 16-bit signed integer (short)</li>\r\n 	<li>u16 16-bit unsigned integer (unsigned short)</li>\r\n</ul>\r\nFor example, if you wanted to construct a 2x1 (column vector) of uniformly distributed 32-bit complex numbers (c32 data type), you would use the following code:\r\n<pre class=\"lang:default decode:true\">// Create a 2x1 column vector of uniformly distributed\r\n// 32-bit complex values:\r\narray randcplx   = randu(2, 1, c32);</pre>\r\n<h4>Indexing</h4>\r\nLike all functions in ArrayFire, indexing is also executed in parallel on the OpenCL/CUDA device. Because of this, indexing becomes part of a JIT operation and is accomplished using parentheses instead of square brackets (i.e. as A(0) instead of A[0]). To index af::arrays you may use one or a combination of the following functions:\r\n<ul>\r\n 	<li>integer scalars</li>\r\n 	<li>seq() representing a linear sequence</li>\r\n 	<li>end representing the last element of a dimension</li>\r\n 	<li>span representing the entire dimension</li>\r\n 	<li>row(i) or col(i) specifying a single row/column</li>\r\n 	<li>rows(first,last) or cols(first,last) specifying a span of rows or columns</li>\r\n</ul>\r\nHere are a few examples of these indexing functions in operation:\r\n<pre class=\"lang:default decode:true\">// Make an 3x3 array containing numbers 1-9:\r\narray A = array(seq(1,9), 3, 3);\r\n\r\nA(0);            // first element\r\nA(0,1);          // first row, second column\r\nA(end);          // last element\r\nA(-1);           // also last element\r\nA(end-1);        // second-to-last element\r\nA(1,span);       // second row\r\nA.row(end);      // last row\r\nA.cols(1,end);   // all but first column</pre>\r\nFor further examples, see the <a href=\"http://arrayfire.org/docs/indexing.htm\">documentation on indexing</a>.\r\n<h4>Querying existing arrays for their properties</h4>\r\nArrayFire array objects carry some ancillary information which can be quite useful when developing applications. For example, once you have an array <span class=\"lang:default decode:true crayon-inline \">A</span> , you can query for:\r\n<ul>\r\n 	<li>Number and size of dimensions via. <span class=\"lang:default decode:true crayon-inline \">A.numdims()</span>  and <span class=\"lang:default decode:true crayon-inline \">A.dims(int)</span>  functions.</li>\r\n 	<li>The size of the array in bytes with <span class=\"lang:default decode:true crayon-inline \">A.bytes()</span></li>\r\n 	<li>The underlying data type using <span class=\"lang:default decode:true crayon-inline \">A.type()</span> or one of many type-specific queries.</li>\r\n 	<li>Whether or not the array is complex or real using <span class=\"lang:default decode:true crayon-inline \">A.iscomplex()</span>  or <span class=\"lang:default decode:true crayon-inline \">A.isreal()</span></li>\r\n 	<li>If the data is scalar, <span class=\"lang:default decode:true crayon-inline \">A.isscalar()</span> , a vector, <span class=\"lang:default decode:true crayon-inline \">A.isvector()</span> , a row, <span class=\"lang:default decode:true crayon-inline \">A.isrow()</span> , or a column, <span class=\"lang:default decode:true crayon-inline \">A.iscolumn()</span> .</li>\r\n</ul>\r\n<h4>Writing mathematical expressions</h4>\r\nArrayFire features an intelligent Just-In-Time (JIT) compilation engine that converts expressions using arrays into the smallest number of CUDA/OpenCL kernels. For most operations on arrays, ArrayFire functions like a vector library. That means that an element-wise operation, like <span class=\"lang:default decode:true crayon-inline \">c[i] = a[i] + b[i]</span>  in C, would be written more concisely without indexing, like <span class=\"lang:default decode:true crayon-inline \">c = a + b</span> . When there are multiple expressions involving arrays, ArrayFire\'s JIT engine will merge them together. This \"kernel fusion\" technology not only decreases the number of kernel calls, but, more importantly, avoids extraneous global memory operations. Our JIT functionality extends across C/C++ function boundaries and only ends when a non-JIT function is encountered or a synchronization operation is explicitly called by the code. Thus writing mathematical functions in ArrayFire is as simple as writing the equations themselves!\r\n\r\nArrayFire provides <a class=\"el\" href=\"http://arrayfire.org/docs/group__arith__mat.htm\">hundreds of functions</a> for element-wise operations. All of the standard operators (e.g. +,-,*,/) are supported as are most transcendental functions (sin, cos, log, sqrt, etc.).\r\n\r\nIn addition to mathematical functions, ArrayFire also includes frequently used computer vision functions (FAST, ORB, SIFT), and image processing functions (colorspace conversion, filters, histograms, transformations, and morphological operations).\r\n\r\n&nbsp;','Introduction to the ArrayFire array','','inherit','closed','closed','','8831-revision-v1','','','2016-05-11 12:31:05','2016-05-11 16:31:05','',8831,'http://sandbox.arrayfire.com/8831-revision-v1/',0,'revision','',0),(8837,18528,'2016-05-12 10:01:29','2016-05-12 14:01:29','Programmers and Data Scientists want to take advantage of fast and parallel computational devices. One of the best ways of doing this is to write vectorized code. In today\'s continuation of the blog series \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\", we will discuss the various methods by which you can le\n\n&nbsp;\n\nWriting vectorized code is necessary to get the best performance out of the current generation parallel hardware and scientific computing software. However, writing vectorized code may not be immediately intuitive. ArrayFire provides many ways to vectorize a given code segment. In this tutorial, we present several methods to vectorize code using ArrayFire and discuss the benefits and drawbacks associated with each method.\n\nContinuing our blog series \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" today we will provide an overview on the various ways to maximize the performance of ArrayFire by using vectorized code.\n\n&nbsp;\n\n<!--more-->\n\nProgrammers and Data Scientists want to take advantage of fast and parallel computational devices. Writing vectorized code is necessary to get the best performance out of the current generation parallel hardware and scientific computing software. However, writing vectorized code may not be immediately intuitive. ArrayFire provides many ways to vectorize a given code segment. In this tutorial, we present several methods to vectorize code using ArrayFire and discuss the benefits and drawbacks associated with each method.\n<h4><a id=\"GenericDefault_vectorization_10\"></a>Generic/Default vectorization</h4>\nBy its very nature, ArrayFire is a vectorized library. Most functions operate on arrays as a whole – on all elements in parallel. Wherever possible, existing vectorized functions should be used opposed to manually indexing into arrays. For example consider the following code:\n<pre class=\"lang:default decode:true \">af::array a = af::range(10); // [0,  9]\nfor(int i = 0; i &lt; a.dims(0); ++i)\n{\n    a(i) = a(i) + 1;         // [1, 10]\n}</pre>\nAlthough completely valid, the code is very inefficient as it results in a kernel kernels that operate on one datum. Instead, the developer should have used ArrayFire\'s overload of the + operator:\n<pre><code class=\"language-{.cpp}\">\naf::array a = af::range(10);  // [0,  9]\na = a + 1;                    // [1, 10]\n</code></pre>\nThis code will result in a single kernel that operates on all 10 elements of <code>a</code> in parallel.\n\nMost ArrayFire functions are vectorized. A small subset of these include:\n\n<strong>Arithmetic operations:</strong> +, -, *, / , %, &gt;&gt;, &lt;&lt;\n<strong>Logical operations:</strong> &amp;&amp;, ||, &lt;, &gt;, ==, !=\n<strong>Numeric functions:</strong> abs(), floor(), round(), min(), max()…\n<strong>Complex operations:</strong> real(), imag(), conj()…\n<strong>Exponential and logarithmic functions:</strong> exp(), log(), expm1(), log1p()…\n<strong>Trigonometric functions:</strong> sin(), cos(), tan()…\n<strong>Hyperbolic functions:</strong> sinh(), cosh(), tanh()…\n\nIn addition to element-wise operations, many other functions are also vectorized in ArrayFire.\n\nNotice that even that perform some form of aggregation (e.g. <code>sum()</code> or <code>min()</code>), signal processing (like <code>convolve()</code>), and even image processing functions (i.e. <code>rotate()</code>) all support vectorization on different columns or images. For example, if we have <code>NUM</code> images of size <code>WIDTH</code> by <code>HEIGHT</code>, one could convolve each image in a vector fashion as follows:\n<pre class=\"lang:default decode:true \">float g_coef[] = { 1, 2, 1,\n                   2, 4, 2,\n                   1, 2, 1 };\naf::array filter = 1.f/16 * af::array(3, 3, f_coef);\naf::array signal = randu(WIDTH, HEIGHT, NUM);\naf::array conv = convolve2(signal, filter);</pre>\nSimilarly, one can rotate 100 images by 45 degrees in a single call using code like the following:\n<div class=\"fragment\">\n<div class=\"line\">\n<pre class=\"lang:default decode:true \">// Construct an array of 100 WIDTH x HEIGHT images of random numbers\naf::array imgs = randu(WIDTH, HEIGHT, 100);\n// Rotate all of the images in a single command\naf::array rot_imgs = rotate(imgs, 45);</pre>\n</div>\n</div>\nAlthough <em>most</em> functions in ArrayFire do support vectorization, some do not. Most notably, all linear algebra functions. Even though they are not vectorized linear algebra operations still execute in parallel on your hardware.\n\nUsing the built in vectorized operations should be the first and preferred method of vectorizing any code written with ArrayFire.\n<h4><a id=\"GFOR_Parallel_forloops_76\"></a>GFOR: Parallel for-loops</h4>\nAnother novel method of vectorization present in ArrayFire is the GFOR loop replacement construct. GFOR allows launching all iterations of a loop in parallel on the GPU or device, as long as the iterations are independent. While the standard for-loop performs each iteration sequentially, ArrayFire\'s gfor-loop performs each iteration at the same time (in parallel). ArrayFire does this by tiling out the values of all loop iterations and then performing computation on those tiles in one pass. You can think of gfor as performing auto-vectorization of your code, e.g. you write a gfor-loop that increments every element of a vector but behind the scenes ArrayFire rewrites it to operate on the entire vector in parallel.\n\nThe original for-loop example at the beginning of this document could be rewritten using GFOR as follows:\n<pre><code class=\"language-{.cpp}\">af::array a = af::range(10);\ngfor(seq i, n)\n    a(i) = a(i) + 1;</code></pre>\nIn this case, each instance of the gfor loop is independent, thus ArrayFire will automatically tile out the <code>a</code> array in device memory and execute the increment kernels in parallel.\n\nTo see another example, you could run an <a class=\"el\" title=\"C++ Interface exclusive sum (cumulative sum) of an array. \" href=\"group__scan__func__accum.htm#gae450135c4ae1bdaa4489804a215f3214\">accum()</a> on every slice of a matrix in a for-loop, or you could \"vectorize\" and simply do it all in one gfor-loop operation:\n<div class=\"fragment\">\n<div class=\"line\">\n<pre class=\"lang:default decode:true \">// runs each accum() in sequence\nfor (int i = 0; i &lt; N; ++i)\n    B(span,i) = accum(A(span,i));\n \n// runs N accums in parallel\ngfor (seq i, N)\n    B(span,i) = accum(A(span,i));</pre>\n</div>\n</div>\nHowever, returning to our previous vectorization technique, <a class=\"el\" title=\"C++ Interface exclusive sum (cumulative sum) of an array. \" href=\"group__scan__func__accum.htm#gae450135c4ae1bdaa4489804a215f3214\">accum()</a> is already vectorized and the operation could be completely replaced with merely:\n<div class=\"fragment\">\n<div class=\"line\">\n<pre class=\"lang:default decode:true \">B = accum(A);</pre>\n</div>\n</div>\nIt is best to vectorize computation as much as possible to avoid the overhead in both for-loops and gfor-loops. However, the gfor-loop construct is most effective in the narrow case of broadcast-style operations. Consider the case when we have a vector of constants that we wish to apply to a collection of variables, such as expressing the values of a linear combination for multiple vectors. The broadcast of one set of constants to many vectors works well with gfor-loops:\n<div class=\"fragment\">\n<div class=\"line\">\n<pre class=\"lang:default decode:true \">const static int p=4, n=1000;\naf::array consts = af::randu(p);\naf::array var_terms = randn(p, n);\n \ngfor(seq i, n)\n    combination(span, i) = consts * var_terms(span, i);</pre>\n</div>\n</div>\nUsing GFOR requires following several rules and multiple guidelines for optimal performance. The details of this vectorization method can be found in the <a class=\"el\" href=\"page_gfor.htm#gfor\">GFOR documentation</a>.\n<h4><a id=\"Batching_127\"></a>Batching</h4>\nThe <a class=\"el\" href=\"namespaceaf.htm#aa0eb9e160f5be4b95234543e5c47934b\">batchFunc()</a> function allows the broad application of existing ArrayFire functions to multiple sets of data. Effectively,<a class=\"el\" href=\"namespaceaf.htm#aa0eb9e160f5be4b95234543e5c47934b\">batchFunc()</a> allows ArrayFire functions to execute in \"batch processing\" mode. In this mode, functions will find a dimension which contains \"batches\" of data to be processed and will parallelize the procedure.\n\nConsider the following example. Here we create a filter which we would like to apply to each of the weight vectors. The naive solution would be using a for-loop as we have seen previously:\n<div class=\"fragment\">\n<div class=\"line\">\n<pre class=\"lang:default decode:true \">// Create the filter and the weight vectors\naf::array filter = randn(1, 5);\naf::array weights = randu(5, 5);\n \n// Apply the filter using a for-loop\naf::array filtered_weights = constant(0, 5, 5);\nfor(int i=0; i&lt;weights.dims(1); ++i){\n    filtered_weights.col(i) = filter * weights.col(i);\n}</pre>\n</div>\n</div>\nHowever, as we have discussed above, this solution will be very inefficient. One may be tempted to implement a vectorized solution as follows:\n<div class=\"fragment\">\n<div class=\"line\">\n<pre class=\"lang:default decode:true \">// Create the filter and the weight vectors\naf::array filter = randn(1, 5);\naf::array weights = randu(5, 5);\n \naf::array filtered_weights = filter * weights; // fails due to dimension mismatch</pre>\n</div>\n</div>\nHowever, the dimensions of <code>filter</code> and <code>weights</code> do not match, thus ArrayFire will generate a runtime error.\n\n<code>batchfunc()</code> was created to solve this specific problem. The signature of the function is as follows:\n<div class=\"fragment\">\n<div class=\"line\">\n<pre class=\"lang:default decode:true \">array batchFunc(const array &amp;lhs, const array &amp;rhs, batchFunc_t func);</pre>\n</div>\n</div>\nwhere <code>__batchFunc_t__</code> is a function pointer of the form:\n<div class=\"fragment\">\n<div class=\"line\">\n<pre class=\"lang:default decode:true \">typedef array (*batchFunc_t) (const array &amp;lhs, const array &amp;rhs);</pre>\n</div>\n</div>\nSo, to use <a class=\"el\" href=\"namespaceaf.htm#aa0eb9e160f5be4b95234543e5c47934b\">batchFunc()</a>, we need to provide the function we wish to apply as a batch operation. For illustration\'s sake, let\'s \"implement\" a multiplication function following the format.\n<div class=\"fragment\">\n<div class=\"line\">\n<pre class=\"lang:default decode:true \">af::array my_mult (const af::array &amp;lhs, const af::array &amp;rhs){\nreturn lhs * rhs;\n}</pre>\n</div>\n</div>\nOur final batch call is not much more difficult than the ideal syntax we imagined.\n<div class=\"fragment\">\n<div class=\"line\">\n<pre class=\"lang:default decode:true \">// Create the filter and the weight vectors\naf::array filter = randn(1, 5);\naf::array weights = randu(5, 5);\n \n// Apply the batch function\naf::array filtered_weights = batchFunc( filter, weights, my_mult );</pre>\n</div>\n</div>\nThe batch function will work with many previously mentioned vectorized ArrayFire functions. It can even work with a combination of those functions if they are wrapped inside a helper function matching the <code>__batchFunc_t__</code> signature. One limitation of <code>batchfunc()</code> is that it cannot be used from within a <code><a class=\"el\" href=\"gfor_8h.htm#a6d6cd11d53daad217fd0b92f5a7ceec6\">gfor()</a></code> loop at the present time.\n<h4><a id=\"Advanced_Vectorization_181\"></a>Advanced Vectorization</h4>\nWe have seen the different methods ArrayFire provides to vectorize our code. Tying them all together is a slightly more involved process that needs to consider data dimensionality and layout, memory usage, nesting order, etc. An excellent example and discussion of these factors can be found in another blog post:\n\n<a href=\"http://sandbox.arrayfire.com/how-to-write-vectorized-code/\">http://sandbox.arrayfire.com/how-to-write-vectorized-code/</a>\n\nIt’s worth noting that the whole implementation discussed in the blog has since been transformed into a convenient <strong>af::nearestNeighbour()</strong> function. Before writing something from scratch, check that ArrayFire doesn’t already have an implementation. The default vectorized nature of ArrayFire and an extensive collection of functions will speed things up in addition to replacing dozens of lines of code!','Introduction to Vectorization','','inherit','closed','closed','','8735-autosave-v1','','','2016-05-12 10:01:29','2016-05-12 14:01:29','',8735,'http://sandbox.arrayfire.com/8735-autosave-v1/',0,'revision','',0),(8838,18528,'2016-05-11 12:38:54','2016-05-11 16:38:54','Programmers and Data Scientists want to take advantage of fast and parallel computational devices. Writing vectorized code is becoming a necessity to get the best performance out of the current generation parallel hardware and scientific computing software. However, writing vectorized code may not be intuitive immediately. Arrayfire provides many ways to vectorize a given code segment. In this tutorial, we will be presenting various ways to vectorize code using ArrayFire and the benefits and drawbacks associated with each method.\r\n<h4><a id=\"GenericDefault_vectorization_10\"></a>Generic/Default vectorization</h4>\r\nBy its very nature, Arrayfire is a vectorized library. Most functions operate on arrays as a whole – on all elements in parallel. Wherever possible, existing vectorized functions should be used opposed to manually indexing into arrays. For example, consider this valid, yet mislead code that attempts to increment each element of an array:\r\n<pre><code class=\"language-{.cpp}\">af::<span class=\"hljs-built_in\">af::array a = af::range(10); // [0,  9]\r\nfor(int i = 0; i &lt; a.dims(0); ++i)\r\n{\r\n    a(i) = a(i) + 1;         // [1, 10]\r\n}\r\n</span></code></pre>\r\nInstead, the existing vectorized Arrayfire overload of the + operator should have been used:\r\n<pre><code class=\"language-{.cpp}\">\r\naf::array a = af::range(10);  // [0,  9]\r\na = a + 1;                    // [1, 10]\r\n</code></pre>\r\nMost Arrayfire functions are vectorized. A small subset of these include:\r\n\r\n<strong>Arithmetic operations:</strong> +, -, *, / , %, &gt;&gt;, &lt;&lt;\r\n<strong>Complex operations:</strong> real(), imag(), conj()…\r\n<strong>Exponential and logarithmic functions:</strong> exp(), log(), expm1(), log1p()…\r\n<strong>Hyperbolic functions:</strong> sinh(), cosh(), tanh()…\r\n<strong>Logical operations:</strong> &amp;&amp;, ||, &lt;, &gt;, ==, !=\r\n<strong>Numeric functions:</strong> abs(), floor(), round(), min(), max()…\r\n<strong>Trigonometric functions:</strong> sin(), cos(), tan()…\r\n\r\nNot only elementwise arithmetic operations are vectorized in Arrayfire.\r\n\r\nVector operations such as <strong>min()</strong> support vectorization:\r\n<pre><code class=\"language-{.cpp}\">af::array arr = randn(100);\r\nstd::cout &lt;&lt; min(arr) &lt;&lt; std::endl;\r\n</code></pre>\r\nSignal processing functions like <strong>convolve()</strong> support vectorization:\r\n<pre><code class=\"language-{.cpp}\">float g_coef[] = { 1, 2, 1,\r\n                   2, 4, 2,\r\n                   1, 2, 1 };\r\n\r\naf::array filter = 1.f/16 * af::array(3, 3, f_coef);\r\n\r\naf::array signal = randu(WIDTH, HEIGHT, NUM);\r\naf::array conv = convolve2(signal, filter);\r\n</code></pre>\r\nImage processing functions such as <strong>rotate()</strong> support vectorization:\r\n<pre><code class=\"language-{.cpp}\">af::array imgs = randu(WIDTH, HEIGHT, 100); // 100 (WIDTH x HEIGHT) images\r\naf::array rot_imgs = rotate(imgs, 45); // 100 rotated images\r\n</code></pre>\r\nOne class of functions that does not support vectorization is the set of linear algebra functions. Using the built in vectorized operations should be the first and preferred method of vectorizing any code written with Arrayfire.\r\n<h4><a id=\"GFOR_Parallel_forloops_76\"></a>GFOR: Parallel for-loops</h4>\r\nAnother novel method of vectorization present in Arrayfire is the GFOR loop replacement construct. GFOR allows launching all iterations of a loop in parallel on the GPU or device, as long as the iterations are independent. While the standard for-loop performs each iteration sequentially, ArrayFire’s gfor-loop performs each iteration at the same time (in parallel). ArrayFire does this by tiling out the values of all loop iterations and then performing computation on those tiles in one pass. You can think of gfor as performing auto-vectorization of your code, e.g. you write a gfor-loop that increments every element of a vector but behind the scenes ArrayFire rewrites it to operate on the entire vector in parallel.\r\n\r\nWe can remedy our first example with GFOR:\r\n<pre><code class=\"language-{.cpp}\">af::array a = af::range(10);\r\ngfor(seq i, n)\r\n    a(i) = a(i) + 1;</code></pre>\r\nTo see another example, you could run an <strong>accum()</strong> on every slice of a matrix in a for-loop, or you could “vectorize” and simply do it all in one gfor-loop operation:\r\n<pre><code class=\"language-{.cpp}\">for (int i = 0; i &lt; N; ++i)\r\n   B(span,i) = accum(A(span,i)); // runs each accum() in sequence\r\ngfor (seq i, N)\r\n   B(span,i) = accum(A(span,i)); // runs N accums in parallel\r\n</code></pre>\r\nHowever, returning to our previous vectorization technique, <strong>accum()</strong> is already vectorized and the operation could be completely replaced with merely:\r\n<pre><code class=\"language-{.cpp}\">    B = accum(A);\r\n</code></pre>\r\nIt is best to vectorize computation as much as possible to avoid the overhead in both for-loops and gfor-loops. However, the gfor-loop construct is most effective in the narrow case of broadcast-style operations. Consider the case when we have a vector of constants that we wish to apply to a collection of variables, such as expressing the values of a linear combination for multiple vectors. The broadcast of one set of constants to many vectors works well with gfor-loops:\r\n<pre><code class=\"language-{.cpp}\">const static int p=4, n=1000;\r\naf::array consts = af::randu(p);\r\naf::array var_terms = randn(p, n);\r\n\r\ngfor(seq i, n)\r\n    combination(span, i) = consts * var_terms(span, i);\r\n</code></pre>\r\nUsing GFOR requires following several rules and multiple guidelines for optimal performance. The details of this vectorization method can be found in the <a href=\"http://www.sandbox.arrayfire.com/docs/page_gfor.htm\">GFOR documentation.</a>\r\n<h4><a id=\"Batching_127\"></a>Batching</h4>\r\nThe <strong>batchFunc()</strong> function allows the broad application of existing Arrayfire functions to multiple sets of data. Effectively, batchFunc() allows Arrayfire functions to execute in “batch processing” mode. In this mode, functions will find a dimension which contains “batches” of data to be processed and will parallelize the procedure. Consider the following example:\r\n<pre><code class=\"language-{.cpp}\">af::array filter = randn(1, 5);\r\naf::array weights = randu(5, 5);\r\n</code></pre>\r\nWe have a filter that we would like to apply to each of several weights vectors. The naive solution would be using a loop as we’ve seen before:\r\n<pre><code class=\"language-{.cpp}\">af::array filtered_weights = constant(0, 5, 5);\r\nfor(int i=0; i &lt; weights.dims(1); ++i){\r\n    filtered_weights.col(i) = filter * weights.col(i);\r\n}\r\n</code></pre>\r\nHowever we would like a vectorized solution. The following syntax begs to be used:\r\n<pre><code class=\"language-{.cpp}\">af::array filtered_weights = filter * weights; // fails due to dimension mismatch\r\n</code></pre>\r\nbut it fails due to the (5x1), (5x5) dimension mismatch. Wouldn’t it be nice if Arrayfire could figure out along which dimension we intend to apply the batch operation? That is exactly what <strong>batchFunc()</strong> does! The signature of the function is:\r\n<code>array batchFunc(const array &amp;lhs, const array &amp;rhs, batchFunc_t func);</code>\r\nwhere <strong>batchFunc_t</strong> is a function pointer of the form:\r\n<code>typedef array (*batchFunc_t) (const array &amp;lhs, const array &amp;rhs);</code>\r\n\r\nSo, to use <strong>batchFunc()</strong>, we need to provide the function we will be applying as a batch operation. For illustration’s sake, let’s “implement” a multiplication function following the format.\r\n<pre><code class=\"language-{.cpp}\">af::array my_mult (const af::array &amp; lhs, const af::array &amp; rhs){\r\n    return lhs * rhs;\r\n}</code></pre>\r\nOur final batch call is not much more difficult than the ideal syntax we imagined.\r\n<pre><code class=\"language-{.cpp}\">af::array filtered_weights = batchFunc( filter, weights, my_mult );\r\n</code></pre>\r\nThe batch function will work with many previously mentioned vectorized Arrayfire functions. It can even work with a combination of those functions if they are wrapped inside a helper function matching the <strong>batchFunc_t</strong> signature. Unfortunately, the batch function cannot be used within a gfor() construct at this moment.\r\n<h4><a id=\"Advanced_Vectorization_181\"></a>Advanced Vectorization</h4>\r\nWe have seen the different methods Arrayfire provides to vectorize our code. Tying them all together is a slightly more involved process that needs to consider data dimensionality and layout, memory usage, nesting order, etc. An excellent example and discussion of these factors can be found in another blog post:\r\n\r\n<a href=\"http://sandbox.arrayfire.com/how-to-write-vectorized-code/\">http://sandbox.arrayfire.com/how-to-write-vectorized-code/</a>\r\n\r\nIt’s worth noting that the whole implementation discussed in the blog has since been transformed into a convenient <strong>af::nearestNeighbour()</strong> function. Before writing something from scratch, check that Arrayfire doesn’t already have an implementation. The default vectorized nature of Arrayfire and an extensive collection of functions will speed things up in addition to replacing dozens of lines of code!','Introduction to Vectorization','','inherit','closed','closed','','8735-revision-v1','','','2016-05-11 12:38:54','2016-05-11 16:38:54','',8735,'http://sandbox.arrayfire.com/8735-revision-v1/',0,'revision','',0),(8839,18528,'2016-05-11 12:41:05','2016-05-11 16:41:05','Programmers and Data Scientists want to take advantage of fast and parallel computational devices. Writing vectorized code is becoming a necessity to get the best performance out of the current generation parallel hardware and scientific computing software. However, writing vectorized code may not be intuitive immediately. Arrayfire provides many ways to vectorize a given code segment. In this tutorial, we will be presenting various ways to vectorize code using ArrayFire and the benefits and drawbacks associated with each method.\r\n<h4><a id=\"GenericDefault_vectorization_10\"></a>Generic/Default vectorization</h4>\r\nBy its very nature, ArrayFire is a vectorized library. Most functions operate on arrays as a whole – on all elements in parallel. Wherever possible, existing vectorized functions should be used opposed to manually indexing into arrays. For example, consider this valid, yet mislead code that attempts to increment each element of an array:\r\n<pre><code class=\"language-{.cpp}\">af::<span class=\"hljs-built_in\">af::array a = af::range(10); // [0,  9]\r\nfor(int i = 0; i &lt; a.dims(0); ++i)\r\n{\r\n    a(i) = a(i) + 1;         // [1, 10]\r\n}\r\n</span></code></pre>\r\nInstead, the existing vectorizedArrayFire overload of the + operator should have been used:\r\n<pre><code class=\"language-{.cpp}\">\r\naf::array a = af::range(10);  // [0,  9]\r\na = a + 1;                    // [1, 10]\r\n</code></pre>\r\nMostArrayFire functions are vectorized. A small subset of these include:\r\n\r\n<strong>Arithmetic operations:</strong> +, -, *, / , %, &gt;&gt;, &lt;&lt;\r\n<strong>Complex operations:</strong> real(), imag(), conj()…\r\n<strong>Exponential and logarithmic functions:</strong> exp(), log(), expm1(), log1p()…\r\n<strong>Hyperbolic functions:</strong> sinh(), cosh(), tanh()…\r\n<strong>Logical operations:</strong> &amp;&amp;, ||, &lt;, &gt;, ==, !=\r\n<strong>Numeric functions:</strong> abs(), floor(), round(), min(), max()…\r\n<strong>Trigonometric functions:</strong> sin(), cos(), tan()…\r\n\r\nNot only elementwise arithmetic operations are vectorized in Arrayfire.\r\n\r\nVector operations such as <strong>min()</strong> support vectorization:\r\n<pre><code class=\"language-{.cpp}\">af::array arr = randn(100);\r\nstd::cout &lt;&lt; min(arr) &lt;&lt; std::endl;\r\n</code></pre>\r\nSignal processing functions like <strong>convolve()</strong> support vectorization:\r\n<pre><code class=\"language-{.cpp}\">float g_coef[] = { 1, 2, 1,\r\n                   2, 4, 2,\r\n                   1, 2, 1 };\r\n\r\naf::array filter = 1.f/16 * af::array(3, 3, f_coef);\r\n\r\naf::array signal = randu(WIDTH, HEIGHT, NUM);\r\naf::array conv = convolve2(signal, filter);\r\n</code></pre>\r\nImage processing functions such as <strong>rotate()</strong> support vectorization:\r\n<pre><code class=\"language-{.cpp}\">af::array imgs = randu(WIDTH, HEIGHT, 100); // 100 (WIDTH x HEIGHT) images\r\naf::array rot_imgs = rotate(imgs, 45); // 100 rotated images\r\n</code></pre>\r\nOne class of functions that does not support vectorization is the set of linear algebra functions. Using the built in vectorized operations should be the first and preferred method of vectorizing any code written withArrayFire.\r\n<h4><a id=\"GFOR_Parallel_forloops_76\"></a>GFOR: Parallel for-loops</h4>\r\nAnother novel method of vectorization present in Arrayfire is the GFOR loop replacement construct. GFOR allows launching all iterations of a loop in parallel on the GPU or device, as long as the iterations are independent. While the standard for-loop performs each iteration sequentially, ArrayFire’s gfor-loop performs each iteration at the same time (in parallel). ArrayFire does this by tiling out the values of all loop iterations and then performing computation on those tiles in one pass. You can think of gfor as performing auto-vectorization of your code, e.g. you write a gfor-loop that increments every element of a vector but behind the scenes ArrayFire rewrites it to operate on the entire vector in parallel.\r\n\r\nWe can remedy our first example with GFOR:\r\n<pre><code class=\"language-{.cpp}\">af::array a = af::range(10);\r\ngfor(seq i, n)\r\n    a(i) = a(i) + 1;</code></pre>\r\nTo see another example, you could run an <strong>accum()</strong> on every slice of a matrix in a for-loop, or you could “vectorize” and simply do it all in one gfor-loop operation:\r\n<pre><code class=\"language-{.cpp}\">for (int i = 0; i &lt; N; ++i)\r\n   B(span,i) = accum(A(span,i)); // runs each accum() in sequence\r\ngfor (seq i, N)\r\n   B(span,i) = accum(A(span,i)); // runs N accums in parallel\r\n</code></pre>\r\nHowever, returning to our previous vectorization technique, <strong>accum()</strong> is already vectorized and the operation could be completely replaced with merely:\r\n<pre><code class=\"language-{.cpp}\">    B = accum(A);\r\n</code></pre>\r\nIt is best to vectorize computation as much as possible to avoid the overhead in both for-loops and gfor-loops. However, the gfor-loop construct is most effective in the narrow case of broadcast-style operations. Consider the case when we have a vector of constants that we wish to apply to a collection of variables, such as expressing the values of a linear combination for multiple vectors. The broadcast of one set of constants to many vectors works well with gfor-loops:\r\n<pre><code class=\"language-{.cpp}\">const static int p=4, n=1000;\r\naf::array consts = af::randu(p);\r\naf::array var_terms = randn(p, n);\r\n\r\ngfor(seq i, n)\r\n    combination(span, i) = consts * var_terms(span, i);\r\n</code></pre>\r\nUsing GFOR requires following several rules and multiple guidelines for optimal performance. The details of this vectorization method can be found in the <a href=\"http://www.sandbox.arrayfire.com/docs/page_gfor.htm\">GFOR documentation.</a>\r\n<h4><a id=\"Batching_127\"></a>Batching</h4>\r\nThe <strong>batchFunc()</strong> function allows the broad application of existing ArrayFire functions to multiple sets of data. Effectively, batchFunc() allows ArrayFire functions to execute in “batch processing” mode. In this mode, functions will find a dimension which contains “batches” of data to be processed and will parallelize the procedure. Consider the following example:\r\n<pre><code class=\"language-{.cpp}\">af::array filter = randn(1, 5);\r\naf::array weights = randu(5, 5);\r\n</code></pre>\r\nWe have a filter that we would like to apply to each of several weights vectors. The naive solution would be using a loop as we’ve seen before:\r\n<pre><code class=\"language-{.cpp}\">af::array filtered_weights = constant(0, 5, 5);\r\nfor(int i=0; i &lt; weights.dims(1); ++i){\r\n    filtered_weights.col(i) = filter * weights.col(i);\r\n}\r\n</code></pre>\r\nHowever we would like a vectorized solution. The following syntax begs to be used:\r\n<pre><code class=\"language-{.cpp}\">af::array filtered_weights = filter * weights; // fails due to dimension mismatch\r\n</code></pre>\r\nbut it fails due to the (5x1), (5x5) dimension mismatch. Wouldn’t it be nice if ArrayFire could figure out along which dimension we intend to apply the batch operation? That is exactly what <strong>batchFunc()</strong> does! The signature of the function is:\r\n<code>array batchFunc(const array &amp;lhs, const array &amp;rhs, batchFunc_t func);</code>\r\nwhere <strong>batchFunc_t</strong> is a function pointer of the form:\r\n<code>typedef array (*batchFunc_t) (const array &amp;lhs, const array &amp;rhs);</code>\r\n\r\nSo, to use <strong>batchFunc()</strong>, we need to provide the function we will be applying as a batch operation. For illustration’s sake, let’s “implement” a multiplication function following the format.\r\n<pre><code class=\"language-{.cpp}\">af::array my_mult (const af::array &amp; lhs, const af::array &amp; rhs){\r\n    return lhs * rhs;\r\n}</code></pre>\r\nOur final batch call is not much more difficult than the ideal syntax we imagined.\r\n<pre><code class=\"language-{.cpp}\">af::array filtered_weights = batchFunc( filter, weights, my_mult );\r\n</code></pre>\r\nThe batch function will work with many previously mentioned vectorized ArrayFire functions. It can even work with a combination of those functions if they are wrapped inside a helper function matching the <strong>batchFunc_t</strong> signature. Unfortunately, the batch function cannot be used within a gfor() construct at this moment.\r\n<h4><a id=\"Advanced_Vectorization_181\"></a>Advanced Vectorization</h4>\r\nWe have seen the different methods ArrayFire provides to vectorize our code. Tying them all together is a slightly more involved process that needs to consider data dimensionality and layout, memory usage, nesting order, etc. An excellent example and discussion of these factors can be found in another blog post:\r\n\r\n<a href=\"http://sandbox.arrayfire.com/how-to-write-vectorized-code/\">http://sandbox.arrayfire.com/how-to-write-vectorized-code/</a>\r\n\r\nIt’s worth noting that the whole implementation discussed in the blog has since been transformed into a convenient <strong>af::nearestNeighbour()</strong> function. Before writing something from scratch, check that ArrayFire doesn’t already have an implementation. The default vectorized nature of ArrayFire and an extensive collection of functions will speed things up in addition to replacing dozens of lines of code!','Introduction to Vectorization','','inherit','closed','closed','','8735-revision-v1','','','2016-05-11 12:41:05','2016-05-11 16:41:05','',8735,'http://sandbox.arrayfire.com/8735-revision-v1/',0,'revision','',0),(8841,18528,'2016-05-11 15:54:08','2016-05-11 19:54:08','Programmers and Data Scientists want to take advantage of fast and parallel computational devices. Writing vectorized code is necessary to get the best performance out of the current generation parallel hardware and scientific computing software. However, writing vectorized code may not be immediately intuitive. ArrayFire provides many ways to vectorize a given code segment. In this tutorial, we present several methods to vectorize code using ArrayFire and discuss the benefits and drawbacks associated with each method.\r\n<h4><a id=\"GenericDefault_vectorization_10\"></a>Generic/Default vectorization</h4>\r\nBy its very nature, ArrayFire is a vectorized library. Most functions operate on arrays as a whole – on all elements in parallel. Wherever possible, existing vectorized functions should be used opposed to manually indexing into arrays. For example consider the following code:\r\n<pre class=\"lang:default decode:true \">af::array a = af::range(10); // [0,  9]\r\nfor(int i = 0; i &lt; a.dims(0); ++i)\r\n{\r\n    a(i) = a(i) + 1;         // [1, 10]\r\n}</pre>\r\nAlthough completely valid, the code is very inefficient as it results in a kernel kernels that operate on one datum. Instead, the developer should have used ArrayFire\'s overload of the + operator:\r\n<pre><code class=\"language-{.cpp}\">\r\naf::array a = af::range(10);  // [0,  9]\r\na = a + 1;                    // [1, 10]\r\n</code></pre>\r\nThis code will result in a single kernel that operates on all 10 elements of <code>a</code> in parallel.\r\n\r\nMost ArrayFire functions are vectorized. A small subset of these include:\r\n\r\n<strong>Arithmetic operations:</strong> +, -, *, / , %, &gt;&gt;, &lt;&lt;\r\n<strong>Logical operations:</strong> &amp;&amp;, ||, &lt;, &gt;, ==, !=\r\n<strong>Numeric functions:</strong> abs(), floor(), round(), min(), max()…\r\n<strong>Complex operations:</strong> real(), imag(), conj()…\r\n<strong>Exponential and logarithmic functions:</strong> exp(), log(), expm1(), log1p()…\r\n<strong>Trigonometric functions:</strong> sin(), cos(), tan()…\r\n<strong>Hyperbolic functions:</strong> sinh(), cosh(), tanh()…\r\n\r\nIn addition to element-wise operations, many other functions are also vectorized in ArrayFire.\r\n\r\nNotice that even that perform some form of aggregation (e.g. <code>sum()</code> or <code>min()</code>), signal processing (like <code>convolve()</code>), and even image processing functions (i.e. <code>rotate()</code>) all support vectorization on different columns or images. For example, if we have <code>NUM</code> images of size <code>WIDTH</code> by <code>HEIGHT</code>, one could convolve each image in a vector fashion as follows:\r\n<pre class=\"lang:default decode:true \">float g_coef[] = { 1, 2, 1,\r\n                   2, 4, 2,\r\n                   1, 2, 1 };\r\naf::array filter = 1.f/16 * af::array(3, 3, f_coef);\r\naf::array signal = randu(WIDTH, HEIGHT, NUM);\r\naf::array conv = convolve2(signal, filter);</pre>\r\nSimilarly, one can rotate 100 images by 45 degrees in a single call using code like the following:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// Construct an array of 100 WIDTH x HEIGHT images of random numbers\r\naf::array imgs = randu(WIDTH, HEIGHT, 100);\r\n// Rotate all of the images in a single command\r\naf::array rot_imgs = rotate(imgs, 45);</pre>\r\n</div>\r\n</div>\r\nAlthough <em>most</em> functions in ArrayFire do support vectorization, some do not. Most notably, all linear algebra functions. Even though they are not vectorized linear algebra operations still execute in parallel on your hardware.\r\n\r\nUsing the built in vectorized operations should be the first and preferred method of vectorizing any code written with ArrayFire.\r\n<h4><a id=\"GFOR_Parallel_forloops_76\"></a>GFOR: Parallel for-loops</h4>\r\nAnother novel method of vectorization present in ArrayFire is the GFOR loop replacement construct. GFOR allows launching all iterations of a loop in parallel on the GPU or device, as long as the iterations are independent. While the standard for-loop performs each iteration sequentially, ArrayFire\'s gfor-loop performs each iteration at the same time (in parallel). ArrayFire does this by tiling out the values of all loop iterations and then performing computation on those tiles in one pass. You can think of gfor as performing auto-vectorization of your code, e.g. you write a gfor-loop that increments every element of a vector but behind the scenes ArrayFire rewrites it to operate on the entire vector in parallel.\r\n\r\nThe original for-loop example at the beginning of this document could be rewritten using GFOR as follows:\r\n<pre><code class=\"language-{.cpp}\">af::array a = af::range(10);\r\ngfor(seq i, n)\r\n    a(i) = a(i) + 1;</code></pre>\r\nIn this case, each instance of the gfor loop is independent, thus ArrayFire will automatically tile out the <code>a</code> array in device memory and execute the increment kernels in parallel.\r\n\r\nTo see another example, you could run an <a class=\"el\" title=\"C++ Interface exclusive sum (cumulative sum) of an array. \" href=\"group__scan__func__accum.htm#gae450135c4ae1bdaa4489804a215f3214\">accum()</a> on every slice of a matrix in a for-loop, or you could \"vectorize\" and simply do it all in one gfor-loop operation:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// runs each accum() in sequence\r\nfor (int i = 0; i &lt; N; ++i)\r\n    B(span,i) = accum(A(span,i));\r\n \r\n// runs N accums in parallel\r\ngfor (seq i, N)\r\n    B(span,i) = accum(A(span,i));</pre>\r\n</div>\r\n</div>\r\nHowever, returning to our previous vectorization technique, <a class=\"el\" title=\"C++ Interface exclusive sum (cumulative sum) of an array. \" href=\"group__scan__func__accum.htm#gae450135c4ae1bdaa4489804a215f3214\">accum()</a> is already vectorized and the operation could be completely replaced with merely:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">B = accum(A);</pre>\r\n</div>\r\n</div>\r\nIt is best to vectorize computation as much as possible to avoid the overhead in both for-loops and gfor-loops. However, the gfor-loop construct is most effective in the narrow case of broadcast-style operations. Consider the case when we have a vector of constants that we wish to apply to a collection of variables, such as expressing the values of a linear combination for multiple vectors. The broadcast of one set of constants to many vectors works well with gfor-loops:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">const static int p=4, n=1000;\r\naf::array consts = af::randu(p);\r\naf::array var_terms = randn(p, n);\r\n \r\ngfor(seq i, n)\r\n    combination(span, i) = consts * var_terms(span, i);</pre>\r\n</div>\r\n</div>\r\nUsing GFOR requires following several rules and multiple guidelines for optimal performance. The details of this vectorization method can be found in the <a class=\"el\" href=\"page_gfor.htm#gfor\">GFOR documentation</a>.\r\n<h4><a id=\"Batching_127\"></a>Batching</h4>\r\nThe <a class=\"el\" href=\"namespaceaf.htm#aa0eb9e160f5be4b95234543e5c47934b\">batchFunc()</a> function allows the broad application of existing ArrayFire functions to multiple sets of data. Effectively,<a class=\"el\" href=\"namespaceaf.htm#aa0eb9e160f5be4b95234543e5c47934b\">batchFunc()</a> allows ArrayFire functions to execute in \"batch processing\" mode. In this mode, functions will find a dimension which contains \"batches\" of data to be processed and will parallelize the procedure.\r\n\r\nConsider the following example. Here we create a filter which we would like to apply to each of the weight vectors. The naive solution would be using a for-loop as we have seen previously:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// Create the filter and the weight vectors\r\naf::array filter = randn(1, 5);\r\naf::array weights = randu(5, 5);\r\n \r\n// Apply the filter using a for-loop\r\naf::array filtered_weights = constant(0, 5, 5);\r\nfor(int i=0; i&lt;weights.dims(1); ++i){\r\n    filtered_weights.col(i) = filter * weights.col(i);\r\n}</pre>\r\n</div>\r\n</div>\r\nHowever, as we have discussed above, this solution will be very inefficient. One may be tempted to implement a vectorized solution as follows:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// Create the filter and the weight vectors\r\naf::array filter = randn(1, 5);\r\naf::array weights = randu(5, 5);\r\n \r\naf::array filtered_weights = filter * weights; // fails due to dimension mismatch</pre>\r\n</div>\r\n</div>\r\nHowever, the dimensions of <code>filter</code> and <code>weights</code> do not match, thus ArrayFire will generate a runtime error.\r\n\r\n<code>batchfunc()</code> was created to solve this specific problem. The signature of the function is as follows:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">array batchFunc(const array &amp;lhs, const array &amp;rhs, batchFunc_t func);</pre>\r\n</div>\r\n</div>\r\nwhere <code>__batchFunc_t__</code> is a function pointer of the form:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">typedef array (*batchFunc_t) (const array &amp;lhs, const array &amp;rhs);</pre>\r\n</div>\r\n</div>\r\nSo, to use <a class=\"el\" href=\"namespaceaf.htm#aa0eb9e160f5be4b95234543e5c47934b\">batchFunc()</a>, we need to provide the function we wish to apply as a batch operation. For illustration\'s sake, let\'s \"implement\" a multiplication function following the format.\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">af::array my_mult (const af::array &amp;lhs, const af::array &amp;rhs){\r\nreturn lhs * rhs;\r\n}</pre>\r\n</div>\r\n</div>\r\nOur final batch call is not much more difficult than the ideal syntax we imagined.\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// Create the filter and the weight vectors\r\naf::array filter = randn(1, 5);\r\naf::array weights = randu(5, 5);\r\n \r\n// Apply the batch function\r\naf::array filtered_weights = batchFunc( filter, weights, my_mult );</pre>\r\n</div>\r\n</div>\r\nThe batch function will work with many previously mentioned vectorized ArrayFire functions. It can even work with a combination of those functions if they are wrapped inside a helper function matching the <code>__batchFunc_t__</code> signature. One limitation of <code>batchfunc()</code> is that it cannot be used from within a <code><a class=\"el\" href=\"gfor_8h.htm#a6d6cd11d53daad217fd0b92f5a7ceec6\">gfor()</a></code> loop at the present time.\r\n<h4><a id=\"Advanced_Vectorization_181\"></a>Advanced Vectorization</h4>\r\nWe have seen the different methods ArrayFire provides to vectorize our code. Tying them all together is a slightly more involved process that needs to consider data dimensionality and layout, memory usage, nesting order, etc. An excellent example and discussion of these factors can be found in another blog post:\r\n\r\n<a href=\"http://sandbox.arrayfire.com/how-to-write-vectorized-code/\">http://sandbox.arrayfire.com/how-to-write-vectorized-code/</a>\r\n\r\nIt’s worth noting that the whole implementation discussed in the blog has since been transformed into a convenient <strong>af::nearestNeighbour()</strong> function. Before writing something from scratch, check that ArrayFire doesn’t already have an implementation. The default vectorized nature of ArrayFire and an extensive collection of functions will speed things up in addition to replacing dozens of lines of code!','Introduction to Vectorization','','inherit','closed','closed','','8735-revision-v1','','','2016-05-11 15:54:08','2016-05-11 19:54:08','',8735,'http://sandbox.arrayfire.com/8735-revision-v1/',0,'revision','',0),(8843,18528,'2016-05-12 09:58:42','2016-05-12 13:58:42','ArrayFire provides several different methods for manipulating arrays and matrices. The functionality includes:\r\n<ul>\r\n 	<li>moddims() - change the dimensions of an array without changing the data</li>\r\n 	<li>array() - create a (shallow) copy of an array with different dimensions.</li>\r\n 	<li>flat() - flatten an array to one dimension</li>\r\n 	<li>flip() - flip an array along a dimension</li>\r\n 	<li>join() - join up to 4 arrays</li>\r\n 	<li>reorder() - changes the dimension order within the array</li>\r\n 	<li>shift() - shifts data along a dimension</li>\r\n 	<li>tile() - repeats an array along a dimension</li>\r\n 	<li>transpose() - performs a matrix transpose</li>\r\n 	<li>T() - transpose a matrix or vector (shorthand notation)</li>\r\n 	<li>H() - Hermitian Transpose (conjugate-transpose) a matrix</li>\r\n</ul>\r\nBelow we provide several examples of these functions and their use.\r\n<h3>flat()</h3>\r\nThe flat() function flattens an array to one dimension:\r\n<pre class=\"lang:default decode:true \">a [3 3 1 1]\r\n1.0000 4.0000 7.0000\r\n2.0000 5.0000 8.0000\r\n3.0000 6.0000 9.0000\r\n\r\nflat(a) [9 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n6.0000\r\n7.0000\r\n8.0000\r\n9.0000</pre>\r\nThe flat function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true \">af_err af_flat(af_array* out, const af_array in) – C interface for flat() function\r\n\r\narray af::flat(const array&amp; in) – C++ interface for flat() function</pre>\r\n<h3>flip()</h3>\r\nThe flip() function flips the contents of an array along a chosen dimension. In the example below, we show the 5x2 array flipped along the zeroth (i.e. within a column) and first (e.g. across rows) axes:\r\n<pre class=\"lang:default decode:true \">a [5 2 1 1]\r\n1.0000 6.0000\r\n2.0000 7.0000\r\n3.0000 8.0000\r\n4.0000 9.0000\r\n5.0000 10.0000\r\n\r\nflip(a, 0) [5 2 1 1]\r\n5.0000 10.0000\r\n4.0000 9.0000\r\n3.0000 8.0000\r\n2.0000 7.0000\r\n1.0000 6.0000\r\n\r\nflip(a, 1) [5 2 1 1]\r\n6.0000 1.0000\r\n7.0000 2.0000\r\n8.0000 3.0000\r\n9.0000 4.0000\r\n10.0000 5.0000</pre>\r\nThe flip function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true \">af_err af_flip(af_array *out, const af_array in, const unsigned dim) – C interface for flip()\r\n\r\narray af::flip(const array &amp;in, const unsigned dim) – C++ interface for flip()</pre>\r\n<h3>join()</h3>\r\nThe join() function joins arrays along a specific dimension. The C++ interface can join up to four arrays whereas the C interface supports up to 10 arrays. Here is an example of how to use join an array to itself:\r\n<pre class=\"lang:default decode:true \">a [5 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(0, a, a) [10 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(1, a, a) [5 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n4.0000 4.0000\r\n5.0000 5.0000</pre>\r\nThe join function has several candidate functions in C:\r\n<pre class=\"lang:default decode:true\">af_err af_join(af_array *out, const int dim, const af_array first, const af_array second) \r\n– C interface function to join 2 arrays along a dimension\r\n\r\naf_err af_join_many(af_array *out, const int dim, const unsigned n_arrays, const af_array *inputs) \r\n– C interface function to join up to 10 arrays along a dimension</pre>\r\nand in C++:\r\n<pre class=\"lang:default decode:true \">array af::join(const int dim, const array &amp;first, const array &amp;second) – Joins 2 arrays along a dimension\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third) – Joins 3 arrays along a dimension.\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third, const array &amp;fourth) – Joins 4 arrays along a dimension</pre>\r\n<h3>moddims()</h3>\r\nThe moddims() function changes the dimensions of an array without changing its data or order. Note that this function modifies only the metadata associated with the array. It does not modify the content of the array. Here is an example of moddims() converting an 8x1 array into a 2x4 and then back to a 8x1:\r\n<pre class=\"lang:default decode:true\">a [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n\r\naf::dim4 new_dims(2, 4);\r\nmoddims(a, new_dims) [2 4 1 1]\r\n1.0000 1.0000 1.0000 1.0000\r\n2.0000 2.0000 2.0000 2.0000\r\n\r\nmoddims(a, a.elements(), 1, 1, 1) [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000</pre>\r\nThe moddims function has a single form in the C API:\r\n<pre class=\"lang:default decode:true \">af_err af_moddims(af_array *out, const af_array in, const unsigned ndims, const dim_t *const dims) – C interface to mod dimensions of an array</pre>\r\nAnd several overloaded candidates in the C++ API:\r\n<pre class=\"lang:default decode:true \">array af::moddims(const array &amp;in, const unsigned ndims, const dim_t *const dims) – mods number of dimensions to match ndims as specidied in the array dims\r\n\r\narray af::moddims(const array &amp;in, const dim4 &amp;dims) – mods dimensions as specified by dims\r\n\r\narray af::moddims(const array &amp;in, const dim_t d0, const dim_t d1=1, const dim_t d2=1, const dim_t d3=1) – mods dimensions of an array</pre>\r\n<h3>reorder()</h3>\r\nThe reorder() function modifies the order of data within an array by exchanging data according to the change in dimensionality. The linear ordering of data within the array is preserved.\r\n<pre class=\"lang:default decode:true \">a [2 2 3 1]\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n\r\nreorder(a, 1, 0, 2) [2 2 3 1] //equivalent to a transpose\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n\r\nreorder(a, 2, 0, 1) [3 2 2 1]\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n3.0000 4.0000\r\n3.0000 4.0000</pre>\r\nThe reorder function has several candidates functions in the C/C++ APIs:\r\n<pre class=\"lang:default decode:true \">af_err af_reorder(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) – C interface for reordering function\r\n\r\narray af::reorder(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=2, const unsigned w=3) – Reorders dimensions of an array</pre>\r\n<h3>shift()</h3>\r\nThe shift() function shifts data in a circular buffer fashion along a chosen dimension. Consider the following example:\r\n<pre class=\"lang:default decode:true \">a [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n\r\nshift(a, 0, 2 ) [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n\r\nshift(a, -1, 2 ) [3 5 1 1]\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n0.0000 0.0000 0.0000 0.0000 0.0000</pre>\r\nThe shift function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true \">af_err af_shift(af_array *out, const af_array in, const int x, const int y, const int z, const int w) – C interface for shifting an array\r\n\r\narray af::shift(const array &amp;in, const int x, const int y=0, const int z=0, const int w=0) – Shifts array along specified dimensions</pre>\r\n<h3>tile()</h3>\r\nThe tile() function repeats an array along the specified dimension. For example below we show how to tile an array along the zeroth and first dimensions of an array:\r\n<pre class=\"lang:default decode:true\">a [3 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice in the zeroth dimension\r\ntile(a, 2) [6 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice along both the zeroth and first dimensions\r\ntile(a, 2, 2) [6 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n\r\n// Repeat array a twice along the first and three times along \r\n// the second dimension.\r\naf::dim4 tile_dims(1, 2, 3);\r\ntile(a, tile_dims) [3 2 3 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000</pre>\r\nThe C interface for tile is as follows:\r\n<pre class=\"lang:default decode:true \">af_err af_tile(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) – C interface for tiling an array</pre>\r\nThe C++ interface has two overloads\r\n<pre class=\"lang:default decode:true \">array af::tile(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=1, const unsigned w=1) – Tiles array along specified dimensions\r\n\r\narray af::tile(const array &amp;in, const dim4 &amp;dims) – Tile an array according to a dim4 object</pre>\r\n<h3>transpose()</h3>\r\nThe transpose() function performs a standard matrix transpose. The input array must have the dimensions of a 2D-matrix.\r\n<pre class=\"lang:default decode:true\">a [3 3 1 1]\r\n1.0000 3.0000 3.0000\r\n2.0000 1.0000 3.0000\r\n2.0000 2.0000 1.0000\r\n\r\ntranspose(a) [3 3 1 1]\r\n1.0000 2.0000 2.0000\r\n3.0000 1.0000 2.0000\r\n3.0000 3.0000 1.0000</pre>\r\nThe C interfaces for transpose are as follows:\r\n<pre class=\"lang:default decode:true \">af_err af_transpose(af_array *out, af_array in, const bool conjugate) – C interface to transpose a matrix.\r\n\r\naf_err af_transpose_inplace(af_array in, const bool conjugate) – C interface to transpose a matrix in-place.</pre>\r\nThe C++ interface has two primary functions and two shorthand versions:\r\n<pre class=\"lang:default decode:true \">array af::transpose(const array &amp;in, const bool conjugate=false) – Transposes a matrix.\r\n\r\nvoid af::transposeInPlace(array &amp;in, const bool conjugate=false) – Transposes a matrix in-place.\r\n\r\n__array af::T() – Transpose a matrix\r\n\r\n__array af::H() – Conjugate Transpose (Hermitian transpose) of a matrix</pre>\r\nHere is an example of how the shorthand versions might be used:\r\n<pre class=\"lang:default decode:true \">array x = randu(2, 2, f32);\r\naf_print(x.T()); // transpose (real)\r\narray c = randu(2, 2, c32);\r\naf_print(c.T()); // transpose (complex)\r\naf_print(c.H()); // Hermitian (conjugate) transpose</pre>\r\n<h3>array()</h3>\r\narray() can be used to create a (shallow) copy of a matrix with different dimensions. The total number of elements must remain the same. This function is a wrapper over the moddims() function discussed earlier.\r\n\r\nCombining re-ordering functions to enumerate grid coordinates\r\n\r\nBy using a combination of the array restructuring functions, one can quickly code complex manipulation patterns with a few lines of code. For example, consider generating (x,y) coordinates for a grid where each axis goes from 1 to n. Instead of using several loops to populate our arrays we can just use a small combination of the above functions.\r\n<pre class=\"lang:default decode:true \">unsigned n=3;\r\naf::array xy = join(1\r\ntile(seq(1, n), n)\r\nflat( transpose(tile(seq(1, n), 1, n)) )\r\n);\r\nxy [9 2 1 1]\r\n1.0000 1.0000\r\n2.0000 1.0000\r\n3.0000 1.0000\r\n1.0000 2.0000\r\n2.0000 2.0000\r\n3.0000 2.0000\r\n1.0000 3.0000\r\n2.0000 3.0000\r\n3.0000 3.0000</pre>\r\n&nbsp;\r\n\r\nasdfasdf','Manipulating and restructuring arrays','','inherit','closed','closed','','8633-revision-v1','','','2016-05-12 09:58:42','2016-05-12 13:58:42','',8633,'http://sandbox.arrayfire.com/8633-revision-v1/',0,'revision','',0),(8844,18528,'2016-05-12 10:02:34','2016-05-12 14:02:34','Programmers and Data Scientists want to take advantage of fast and parallel computational devices. One of the best ways of doing this is to write vectorized code; however, this is often easier said than done. In today\'s continuation of the blog series \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\", we will discuss the various methods by which you can maximize the performance of your code by using ArrayFire\'s built-in vectorization features.\r\n\r\n<!--more-->\r\n\r\nArrayFire provides many ways to vectorize a given code segment. In this tutorial, we present several methods to vectorize code using ArrayFire and discuss the benefits and drawbacks associated with each method.\r\n<h4><a id=\"GenericDefault_vectorization_10\"></a>Generic/Default vectorization</h4>\r\nBy its very nature, ArrayFire is a vectorized library. Most functions operate on arrays as a whole – on all elements in parallel. Wherever possible, existing vectorized functions should be used opposed to manually indexing into arrays. For example consider the following code:\r\n<pre class=\"lang:default decode:true \">af::array a = af::range(10); // [0,  9]\r\nfor(int i = 0; i &lt; a.dims(0); ++i)\r\n{\r\n    a(i) = a(i) + 1;         // [1, 10]\r\n}</pre>\r\nAlthough completely valid, the code is very inefficient as it results in a kernel kernels that operate on one datum. Instead, the developer should have used ArrayFire\'s overload of the + operator:\r\n<pre><code class=\"language-{.cpp}\">\r\naf::array a = af::range(10);  // [0,  9]\r\na = a + 1;                    // [1, 10]\r\n</code></pre>\r\nThis code will result in a single kernel that operates on all 10 elements of <code>a</code> in parallel.\r\n\r\nMost ArrayFire functions are vectorized. A small subset of these include:\r\n\r\n<strong>Arithmetic operations:</strong> +, -, *, / , %, &gt;&gt;, &lt;&lt;\r\n<strong>Logical operations:</strong> &amp;&amp;, ||, &lt;, &gt;, ==, !=\r\n<strong>Numeric functions:</strong> abs(), floor(), round(), min(), max()…\r\n<strong>Complex operations:</strong> real(), imag(), conj()…\r\n<strong>Exponential and logarithmic functions:</strong> exp(), log(), expm1(), log1p()…\r\n<strong>Trigonometric functions:</strong> sin(), cos(), tan()…\r\n<strong>Hyperbolic functions:</strong> sinh(), cosh(), tanh()…\r\n\r\nIn addition to element-wise operations, many other functions are also vectorized in ArrayFire.\r\n\r\nNotice that even that perform some form of aggregation (e.g. <code>sum()</code> or <code>min()</code>), signal processing (like <code>convolve()</code>), and even image processing functions (i.e. <code>rotate()</code>) all support vectorization on different columns or images. For example, if we have <code>NUM</code> images of size <code>WIDTH</code> by <code>HEIGHT</code>, one could convolve each image in a vector fashion as follows:\r\n<pre class=\"lang:default decode:true \">float g_coef[] = { 1, 2, 1,\r\n                   2, 4, 2,\r\n                   1, 2, 1 };\r\naf::array filter = 1.f/16 * af::array(3, 3, f_coef);\r\naf::array signal = randu(WIDTH, HEIGHT, NUM);\r\naf::array conv = convolve2(signal, filter);</pre>\r\nSimilarly, one can rotate 100 images by 45 degrees in a single call using code like the following:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// Construct an array of 100 WIDTH x HEIGHT images of random numbers\r\naf::array imgs = randu(WIDTH, HEIGHT, 100);\r\n// Rotate all of the images in a single command\r\naf::array rot_imgs = rotate(imgs, 45);</pre>\r\n</div>\r\n</div>\r\nAlthough <em>most</em> functions in ArrayFire do support vectorization, some do not. Most notably, all linear algebra functions. Even though they are not vectorized linear algebra operations still execute in parallel on your hardware.\r\n\r\nUsing the built in vectorized operations should be the first and preferred method of vectorizing any code written with ArrayFire.\r\n<h4><a id=\"GFOR_Parallel_forloops_76\"></a>GFOR: Parallel for-loops</h4>\r\nAnother novel method of vectorization present in ArrayFire is the GFOR loop replacement construct. GFOR allows launching all iterations of a loop in parallel on the GPU or device, as long as the iterations are independent. While the standard for-loop performs each iteration sequentially, ArrayFire\'s gfor-loop performs each iteration at the same time (in parallel). ArrayFire does this by tiling out the values of all loop iterations and then performing computation on those tiles in one pass. You can think of gfor as performing auto-vectorization of your code, e.g. you write a gfor-loop that increments every element of a vector but behind the scenes ArrayFire rewrites it to operate on the entire vector in parallel.\r\n\r\nThe original for-loop example at the beginning of this document could be rewritten using GFOR as follows:\r\n<pre><code class=\"language-{.cpp}\">af::array a = af::range(10);\r\ngfor(seq i, n)\r\n    a(i) = a(i) + 1;</code></pre>\r\nIn this case, each instance of the gfor loop is independent, thus ArrayFire will automatically tile out the <code>a</code> array in device memory and execute the increment kernels in parallel.\r\n\r\nTo see another example, you could run an <a class=\"el\" title=\"C++ Interface exclusive sum (cumulative sum) of an array. \" href=\"group__scan__func__accum.htm#gae450135c4ae1bdaa4489804a215f3214\">accum()</a> on every slice of a matrix in a for-loop, or you could \"vectorize\" and simply do it all in one gfor-loop operation:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// runs each accum() in sequence\r\nfor (int i = 0; i &lt; N; ++i)\r\n    B(span,i) = accum(A(span,i));\r\n \r\n// runs N accums in parallel\r\ngfor (seq i, N)\r\n    B(span,i) = accum(A(span,i));</pre>\r\n</div>\r\n</div>\r\nHowever, returning to our previous vectorization technique, <a class=\"el\" title=\"C++ Interface exclusive sum (cumulative sum) of an array. \" href=\"group__scan__func__accum.htm#gae450135c4ae1bdaa4489804a215f3214\">accum()</a> is already vectorized and the operation could be completely replaced with merely:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">B = accum(A);</pre>\r\n</div>\r\n</div>\r\nIt is best to vectorize computation as much as possible to avoid the overhead in both for-loops and gfor-loops. However, the gfor-loop construct is most effective in the narrow case of broadcast-style operations. Consider the case when we have a vector of constants that we wish to apply to a collection of variables, such as expressing the values of a linear combination for multiple vectors. The broadcast of one set of constants to many vectors works well with gfor-loops:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">const static int p=4, n=1000;\r\naf::array consts = af::randu(p);\r\naf::array var_terms = randn(p, n);\r\n \r\ngfor(seq i, n)\r\n    combination(span, i) = consts * var_terms(span, i);</pre>\r\n</div>\r\n</div>\r\nUsing GFOR requires following several rules and multiple guidelines for optimal performance. The details of this vectorization method can be found in the <a class=\"el\" href=\"page_gfor.htm#gfor\">GFOR documentation</a>.\r\n<h4><a id=\"Batching_127\"></a>Batching</h4>\r\nThe <a class=\"el\" href=\"namespaceaf.htm#aa0eb9e160f5be4b95234543e5c47934b\">batchFunc()</a> function allows the broad application of existing ArrayFire functions to multiple sets of data. Effectively,<a class=\"el\" href=\"namespaceaf.htm#aa0eb9e160f5be4b95234543e5c47934b\">batchFunc()</a> allows ArrayFire functions to execute in \"batch processing\" mode. In this mode, functions will find a dimension which contains \"batches\" of data to be processed and will parallelize the procedure.\r\n\r\nConsider the following example. Here we create a filter which we would like to apply to each of the weight vectors. The naive solution would be using a for-loop as we have seen previously:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// Create the filter and the weight vectors\r\naf::array filter = randn(1, 5);\r\naf::array weights = randu(5, 5);\r\n \r\n// Apply the filter using a for-loop\r\naf::array filtered_weights = constant(0, 5, 5);\r\nfor(int i=0; i&lt;weights.dims(1); ++i){\r\n    filtered_weights.col(i) = filter * weights.col(i);\r\n}</pre>\r\n</div>\r\n</div>\r\nHowever, as we have discussed above, this solution will be very inefficient. One may be tempted to implement a vectorized solution as follows:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// Create the filter and the weight vectors\r\naf::array filter = randn(1, 5);\r\naf::array weights = randu(5, 5);\r\n \r\naf::array filtered_weights = filter * weights; // fails due to dimension mismatch</pre>\r\n</div>\r\n</div>\r\nHowever, the dimensions of <code>filter</code> and <code>weights</code> do not match, thus ArrayFire will generate a runtime error.\r\n\r\n<code>batchfunc()</code> was created to solve this specific problem. The signature of the function is as follows:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">array batchFunc(const array &amp;lhs, const array &amp;rhs, batchFunc_t func);</pre>\r\n</div>\r\n</div>\r\nwhere <code>__batchFunc_t__</code> is a function pointer of the form:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">typedef array (*batchFunc_t) (const array &amp;lhs, const array &amp;rhs);</pre>\r\n</div>\r\n</div>\r\nSo, to use <a class=\"el\" href=\"namespaceaf.htm#aa0eb9e160f5be4b95234543e5c47934b\">batchFunc()</a>, we need to provide the function we wish to apply as a batch operation. For illustration\'s sake, let\'s \"implement\" a multiplication function following the format.\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">af::array my_mult (const af::array &amp;lhs, const af::array &amp;rhs){\r\nreturn lhs * rhs;\r\n}</pre>\r\n</div>\r\n</div>\r\nOur final batch call is not much more difficult than the ideal syntax we imagined.\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// Create the filter and the weight vectors\r\naf::array filter = randn(1, 5);\r\naf::array weights = randu(5, 5);\r\n \r\n// Apply the batch function\r\naf::array filtered_weights = batchFunc( filter, weights, my_mult );</pre>\r\n</div>\r\n</div>\r\nThe batch function will work with many previously mentioned vectorized ArrayFire functions. It can even work with a combination of those functions if they are wrapped inside a helper function matching the <code>__batchFunc_t__</code> signature. One limitation of <code>batchfunc()</code> is that it cannot be used from within a <code><a class=\"el\" href=\"gfor_8h.htm#a6d6cd11d53daad217fd0b92f5a7ceec6\">gfor()</a></code> loop at the present time.\r\n<h4><a id=\"Advanced_Vectorization_181\"></a>Advanced Vectorization</h4>\r\nWe have seen the different methods ArrayFire provides to vectorize our code. Tying them all together is a slightly more involved process that needs to consider data dimensionality and layout, memory usage, nesting order, etc. An excellent example and discussion of these factors can be found in another blog post:\r\n\r\n<a href=\"http://sandbox.arrayfire.com/how-to-write-vectorized-code/\">http://sandbox.arrayfire.com/how-to-write-vectorized-code/</a>\r\n\r\nIt’s worth noting that the whole implementation discussed in the blog has since been transformed into a convenient <strong>af::nearestNeighbour()</strong> function. Before writing something from scratch, check that ArrayFire doesn’t already have an implementation. The default vectorized nature of ArrayFire and an extensive collection of functions will speed things up in addition to replacing dozens of lines of code!','Introduction to Vectorization','','inherit','closed','closed','','8735-revision-v1','','','2016-05-12 10:02:34','2016-05-12 14:02:34','',8735,'http://sandbox.arrayfire.com/8735-revision-v1/',0,'revision','',0),(8845,18528,'2016-05-12 10:18:35','2016-05-12 14:18:35','One of the most common questions we see on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a> pertains to methods to manipulate the dimensions of ArrayFire array objects. Thus we will continue the \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" blog series by providing a detailed discussion of the numerous functions that permit you to change the dimentionality, flatten, flip, join, shift, transpose, and tile arrays.\r\n\r\n<!--more-->\r\n\r\nArrayFire provides several different methods for manipulating arrays and matrices. The functionality includes:\r\n<ul>\r\n 	<li>moddims() - change the dimensions of an array without changing the data</li>\r\n 	<li>array() - create a (shallow) copy of an array with different dimensions.</li>\r\n 	<li>flat() - flatten an array to one dimension</li>\r\n 	<li>flip() - flip an array along a dimension</li>\r\n 	<li>join() - join up to 4 arrays</li>\r\n 	<li>reorder() - changes the dimension order within the array</li>\r\n 	<li>shift() - shifts data along a dimension</li>\r\n 	<li>tile() - repeats an array along a dimension</li>\r\n 	<li>transpose() - performs a matrix transpose</li>\r\n 	<li>T() - transpose a matrix or vector (shorthand notation)</li>\r\n 	<li>H() - Hermitian Transpose (conjugate-transpose) a matrix</li>\r\n</ul>\r\nBelow we provide several examples of these functions and their use. However, if you come to this page far in the future, we suggest you <a href=\"http://arrayfire.org/docs/matrixmanipulation.htm\">visit the documentation on this topic</a> to see the latest information on these topics.\r\n<h3>flat()</h3>\r\nThe flat() function flattens an array to one dimension:\r\n<pre class=\"lang:default decode:true \">a [3 3 1 1]\r\n1.0000 4.0000 7.0000\r\n2.0000 5.0000 8.0000\r\n3.0000 6.0000 9.0000\r\n\r\nflat(a) [9 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n6.0000\r\n7.0000\r\n8.0000\r\n9.0000</pre>\r\nThe flat function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_flat(af_array* out, const af_array in) \r\n– C interface for flat() function\r\n\r\narray af::flat(const array&amp; in)\r\n– C++ interface for flat() function</pre>\r\n<h3>flip()</h3>\r\nThe flip() function flips the contents of an array along a chosen dimension. In the example below, we show the 5x2 array flipped along the zeroth (i.e. within a column) and first (e.g. across rows) axes:\r\n<pre class=\"lang:default decode:true \">a [5 2 1 1]\r\n1.0000 6.0000\r\n2.0000 7.0000\r\n3.0000 8.0000\r\n4.0000 9.0000\r\n5.0000 10.0000\r\n\r\nflip(a, 0) [5 2 1 1]\r\n5.0000 10.0000\r\n4.0000 9.0000\r\n3.0000 8.0000\r\n2.0000 7.0000\r\n1.0000 6.0000\r\n\r\nflip(a, 1) [5 2 1 1]\r\n6.0000 1.0000\r\n7.0000 2.0000\r\n8.0000 3.0000\r\n9.0000 4.0000\r\n10.0000 5.0000</pre>\r\nThe flip function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_flip(af_array *out, const af_array in, const unsigned dim) \r\n– C interface for flip()\r\n\r\narray af::flip(const array &amp;in, const unsigned dim) \r\n– C++ interface for flip()</pre>\r\n<h3>join()</h3>\r\nThe join() function joins arrays along a specific dimension. The C++ interface can join up to four arrays whereas the C interface supports up to 10 arrays. Here is an example of how to use join an array to itself:\r\n<pre class=\"lang:default decode:true \">a [5 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(0, a, a) [10 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(1, a, a) [5 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n4.0000 4.0000\r\n5.0000 5.0000</pre>\r\nThe join function has several candidate functions in C:\r\n<pre class=\"lang:default decode:true\">af_err af_join(af_array *out, const int dim, const af_array first, const af_array second) \r\n– C interface function to join 2 arrays along a dimension\r\n\r\naf_err af_join_many(af_array *out, const int dim, const unsigned n_arrays, const af_array *inputs) \r\n– C interface function to join up to 10 arrays along a dimension</pre>\r\nand in C++:\r\n<pre class=\"lang:default decode:true\">array af::join(const int dim, const array &amp;first, const array &amp;second) \r\n– Joins 2 arrays along a dimension\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third) \r\n– Joins 3 arrays along a dimension.\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third, const array &amp;fourth) \r\n– Joins 4 arrays along a dimension</pre>\r\n<h3>moddims()</h3>\r\nThe moddims() function changes the dimensions of an array without changing its data or order. Note that this function modifies only the metadata associated with the array. It does not modify the content of the array. Here is an example of moddims() converting an 8x1 array into a 2x4 and then back to a 8x1:\r\n<pre class=\"lang:default decode:true\">a [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n\r\naf::dim4 new_dims(2, 4);\r\nmoddims(a, new_dims) [2 4 1 1]\r\n1.0000 1.0000 1.0000 1.0000\r\n2.0000 2.0000 2.0000 2.0000\r\n\r\nmoddims(a, a.elements(), 1, 1, 1) [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000</pre>\r\nThe moddims function has a single form in the C API:\r\n<pre class=\"lang:default decode:true\">af_err af_moddims(af_array *out, const af_array in, const unsigned ndims, const dim_t *const dims) \r\n– C interface to mod dimensions of an array</pre>\r\nAnd several overloaded candidates in the C++ API:\r\n<pre class=\"lang:default decode:true\">array af::moddims(const array &amp;in, const unsigned ndims, const dim_t *const dims) \r\n– mods number of dimensions to match ndims as specidied in the array dims\r\n\r\narray af::moddims(const array &amp;in, const dim4 &amp;dims) \r\n– mods dimensions as specified by dims\r\n\r\narray af::moddims(const array &amp;in, const dim_t d0, const dim_t d1=1, const dim_t d2=1, const dim_t d3=1) \r\n– mods dimensions of an array</pre>\r\n<h3>reorder()</h3>\r\nThe reorder() function modifies the order of data within an array by exchanging data according to the change in dimensionality. The linear ordering of data within the array is preserved.\r\n<pre class=\"lang:default decode:true \">a [2 2 3 1]\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n\r\nreorder(a, 1, 0, 2) [2 2 3 1] //equivalent to a transpose\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n\r\nreorder(a, 2, 0, 1) [3 2 2 1]\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n3.0000 4.0000\r\n3.0000 4.0000</pre>\r\nThe reorder function has several candidates functions in the C/C++ APIs:\r\n<pre class=\"lang:default decode:true\">af_err af_reorder(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for reordering function\r\n\r\narray af::reorder(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=2, const unsigned w=3) \r\n– Reorders dimensions of an array</pre>\r\n<h3>shift()</h3>\r\nThe shift() function shifts data in a circular buffer fashion along a chosen dimension. Consider the following example:\r\n<pre class=\"lang:default decode:true \">a [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n\r\nshift(a, 0, 2 ) [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n\r\nshift(a, -1, 2 ) [3 5 1 1]\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n0.0000 0.0000 0.0000 0.0000 0.0000</pre>\r\nThe shift function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_shift(af_array *out, const af_array in, const int x, const int y, const int z, const int w) \r\n– C interface for shifting an array\r\n\r\narray af::shift(const array &amp;in, const int x, const int y=0, const int z=0, const int w=0) \r\n– Shifts array along specified dimensions</pre>\r\n<h3>tile()</h3>\r\nThe tile() function repeats an array along the specified dimension. For example below we show how to tile an array along the zeroth and first dimensions of an array:\r\n<pre class=\"lang:default decode:true\">a [3 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice in the zeroth dimension\r\ntile(a, 2) [6 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice along both the zeroth and first dimensions\r\ntile(a, 2, 2) [6 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n\r\n// Repeat array a twice along the first and three times along \r\n// the second dimension.\r\naf::dim4 tile_dims(1, 2, 3);\r\ntile(a, tile_dims) [3 2 3 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000</pre>\r\nThe C interface for tile is as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_tile(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for tiling an array</pre>\r\nThe C++ interface has two overloads\r\n<pre class=\"lang:default decode:true\">array af::tile(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=1, const unsigned w=1) \r\n– Tiles array along specified dimensions\r\n\r\narray af::tile(const array &amp;in, const dim4 &amp;dims) \r\n– Tile an array according to a dim4 object</pre>\r\n<h3>transpose()</h3>\r\nThe transpose() function performs a standard matrix transpose. The input array must have the dimensions of a 2D-matrix.\r\n<pre class=\"lang:default decode:true\">a [3 3 1 1]\r\n1.0000 3.0000 3.0000\r\n2.0000 1.0000 3.0000\r\n2.0000 2.0000 1.0000\r\n\r\ntranspose(a) [3 3 1 1]\r\n1.0000 2.0000 2.0000\r\n3.0000 1.0000 2.0000\r\n3.0000 3.0000 1.0000</pre>\r\nThe C interfaces for transpose are as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_transpose(af_array *out, af_array in, const bool conjugate) \r\n– C interface to transpose a matrix.\r\n\r\naf_err af_transpose_inplace(af_array in, const bool conjugate) \r\n– C interface to transpose a matrix in-place.</pre>\r\nThe C++ interface has two primary functions and two shorthand versions:\r\n<pre class=\"lang:default decode:true\">array af::transpose(const array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix.\r\n\r\nvoid af::transposeInPlace(array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix in-place.\r\n\r\n__array af::T() \r\n– Transpose a matrix\r\n\r\n__array af::H() \r\n– Conjugate Transpose (Hermitian transpose) of a matrix</pre>\r\nHere is an example of how the shorthand versions might be used:\r\n<pre class=\"lang:default decode:true \">array x = randu(2, 2, f32);\r\naf_print(x.T()); // transpose (real)\r\narray c = randu(2, 2, c32);\r\naf_print(c.T()); // transpose (complex)\r\naf_print(c.H()); // Hermitian (conjugate) transpose</pre>\r\n<h3>array()</h3>\r\narray() can be used to create a (shallow) copy of a matrix with different dimensions. The total number of elements must remain the same. This function is a wrapper over the moddims() function discussed earlier.\r\n\r\nCombining re-ordering functions to enumerate grid coordinates\r\n\r\nBy using a combination of the array restructuring functions, one can quickly code complex manipulation patterns with a few lines of code. For example, consider generating (x,y) coordinates for a grid where each axis goes from 1 to n. Instead of using several loops to populate our arrays we can just use a small combination of the above functions.\r\n<pre class=\"lang:default decode:true \">unsigned n=3;\r\naf::array xy = join(1\r\ntile(seq(1, n), n)\r\nflat( transpose(tile(seq(1, n), 1, n)) )\r\n);\r\nxy [9 2 1 1]\r\n1.0000 1.0000\r\n2.0000 1.0000\r\n3.0000 1.0000\r\n1.0000 2.0000\r\n2.0000 2.0000\r\n3.0000 2.0000\r\n1.0000 3.0000\r\n2.0000 3.0000\r\n3.0000 3.0000</pre>\r\n&nbsp;\r\n\r\nWe hope you have found these instructions to be useful. As always, if you have questions about ArrayFire, feel free to drop us a line on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">Google Group</a>.','Manipulating and restructuring arrays','','inherit','closed','closed','','8633-revision-v1','','','2016-05-12 10:18:35','2016-05-12 14:18:35','',8633,'http://sandbox.arrayfire.com/8633-revision-v1/',0,'revision','',0),(8846,18528,'2016-05-12 10:19:23','2016-05-12 14:19:23','One of the most common questions we see on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a> pertains to methods to manipulate the dimensions of ArrayFire array objects. Thus we will continue the \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" blog series by providing a detailed discussion of the numerous functions that permit you to change the dimentionality, flatten, flip, join, shift, transpose, and tile arrays.\r\n\r\n<!--more-->\r\n\r\nArrayFire provides several different methods for manipulating arrays and matrices. The functionality includes:\r\n<ul>\r\n 	<li>moddims() - change the dimensions of an array without changing the data</li>\r\n 	<li>array() - create a (shallow) copy of an array with different dimensions.</li>\r\n 	<li>flat() - flatten an array to one dimension</li>\r\n 	<li>flip() - flip an array along a dimension</li>\r\n 	<li>join() - join up to 4 arrays</li>\r\n 	<li>reorder() - changes the dimension order within the array</li>\r\n 	<li>shift() - shifts data along a dimension</li>\r\n 	<li>tile() - repeats an array along a dimension</li>\r\n 	<li>transpose() - performs a matrix transpose</li>\r\n 	<li>T() - transpose a matrix or vector (shorthand notation)</li>\r\n 	<li>H() - Hermitian Transpose (conjugate-transpose) a matrix</li>\r\n</ul>\r\nBelow we provide several examples of these functions and their use. However, if you come to this page far in the future, we suggest you <a href=\"http://arrayfire.org/docs/matrixmanipulation.htm\">visit the documentation on this topic</a> to see the latest information on these topics.\r\n<h4>flat()</h4>\r\nThe flat() function flattens an array to one dimension:\r\n<pre class=\"lang:default decode:true \">a [3 3 1 1]\r\n1.0000 4.0000 7.0000\r\n2.0000 5.0000 8.0000\r\n3.0000 6.0000 9.0000\r\n\r\nflat(a) [9 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n6.0000\r\n7.0000\r\n8.0000\r\n9.0000</pre>\r\nThe flat function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_flat(af_array* out, const af_array in) \r\n– C interface for flat() function\r\n\r\narray af::flat(const array&amp; in)\r\n– C++ interface for flat() function</pre>\r\n<h4>flip()</h4>\r\nThe flip() function flips the contents of an array along a chosen dimension. In the example below, we show the 5x2 array flipped along the zeroth (i.e. within a column) and first (e.g. across rows) axes:\r\n<pre class=\"lang:default decode:true \">a [5 2 1 1]\r\n1.0000 6.0000\r\n2.0000 7.0000\r\n3.0000 8.0000\r\n4.0000 9.0000\r\n5.0000 10.0000\r\n\r\nflip(a, 0) [5 2 1 1]\r\n5.0000 10.0000\r\n4.0000 9.0000\r\n3.0000 8.0000\r\n2.0000 7.0000\r\n1.0000 6.0000\r\n\r\nflip(a, 1) [5 2 1 1]\r\n6.0000 1.0000\r\n7.0000 2.0000\r\n8.0000 3.0000\r\n9.0000 4.0000\r\n10.0000 5.0000</pre>\r\nThe flip function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_flip(af_array *out, const af_array in, const unsigned dim) \r\n– C interface for flip()\r\n\r\narray af::flip(const array &amp;in, const unsigned dim) \r\n– C++ interface for flip()</pre>\r\n<h4>join()</h4>\r\nThe join() function joins arrays along a specific dimension. The C++ interface can join up to four arrays whereas the C interface supports up to 10 arrays. Here is an example of how to use join an array to itself:\r\n<pre class=\"lang:default decode:true \">a [5 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(0, a, a) [10 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(1, a, a) [5 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n4.0000 4.0000\r\n5.0000 5.0000</pre>\r\nThe join function has several candidate functions in C:\r\n<pre class=\"lang:default decode:true\">af_err af_join(af_array *out, const int dim, const af_array first, const af_array second) \r\n– C interface function to join 2 arrays along a dimension\r\n\r\naf_err af_join_many(af_array *out, const int dim, const unsigned n_arrays, const af_array *inputs) \r\n– C interface function to join up to 10 arrays along a dimension</pre>\r\nand in C++:\r\n<pre class=\"lang:default decode:true\">array af::join(const int dim, const array &amp;first, const array &amp;second) \r\n– Joins 2 arrays along a dimension\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third) \r\n– Joins 3 arrays along a dimension.\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third, const array &amp;fourth) \r\n– Joins 4 arrays along a dimension</pre>\r\n<h4>moddims()</h4>\r\nThe moddims() function changes the dimensions of an array without changing its data or order. Note that this function modifies only the metadata associated with the array. It does not modify the content of the array. Here is an example of moddims() converting an 8x1 array into a 2x4 and then back to a 8x1:\r\n<pre class=\"lang:default decode:true\">a [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n\r\naf::dim4 new_dims(2, 4);\r\nmoddims(a, new_dims) [2 4 1 1]\r\n1.0000 1.0000 1.0000 1.0000\r\n2.0000 2.0000 2.0000 2.0000\r\n\r\nmoddims(a, a.elements(), 1, 1, 1) [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000</pre>\r\nThe moddims function has a single form in the C API:\r\n<pre class=\"lang:default decode:true\">af_err af_moddims(af_array *out, const af_array in, const unsigned ndims, const dim_t *const dims) \r\n– C interface to mod dimensions of an array</pre>\r\nAnd several overloaded candidates in the C++ API:\r\n<pre class=\"lang:default decode:true\">array af::moddims(const array &amp;in, const unsigned ndims, const dim_t *const dims) \r\n– mods number of dimensions to match ndims as specidied in the array dims\r\n\r\narray af::moddims(const array &amp;in, const dim4 &amp;dims) \r\n– mods dimensions as specified by dims\r\n\r\narray af::moddims(const array &amp;in, const dim_t d0, const dim_t d1=1, const dim_t d2=1, const dim_t d3=1) \r\n– mods dimensions of an array</pre>\r\n<h4>reorder()</h4>\r\nThe reorder() function modifies the order of data within an array by exchanging data according to the change in dimensionality. The linear ordering of data within the array is preserved.\r\n<pre class=\"lang:default decode:true \">a [2 2 3 1]\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n\r\nreorder(a, 1, 0, 2) [2 2 3 1] //equivalent to a transpose\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n\r\nreorder(a, 2, 0, 1) [3 2 2 1]\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n3.0000 4.0000\r\n3.0000 4.0000</pre>\r\nThe reorder function has several candidates functions in the C/C++ APIs:\r\n<pre class=\"lang:default decode:true\">af_err af_reorder(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for reordering function\r\n\r\narray af::reorder(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=2, const unsigned w=3) \r\n– Reorders dimensions of an array</pre>\r\n<h4>shift()</h4>\r\nThe shift() function shifts data in a circular buffer fashion along a chosen dimension. Consider the following example:\r\n<pre class=\"lang:default decode:true \">a [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n\r\nshift(a, 0, 2 ) [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n\r\nshift(a, -1, 2 ) [3 5 1 1]\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n0.0000 0.0000 0.0000 0.0000 0.0000</pre>\r\nThe shift function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_shift(af_array *out, const af_array in, const int x, const int y, const int z, const int w) \r\n– C interface for shifting an array\r\n\r\narray af::shift(const array &amp;in, const int x, const int y=0, const int z=0, const int w=0) \r\n– Shifts array along specified dimensions</pre>\r\n<h4>tile()</h4>\r\nThe tile() function repeats an array along the specified dimension. For example below we show how to tile an array along the zeroth and first dimensions of an array:\r\n<pre class=\"lang:default decode:true\">a [3 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice in the zeroth dimension\r\ntile(a, 2) [6 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice along both the zeroth and first dimensions\r\ntile(a, 2, 2) [6 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n\r\n// Repeat array a twice along the first and three times along \r\n// the second dimension.\r\naf::dim4 tile_dims(1, 2, 3);\r\ntile(a, tile_dims) [3 2 3 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000</pre>\r\nThe C interface for tile is as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_tile(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for tiling an array</pre>\r\nThe C++ interface has two overloads\r\n<pre class=\"lang:default decode:true\">array af::tile(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=1, const unsigned w=1) \r\n– Tiles array along specified dimensions\r\n\r\narray af::tile(const array &amp;in, const dim4 &amp;dims) \r\n– Tile an array according to a dim4 object</pre>\r\n<h4>transpose()</h4>\r\nThe transpose() function performs a standard matrix transpose. The input array must have the dimensions of a 2D-matrix.\r\n<pre class=\"lang:default decode:true\">a [3 3 1 1]\r\n1.0000 3.0000 3.0000\r\n2.0000 1.0000 3.0000\r\n2.0000 2.0000 1.0000\r\n\r\ntranspose(a) [3 3 1 1]\r\n1.0000 2.0000 2.0000\r\n3.0000 1.0000 2.0000\r\n3.0000 3.0000 1.0000</pre>\r\nThe C interfaces for transpose are as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_transpose(af_array *out, af_array in, const bool conjugate) \r\n– C interface to transpose a matrix.\r\n\r\naf_err af_transpose_inplace(af_array in, const bool conjugate) \r\n– C interface to transpose a matrix in-place.</pre>\r\nThe C++ interface has two primary functions and two shorthand versions:\r\n<pre class=\"lang:default decode:true\">array af::transpose(const array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix.\r\n\r\nvoid af::transposeInPlace(array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix in-place.\r\n\r\n__array af::T() \r\n– Transpose a matrix\r\n\r\n__array af::H() \r\n– Conjugate Transpose (Hermitian transpose) of a matrix</pre>\r\nHere is an example of how the shorthand versions might be used:\r\n<pre class=\"lang:default decode:true \">array x = randu(2, 2, f32);\r\naf_print(x.T()); // transpose (real)\r\narray c = randu(2, 2, c32);\r\naf_print(c.T()); // transpose (complex)\r\naf_print(c.H()); // Hermitian (conjugate) transpose</pre>\r\n<h4>array()</h4>\r\narray() can be used to create a (shallow) copy of a matrix with different dimensions. The total number of elements must remain the same. This function is a wrapper over the moddims() function discussed earlier.\r\n\r\nCombining re-ordering functions to enumerate grid coordinates\r\n\r\nBy using a combination of the array restructuring functions, one can quickly code complex manipulation patterns with a few lines of code. For example, consider generating (x,y) coordinates for a grid where each axis goes from 1 to n. Instead of using several loops to populate our arrays we can just use a small combination of the above functions.\r\n<pre class=\"lang:default decode:true \">unsigned n=3;\r\naf::array xy = join(1\r\ntile(seq(1, n), n)\r\nflat( transpose(tile(seq(1, n), 1, n)) )\r\n);\r\nxy [9 2 1 1]\r\n1.0000 1.0000\r\n2.0000 1.0000\r\n3.0000 1.0000\r\n1.0000 2.0000\r\n2.0000 2.0000\r\n3.0000 2.0000\r\n1.0000 3.0000\r\n2.0000 3.0000\r\n3.0000 3.0000</pre>\r\nWe hope you have found these instructions to be useful. As always, if you have questions about ArrayFire, feel free to drop us a line on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">Google Group</a>.','Manipulating and restructuring arrays','','inherit','closed','closed','','8633-revision-v1','','','2016-05-12 10:19:23','2016-05-12 14:19:23','',8633,'http://sandbox.arrayfire.com/8633-revision-v1/',0,'revision','',0),(8847,18528,'2016-05-12 10:27:41','2016-05-12 14:27:41','One of the most common questions we see on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a> pertains to methods to manipulate the dimensions of ArrayFire array objects. Thus we will continue the \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" blog series by providing a detailed discussion of the numerous functions that permit you to change the dimentionality, flatten, flip, join, shift, transpose, and tile arrays.\r\n\r\n<!--more-->\r\n\r\nArrayFire provides several different methods for manipulating arrays and matrices. The functionality includes:\r\n<ul>\r\n 	<li><a href=\"#moddims\">moddims()</a> - change the dimensions of an array without changing the data</li>\r\n 	<li><a href=\"#array\">array()</a> - create a (shallow) copy of an array with different dimensions.</li>\r\n 	<li><a href=\"#flat\">flat()</a> - flatten an array to one dimension</li>\r\n 	<li>flip() - flip an array along a dimension</li>\r\n 	<li>join() - join up to 4 arrays</li>\r\n 	<li>reorder() - changes the dimension order within the array</li>\r\n 	<li>shift() - shifts data along a dimension</li>\r\n 	<li>tile() - repeats an array along a dimension</li>\r\n 	<li>transpose() - performs a matrix transpose</li>\r\n 	<li>T() - transpose a matrix or vector (shorthand notation)</li>\r\n 	<li>H() - Hermitian Transpose (conjugate-transpose) a matrix</li>\r\n</ul>\r\nBelow we provide several examples of these functions and their use. However, if you come to this page far in the future, we suggest you <a href=\"http://arrayfire.org/docs/matrixmanipulation.htm\">visit the documentation on this topic</a> to see the latest information on these topics.\r\n<h4 id=\"flat\">flat()</h4>\r\nThe flat() function flattens an array to one dimension:\r\n<pre class=\"lang:default decode:true \">a [3 3 1 1]\r\n1.0000 4.0000 7.0000\r\n2.0000 5.0000 8.0000\r\n3.0000 6.0000 9.0000\r\n\r\nflat(a) [9 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n6.0000\r\n7.0000\r\n8.0000\r\n9.0000</pre>\r\nThe flat function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_flat(af_array* out, const af_array in) \r\n– C interface for flat() function\r\n\r\narray af::flat(const array&amp; in)\r\n– C++ interface for flat() function</pre>\r\n<h4>flip()</h4>\r\nThe flip() function flips the contents of an array along a chosen dimension. In the example below, we show the 5x2 array flipped along the zeroth (i.e. within a column) and first (e.g. across rows) axes:\r\n<pre class=\"lang:default decode:true \">a [5 2 1 1]\r\n1.0000 6.0000\r\n2.0000 7.0000\r\n3.0000 8.0000\r\n4.0000 9.0000\r\n5.0000 10.0000\r\n\r\nflip(a, 0) [5 2 1 1]\r\n5.0000 10.0000\r\n4.0000 9.0000\r\n3.0000 8.0000\r\n2.0000 7.0000\r\n1.0000 6.0000\r\n\r\nflip(a, 1) [5 2 1 1]\r\n6.0000 1.0000\r\n7.0000 2.0000\r\n8.0000 3.0000\r\n9.0000 4.0000\r\n10.0000 5.0000</pre>\r\nThe flip function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_flip(af_array *out, const af_array in, const unsigned dim) \r\n– C interface for flip()\r\n\r\narray af::flip(const array &amp;in, const unsigned dim) \r\n– C++ interface for flip()</pre>\r\n<h4>join()</h4>\r\nThe join() function joins arrays along a specific dimension. The C++ interface can join up to four arrays whereas the C interface supports up to 10 arrays. Here is an example of how to use join an array to itself:\r\n<pre class=\"lang:default decode:true \">a [5 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(0, a, a) [10 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(1, a, a) [5 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n4.0000 4.0000\r\n5.0000 5.0000</pre>\r\nThe join function has several candidate functions in C:\r\n<pre class=\"lang:default decode:true\">af_err af_join(af_array *out, const int dim, const af_array first, const af_array second) \r\n– C interface function to join 2 arrays along a dimension\r\n\r\naf_err af_join_many(af_array *out, const int dim, const unsigned n_arrays, const af_array *inputs) \r\n– C interface function to join up to 10 arrays along a dimension</pre>\r\nand in C++:\r\n<pre class=\"lang:default decode:true\">array af::join(const int dim, const array &amp;first, const array &amp;second) \r\n– Joins 2 arrays along a dimension\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third) \r\n– Joins 3 arrays along a dimension.\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third, const array &amp;fourth) \r\n– Joins 4 arrays along a dimension</pre>\r\n<h4>moddims()</h4>\r\nThe moddims() function changes the dimensions of an array without changing its data or order. Note that this function modifies only the metadata associated with the array. It does not modify the content of the array. Here is an example of moddims() converting an 8x1 array into a 2x4 and then back to a 8x1:\r\n<pre class=\"lang:default decode:true\">a [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n\r\naf::dim4 new_dims(2, 4);\r\nmoddims(a, new_dims) [2 4 1 1]\r\n1.0000 1.0000 1.0000 1.0000\r\n2.0000 2.0000 2.0000 2.0000\r\n\r\nmoddims(a, a.elements(), 1, 1, 1) [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000</pre>\r\nThe moddims function has a single form in the C API:\r\n<pre class=\"lang:default decode:true\">af_err af_moddims(af_array *out, const af_array in, const unsigned ndims, const dim_t *const dims) \r\n– C interface to mod dimensions of an array</pre>\r\nAnd several overloaded candidates in the C++ API:\r\n<pre class=\"lang:default decode:true\">array af::moddims(const array &amp;in, const unsigned ndims, const dim_t *const dims) \r\n– mods number of dimensions to match ndims as specidied in the array dims\r\n\r\narray af::moddims(const array &amp;in, const dim4 &amp;dims) \r\n– mods dimensions as specified by dims\r\n\r\narray af::moddims(const array &amp;in, const dim_t d0, const dim_t d1=1, const dim_t d2=1, const dim_t d3=1) \r\n– mods dimensions of an array</pre>\r\n<h4>reorder()</h4>\r\nThe reorder() function modifies the order of data within an array by exchanging data according to the change in dimensionality. The linear ordering of data within the array is preserved.\r\n<pre class=\"lang:default decode:true \">a [2 2 3 1]\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n\r\nreorder(a, 1, 0, 2) [2 2 3 1] //equivalent to a transpose\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n\r\nreorder(a, 2, 0, 1) [3 2 2 1]\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n3.0000 4.0000\r\n3.0000 4.0000</pre>\r\nThe reorder function has several candidates functions in the C/C++ APIs:\r\n<pre class=\"lang:default decode:true\">af_err af_reorder(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for reordering function\r\n\r\narray af::reorder(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=2, const unsigned w=3) \r\n– Reorders dimensions of an array</pre>\r\n<h4>shift()</h4>\r\nThe shift() function shifts data in a circular buffer fashion along a chosen dimension. Consider the following example:\r\n<pre class=\"lang:default decode:true \">a [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n\r\nshift(a, 0, 2 ) [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n\r\nshift(a, -1, 2 ) [3 5 1 1]\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n0.0000 0.0000 0.0000 0.0000 0.0000</pre>\r\nThe shift function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_shift(af_array *out, const af_array in, const int x, const int y, const int z, const int w) \r\n– C interface for shifting an array\r\n\r\narray af::shift(const array &amp;in, const int x, const int y=0, const int z=0, const int w=0) \r\n– Shifts array along specified dimensions</pre>\r\n<h4>tile()</h4>\r\nThe tile() function repeats an array along the specified dimension. For example below we show how to tile an array along the zeroth and first dimensions of an array:\r\n<pre class=\"lang:default decode:true\">a [3 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice in the zeroth dimension\r\ntile(a, 2) [6 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice along both the zeroth and first dimensions\r\ntile(a, 2, 2) [6 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n\r\n// Repeat array a twice along the first and three times along \r\n// the second dimension.\r\naf::dim4 tile_dims(1, 2, 3);\r\ntile(a, tile_dims) [3 2 3 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000</pre>\r\nThe C interface for tile is as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_tile(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for tiling an array</pre>\r\nThe C++ interface has two overloads\r\n<pre class=\"lang:default decode:true\">array af::tile(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=1, const unsigned w=1) \r\n– Tiles array along specified dimensions\r\n\r\narray af::tile(const array &amp;in, const dim4 &amp;dims) \r\n– Tile an array according to a dim4 object</pre>\r\n<h4>transpose()</h4>\r\nThe transpose() function performs a standard matrix transpose. The input array must have the dimensions of a 2D-matrix.\r\n<pre class=\"lang:default decode:true\">a [3 3 1 1]\r\n1.0000 3.0000 3.0000\r\n2.0000 1.0000 3.0000\r\n2.0000 2.0000 1.0000\r\n\r\ntranspose(a) [3 3 1 1]\r\n1.0000 2.0000 2.0000\r\n3.0000 1.0000 2.0000\r\n3.0000 3.0000 1.0000</pre>\r\nThe C interfaces for transpose are as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_transpose(af_array *out, af_array in, const bool conjugate) \r\n– C interface to transpose a matrix.\r\n\r\naf_err af_transpose_inplace(af_array in, const bool conjugate) \r\n– C interface to transpose a matrix in-place.</pre>\r\nThe C++ interface has two primary functions and two shorthand versions:\r\n<pre class=\"lang:default decode:true\">array af::transpose(const array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix.\r\n\r\nvoid af::transposeInPlace(array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix in-place.\r\n\r\n__array af::T() \r\n– Transpose a matrix\r\n\r\n__array af::H() \r\n– Conjugate Transpose (Hermitian transpose) of a matrix</pre>\r\nHere is an example of how the shorthand versions might be used:\r\n<pre class=\"lang:default decode:true \">array x = randu(2, 2, f32);\r\naf_print(x.T()); // transpose (real)\r\narray c = randu(2, 2, c32);\r\naf_print(c.T()); // transpose (complex)\r\naf_print(c.H()); // Hermitian (conjugate) transpose</pre>\r\n<h4>array()</h4>\r\narray() can be used to create a (shallow) copy of a matrix with different dimensions. The total number of elements must remain the same. This function is a wrapper over the moddims() function discussed earlier.\r\n\r\nCombining re-ordering functions to enumerate grid coordinates\r\n\r\nBy using a combination of the array restructuring functions, one can quickly code complex manipulation patterns with a few lines of code. For example, consider generating (x,y) coordinates for a grid where each axis goes from 1 to n. Instead of using several loops to populate our arrays we can just use a small combination of the above functions.\r\n<pre class=\"lang:default decode:true \">unsigned n=3;\r\naf::array xy = join(1\r\ntile(seq(1, n), n)\r\nflat( transpose(tile(seq(1, n), 1, n)) )\r\n);\r\nxy [9 2 1 1]\r\n1.0000 1.0000\r\n2.0000 1.0000\r\n3.0000 1.0000\r\n1.0000 2.0000\r\n2.0000 2.0000\r\n3.0000 2.0000\r\n1.0000 3.0000\r\n2.0000 3.0000\r\n3.0000 3.0000</pre>\r\nWe hope you have found these instructions to be useful. As always, if you have questions about ArrayFire, feel free to drop us a line on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">Google Group</a>.','Manipulating and restructuring arrays','','inherit','closed','closed','','8633-revision-v1','','','2016-05-12 10:27:41','2016-05-12 14:27:41','',8633,'http://sandbox.arrayfire.com/8633-revision-v1/',0,'revision','',0),(8848,18528,'2016-05-12 10:32:09','2016-05-12 14:32:09','One of the most common questions we see on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a> pertains to methods to manipulate the dimensions of ArrayFire array objects. Thus we will continue the \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" blog series by providing a detailed discussion of the numerous functions that permit you to change the dimentionality, flatten, flip, join, shift, transpose, and tile arrays.\r\n\r\n<!--more-->\r\n\r\nArrayFire provides several different methods for manipulating arrays and matrices. The functionality includes:\r\n<ul>\r\n 	<li><a href=\"#moddims\">moddims()</a> - change the dimensions of an array without changing the data</li>\r\n 	<li><a href=\"#array\">array()</a> - create a (shallow) copy of an array with different dimensions.</li>\r\n 	<li><a href=\"#flat\">flat()</a> - flatten an array to one dimension</li>\r\n 	<li>flip() - flip an array along a dimension</li>\r\n 	<li>join() - join up to 4 arrays</li>\r\n 	<li>reorder() - changes the dimension order within the array</li>\r\n 	<li>shift() - shifts data along a dimension</li>\r\n 	<li>tile() - repeats an array along a dimension</li>\r\n 	<li>transpose() - performs a matrix transpose</li>\r\n 	<li>T() - transpose a matrix or vector (shorthand notation)</li>\r\n 	<li>H() - Hermitian Transpose (conjugate-transpose) a matrix</li>\r\n</ul>\r\nBelow we provide several examples of these functions and their use. However, if you come to this page far in the future, we suggest you <a href=\"http://arrayfire.org/docs/matrixmanipulation.htm\">visit the documentation on this topic</a> to see the latest information on these topics.\r\n<a name=\"flat\"></a>\r\n<h4>flat()</h4>\r\n<a name=\"flat\"></a>\r\n\r\nThe flat() function flattens an array to one dimension:\r\n\r\n<a name=\"flat\"></a>\r\n<pre class=\"lang:default decode:true \">a [3 3 1 1]\r\n1.0000 4.0000 7.0000\r\n2.0000 5.0000 8.0000\r\n3.0000 6.0000 9.0000\r\n\r\nflat(a) [9 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n6.0000\r\n7.0000\r\n8.0000\r\n9.0000</pre>\r\n<a name=\"flat\"></a>\r\n\r\nThe flat function can be called from C and C++ as follows:\r\n\r\n<a name=\"flat\"></a>\r\n<pre class=\"lang:default decode:true\">af_err af_flat(af_array* out, const af_array in) \r\n– C interface for flat() function\r\n\r\narray af::flat(const array&amp; in)\r\n– C++ interface for flat() function</pre>\r\n<a name=\"flat\"></a>\r\n\r\n<a name=\"flip\"></a>\r\n<h4>flip()</h4>\r\n<a name=\"flip\"></a>\r\n\r\nThe flip() function flips the contents of an array along a chosen dimension. In the example below, we show the 5x2 array flipped along the zeroth (i.e. within a column) and first (e.g. across rows) axes:\r\n\r\n<a name=\"flip\"></a>\r\n<pre class=\"lang:default decode:true \">a [5 2 1 1]\r\n1.0000 6.0000\r\n2.0000 7.0000\r\n3.0000 8.0000\r\n4.0000 9.0000\r\n5.0000 10.0000\r\n\r\nflip(a, 0) [5 2 1 1]\r\n5.0000 10.0000\r\n4.0000 9.0000\r\n3.0000 8.0000\r\n2.0000 7.0000\r\n1.0000 6.0000\r\n\r\nflip(a, 1) [5 2 1 1]\r\n6.0000 1.0000\r\n7.0000 2.0000\r\n8.0000 3.0000\r\n9.0000 4.0000\r\n10.0000 5.0000</pre>\r\n<a name=\"flip\"></a>\r\n\r\nThe flip function can be called from C and C++ as follows:\r\n\r\n<a name=\"flip\"></a>\r\n<pre class=\"lang:default decode:true\">af_err af_flip(af_array *out, const af_array in, const unsigned dim) \r\n– C interface for flip()\r\n\r\narray af::flip(const array &amp;in, const unsigned dim) \r\n– C++ interface for flip()</pre>\r\n<a name=\"flip\"></a>\r\n\r\n<a name=\"join\"></a>\r\n<h4>join()</h4>\r\n<a name=\"join\"></a>\r\n\r\nThe join() function joins arrays along a specific dimension. The C++ interface can join up to four arrays whereas the C interface supports up to 10 arrays. Here is an example of how to use join an array to itself:\r\n\r\n<a name=\"join\"></a>\r\n<pre class=\"lang:default decode:true \">a [5 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(0, a, a) [10 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(1, a, a) [5 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n4.0000 4.0000\r\n5.0000 5.0000</pre>\r\n<a name=\"join\"></a>\r\n\r\nThe join function has several candidate functions in C:\r\n\r\n<a name=\"join\"></a>\r\n<pre class=\"lang:default decode:true\">af_err af_join(af_array *out, const int dim, const af_array first, const af_array second) \r\n– C interface function to join 2 arrays along a dimension\r\n\r\naf_err af_join_many(af_array *out, const int dim, const unsigned n_arrays, const af_array *inputs) \r\n– C interface function to join up to 10 arrays along a dimension</pre>\r\n<a name=\"join\"></a>\r\n\r\nand in C++:\r\n\r\n<a name=\"join\"></a>\r\n<pre class=\"lang:default decode:true\">array af::join(const int dim, const array &amp;first, const array &amp;second) \r\n– Joins 2 arrays along a dimension\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third) \r\n– Joins 3 arrays along a dimension.\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third, const array &amp;fourth) \r\n– Joins 4 arrays along a dimension</pre>\r\n<a name=\"join\"></a>\r\n\r\n<a name=\"moddims\"></a>\r\n<h4>moddims()</h4>\r\n<a name=\"moddims\"></a>\r\n\r\nThe moddims() function changes the dimensions of an array without changing its data or order. Note that this function modifies only the metadata associated with the array. It does not modify the content of the array. Here is an example of moddims() converting an 8x1 array into a 2x4 and then back to a 8x1:\r\n\r\n<a name=\"moddims\"></a>\r\n<pre class=\"lang:default decode:true\">a [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n\r\naf::dim4 new_dims(2, 4);\r\nmoddims(a, new_dims) [2 4 1 1]\r\n1.0000 1.0000 1.0000 1.0000\r\n2.0000 2.0000 2.0000 2.0000\r\n\r\nmoddims(a, a.elements(), 1, 1, 1) [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000</pre>\r\n<a name=\"moddims\"></a>\r\n\r\nThe moddims function has a single form in the C API:\r\n\r\n<a name=\"moddims\"></a>\r\n<pre class=\"lang:default decode:true\">af_err af_moddims(af_array *out, const af_array in, const unsigned ndims, const dim_t *const dims) \r\n– C interface to mod dimensions of an array</pre>\r\n<a name=\"moddims\"></a>\r\n\r\nAnd several overloaded candidates in the C++ API:\r\n\r\n<a name=\"moddims\"></a>\r\n<pre class=\"lang:default decode:true\">array af::moddims(const array &amp;in, const unsigned ndims, const dim_t *const dims) \r\n– mods number of dimensions to match ndims as specidied in the array dims\r\n\r\narray af::moddims(const array &amp;in, const dim4 &amp;dims) \r\n– mods dimensions as specified by dims\r\n\r\narray af::moddims(const array &amp;in, const dim_t d0, const dim_t d1=1, const dim_t d2=1, const dim_t d3=1) \r\n– mods dimensions of an array</pre>\r\n<a name=\"moddims\"></a>\r\n\r\n<a name=\"reorder\"></a>\r\n<h4>reorder()</h4>\r\n<a name=\"reorder\"></a>\r\n\r\nThe reorder() function modifies the order of data within an array by exchanging data according to the change in dimensionality. The linear ordering of data within the array is preserved.\r\n\r\n<a name=\"reorder\"></a>\r\n<pre class=\"lang:default decode:true \">a [2 2 3 1]\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n\r\nreorder(a, 1, 0, 2) [2 2 3 1] //equivalent to a transpose\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n\r\nreorder(a, 2, 0, 1) [3 2 2 1]\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n3.0000 4.0000\r\n3.0000 4.0000</pre>\r\n<a name=\"reorder\"></a>\r\n\r\nThe reorder function has several candidates functions in the C/C++ APIs:\r\n\r\n<a name=\"reorder\"></a>\r\n<pre class=\"lang:default decode:true\">af_err af_reorder(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for reordering function\r\n\r\narray af::reorder(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=2, const unsigned w=3) \r\n– Reorders dimensions of an array</pre>\r\n<a name=\"reorder\"></a>\r\n\r\n<a name=\"shift\"></a>\r\n<h4>shift()</h4>\r\n<a name=\"shift\"></a>\r\n\r\nThe shift() function shifts data in a circular buffer fashion along a chosen dimension. Consider the following example:\r\n\r\n<a name=\"shift\"></a>\r\n<pre class=\"lang:default decode:true \">a [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n\r\nshift(a, 0, 2 ) [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n\r\nshift(a, -1, 2 ) [3 5 1 1]\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n0.0000 0.0000 0.0000 0.0000 0.0000</pre>\r\n<a name=\"shift\"></a>\r\n\r\nThe shift function can be called from C and C++ as follows:\r\n\r\n<a name=\"shift\"></a>\r\n<pre class=\"lang:default decode:true\">af_err af_shift(af_array *out, const af_array in, const int x, const int y, const int z, const int w) \r\n– C interface for shifting an array\r\n\r\narray af::shift(const array &amp;in, const int x, const int y=0, const int z=0, const int w=0) \r\n– Shifts array along specified dimensions</pre>\r\n<a name=\"shift\"></a>\r\n\r\n<a name=\"tile\"></a>\r\n<h4>tile()</h4>\r\n<a name=\"tile\"></a>\r\n\r\nThe tile() function repeats an array along the specified dimension. For example below we show how to tile an array along the zeroth and first dimensions of an array:\r\n\r\n<a name=\"tile\"></a>\r\n<pre class=\"lang:default decode:true\">a [3 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice in the zeroth dimension\r\ntile(a, 2) [6 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice along both the zeroth and first dimensions\r\ntile(a, 2, 2) [6 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n\r\n// Repeat array a twice along the first and three times along \r\n// the second dimension.\r\naf::dim4 tile_dims(1, 2, 3);\r\ntile(a, tile_dims) [3 2 3 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000</pre>\r\n<a name=\"tile\"></a>\r\n\r\nThe C interface for tile is as follows:\r\n\r\n<a name=\"tile\"></a>\r\n<pre class=\"lang:default decode:true\">af_err af_tile(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for tiling an array</pre>\r\n<a name=\"tile\"></a>\r\n\r\nThe C++ interface has two overloads\r\n\r\n<a name=\"tile\"></a>\r\n<pre class=\"lang:default decode:true\">array af::tile(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=1, const unsigned w=1) \r\n– Tiles array along specified dimensions\r\n\r\narray af::tile(const array &amp;in, const dim4 &amp;dims) \r\n– Tile an array according to a dim4 object</pre>\r\n<a name=\"tile\"></a>\r\n\r\n<a name=\"transpose\"></a>\r\n<h4>transpose()</h4>\r\n<a name=\"transpose\"></a>\r\n\r\nThe transpose() function performs a standard matrix transpose. The input array must have the dimensions of a 2D-matrix.\r\n\r\n<a name=\"transpose\"></a>\r\n<pre class=\"lang:default decode:true\">a [3 3 1 1]\r\n1.0000 3.0000 3.0000\r\n2.0000 1.0000 3.0000\r\n2.0000 2.0000 1.0000\r\n\r\ntranspose(a) [3 3 1 1]\r\n1.0000 2.0000 2.0000\r\n3.0000 1.0000 2.0000\r\n3.0000 3.0000 1.0000</pre>\r\n<a name=\"transpose\"></a>\r\n\r\nThe C interfaces for transpose are as follows:\r\n\r\n<a name=\"transpose\"></a>\r\n<pre class=\"lang:default decode:true\">af_err af_transpose(af_array *out, af_array in, const bool conjugate) \r\n– C interface to transpose a matrix.\r\n\r\naf_err af_transpose_inplace(af_array in, const bool conjugate) \r\n– C interface to transpose a matrix in-place.</pre>\r\n<a name=\"transpose\"></a>\r\n\r\nThe C++ interface has two primary functions and two shorthand versions:\r\n\r\n<a name=\"transpose\"></a>\r\n<pre class=\"lang:default decode:true\">array af::transpose(const array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix.\r\n\r\nvoid af::transposeInPlace(array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix in-place.\r\n\r\n__array af::T() \r\n– Transpose a matrix\r\n\r\n__array af::H() \r\n– Conjugate Transpose (Hermitian transpose) of a matrix</pre>\r\n<a name=\"transpose\"></a>\r\n\r\nHere is an example of how the shorthand versions might be used:\r\n\r\n<a name=\"transpose\"></a>\r\n<pre class=\"lang:default decode:true \">array x = randu(2, 2, f32);\r\naf_print(x.T()); // transpose (real)\r\narray c = randu(2, 2, c32);\r\naf_print(c.T()); // transpose (complex)\r\naf_print(c.H()); // Hermitian (conjugate) transpose</pre>\r\n<a name=\"transpose\"></a>\r\n\r\n<a name=\"array\"></a>\r\n<h4>array()</h4>\r\n<a name=\"array\"></a>\r\n\r\narray() can be used to create a (shallow) copy of a matrix with different dimensions. The total number of elements must remain the same. This function is a wrapper over the moddims() function discussed earlier.\r\n\r\n<a name=\"array\"></a>\r\n\r\nCombining re-ordering functions to enumerate grid coordinates\r\n\r\n<a name=\"array\"></a>\r\n\r\nBy using a combination of the array restructuring functions, one can quickly code complex manipulation patterns with a few lines of code. For example, consider generating (x,y) coordinates for a grid where each axis goes from 1 to n. Instead of using several loops to populate our arrays we can just use a small combination of the above functions.\r\n\r\n<a name=\"array\"></a>\r\n<pre class=\"lang:default decode:true \">unsigned n=3;\r\naf::array xy = join(1\r\ntile(seq(1, n), n)\r\nflat( transpose(tile(seq(1, n), 1, n)) )\r\n);\r\nxy [9 2 1 1]\r\n1.0000 1.0000\r\n2.0000 1.0000\r\n3.0000 1.0000\r\n1.0000 2.0000\r\n2.0000 2.0000\r\n3.0000 2.0000\r\n1.0000 3.0000\r\n2.0000 3.0000\r\n3.0000 3.0000</pre>\r\n<a name=\"array\"></a>\r\n\r\nWe hope you have found these instructions to be useful. As always, if you have questions about ArrayFire, feel free to drop us a line on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">Google Group</a>.\r\n\r\n<a name=\"array\"></a>\r\n\r\n<a name=\"transpose\"></a>\r\n\r\n<a name=\"tile\"></a>\r\n\r\n<a name=\"shift\"></a>\r\n\r\n<a name=\"reorder\"></a>\r\n\r\n<a name=\"moddims\"></a>\r\n\r\n<a name=\"join\"></a>\r\n\r\n<a name=\"flip\"></a>\r\n\r\n<a name=\"flat\"></a>','Manipulating and restructuring arrays','','inherit','closed','closed','','8633-revision-v1','','','2016-05-12 10:32:09','2016-05-12 14:32:09','',8633,'http://sandbox.arrayfire.com/8633-revision-v1/',0,'revision','',0),(8849,18528,'2016-05-12 10:33:43','2016-05-12 14:33:43','One of the most common questions we see on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a> pertains to methods to manipulate the dimensions of ArrayFire array objects. Thus we will continue the \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" blog series by providing a detailed discussion of the numerous functions that permit you to change the dimentionality, flatten, flip, join, shift, transpose, and tile arrays.\r\n\r\n<!--more-->\r\n\r\nArrayFire provides several different methods for manipulating arrays and matrices. The functionality includes:\r\n<ul>\r\n 	<li><a href=\"#moddims\">moddims()</a> - change the dimensions of an array without changing the data</li>\r\n 	<li><a href=\"#array\">array()</a> - create a (shallow) copy of an array with different dimensions.</li>\r\n 	<li><a href=\"#flat\">flat()</a> - flatten an array to one dimension</li>\r\n 	<li><a href=\"http://flip\">flip()</a> - flip an array along a dimension</li>\r\n 	<li><a href=\"http://join\">join()</a> - join up to 4 arrays</li>\r\n 	<li><a href=\"http://reorder\">reorder()</a> - changes the dimension order within the array</li>\r\n 	<li><a href=\"http://shift\">shift()</a> - shifts data along a dimension</li>\r\n 	<li><a href=\"http://tile\">tile()</a> - repeats an array along a dimension</li>\r\n 	<li><a href=\"http://transpose\">transpose()</a> - performs a matrix transpose</li>\r\n 	<li><a href=\"http://transpose\">T()</a> - transpose a matrix or vector (shorthand notation)</li>\r\n 	<li><a href=\"http://transpose\">H()</a> - Hermitian Transpose (conjugate-transpose) a matrix</li>\r\n</ul>\r\nBelow we provide several examples of these functions and their use. However, if you come to this page far in the future, we suggest you <a href=\"http://arrayfire.org/docs/matrixmanipulation.htm\">visit the documentation on this topic</a> to see the latest information on these topics.\r\n<a name=\"flat\"></a>\r\n<h4>flat()</h4>\r\n<a name=\"flat\"></a>\r\n\r\nThe flat() function flattens an array to one dimension:\r\n\r\n<a name=\"flat\"></a>\r\n<pre class=\"lang:default decode:true \">a [3 3 1 1]\r\n1.0000 4.0000 7.0000\r\n2.0000 5.0000 8.0000\r\n3.0000 6.0000 9.0000\r\n\r\nflat(a) [9 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n6.0000\r\n7.0000\r\n8.0000\r\n9.0000</pre>\r\n<a name=\"flat\"></a>\r\n\r\nThe flat function can be called from C and C++ as follows:\r\n\r\n<a name=\"flat\"></a>\r\n<pre class=\"lang:default decode:true\">af_err af_flat(af_array* out, const af_array in) \r\n– C interface for flat() function\r\n\r\narray af::flat(const array&amp; in)\r\n– C++ interface for flat() function</pre>\r\n<a name=\"flat\"></a>\r\n\r\n<a name=\"flip\"></a>\r\n<h4>flip()</h4>\r\n<a name=\"flip\"></a>\r\n\r\nThe flip() function flips the contents of an array along a chosen dimension. In the example below, we show the 5x2 array flipped along the zeroth (i.e. within a column) and first (e.g. across rows) axes:\r\n\r\n<a name=\"flip\"></a>\r\n<pre class=\"lang:default decode:true \">a [5 2 1 1]\r\n1.0000 6.0000\r\n2.0000 7.0000\r\n3.0000 8.0000\r\n4.0000 9.0000\r\n5.0000 10.0000\r\n\r\nflip(a, 0) [5 2 1 1]\r\n5.0000 10.0000\r\n4.0000 9.0000\r\n3.0000 8.0000\r\n2.0000 7.0000\r\n1.0000 6.0000\r\n\r\nflip(a, 1) [5 2 1 1]\r\n6.0000 1.0000\r\n7.0000 2.0000\r\n8.0000 3.0000\r\n9.0000 4.0000\r\n10.0000 5.0000</pre>\r\n<a name=\"flip\"></a>\r\n\r\nThe flip function can be called from C and C++ as follows:\r\n\r\n<a name=\"flip\"></a>\r\n<pre class=\"lang:default decode:true\">af_err af_flip(af_array *out, const af_array in, const unsigned dim) \r\n– C interface for flip()\r\n\r\narray af::flip(const array &amp;in, const unsigned dim) \r\n– C++ interface for flip()</pre>\r\n<a name=\"flip\"></a>\r\n\r\n<a name=\"join\"></a>\r\n<h4>join()</h4>\r\n<a name=\"join\"></a>\r\n\r\nThe join() function joins arrays along a specific dimension. The C++ interface can join up to four arrays whereas the C interface supports up to 10 arrays. Here is an example of how to use join an array to itself:\r\n\r\n<a name=\"join\"></a>\r\n<pre class=\"lang:default decode:true \">a [5 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(0, a, a) [10 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(1, a, a) [5 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n4.0000 4.0000\r\n5.0000 5.0000</pre>\r\n<a name=\"join\"></a>\r\n\r\nThe join function has several candidate functions in C:\r\n\r\n<a name=\"join\"></a>\r\n<pre class=\"lang:default decode:true\">af_err af_join(af_array *out, const int dim, const af_array first, const af_array second) \r\n– C interface function to join 2 arrays along a dimension\r\n\r\naf_err af_join_many(af_array *out, const int dim, const unsigned n_arrays, const af_array *inputs) \r\n– C interface function to join up to 10 arrays along a dimension</pre>\r\n<a name=\"join\"></a>\r\n\r\nand in C++:\r\n\r\n<a name=\"join\"></a>\r\n<pre class=\"lang:default decode:true\">array af::join(const int dim, const array &amp;first, const array &amp;second) \r\n– Joins 2 arrays along a dimension\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third) \r\n– Joins 3 arrays along a dimension.\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third, const array &amp;fourth) \r\n– Joins 4 arrays along a dimension</pre>\r\n<a name=\"join\"></a>\r\n\r\n<a name=\"moddims\"></a>\r\n<h4>moddims()</h4>\r\n<a name=\"moddims\"></a>\r\n\r\nThe moddims() function changes the dimensions of an array without changing its data or order. Note that this function modifies only the metadata associated with the array. It does not modify the content of the array. Here is an example of moddims() converting an 8x1 array into a 2x4 and then back to a 8x1:\r\n\r\n<a name=\"moddims\"></a>\r\n<pre class=\"lang:default decode:true\">a [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n\r\naf::dim4 new_dims(2, 4);\r\nmoddims(a, new_dims) [2 4 1 1]\r\n1.0000 1.0000 1.0000 1.0000\r\n2.0000 2.0000 2.0000 2.0000\r\n\r\nmoddims(a, a.elements(), 1, 1, 1) [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000</pre>\r\n<a name=\"moddims\"></a>\r\n\r\nThe moddims function has a single form in the C API:\r\n\r\n<a name=\"moddims\"></a>\r\n<pre class=\"lang:default decode:true\">af_err af_moddims(af_array *out, const af_array in, const unsigned ndims, const dim_t *const dims) \r\n– C interface to mod dimensions of an array</pre>\r\n<a name=\"moddims\"></a>\r\n\r\nAnd several overloaded candidates in the C++ API:\r\n\r\n<a name=\"moddims\"></a>\r\n<pre class=\"lang:default decode:true\">array af::moddims(const array &amp;in, const unsigned ndims, const dim_t *const dims) \r\n– mods number of dimensions to match ndims as specidied in the array dims\r\n\r\narray af::moddims(const array &amp;in, const dim4 &amp;dims) \r\n– mods dimensions as specified by dims\r\n\r\narray af::moddims(const array &amp;in, const dim_t d0, const dim_t d1=1, const dim_t d2=1, const dim_t d3=1) \r\n– mods dimensions of an array</pre>\r\n<a name=\"moddims\"></a>\r\n\r\n<a name=\"reorder\"></a>\r\n<h4>reorder()</h4>\r\n<a name=\"reorder\"></a>\r\n\r\nThe reorder() function modifies the order of data within an array by exchanging data according to the change in dimensionality. The linear ordering of data within the array is preserved.\r\n\r\n<a name=\"reorder\"></a>\r\n<pre class=\"lang:default decode:true \">a [2 2 3 1]\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n\r\nreorder(a, 1, 0, 2) [2 2 3 1] //equivalent to a transpose\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n\r\nreorder(a, 2, 0, 1) [3 2 2 1]\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n3.0000 4.0000\r\n3.0000 4.0000</pre>\r\n<a name=\"reorder\"></a>\r\n\r\nThe reorder function has several candidates functions in the C/C++ APIs:\r\n\r\n<a name=\"reorder\"></a>\r\n<pre class=\"lang:default decode:true\">af_err af_reorder(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for reordering function\r\n\r\narray af::reorder(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=2, const unsigned w=3) \r\n– Reorders dimensions of an array</pre>\r\n<a name=\"reorder\"></a>\r\n\r\n<a name=\"shift\"></a>\r\n<h4>shift()</h4>\r\n<a name=\"shift\"></a>\r\n\r\nThe shift() function shifts data in a circular buffer fashion along a chosen dimension. Consider the following example:\r\n\r\n<a name=\"shift\"></a>\r\n<pre class=\"lang:default decode:true \">a [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n\r\nshift(a, 0, 2 ) [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n\r\nshift(a, -1, 2 ) [3 5 1 1]\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n0.0000 0.0000 0.0000 0.0000 0.0000</pre>\r\n<a name=\"shift\"></a>\r\n\r\nThe shift function can be called from C and C++ as follows:\r\n\r\n<a name=\"shift\"></a>\r\n<pre class=\"lang:default decode:true\">af_err af_shift(af_array *out, const af_array in, const int x, const int y, const int z, const int w) \r\n– C interface for shifting an array\r\n\r\narray af::shift(const array &amp;in, const int x, const int y=0, const int z=0, const int w=0) \r\n– Shifts array along specified dimensions</pre>\r\n<a name=\"shift\"></a>\r\n\r\n<a name=\"tile\"></a>\r\n<h4>tile()</h4>\r\n<a name=\"tile\"></a>\r\n\r\nThe tile() function repeats an array along the specified dimension. For example below we show how to tile an array along the zeroth and first dimensions of an array:\r\n\r\n<a name=\"tile\"></a>\r\n<pre class=\"lang:default decode:true\">a [3 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice in the zeroth dimension\r\ntile(a, 2) [6 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice along both the zeroth and first dimensions\r\ntile(a, 2, 2) [6 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n\r\n// Repeat array a twice along the first and three times along \r\n// the second dimension.\r\naf::dim4 tile_dims(1, 2, 3);\r\ntile(a, tile_dims) [3 2 3 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000</pre>\r\n<a name=\"tile\"></a>\r\n\r\nThe C interface for tile is as follows:\r\n\r\n<a name=\"tile\"></a>\r\n<pre class=\"lang:default decode:true\">af_err af_tile(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for tiling an array</pre>\r\n<a name=\"tile\"></a>\r\n\r\nThe C++ interface has two overloads\r\n\r\n<a name=\"tile\"></a>\r\n<pre class=\"lang:default decode:true\">array af::tile(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=1, const unsigned w=1) \r\n– Tiles array along specified dimensions\r\n\r\narray af::tile(const array &amp;in, const dim4 &amp;dims) \r\n– Tile an array according to a dim4 object</pre>\r\n<a name=\"tile\"></a>\r\n\r\n<a name=\"transpose\"></a>\r\n<h4>transpose()</h4>\r\n<a name=\"transpose\"></a>\r\n\r\nThe transpose() function performs a standard matrix transpose. The input array must have the dimensions of a 2D-matrix.\r\n\r\n<a name=\"transpose\"></a>\r\n<pre class=\"lang:default decode:true\">a [3 3 1 1]\r\n1.0000 3.0000 3.0000\r\n2.0000 1.0000 3.0000\r\n2.0000 2.0000 1.0000\r\n\r\ntranspose(a) [3 3 1 1]\r\n1.0000 2.0000 2.0000\r\n3.0000 1.0000 2.0000\r\n3.0000 3.0000 1.0000</pre>\r\n<a name=\"transpose\"></a>\r\n\r\nThe C interfaces for transpose are as follows:\r\n\r\n<a name=\"transpose\"></a>\r\n<pre class=\"lang:default decode:true\">af_err af_transpose(af_array *out, af_array in, const bool conjugate) \r\n– C interface to transpose a matrix.\r\n\r\naf_err af_transpose_inplace(af_array in, const bool conjugate) \r\n– C interface to transpose a matrix in-place.</pre>\r\n<a name=\"transpose\"></a>\r\n\r\nThe C++ interface has two primary functions and two shorthand versions:\r\n\r\n<a name=\"transpose\"></a>\r\n<pre class=\"lang:default decode:true\">array af::transpose(const array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix.\r\n\r\nvoid af::transposeInPlace(array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix in-place.\r\n\r\n__array af::T() \r\n– Transpose a matrix\r\n\r\n__array af::H() \r\n– Conjugate Transpose (Hermitian transpose) of a matrix</pre>\r\n<a name=\"transpose\"></a>\r\n\r\nHere is an example of how the shorthand versions might be used:\r\n\r\n<a name=\"transpose\"></a>\r\n<pre class=\"lang:default decode:true \">array x = randu(2, 2, f32);\r\naf_print(x.T()); // transpose (real)\r\narray c = randu(2, 2, c32);\r\naf_print(c.T()); // transpose (complex)\r\naf_print(c.H()); // Hermitian (conjugate) transpose</pre>\r\n<a name=\"transpose\"></a>\r\n\r\n<a name=\"array\"></a>\r\n<h4>array()</h4>\r\n<a name=\"array\"></a>\r\n\r\narray() can be used to create a (shallow) copy of a matrix with different dimensions. The total number of elements must remain the same. This function is a wrapper over the moddims() function discussed earlier.\r\n\r\n<a name=\"array\"></a>\r\n\r\nCombining re-ordering functions to enumerate grid coordinates\r\n\r\n<a name=\"array\"></a>\r\n\r\nBy using a combination of the array restructuring functions, one can quickly code complex manipulation patterns with a few lines of code. For example, consider generating (x,y) coordinates for a grid where each axis goes from 1 to n. Instead of using several loops to populate our arrays we can just use a small combination of the above functions.\r\n\r\n<a name=\"array\"></a>\r\n<pre class=\"lang:default decode:true \">unsigned n=3;\r\naf::array xy = join(1\r\ntile(seq(1, n), n)\r\nflat( transpose(tile(seq(1, n), 1, n)) )\r\n);\r\nxy [9 2 1 1]\r\n1.0000 1.0000\r\n2.0000 1.0000\r\n3.0000 1.0000\r\n1.0000 2.0000\r\n2.0000 2.0000\r\n3.0000 2.0000\r\n1.0000 3.0000\r\n2.0000 3.0000\r\n3.0000 3.0000</pre>\r\n<a name=\"array\"></a>\r\n\r\nWe hope you have found these instructions to be useful. As always, if you have questions about ArrayFire, feel free to drop us a line on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">Google Group</a>.\r\n\r\n<a name=\"array\"></a>\r\n\r\n<a name=\"transpose\"></a>\r\n\r\n<a name=\"tile\"></a>\r\n\r\n<a name=\"shift\"></a>\r\n\r\n<a name=\"reorder\"></a>\r\n\r\n<a name=\"moddims\"></a>\r\n\r\n<a name=\"join\"></a>\r\n\r\n<a name=\"flip\"></a>\r\n\r\n<a name=\"flat\"></a>','Manipulating and restructuring arrays','','inherit','closed','closed','','8633-revision-v1','','','2016-05-12 10:33:43','2016-05-12 14:33:43','',8633,'http://sandbox.arrayfire.com/8633-revision-v1/',0,'revision','',0),(8850,18528,'2016-05-12 10:36:39','2016-05-12 14:36:39','One of the most common questions we see on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a> pertains to methods to manipulate the dimensions of ArrayFire array objects. Thus we will continue the \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" blog series by providing a detailed discussion of the numerous functions that permit you to change the dimentionality, flatten, flip, join, shift, transpose, and tile arrays.\r\n\r\n<!--more-->\r\n\r\nArrayFire provides several different methods for manipulating arrays and matrices. The functionality includes:\r\n<ul>\r\n 	<li><a href=\"#moddims\">moddims()</a> - change the dimensions of an array without changing the data</li>\r\n 	<li><a href=\"#array\">array()</a> - create a (shallow) copy of an array with different dimensions.</li>\r\n 	<li><a href=\"#flat\">flat()</a> - flatten an array to one dimension</li>\r\n 	<li><a href=\"http://flip\">flip()</a> - flip an array along a dimension</li>\r\n 	<li><a href=\"http://join\">join()</a> - join up to 4 arrays</li>\r\n 	<li><a href=\"http://reorder\">reorder()</a> - changes the dimension order within the array</li>\r\n 	<li><a href=\"http://shift\">shift()</a> - shifts data along a dimension</li>\r\n 	<li><a href=\"http://tile\">tile()</a> - repeats an array along a dimension</li>\r\n 	<li><a href=\"http://transpose\">transpose()</a> - performs a matrix transpose</li>\r\n 	<li><a href=\"http://transpose\">T()</a> - transpose a matrix or vector (shorthand notation)</li>\r\n 	<li><a href=\"http://transpose\">H()</a> - Hermitian Transpose (conjugate-transpose) a matrix</li>\r\n</ul>\r\nBelow we provide several examples of these functions and their use. However, if you come to this page far in the future, we suggest you <a href=\"http://arrayfire.org/docs/matrixmanipulation.htm\">visit the documentation on this topic</a> to see the latest information on these topics.\r\n<a name=\"flat\"></a>\r\n<h4>flat()</h4>\r\n\r\nThe flat() function flattens an array to one dimension:\r\n\r\n<pre class=\"lang:default decode:true \">a [3 3 1 1]\r\n1.0000 4.0000 7.0000\r\n2.0000 5.0000 8.0000\r\n3.0000 6.0000 9.0000\r\n\r\nflat(a) [9 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n6.0000\r\n7.0000\r\n8.0000\r\n9.0000</pre>\r\n\r\nThe flat function can be called from C and C++ as follows:\r\n\r\n<pre class=\"lang:default decode:true\">af_err af_flat(af_array* out, const af_array in) \r\n– C interface for flat() function\r\n\r\narray af::flat(const array&amp; in)\r\n– C++ interface for flat() function</pre>\r\n\r\n<a name=\"flip\"></a>\r\n<h4>flip()</h4>\r\n\r\nThe flip() function flips the contents of an array along a chosen dimension. In the example below, we show the 5x2 array flipped along the zeroth (i.e. within a column) and first (e.g. across rows) axes:\r\n\r\n<pre class=\"lang:default decode:true \">a [5 2 1 1]\r\n1.0000 6.0000\r\n2.0000 7.0000\r\n3.0000 8.0000\r\n4.0000 9.0000\r\n5.0000 10.0000\r\n\r\nflip(a, 0) [5 2 1 1]\r\n5.0000 10.0000\r\n4.0000 9.0000\r\n3.0000 8.0000\r\n2.0000 7.0000\r\n1.0000 6.0000\r\n\r\nflip(a, 1) [5 2 1 1]\r\n6.0000 1.0000\r\n7.0000 2.0000\r\n8.0000 3.0000\r\n9.0000 4.0000\r\n10.0000 5.0000</pre>\r\n\r\nThe flip function can be called from C and C++ as follows:\r\n\r\n<pre class=\"lang:default decode:true\">af_err af_flip(af_array *out, const af_array in, const unsigned dim) \r\n– C interface for flip()\r\n\r\narray af::flip(const array &amp;in, const unsigned dim) \r\n– C++ interface for flip()</pre>\r\n\r\n<a name=\"join\"></a>\r\n<h4>join()</h4>\r\n\r\nThe join() function joins arrays along a specific dimension. The C++ interface can join up to four arrays whereas the C interface supports up to 10 arrays. Here is an example of how to use join an array to itself:\r\n\r\n<pre class=\"lang:default decode:true \">a [5 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(0, a, a) [10 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(1, a, a) [5 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n4.0000 4.0000\r\n5.0000 5.0000</pre>\r\n\r\nThe join function has several candidate functions in C:\r\n\r\n<pre class=\"lang:default decode:true\">af_err af_join(af_array *out, const int dim, const af_array first, const af_array second) \r\n– C interface function to join 2 arrays along a dimension\r\n\r\naf_err af_join_many(af_array *out, const int dim, const unsigned n_arrays, const af_array *inputs) \r\n– C interface function to join up to 10 arrays along a dimension</pre>\r\n\r\nand in C++:\r\n\r\n<pre class=\"lang:default decode:true\">array af::join(const int dim, const array &amp;first, const array &amp;second) \r\n– Joins 2 arrays along a dimension\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third) \r\n– Joins 3 arrays along a dimension.\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third, const array &amp;fourth) \r\n– Joins 4 arrays along a dimension</pre>\r\n<a name=\"join\"></a>\r\n\r\n<a name=\"moddims\"></a>\r\n<h4>moddims()</h4>\r\n\r\nThe moddims() function changes the dimensions of an array without changing its data or order. Note that this function modifies only the metadata associated with the array. It does not modify the content of the array. Here is an example of moddims() converting an 8x1 array into a 2x4 and then back to a 8x1:\r\n\r\n<pre class=\"lang:default decode:true\">a [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n\r\naf::dim4 new_dims(2, 4);\r\nmoddims(a, new_dims) [2 4 1 1]\r\n1.0000 1.0000 1.0000 1.0000\r\n2.0000 2.0000 2.0000 2.0000\r\n\r\nmoddims(a, a.elements(), 1, 1, 1) [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000</pre>\r\n\r\nThe moddims function has a single form in the C API:\r\n\r\n<pre class=\"lang:default decode:true\">af_err af_moddims(af_array *out, const af_array in, const unsigned ndims, const dim_t *const dims) \r\n– C interface to mod dimensions of an array</pre>\r\n\r\nAnd several overloaded candidates in the C++ API:\r\n\r\n<pre class=\"lang:default decode:true\">array af::moddims(const array &amp;in, const unsigned ndims, const dim_t *const dims) \r\n– mods number of dimensions to match ndims as specidied in the array dims\r\n\r\narray af::moddims(const array &amp;in, const dim4 &amp;dims) \r\n– mods dimensions as specified by dims\r\n\r\narray af::moddims(const array &amp;in, const dim_t d0, const dim_t d1=1, const dim_t d2=1, const dim_t d3=1) \r\n– mods dimensions of an array</pre>\r\n<a name=\"moddims\"></a>\r\n\r\n<a name=\"reorder\"></a>\r\n<h4>reorder()</h4>\r\n\r\nThe reorder() function modifies the order of data within an array by exchanging data according to the change in dimensionality. The linear ordering of data within the array is preserved.\r\n\r\n<pre class=\"lang:default decode:true \">a [2 2 3 1]\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n\r\nreorder(a, 1, 0, 2) [2 2 3 1] //equivalent to a transpose\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n\r\nreorder(a, 2, 0, 1) [3 2 2 1]\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n3.0000 4.0000\r\n3.0000 4.0000</pre>\r\n\r\nThe reorder function has several candidates functions in the C/C++ APIs:\r\n\r\n<pre class=\"lang:default decode:true\">af_err af_reorder(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for reordering function\r\n\r\narray af::reorder(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=2, const unsigned w=3) \r\n– Reorders dimensions of an array</pre>\r\n<a name=\"reorder\"></a>\r\n\r\n<a name=\"shift\"></a>\r\n<h4>shift()</h4>\r\n\r\nThe shift() function shifts data in a circular buffer fashion along a chosen dimension. Consider the following example:\r\n\r\n<pre class=\"lang:default decode:true \">a [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n\r\nshift(a, 0, 2 ) [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n\r\nshift(a, -1, 2 ) [3 5 1 1]\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n0.0000 0.0000 0.0000 0.0000 0.0000</pre>\r\n\r\nThe shift function can be called from C and C++ as follows:\r\n\r\n\r\n<pre class=\"lang:default decode:true\">af_err af_shift(af_array *out, const af_array in, const int x, const int y, const int z, const int w) \r\n– C interface for shifting an array\r\n\r\narray af::shift(const array &amp;in, const int x, const int y=0, const int z=0, const int w=0) \r\n– Shifts array along specified dimensions</pre>\r\n<a name=\"shift\"></a>\r\n\r\n<a name=\"tile\"></a>\r\n<h4>tile()</h4>\r\n\r\nThe tile() function repeats an array along the specified dimension. For example below we show how to tile an array along the zeroth and first dimensions of an array:\r\n\r\n<pre class=\"lang:default decode:true\">a [3 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice in the zeroth dimension\r\ntile(a, 2) [6 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice along both the zeroth and first dimensions\r\ntile(a, 2, 2) [6 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n\r\n// Repeat array a twice along the first and three times along \r\n// the second dimension.\r\naf::dim4 tile_dims(1, 2, 3);\r\ntile(a, tile_dims) [3 2 3 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000</pre>\r\n\r\nThe C interface for tile is as follows:\r\n\r\n<pre class=\"lang:default decode:true\">af_err af_tile(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for tiling an array</pre>\r\n\r\nThe C++ interface has two overloads\r\n\r\n<pre class=\"lang:default decode:true\">array af::tile(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=1, const unsigned w=1) \r\n– Tiles array along specified dimensions\r\n\r\narray af::tile(const array &amp;in, const dim4 &amp;dims) \r\n– Tile an array according to a dim4 object</pre>\r\n<a name=\"tile\"></a>\r\n\r\n<a name=\"transpose\"></a>\r\n<h4>transpose()</h4>\r\n\r\nThe transpose() function performs a standard matrix transpose. The input array must have the dimensions of a 2D-matrix.\r\n\r\n<pre class=\"lang:default decode:true\">a [3 3 1 1]\r\n1.0000 3.0000 3.0000\r\n2.0000 1.0000 3.0000\r\n2.0000 2.0000 1.0000\r\n\r\ntranspose(a) [3 3 1 1]\r\n1.0000 2.0000 2.0000\r\n3.0000 1.0000 2.0000\r\n3.0000 3.0000 1.0000</pre>\r\n\r\nThe C interfaces for transpose are as follows:\r\n\r\n<pre class=\"lang:default decode:true\">af_err af_transpose(af_array *out, af_array in, const bool conjugate) \r\n– C interface to transpose a matrix.\r\n\r\naf_err af_transpose_inplace(af_array in, const bool conjugate) \r\n– C interface to transpose a matrix in-place.</pre>\r\n\r\nThe C++ interface has two primary functions and two shorthand versions:\r\n\r\n<pre class=\"lang:default decode:true\">array af::transpose(const array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix.\r\n\r\nvoid af::transposeInPlace(array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix in-place.\r\n\r\n__array af::T() \r\n– Transpose a matrix\r\n\r\n__array af::H() \r\n– Conjugate Transpose (Hermitian transpose) of a matrix</pre>\r\n\r\nHere is an example of how the shorthand versions might be used:\r\n\r\n<pre class=\"lang:default decode:true \">array x = randu(2, 2, f32);\r\naf_print(x.T()); // transpose (real)\r\narray c = randu(2, 2, c32);\r\naf_print(c.T()); // transpose (complex)\r\naf_print(c.H()); // Hermitian (conjugate) transpose</pre>\r\n<a name=\"transpose\"></a>\r\n\r\n<a name=\"array\"></a>\r\n<h4>array()</h4>\r\n\r\narray() can be used to create a (shallow) copy of a matrix with different dimensions. The total number of elements must remain the same. This function is a wrapper over the moddims() function discussed earlier.\r\n\r\nCombining re-ordering functions to enumerate grid coordinates\r\n\r\nBy using a combination of the array restructuring functions, one can quickly code complex manipulation patterns with a few lines of code. For example, consider generating (x,y) coordinates for a grid where each axis goes from 1 to n. Instead of using several loops to populate our arrays we can just use a small combination of the above functions.\r\n\r\n<pre class=\"lang:default decode:true \">unsigned n=3;\r\naf::array xy = join(1\r\ntile(seq(1, n), n)\r\nflat( transpose(tile(seq(1, n), 1, n)) )\r\n);\r\nxy [9 2 1 1]\r\n1.0000 1.0000\r\n2.0000 1.0000\r\n3.0000 1.0000\r\n1.0000 2.0000\r\n2.0000 2.0000\r\n3.0000 2.0000\r\n1.0000 3.0000\r\n2.0000 3.0000\r\n3.0000 3.0000</pre>\r\nWe hope you have found these instructions to be useful. As always, if you have questions about ArrayFire, feel free to drop us a line on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">Google Group</a>.','Manipulating and restructuring arrays','','inherit','closed','closed','','8633-revision-v1','','','2016-05-12 10:36:39','2016-05-12 14:36:39','',8633,'http://sandbox.arrayfire.com/8633-revision-v1/',0,'revision','',0),(8851,18528,'2016-05-12 10:38:34','2016-05-12 14:38:34','One of the most common questions we see on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a> pertains to methods to manipulate the dimensions of ArrayFire array objects. Thus we will continue the \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" blog series by providing a detailed discussion of the numerous functions that permit you to change the dimentionality, flatten, flip, join, shift, transpose, and tile arrays.\r\n\r\n<!--more-->\r\n\r\nArrayFire provides several different methods for manipulating arrays and matrices. The functionality includes:\r\n<ul>\r\n 	<li><a href=\"#moddims\">moddims()</a> - change the dimensions of an array without changing the data</li>\r\n 	<li><a href=\"#array\">array()</a> - create a (shallow) copy of an array with different dimensions.</li>\r\n 	<li><a href=\"#flat\">flat()</a> - flatten an array to one dimension</li>\r\n 	<li><a href=\"#flip\">flip()</a> - flip an array along a dimension</li>\r\n 	<li><a href=\"#join\">join()</a> - join up to 4 arrays</li>\r\n 	<li><a href=\"http://reorder\">reorder()</a> - changes the dimension order within the array</li>\r\n 	<li><a href=\"http://shift\">shift()</a> - shifts data along a dimension</li>\r\n 	<li><a href=\"#tile\">tile()</a> - repeats an array along a dimension</li>\r\n 	<li><a href=\"#transpose\">transpose()</a> - performs a matrix transpose</li>\r\n 	<li><a href=\"#transpose\">T()</a> - transpose a matrix or vector (shorthand notation)</li>\r\n 	<li><a href=\"http://transpose\">H()</a> - Hermitian Transpose (conjugate-transpose) a matrix</li>\r\n</ul>\r\nBelow we provide several examples of these functions and their use. However, if you come to this page far in the future, we suggest you <a href=\"http://arrayfire.org/docs/matrixmanipulation.htm\">visit the documentation on this topic</a> to see the latest information on these topics.\r\n<a name=\"flat\"></a>\r\n<h4>flat()</h4>\r\nThe flat() function flattens an array to one dimension:\r\n<pre class=\"lang:default decode:true \">a [3 3 1 1]\r\n1.0000 4.0000 7.0000\r\n2.0000 5.0000 8.0000\r\n3.0000 6.0000 9.0000\r\n\r\nflat(a) [9 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n6.0000\r\n7.0000\r\n8.0000\r\n9.0000</pre>\r\nThe flat function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_flat(af_array* out, const af_array in) \r\n– C interface for flat() function\r\n\r\narray af::flat(const array&amp; in)\r\n– C++ interface for flat() function</pre>\r\n<a name=\"flip\"></a>\r\n<h4>flip()</h4>\r\nThe flip() function flips the contents of an array along a chosen dimension. In the example below, we show the 5x2 array flipped along the zeroth (i.e. within a column) and first (e.g. across rows) axes:\r\n<pre class=\"lang:default decode:true \">a [5 2 1 1]\r\n1.0000 6.0000\r\n2.0000 7.0000\r\n3.0000 8.0000\r\n4.0000 9.0000\r\n5.0000 10.0000\r\n\r\nflip(a, 0) [5 2 1 1]\r\n5.0000 10.0000\r\n4.0000 9.0000\r\n3.0000 8.0000\r\n2.0000 7.0000\r\n1.0000 6.0000\r\n\r\nflip(a, 1) [5 2 1 1]\r\n6.0000 1.0000\r\n7.0000 2.0000\r\n8.0000 3.0000\r\n9.0000 4.0000\r\n10.0000 5.0000</pre>\r\nThe flip function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_flip(af_array *out, const af_array in, const unsigned dim) \r\n– C interface for flip()\r\n\r\narray af::flip(const array &amp;in, const unsigned dim) \r\n– C++ interface for flip()</pre>\r\n<a name=\"join\"></a>\r\n<h4>join()</h4>\r\nThe join() function joins arrays along a specific dimension. The C++ interface can join up to four arrays whereas the C interface supports up to 10 arrays. Here is an example of how to use join an array to itself:\r\n<pre class=\"lang:default decode:true \">a [5 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(0, a, a) [10 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(1, a, a) [5 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n4.0000 4.0000\r\n5.0000 5.0000</pre>\r\nThe join function has several candidate functions in C:\r\n<pre class=\"lang:default decode:true\">af_err af_join(af_array *out, const int dim, const af_array first, const af_array second) \r\n– C interface function to join 2 arrays along a dimension\r\n\r\naf_err af_join_many(af_array *out, const int dim, const unsigned n_arrays, const af_array *inputs) \r\n– C interface function to join up to 10 arrays along a dimension</pre>\r\nand in C++:\r\n<pre class=\"lang:default decode:true\">array af::join(const int dim, const array &amp;first, const array &amp;second) \r\n– Joins 2 arrays along a dimension\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third) \r\n– Joins 3 arrays along a dimension.\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third, const array &amp;fourth) \r\n– Joins 4 arrays along a dimension</pre>\r\n<a name=\"join\"></a>\r\n\r\n<a name=\"moddims\"></a>\r\n<h4>moddims()</h4>\r\nThe moddims() function changes the dimensions of an array without changing its data or order. Note that this function modifies only the metadata associated with the array. It does not modify the content of the array. Here is an example of moddims() converting an 8x1 array into a 2x4 and then back to a 8x1:\r\n<pre class=\"lang:default decode:true\">a [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n\r\naf::dim4 new_dims(2, 4);\r\nmoddims(a, new_dims) [2 4 1 1]\r\n1.0000 1.0000 1.0000 1.0000\r\n2.0000 2.0000 2.0000 2.0000\r\n\r\nmoddims(a, a.elements(), 1, 1, 1) [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000</pre>\r\nThe moddims function has a single form in the C API:\r\n<pre class=\"lang:default decode:true\">af_err af_moddims(af_array *out, const af_array in, const unsigned ndims, const dim_t *const dims) \r\n– C interface to mod dimensions of an array</pre>\r\nAnd several overloaded candidates in the C++ API:\r\n<pre class=\"lang:default decode:true\">array af::moddims(const array &amp;in, const unsigned ndims, const dim_t *const dims) \r\n– mods number of dimensions to match ndims as specidied in the array dims\r\n\r\narray af::moddims(const array &amp;in, const dim4 &amp;dims) \r\n– mods dimensions as specified by dims\r\n\r\narray af::moddims(const array &amp;in, const dim_t d0, const dim_t d1=1, const dim_t d2=1, const dim_t d3=1) \r\n– mods dimensions of an array</pre>\r\n<a name=\"moddims\"></a>\r\n\r\n<a name=\"reorder\"></a>\r\n<h4>reorder()</h4>\r\nThe reorder() function modifies the order of data within an array by exchanging data according to the change in dimensionality. The linear ordering of data within the array is preserved.\r\n<pre class=\"lang:default decode:true \">a [2 2 3 1]\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n\r\nreorder(a, 1, 0, 2) [2 2 3 1] //equivalent to a transpose\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n\r\nreorder(a, 2, 0, 1) [3 2 2 1]\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n3.0000 4.0000\r\n3.0000 4.0000</pre>\r\nThe reorder function has several candidates functions in the C/C++ APIs:\r\n<pre class=\"lang:default decode:true\">af_err af_reorder(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for reordering function\r\n\r\narray af::reorder(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=2, const unsigned w=3) \r\n– Reorders dimensions of an array</pre>\r\n<a name=\"reorder\"></a>\r\n\r\n<a name=\"shift\"></a>\r\n<h4>shift()</h4>\r\nThe shift() function shifts data in a circular buffer fashion along a chosen dimension. Consider the following example:\r\n<pre class=\"lang:default decode:true \">a [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n\r\nshift(a, 0, 2 ) [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n\r\nshift(a, -1, 2 ) [3 5 1 1]\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n0.0000 0.0000 0.0000 0.0000 0.0000</pre>\r\nThe shift function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_shift(af_array *out, const af_array in, const int x, const int y, const int z, const int w) \r\n– C interface for shifting an array\r\n\r\narray af::shift(const array &amp;in, const int x, const int y=0, const int z=0, const int w=0) \r\n– Shifts array along specified dimensions</pre>\r\n<a name=\"shift\"></a>\r\n\r\n<a name=\"tile\"></a>\r\n<h4>tile()</h4>\r\nThe tile() function repeats an array along the specified dimension. For example below we show how to tile an array along the zeroth and first dimensions of an array:\r\n<pre class=\"lang:default decode:true\">a [3 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice in the zeroth dimension\r\ntile(a, 2) [6 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice along both the zeroth and first dimensions\r\ntile(a, 2, 2) [6 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n\r\n// Repeat array a twice along the first and three times along \r\n// the second dimension.\r\naf::dim4 tile_dims(1, 2, 3);\r\ntile(a, tile_dims) [3 2 3 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000</pre>\r\nThe C interface for tile is as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_tile(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for tiling an array</pre>\r\nThe C++ interface has two overloads\r\n<pre class=\"lang:default decode:true\">array af::tile(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=1, const unsigned w=1) \r\n– Tiles array along specified dimensions\r\n\r\narray af::tile(const array &amp;in, const dim4 &amp;dims) \r\n– Tile an array according to a dim4 object</pre>\r\n<a name=\"tile\"></a>\r\n\r\n<a name=\"transpose\"></a>\r\n<h4>transpose()</h4>\r\nThe transpose() function performs a standard matrix transpose. The input array must have the dimensions of a 2D-matrix.\r\n<pre class=\"lang:default decode:true\">a [3 3 1 1]\r\n1.0000 3.0000 3.0000\r\n2.0000 1.0000 3.0000\r\n2.0000 2.0000 1.0000\r\n\r\ntranspose(a) [3 3 1 1]\r\n1.0000 2.0000 2.0000\r\n3.0000 1.0000 2.0000\r\n3.0000 3.0000 1.0000</pre>\r\nThe C interfaces for transpose are as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_transpose(af_array *out, af_array in, const bool conjugate) \r\n– C interface to transpose a matrix.\r\n\r\naf_err af_transpose_inplace(af_array in, const bool conjugate) \r\n– C interface to transpose a matrix in-place.</pre>\r\nThe C++ interface has two primary functions and two shorthand versions:\r\n<pre class=\"lang:default decode:true\">array af::transpose(const array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix.\r\n\r\nvoid af::transposeInPlace(array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix in-place.\r\n\r\n__array af::T() \r\n– Transpose a matrix\r\n\r\n__array af::H() \r\n– Conjugate Transpose (Hermitian transpose) of a matrix</pre>\r\nHere is an example of how the shorthand versions might be used:\r\n<pre class=\"lang:default decode:true \">array x = randu(2, 2, f32);\r\naf_print(x.T()); // transpose (real)\r\narray c = randu(2, 2, c32);\r\naf_print(c.T()); // transpose (complex)\r\naf_print(c.H()); // Hermitian (conjugate) transpose</pre>\r\n<a name=\"transpose\"></a>\r\n\r\n<a name=\"array\"></a>\r\n<h4>array()</h4>\r\narray() can be used to create a (shallow) copy of a matrix with different dimensions. The total number of elements must remain the same. This function is a wrapper over the moddims() function discussed earlier.\r\n\r\nCombining re-ordering functions to enumerate grid coordinates\r\n\r\nBy using a combination of the array restructuring functions, one can quickly code complex manipulation patterns with a few lines of code. For example, consider generating (x,y) coordinates for a grid where each axis goes from 1 to n. Instead of using several loops to populate our arrays we can just use a small combination of the above functions.\r\n<pre class=\"lang:default decode:true \">unsigned n=3;\r\naf::array xy = join(1\r\ntile(seq(1, n), n)\r\nflat( transpose(tile(seq(1, n), 1, n)) )\r\n);\r\nxy [9 2 1 1]\r\n1.0000 1.0000\r\n2.0000 1.0000\r\n3.0000 1.0000\r\n1.0000 2.0000\r\n2.0000 2.0000\r\n3.0000 2.0000\r\n1.0000 3.0000\r\n2.0000 3.0000\r\n3.0000 3.0000</pre>\r\nWe hope you have found these instructions to be useful. As always, if you have questions about ArrayFire, feel free to drop us a line on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">Google Group</a>.','Manipulating and restructuring arrays','','inherit','closed','closed','','8633-revision-v1','','','2016-05-12 10:38:34','2016-05-12 14:38:34','',8633,'http://sandbox.arrayfire.com/8633-revision-v1/',0,'revision','',0),(8852,18528,'2016-05-12 10:40:01','2016-05-12 14:40:01','One of the most common questions we see on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a> pertains to methods to manipulate the dimensions of ArrayFire array objects. Thus we will continue the \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" blog series by providing a detailed discussion of the numerous functions that permit you to change the dimentionality, flatten, flip, join, shift, transpose, and tile arrays.\r\n\r\n<!--more-->\r\n\r\nArrayFire provides several different methods for manipulating arrays and matrices. The functionality includes:\r\n<ul>\r\n 	<li><a href=\"#moddims\">moddims()</a> - change the dimensions of an array without changing the data</li>\r\n 	<li><a href=\"#array\">array()</a> - create a (shallow) copy of an array with different dimensions.</li>\r\n 	<li><a href=\"#flat\">flat()</a> - flatten an array to one dimension</li>\r\n 	<li><a href=\"#flip\">flip()</a> - flip an array along a dimension</li>\r\n 	<li><a href=\"#join\">join()</a> - join up to 4 arrays</li>\r\n 	<li><a href=\"#reorder\">reorder()</a> - changes the dimension order within the array</li>\r\n 	<li><a href=\"http://shift\">shift()</a> - shifts data along a dimension</li>\r\n 	<li><a href=\"#tile\">tile()</a> - repeats an array along a dimension</li>\r\n 	<li><a href=\"#transpose\">transpose()</a> - performs a matrix transpose</li>\r\n 	<li><a href=\"#transpose\">T()</a> - transpose a matrix or vector (shorthand notation)</li>\r\n 	<li><a href=\"http://transpose\">H()</a> - Hermitian Transpose (conjugate-transpose) a matrix</li>\r\n</ul>\r\nBelow we provide several examples of these functions and their use. However, if you come to this page far in the future, we suggest you <a href=\"http://arrayfire.org/docs/matrixmanipulation.htm\">visit the documentation on this topic</a> to see the latest information on these topics.\r\n<a name=\"flat\"></a>\r\n<h4>flat()</h4>\r\nThe flat() function flattens an array to one dimension:\r\n<pre class=\"lang:default decode:true \">a [3 3 1 1]\r\n1.0000 4.0000 7.0000\r\n2.0000 5.0000 8.0000\r\n3.0000 6.0000 9.0000\r\n\r\nflat(a) [9 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n6.0000\r\n7.0000\r\n8.0000\r\n9.0000</pre>\r\nThe flat function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_flat(af_array* out, const af_array in) \r\n– C interface for flat() function\r\n\r\narray af::flat(const array&amp; in)\r\n– C++ interface for flat() function</pre>\r\n<a name=\"flip\"></a>\r\n<h4>flip()</h4>\r\nThe flip() function flips the contents of an array along a chosen dimension. In the example below, we show the 5x2 array flipped along the zeroth (i.e. within a column) and first (e.g. across rows) axes:\r\n<pre class=\"lang:default decode:true \">a [5 2 1 1]\r\n1.0000 6.0000\r\n2.0000 7.0000\r\n3.0000 8.0000\r\n4.0000 9.0000\r\n5.0000 10.0000\r\n\r\nflip(a, 0) [5 2 1 1]\r\n5.0000 10.0000\r\n4.0000 9.0000\r\n3.0000 8.0000\r\n2.0000 7.0000\r\n1.0000 6.0000\r\n\r\nflip(a, 1) [5 2 1 1]\r\n6.0000 1.0000\r\n7.0000 2.0000\r\n8.0000 3.0000\r\n9.0000 4.0000\r\n10.0000 5.0000</pre>\r\nThe flip function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_flip(af_array *out, const af_array in, const unsigned dim) \r\n– C interface for flip()\r\n\r\narray af::flip(const array &amp;in, const unsigned dim) \r\n– C++ interface for flip()</pre>\r\n<a name=\"join\"></a>\r\n<h4>join()</h4>\r\nThe join() function joins arrays along a specific dimension. The C++ interface can join up to four arrays whereas the C interface supports up to 10 arrays. Here is an example of how to use join an array to itself:\r\n<pre class=\"lang:default decode:true \">a [5 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(0, a, a) [10 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(1, a, a) [5 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n4.0000 4.0000\r\n5.0000 5.0000</pre>\r\nThe join function has several candidate functions in C:\r\n<pre class=\"lang:default decode:true\">af_err af_join(af_array *out, const int dim, const af_array first, const af_array second) \r\n– C interface function to join 2 arrays along a dimension\r\n\r\naf_err af_join_many(af_array *out, const int dim, const unsigned n_arrays, const af_array *inputs) \r\n– C interface function to join up to 10 arrays along a dimension</pre>\r\nand in C++:\r\n<pre class=\"lang:default decode:true\">array af::join(const int dim, const array &amp;first, const array &amp;second) \r\n– Joins 2 arrays along a dimension\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third) \r\n– Joins 3 arrays along a dimension.\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third, const array &amp;fourth) \r\n– Joins 4 arrays along a dimension</pre>\r\n<a name=\"join\"></a>\r\n\r\n<a name=\"moddims\"></a>\r\n<h4>moddims()</h4>\r\nThe moddims() function changes the dimensions of an array without changing its data or order. Note that this function modifies only the metadata associated with the array. It does not modify the content of the array. Here is an example of moddims() converting an 8x1 array into a 2x4 and then back to a 8x1:\r\n<pre class=\"lang:default decode:true\">a [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n\r\naf::dim4 new_dims(2, 4);\r\nmoddims(a, new_dims) [2 4 1 1]\r\n1.0000 1.0000 1.0000 1.0000\r\n2.0000 2.0000 2.0000 2.0000\r\n\r\nmoddims(a, a.elements(), 1, 1, 1) [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000</pre>\r\nThe moddims function has a single form in the C API:\r\n<pre class=\"lang:default decode:true\">af_err af_moddims(af_array *out, const af_array in, const unsigned ndims, const dim_t *const dims) \r\n– C interface to mod dimensions of an array</pre>\r\nAnd several overloaded candidates in the C++ API:\r\n<pre class=\"lang:default decode:true\">array af::moddims(const array &amp;in, const unsigned ndims, const dim_t *const dims) \r\n– mods number of dimensions to match ndims as specidied in the array dims\r\n\r\narray af::moddims(const array &amp;in, const dim4 &amp;dims) \r\n– mods dimensions as specified by dims\r\n\r\narray af::moddims(const array &amp;in, const dim_t d0, const dim_t d1=1, const dim_t d2=1, const dim_t d3=1) \r\n– mods dimensions of an array</pre>\r\n<a name=\"moddims\"></a>\r\n\r\n<a name=\"reorder\"></a>\r\n<h4>reorder()</h4>\r\nThe reorder() function modifies the order of data within an array by exchanging data according to the change in dimensionality. The linear ordering of data within the array is preserved.\r\n<pre class=\"lang:default decode:true \">a [2 2 3 1]\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n\r\nreorder(a, 1, 0, 2) [2 2 3 1] //equivalent to a transpose\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n\r\nreorder(a, 2, 0, 1) [3 2 2 1]\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n3.0000 4.0000\r\n3.0000 4.0000</pre>\r\nThe reorder function has several candidates functions in the C/C++ APIs:\r\n<pre class=\"lang:default decode:true\">af_err af_reorder(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for reordering function\r\n\r\narray af::reorder(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=2, const unsigned w=3) \r\n– Reorders dimensions of an array</pre>\r\n<a name=\"reorder\"></a>\r\n\r\n<a name=\"shift\"></a>\r\n<h4>shift()</h4>\r\nThe shift() function shifts data in a circular buffer fashion along a chosen dimension. Consider the following example:\r\n<pre class=\"lang:default decode:true \">a [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n\r\nshift(a, 0, 2 ) [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n\r\nshift(a, -1, 2 ) [3 5 1 1]\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n0.0000 0.0000 0.0000 0.0000 0.0000</pre>\r\nThe shift function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_shift(af_array *out, const af_array in, const int x, const int y, const int z, const int w) \r\n– C interface for shifting an array\r\n\r\narray af::shift(const array &amp;in, const int x, const int y=0, const int z=0, const int w=0) \r\n– Shifts array along specified dimensions</pre>\r\n<a name=\"shift\"></a>\r\n\r\n<a name=\"tile\"></a>\r\n<h4>tile()</h4>\r\nThe tile() function repeats an array along the specified dimension. For example below we show how to tile an array along the zeroth and first dimensions of an array:\r\n<pre class=\"lang:default decode:true\">a [3 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice in the zeroth dimension\r\ntile(a, 2) [6 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice along both the zeroth and first dimensions\r\ntile(a, 2, 2) [6 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n\r\n// Repeat array a twice along the first and three times along \r\n// the second dimension.\r\naf::dim4 tile_dims(1, 2, 3);\r\ntile(a, tile_dims) [3 2 3 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000</pre>\r\nThe C interface for tile is as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_tile(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for tiling an array</pre>\r\nThe C++ interface has two overloads\r\n<pre class=\"lang:default decode:true\">array af::tile(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=1, const unsigned w=1) \r\n– Tiles array along specified dimensions\r\n\r\narray af::tile(const array &amp;in, const dim4 &amp;dims) \r\n– Tile an array according to a dim4 object</pre>\r\n<a name=\"tile\"></a>\r\n\r\n<a name=\"transpose\"></a>\r\n<h4>transpose()</h4>\r\nThe transpose() function performs a standard matrix transpose. The input array must have the dimensions of a 2D-matrix.\r\n<pre class=\"lang:default decode:true\">a [3 3 1 1]\r\n1.0000 3.0000 3.0000\r\n2.0000 1.0000 3.0000\r\n2.0000 2.0000 1.0000\r\n\r\ntranspose(a) [3 3 1 1]\r\n1.0000 2.0000 2.0000\r\n3.0000 1.0000 2.0000\r\n3.0000 3.0000 1.0000</pre>\r\nThe C interfaces for transpose are as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_transpose(af_array *out, af_array in, const bool conjugate) \r\n– C interface to transpose a matrix.\r\n\r\naf_err af_transpose_inplace(af_array in, const bool conjugate) \r\n– C interface to transpose a matrix in-place.</pre>\r\nThe C++ interface has two primary functions and two shorthand versions:\r\n<pre class=\"lang:default decode:true\">array af::transpose(const array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix.\r\n\r\nvoid af::transposeInPlace(array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix in-place.\r\n\r\n__array af::T() \r\n– Transpose a matrix\r\n\r\n__array af::H() \r\n– Conjugate Transpose (Hermitian transpose) of a matrix</pre>\r\nHere is an example of how the shorthand versions might be used:\r\n<pre class=\"lang:default decode:true \">array x = randu(2, 2, f32);\r\naf_print(x.T()); // transpose (real)\r\narray c = randu(2, 2, c32);\r\naf_print(c.T()); // transpose (complex)\r\naf_print(c.H()); // Hermitian (conjugate) transpose</pre>\r\n<a name=\"transpose\"></a>\r\n\r\n<a name=\"array\"></a>\r\n<h4>array()</h4>\r\narray() can be used to create a (shallow) copy of a matrix with different dimensions. The total number of elements must remain the same. This function is a wrapper over the moddims() function discussed earlier.\r\n\r\nCombining re-ordering functions to enumerate grid coordinates\r\n\r\nBy using a combination of the array restructuring functions, one can quickly code complex manipulation patterns with a few lines of code. For example, consider generating (x,y) coordinates for a grid where each axis goes from 1 to n. Instead of using several loops to populate our arrays we can just use a small combination of the above functions.\r\n<pre class=\"lang:default decode:true \">unsigned n=3;\r\naf::array xy = join(1\r\ntile(seq(1, n), n)\r\nflat( transpose(tile(seq(1, n), 1, n)) )\r\n);\r\nxy [9 2 1 1]\r\n1.0000 1.0000\r\n2.0000 1.0000\r\n3.0000 1.0000\r\n1.0000 2.0000\r\n2.0000 2.0000\r\n3.0000 2.0000\r\n1.0000 3.0000\r\n2.0000 3.0000\r\n3.0000 3.0000</pre>\r\nWe hope you have found these instructions to be useful. As always, if you have questions about ArrayFire, feel free to drop us a line on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">Google Group</a>.','Manipulating and restructuring arrays','','inherit','closed','closed','','8633-revision-v1','','','2016-05-12 10:40:01','2016-05-12 14:40:01','',8633,'http://sandbox.arrayfire.com/8633-revision-v1/',0,'revision','',0),(8853,18528,'2016-05-12 10:40:29','2016-05-12 14:40:29','One of the most common questions we see on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a> pertains to methods to manipulate the dimensions of ArrayFire array objects. Thus we will continue the \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" blog series by providing a detailed discussion of the numerous functions that permit you to change the dimentionality, flatten, flip, join, shift, transpose, and tile arrays.\r\n\r\n<!--more-->\r\n\r\nArrayFire provides several different methods for manipulating arrays and matrices. The functionality includes:\r\n<ul>\r\n 	<li><a href=\"#moddims\">moddims()</a> - change the dimensions of an array without changing the data</li>\r\n 	<li><a href=\"#array\">array()</a> - create a (shallow) copy of an array with different dimensions.</li>\r\n 	<li><a href=\"#flat\">flat()</a> - flatten an array to one dimension</li>\r\n 	<li><a href=\"#flip\">flip()</a> - flip an array along a dimension</li>\r\n 	<li><a href=\"#join\">join()</a> - join up to 4 arrays</li>\r\n 	<li><a href=\"#reorder\">reorder()</a> - changes the dimension order within the array</li>\r\n 	<li><a href=\"#shift\">shift()</a> - shifts data along a dimension</li>\r\n 	<li><a href=\"#tile\">tile()</a> - repeats an array along a dimension</li>\r\n 	<li><a href=\"#transpose\">transpose()</a> - performs a matrix transpose</li>\r\n 	<li><a href=\"#transpose\">T()</a> - transpose a matrix or vector (shorthand notation)</li>\r\n 	<li><a href=\"#transpose\">H()</a> - Hermitian Transpose (conjugate-transpose) a matrix</li>\r\n</ul>\r\nBelow we provide several examples of these functions and their use. However, if you come to this page far in the future, we suggest you <a href=\"http://arrayfire.org/docs/matrixmanipulation.htm\">visit the documentation on this topic</a> to see the latest information on these topics.\r\n<a name=\"flat\"></a>\r\n<h4>flat()</h4>\r\nThe flat() function flattens an array to one dimension:\r\n<pre class=\"lang:default decode:true \">a [3 3 1 1]\r\n1.0000 4.0000 7.0000\r\n2.0000 5.0000 8.0000\r\n3.0000 6.0000 9.0000\r\n\r\nflat(a) [9 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n6.0000\r\n7.0000\r\n8.0000\r\n9.0000</pre>\r\nThe flat function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_flat(af_array* out, const af_array in) \r\n– C interface for flat() function\r\n\r\narray af::flat(const array&amp; in)\r\n– C++ interface for flat() function</pre>\r\n<a name=\"flip\"></a>\r\n<h4>flip()</h4>\r\nThe flip() function flips the contents of an array along a chosen dimension. In the example below, we show the 5x2 array flipped along the zeroth (i.e. within a column) and first (e.g. across rows) axes:\r\n<pre class=\"lang:default decode:true \">a [5 2 1 1]\r\n1.0000 6.0000\r\n2.0000 7.0000\r\n3.0000 8.0000\r\n4.0000 9.0000\r\n5.0000 10.0000\r\n\r\nflip(a, 0) [5 2 1 1]\r\n5.0000 10.0000\r\n4.0000 9.0000\r\n3.0000 8.0000\r\n2.0000 7.0000\r\n1.0000 6.0000\r\n\r\nflip(a, 1) [5 2 1 1]\r\n6.0000 1.0000\r\n7.0000 2.0000\r\n8.0000 3.0000\r\n9.0000 4.0000\r\n10.0000 5.0000</pre>\r\nThe flip function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_flip(af_array *out, const af_array in, const unsigned dim) \r\n– C interface for flip()\r\n\r\narray af::flip(const array &amp;in, const unsigned dim) \r\n– C++ interface for flip()</pre>\r\n<a name=\"join\"></a>\r\n<h4>join()</h4>\r\nThe join() function joins arrays along a specific dimension. The C++ interface can join up to four arrays whereas the C interface supports up to 10 arrays. Here is an example of how to use join an array to itself:\r\n<pre class=\"lang:default decode:true \">a [5 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(0, a, a) [10 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(1, a, a) [5 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n4.0000 4.0000\r\n5.0000 5.0000</pre>\r\nThe join function has several candidate functions in C:\r\n<pre class=\"lang:default decode:true\">af_err af_join(af_array *out, const int dim, const af_array first, const af_array second) \r\n– C interface function to join 2 arrays along a dimension\r\n\r\naf_err af_join_many(af_array *out, const int dim, const unsigned n_arrays, const af_array *inputs) \r\n– C interface function to join up to 10 arrays along a dimension</pre>\r\nand in C++:\r\n<pre class=\"lang:default decode:true\">array af::join(const int dim, const array &amp;first, const array &amp;second) \r\n– Joins 2 arrays along a dimension\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third) \r\n– Joins 3 arrays along a dimension.\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third, const array &amp;fourth) \r\n– Joins 4 arrays along a dimension</pre>\r\n<a name=\"join\"></a>\r\n\r\n<a name=\"moddims\"></a>\r\n<h4>moddims()</h4>\r\nThe moddims() function changes the dimensions of an array without changing its data or order. Note that this function modifies only the metadata associated with the array. It does not modify the content of the array. Here is an example of moddims() converting an 8x1 array into a 2x4 and then back to a 8x1:\r\n<pre class=\"lang:default decode:true\">a [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n\r\naf::dim4 new_dims(2, 4);\r\nmoddims(a, new_dims) [2 4 1 1]\r\n1.0000 1.0000 1.0000 1.0000\r\n2.0000 2.0000 2.0000 2.0000\r\n\r\nmoddims(a, a.elements(), 1, 1, 1) [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000</pre>\r\nThe moddims function has a single form in the C API:\r\n<pre class=\"lang:default decode:true\">af_err af_moddims(af_array *out, const af_array in, const unsigned ndims, const dim_t *const dims) \r\n– C interface to mod dimensions of an array</pre>\r\nAnd several overloaded candidates in the C++ API:\r\n<pre class=\"lang:default decode:true\">array af::moddims(const array &amp;in, const unsigned ndims, const dim_t *const dims) \r\n– mods number of dimensions to match ndims as specidied in the array dims\r\n\r\narray af::moddims(const array &amp;in, const dim4 &amp;dims) \r\n– mods dimensions as specified by dims\r\n\r\narray af::moddims(const array &amp;in, const dim_t d0, const dim_t d1=1, const dim_t d2=1, const dim_t d3=1) \r\n– mods dimensions of an array</pre>\r\n<a name=\"moddims\"></a>\r\n\r\n<a name=\"reorder\"></a>\r\n<h4>reorder()</h4>\r\nThe reorder() function modifies the order of data within an array by exchanging data according to the change in dimensionality. The linear ordering of data within the array is preserved.\r\n<pre class=\"lang:default decode:true \">a [2 2 3 1]\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n\r\nreorder(a, 1, 0, 2) [2 2 3 1] //equivalent to a transpose\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n\r\nreorder(a, 2, 0, 1) [3 2 2 1]\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n3.0000 4.0000\r\n3.0000 4.0000</pre>\r\nThe reorder function has several candidates functions in the C/C++ APIs:\r\n<pre class=\"lang:default decode:true\">af_err af_reorder(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for reordering function\r\n\r\narray af::reorder(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=2, const unsigned w=3) \r\n– Reorders dimensions of an array</pre>\r\n<a name=\"reorder\"></a>\r\n\r\n<a name=\"shift\"></a>\r\n<h4>shift()</h4>\r\nThe shift() function shifts data in a circular buffer fashion along a chosen dimension. Consider the following example:\r\n<pre class=\"lang:default decode:true \">a [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n\r\nshift(a, 0, 2 ) [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n\r\nshift(a, -1, 2 ) [3 5 1 1]\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n0.0000 0.0000 0.0000 0.0000 0.0000</pre>\r\nThe shift function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_shift(af_array *out, const af_array in, const int x, const int y, const int z, const int w) \r\n– C interface for shifting an array\r\n\r\narray af::shift(const array &amp;in, const int x, const int y=0, const int z=0, const int w=0) \r\n– Shifts array along specified dimensions</pre>\r\n<a name=\"shift\"></a>\r\n\r\n<a name=\"tile\"></a>\r\n<h4>tile()</h4>\r\nThe tile() function repeats an array along the specified dimension. For example below we show how to tile an array along the zeroth and first dimensions of an array:\r\n<pre class=\"lang:default decode:true\">a [3 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice in the zeroth dimension\r\ntile(a, 2) [6 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice along both the zeroth and first dimensions\r\ntile(a, 2, 2) [6 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n\r\n// Repeat array a twice along the first and three times along \r\n// the second dimension.\r\naf::dim4 tile_dims(1, 2, 3);\r\ntile(a, tile_dims) [3 2 3 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000</pre>\r\nThe C interface for tile is as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_tile(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for tiling an array</pre>\r\nThe C++ interface has two overloads\r\n<pre class=\"lang:default decode:true\">array af::tile(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=1, const unsigned w=1) \r\n– Tiles array along specified dimensions\r\n\r\narray af::tile(const array &amp;in, const dim4 &amp;dims) \r\n– Tile an array according to a dim4 object</pre>\r\n<a name=\"tile\"></a>\r\n\r\n<a name=\"transpose\"></a>\r\n<h4>transpose()</h4>\r\nThe transpose() function performs a standard matrix transpose. The input array must have the dimensions of a 2D-matrix.\r\n<pre class=\"lang:default decode:true\">a [3 3 1 1]\r\n1.0000 3.0000 3.0000\r\n2.0000 1.0000 3.0000\r\n2.0000 2.0000 1.0000\r\n\r\ntranspose(a) [3 3 1 1]\r\n1.0000 2.0000 2.0000\r\n3.0000 1.0000 2.0000\r\n3.0000 3.0000 1.0000</pre>\r\nThe C interfaces for transpose are as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_transpose(af_array *out, af_array in, const bool conjugate) \r\n– C interface to transpose a matrix.\r\n\r\naf_err af_transpose_inplace(af_array in, const bool conjugate) \r\n– C interface to transpose a matrix in-place.</pre>\r\nThe C++ interface has two primary functions and two shorthand versions:\r\n<pre class=\"lang:default decode:true\">array af::transpose(const array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix.\r\n\r\nvoid af::transposeInPlace(array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix in-place.\r\n\r\n__array af::T() \r\n– Transpose a matrix\r\n\r\n__array af::H() \r\n– Conjugate Transpose (Hermitian transpose) of a matrix</pre>\r\nHere is an example of how the shorthand versions might be used:\r\n<pre class=\"lang:default decode:true \">array x = randu(2, 2, f32);\r\naf_print(x.T()); // transpose (real)\r\narray c = randu(2, 2, c32);\r\naf_print(c.T()); // transpose (complex)\r\naf_print(c.H()); // Hermitian (conjugate) transpose</pre>\r\n<a name=\"transpose\"></a>\r\n\r\n<a name=\"array\"></a>\r\n<h4>array()</h4>\r\narray() can be used to create a (shallow) copy of a matrix with different dimensions. The total number of elements must remain the same. This function is a wrapper over the moddims() function discussed earlier.\r\n\r\nCombining re-ordering functions to enumerate grid coordinates\r\n\r\nBy using a combination of the array restructuring functions, one can quickly code complex manipulation patterns with a few lines of code. For example, consider generating (x,y) coordinates for a grid where each axis goes from 1 to n. Instead of using several loops to populate our arrays we can just use a small combination of the above functions.\r\n<pre class=\"lang:default decode:true \">unsigned n=3;\r\naf::array xy = join(1\r\ntile(seq(1, n), n)\r\nflat( transpose(tile(seq(1, n), 1, n)) )\r\n);\r\nxy [9 2 1 1]\r\n1.0000 1.0000\r\n2.0000 1.0000\r\n3.0000 1.0000\r\n1.0000 2.0000\r\n2.0000 2.0000\r\n3.0000 2.0000\r\n1.0000 3.0000\r\n2.0000 3.0000\r\n3.0000 3.0000</pre>\r\nWe hope you have found these instructions to be useful. As always, if you have questions about ArrayFire, feel free to drop us a line on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">Google Group</a>.','Manipulating and restructuring arrays','','inherit','closed','closed','','8633-revision-v1','','','2016-05-12 10:40:29','2016-05-12 14:40:29','',8633,'http://sandbox.arrayfire.com/8633-revision-v1/',0,'revision','',0),(8854,18528,'2016-05-12 10:43:34','2016-05-12 14:43:34','The fundamental primitive of the ArrayFire Library is our container object, the array. As the next post in our blog series, \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\", we will describe how to construct arrays, what datatypes arrays support, indexing, how to query an array for various properties (content, dimensions), and how to write mathematical expressions that involve arrays.\r\n\r\n<!--more-->\r\n\r\nArrayFire abstracts away much of the details of programming parallel architectures by providing a high-level container object, the <a class=\"el\" href=\"classaf_1_1array.htm\">array</a>, that represents data stored on a CPU, GPU, FPGA, or other type of accelerator. This abstraction permits developers to write massively parallel applications in a high-level language where they need not be concerned about low-level optimizations that are frequently required to achieve high throughput on most parallel architectures.\r\n<h4>Creating ArrayFire Arrays</h4>\r\nArrays represent memory on a supported device. You can create arrays of uninitialized memory using the array constructor:\r\n<pre class=\"lang:c++ decode:true\">// Arrays may be created using the af::array constructor and dimensioned\r\n// as 1D, 2D, 3D; however, the values in these arrays will be undefined\r\narray undefined_1D = array(100);        // 1D array with 100 elements\r\narray undefined_2D = array(10, 100);    // 2D array of size 10 x 100\r\narray undefined_3D = array(10, 10, 10); // 3D array of size 10 x 10 x 10</pre>\r\nOr using one of many constructors that initialize memory:\r\n<pre class=\"lang:default decode:true\">// Create an array of zeros of length three:\r\narray zeros      = constant(0, 3);\r\n\r\n// Generate a 1x4 array of uniformly distributed [0,1] random numbe// using af::randu():\r\narray rand1      = randu(1, 4);\r\n    \r\n// Make a 2x2 array (or matrix, if you prefer) of random numbers\r\n// sampled from a normal distribution using af::randn():\r\narray rand2      = randn(2, 2);\r\n\r\n// Construct a 3x3 identity matrix. \r\narray iden       = af::identity(3, 3);</pre>\r\nLastly, arrays may be populated with data from the host using our copy constructor:\r\n<pre class=\"lang:default decode:true\">// Create a six-element array on the host\r\nfloat hA[] = {0, 1, 2, 3, 4, 5};\r\n    \r\n// Using the array copy constructor, we can create a 2x3\r\n// matrix from this data:\r\narray A(2, 3, hA);</pre>\r\nArrays can also be created from CUDA device pointers or OpenCL memory buffers. Please consult the <a href=\"http://arrayfire.org/docs/gettingstarted.htm\">documentation</a> on these aspects.\r\n<h4>Supported data types</h4>\r\nArrayFire arrays support standard integral and complex data types found in C/C++. The data type for an array is specified by providing an (optional) final parameter to any of the array constructors. The type field and supported types are as follows:\r\n<ul>\r\n 	<li>b8 8-bit boolean values (bool)</li>\r\n 	<li>f32 real single-precision (float)</li>\r\n 	<li>c32 complex single-precision (cfloat)</li>\r\n 	<li>s32 32-bit signed integer (int)</li>\r\n 	<li>u32 32-bit unsigned integer (unsigned)</li>\r\n 	<li>f64 real double-precision (double)</li>\r\n 	<li>c64 complex double-precision (cdouble)</li>\r\n 	<li>s64 64-bit signed integer (intl)</li>\r\n 	<li>u64 64-bit unsigned integer (uintl)</li>\r\n 	<li>s16 16-bit signed integer (short)</li>\r\n 	<li>u16 16-bit unsigned integer (unsigned short)</li>\r\n</ul>\r\nFor example, if you wanted to construct a 2x1 (column vector) of uniformly distributed 32-bit complex numbers (c32 data type), you would use the following code:\r\n<pre class=\"lang:default decode:true\">// Create a 2x1 column vector of uniformly distributed\r\n// 32-bit complex values:\r\narray randcplx   = randu(2, 1, c32);</pre>\r\n<h4>Indexing</h4>\r\nLike all functions in ArrayFire, indexing is also executed in parallel on the OpenCL/CUDA device. Because of this, indexing becomes part of a JIT operation and is accomplished using parentheses instead of square brackets (i.e. as A(0) instead of A[0]). To index af::arrays you may use one or a combination of the following functions:\r\n<ul>\r\n 	<li>integer scalars</li>\r\n 	<li>seq() representing a linear sequence</li>\r\n 	<li>end representing the last element of a dimension</li>\r\n 	<li>span representing the entire dimension</li>\r\n 	<li>row(i) or col(i) specifying a single row/column</li>\r\n 	<li>rows(first,last) or cols(first,last) specifying a span of rows or columns</li>\r\n</ul>\r\nHere are a few examples of these indexing functions in operation:\r\n<pre class=\"lang:default decode:true\">// Make an 3x3 array containing numbers 1-9:\r\narray A = array(seq(1,9), 3, 3);\r\n\r\nA(0);            // first element\r\nA(0,1);          // first row, second column\r\nA(end);          // last element\r\nA(-1);           // also last element\r\nA(end-1);        // second-to-last element\r\nA(1,span);       // second row\r\nA.row(end);      // last row\r\nA.cols(1,end);   // all but first column</pre>\r\nFor further examples, see the <a href=\"http://arrayfire.org/docs/indexing.htm\">documentation on indexing</a>.\r\n<h4>Querying existing arrays for their properties</h4>\r\nArrayFire array objects carry some ancillary information which can be quite useful when developing applications. For example, once you have an array <span class=\"lang:default decode:true crayon-inline \">A</span> , you can query for:\r\n<ul>\r\n 	<li>Number and size of dimensions via. <span class=\"lang:default decode:true crayon-inline \">A.numdims()</span>  and <span class=\"lang:default decode:true crayon-inline \">A.dims(int)</span>  functions.</li>\r\n 	<li>The size of the array in bytes with <span class=\"lang:default decode:true crayon-inline \">A.bytes()</span></li>\r\n 	<li>The underlying data type using <span class=\"lang:default decode:true crayon-inline \">A.type()</span> or one of many type-specific queries.</li>\r\n 	<li>Whether or not the array is complex or real using <span class=\"lang:default decode:true crayon-inline \">A.iscomplex()</span>  or <span class=\"lang:default decode:true crayon-inline \">A.isreal()</span></li>\r\n 	<li>If the data is scalar, <span class=\"lang:default decode:true crayon-inline \">A.isscalar()</span> , a vector, <span class=\"lang:default decode:true crayon-inline \">A.isvector()</span> , a row, <span class=\"lang:default decode:true crayon-inline \">A.isrow()</span> , or a column, <span class=\"lang:default decode:true crayon-inline \">A.iscolumn()</span> .</li>\r\n</ul>\r\n<h4>Writing mathematical expressions</h4>\r\nArrayFire features an intelligent Just-In-Time (JIT) compilation engine that converts expressions using arrays into the smallest number of CUDA/OpenCL kernels. For most operations on arrays, ArrayFire functions like a vector library. That means that an element-wise operation, like <span class=\"lang:default decode:true crayon-inline \">c[i] = a[i] + b[i]</span>  in C, would be written more concisely without indexing, like <span class=\"lang:default decode:true crayon-inline \">c = a + b</span> . When there are multiple expressions involving arrays, ArrayFire\'s JIT engine will merge them together. This \"kernel fusion\" technology not only decreases the number of kernel calls, but, more importantly, avoids extraneous global memory operations. Our JIT functionality extends across C/C++ function boundaries and only ends when a non-JIT function is encountered or a synchronization operation is explicitly called by the code. Thus writing mathematical functions in ArrayFire is as simple as writing the equations themselves!\r\n\r\nArrayFire provides <a class=\"el\" href=\"http://arrayfire.org/docs/group__arith__mat.htm\">hundreds of functions</a> for element-wise operations. All of the standard operators (e.g. +,-,*,/) are supported as are most transcendental functions (sin, cos, log, sqrt, etc.).\r\n\r\nIn addition to mathematical functions, ArrayFire also includes frequently used computer vision functions (FAST, ORB, SIFT), and image processing functions (colorspace conversion, filters, histograms, transformations, and morphological operations).\r\n\r\n&nbsp;','Introduction to the ArrayFire array','','inherit','closed','closed','','8831-revision-v1','','','2016-05-12 10:43:34','2016-05-12 14:43:34','',8831,'http://sandbox.arrayfire.com/8831-revision-v1/',0,'revision','',0),(8855,18528,'2016-05-12 10:45:56','2016-05-12 14:45:56','One of the most common questions we see on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a> pertains to methods to manipulate the dimensions of ArrayFire array objects. Thus we will continue the \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" blog series by providing a detailed discussion of the numerous functions that permit you to change the dimentionality, flatten, flip, join, shift, transpose, and tile arrays.\n\n<!--more-->\n\nArrayFire provides several different methods for manipulating arrays and matrices. The functionality includes:\n<ul>\n 	<li><a href=\"#moddims\">moddims()</a> - change the dimensions of an array without changing the data</li>\n 	<li><a href=\"#array\">array()</a> - create a (shallow) copy of an array with different dimensions.</li>\n 	<li><a href=\"#flat\">flat()</a> - flatten an array to one dimension</li>\n 	<li><a href=\"#flip\">flip()</a> - flip an array along a dimension</li>\n 	<li><a href=\"#join\">join()</a> - join up to 4 arrays</li>\n 	<li><a href=\"#reorder\">reorder()</a> - changes the dimension order within the array</li>\n 	<li><a href=\"#shift\">shift()</a> - shifts data along a dimension</li>\n 	<li><a href=\"#tile\">tile()</a> - repeats an array along a dimension</li>\n 	<li><a href=\"#transpose\">transpose()</a> - performs a matrix transpose</li>\n 	<li><a href=\"#transpose\">T()</a> - transpose a matrix or vector (shorthand notation)</li>\n 	<li><a href=\"#transpose\">H()</a> - Hermitian Transpose (conjugate-transpose) a matrix</li>\n</ul>\nBelow we provide several examples of these functions and their use. However, if you come to this page far in the future, we suggest you <a href=\"http://arrayfire.org/docs/matrixmanipulation.htm\">visit the documentation on this topic</a> to see the latest information on these topics.\n<a name=\"flat\"></a>\n<h4>flat()</h4>\nThe flat() function flattens an array to one dimension:\n<pre class=\"lang:default decode:true \">a [3 3 1 1]\n1.0000 4.0000 7.0000\n2.0000 5.0000 8.0000\n3.0000 6.0000 9.0000\n\nflat(a) [9 1 1 1]\n1.0000\n2.0000\n3.0000\n4.0000\n5.0000\n6.0000\n7.0000\n8.0000\n9.0000</pre>\nThe flat function can be called from C and C++ as follows:\n<pre class=\"lang:default decode:true\">af_err af_flat(af_array* out, const af_array in) \n– C interface for flat() function\n\narray af::flat(const array&amp; in)\n– C++ interface for flat() function</pre>\n<a name=\"flip\"></a>\n<h4>flip()</h4>\nThe flip() function flips the contents of an array along a chosen dimension. In the example below, we show the 5x2 array flipped along the zeroth (i.e. within a column) and first (e.g. across rows) axes:\n<pre class=\"lang:default decode:true \">a [5 2 1 1]\n1.0000 6.0000\n2.0000 7.0000\n3.0000 8.0000\n4.0000 9.0000\n5.0000 10.0000\n\nflip(a, 0) [5 2 1 1]\n5.0000 10.0000\n4.0000 9.0000\n3.0000 8.0000\n2.0000 7.0000\n1.0000 6.0000\n\nflip(a, 1) [5 2 1 1]\n6.0000 1.0000\n7.0000 2.0000\n8.0000 3.0000\n9.0000 4.0000\n10.0000 5.0000</pre>\nThe flip function can be called from C and C++ as follows:\n<pre class=\"lang:default decode:true\">af_err af_flip(af_array *out, const af_array in, const unsigned dim) \n– C interface for flip()\n\narray af::flip(const array &amp;in, const unsigned dim) \n– C++ interface for flip()</pre>\n<a name=\"join\"></a>\n<h4>join()</h4>\nThe join() function joins arrays along a specific dimension. The C++ interface can join up to four arrays whereas the C interface supports up to 10 arrays. Here is an example of how to use join an array to itself:\n<pre class=\"lang:default decode:true \">a [5 1 1 1]\n1.0000\n2.0000\n3.0000\n4.0000\n5.0000\n\njoin(0, a, a) [10 1 1 1]\n1.0000\n2.0000\n3.0000\n4.0000\n5.0000\n1.0000\n2.0000\n3.0000\n4.0000\n5.0000\n\njoin(1, a, a) [5 2 1 1]\n1.0000 1.0000\n2.0000 2.0000\n3.0000 3.0000\n4.0000 4.0000\n5.0000 5.0000</pre>\nThe join function has several candidate functions in C:\n<pre class=\"lang:default decode:true\">af_err af_join(af_array *out, const int dim, const af_array first, const af_array second) \n– C interface function to join 2 arrays along a dimension\n\naf_err af_join_many(af_array *out, const int dim, const unsigned n_arrays, const af_array *inputs) \n– C interface function to join up to 10 arrays along a dimension</pre>\nand in C++:\n<pre class=\"lang:default decode:true\">array af::join(const int dim, const array &amp;first, const array &amp;second) \n– Joins 2 arrays along a dimension\n\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third) \n– Joins 3 arrays along a dimension.\n\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third, const array &amp;fourth) \n– Joins 4 arrays along a dimension</pre>\n<a name=\"join\"></a>\n\n<a name=\"moddims\"></a>\n<h4>moddims()</h4>\nThe moddims() function changes the dimensions of an array without changing its data or order. Note that this function modifies only the metadata associated with the array. It does not modify the content of the array. Here is an example of moddims() converting an 8x1 array into a 2x4 and then back to a 8x1:\n<pre class=\"lang:default decode:true\">a [8 1 1 1]\n1.0000\n2.0000\n1.0000\n2.0000\n1.0000\n2.0000\n1.0000\n2.0000\n\naf::dim4 new_dims(2, 4);\nmoddims(a, new_dims) [2 4 1 1]\n1.0000 1.0000 1.0000 1.0000\n2.0000 2.0000 2.0000 2.0000\n\nmoddims(a, a.elements(), 1, 1, 1) [8 1 1 1]\n1.0000\n2.0000\n1.0000\n2.0000\n1.0000\n2.0000\n1.0000\n2.0000</pre>\nThe moddims function has a single form in the C API:\n<pre class=\"lang:default decode:true\">af_err af_moddims(af_array *out, const af_array in, const unsigned ndims, const dim_t *const dims) \n– C interface to mod dimensions of an array</pre>\nAnd several overloaded candidates in the C++ API:\n<pre class=\"lang:default decode:true\">array af::moddims(const array &amp;in, const unsigned ndims, const dim_t *const dims) \n– mods number of dimensions to match ndims as specidied in the array dims\n\narray af::moddims(const array &amp;in, const dim4 &amp;dims) \n– mods dimensions as specified by dims\n\narray af::moddims(const array &amp;in, const dim_t d0, const dim_t d1=1, const dim_t d2=1, const dim_t d3=1) \n– mods dimensions of an array</pre>\n<a name=\"moddims\"></a>\n\n<a name=\"reorder\"></a>\n<h4>reorder()</h4>\nThe reorder() function modifies the order of data within an array by exchanging data according to the change in dimensionality. The linear ordering of data within the array is preserved.\n<pre class=\"lang:default decode:true \">a [2 2 3 1]\n1.0000 3.0000\n2.0000 4.0000\n1.0000 3.0000\n2.0000 4.0000\n1.0000 3.0000\n2.0000 4.0000\n\nreorder(a, 1, 0, 2) [2 2 3 1] //equivalent to a transpose\n1.0000 2.0000\n3.0000 4.0000\n1.0000 2.0000\n3.0000 4.0000\n1.0000 2.0000\n3.0000 4.0000\n\nreorder(a, 2, 0, 1) [3 2 2 1]\n1.0000 2.0000\n1.0000 2.0000\n1.0000 2.0000\n3.0000 4.0000\n3.0000 4.0000\n3.0000 4.0000</pre>\nThe reorder function has several candidates functions in the C/C++ APIs:\n<pre class=\"lang:default decode:true\">af_err af_reorder(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \n– C interface for reordering function\n\narray af::reorder(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=2, const unsigned w=3) \n– Reorders dimensions of an array</pre>\n<a name=\"reorder\"></a>\n\n<a name=\"shift\"></a>\n<h4>shift()</h4>\nThe shift() function shifts data in a circular buffer fashion along a chosen dimension. Consider the following example:\n<pre class=\"lang:default decode:true \">a [3 5 1 1]\n0.0000 0.0000 0.0000 0.0000 0.0000\n3.0000 4.0000 5.0000 1.0000 2.0000\n3.0000 4.0000 5.0000 1.0000 2.0000\n\nshift(a, 0, 2 ) [3 5 1 1]\n0.0000 0.0000 0.0000 0.0000 0.0000\n1.0000 2.0000 3.0000 4.0000 5.0000\n1.0000 2.0000 3.0000 4.0000 5.0000\n\nshift(a, -1, 2 ) [3 5 1 1]\n1.0000 2.0000 3.0000 4.0000 5.0000\n1.0000 2.0000 3.0000 4.0000 5.0000\n0.0000 0.0000 0.0000 0.0000 0.0000</pre>\nThe shift function can be called from C and C++ as follows:\n<pre class=\"lang:default decode:true\">af_err af_shift(af_array *out, const af_array in, const int x, const int y, const int z, const int w) \n– C interface for shifting an array\n\narray af::shift(const array &amp;in, const int x, const int y=0, const int z=0, const int w=0) \n– Shifts array along specified dimensions</pre>\n<a name=\"shift\"></a>\n\n<a name=\"tile\"></a>\n<h4>tile()</h4>\nThe tile() function repeats an array along the specified dimension. For example below we show how to tile an array along the zeroth and first dimensions of an array:\n<pre class=\"lang:default decode:true\">a [3 1 1 1]\n1.0000\n2.0000\n3.0000\n\n// Repeat array a twice in the zeroth dimension\ntile(a, 2) [6 1 1 1]\n1.0000\n2.0000\n3.0000\n1.0000\n2.0000\n3.0000\n\n// Repeat array a twice along both the zeroth and first dimensions\ntile(a, 2, 2) [6 2 1 1]\n1.0000 1.0000\n2.0000 2.0000\n3.0000 3.0000\n1.0000 1.0000\n2.0000 2.0000\n3.0000 3.0000\n\n// Repeat array a twice along the first and three times along \n// the second dimension.\naf::dim4 tile_dims(1, 2, 3);\ntile(a, tile_dims) [3 2 3 1]\n1.0000 1.0000\n2.0000 2.0000\n3.0000 3.0000\n1.0000 1.0000\n2.0000 2.0000\n3.0000 3.0000\n1.0000 1.0000\n2.0000 2.0000\n3.0000 3.0000</pre>\nThe C interface for tile is as follows:\n<pre class=\"lang:default decode:true\">af_err af_tile(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \n– C interface for tiling an array</pre>\nThe C++ interface has two overloads\n<pre class=\"lang:default decode:true\">array af::tile(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=1, const unsigned w=1) \n– Tiles array along specified dimensions\n\narray af::tile(const array &amp;in, const dim4 &amp;dims) \n– Tile an array according to a dim4 object</pre>\n<a name=\"tile\"></a>\n\n<a name=\"transpose\"></a>\n<h4>transpose()</h4>\nThe transpose() function performs a standard matrix transpose. The input array must have the dimensions of a 2D-matrix.\n<pre class=\"lang:default decode:true\">a [3 3 1 1]\n1.0000 3.0000 3.0000\n2.0000 1.0000 3.0000\n2.0000 2.0000 1.0000\n\ntranspose(a) [3 3 1 1]\n1.0000 2.0000 2.0000\n3.0000 1.0000 2.0000\n3.0000 3.0000 1.0000</pre>\nThe C interfaces for transpose are as follows:\n<pre class=\"lang:default decode:true\">af_err af_transpose(af_array *out, af_array in, const bool conjugate) \n– C interface to transpose a matrix.\n\naf_err af_transpose_inplace(af_array in, const bool conjugate) \n– C interface to transpose a matrix in-place.</pre>\nThe C++ interface has two primary functions and two shorthand versions:\n<pre class=\"lang:default decode:true\">array af::transpose(const array &amp;in, const bool conjugate=false) \n– Transposes a matrix.\n\nvoid af::transposeInPlace(array &amp;in, const bool conjugate=false) \n– Transposes a matrix in-place.\n\n__array af::T() \n– Transpose a matrix\n\n__array af::H() \n– Conjugate Transpose (Hermitian transpose) of a matrix</pre>\nHere is an example of how the shorthand versions might be used:\n<pre class=\"lang:default decode:true \">array x = randu(2, 2, f32);\naf_print(x.T()); // transpose (real)\narray c = randu(2, 2, c32);\naf_print(c.T()); // transpose (complex)\naf_print(c.H()); // Hermitian (conjugate) transpose</pre>\n<a name=\"transpose\"></a>\n\n<a name=\"array\"></a>\n<h4>array()</h4>\narray() can be used to create a (shallow) copy of a matrix with different dimensions. The total number of elements must remain the same. This function is a wrapper over the moddims() function discussed earlier.\n\nCombining re-ordering functions to enumerate grid coordinates\n\nBy using a combination of the array restructuring functions, one can quickly code complex manipulation patterns with a few lines of code. For example, consider generating (x,y) coordinates for a grid where each axis goes from 1 to n. Instead of using several loops to populate our arrays we can just use a small combination of the above functions.\n<pre class=\"lang:default decode:true  \">unsigned n=3;\naf::array xy = join(1\ntile(seq(1, n), n)\n   flat( transpose(tile(seq(1, n), 1, n)) )\n);\nxy [9 2 1 1]\n1.0000 1.0000\n2.0000 1.0000\n3.0000 1.0000\n1.0000 2.0000\n2.0000 2.0000\n3.0000 2.0000\n1.0000 3.0000\n2.0000 3.0000\n3.0000 3.0000</pre>\nWe hope you have found these instructions to be useful. As always, if you have questions about ArrayFire, feel free to drop us a line on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">Google Group</a>.','Manipulating and restructuring arrays','','inherit','closed','closed','','8633-autosave-v1','','','2016-05-12 10:45:56','2016-05-12 14:45:56','',8633,'http://sandbox.arrayfire.com/8633-autosave-v1/',0,'revision','',0),(8856,18528,'2016-05-12 10:46:43','2016-05-12 14:46:43','One of the most common questions we see on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a> pertains to methods to manipulate the dimensions of ArrayFire array objects. Thus we will continue the \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" blog series by providing a detailed discussion of the numerous functions that permit you to change the dimentionality, flatten, flip, join, shift, transpose, and tile arrays.\r\n\r\n<!--more-->\r\n\r\nArrayFire provides several different methods for manipulating arrays and matrices. The functionality includes:\r\n<ul>\r\n 	<li><a href=\"#moddims\">moddims()</a> - change the dimensions of an array without changing the data</li>\r\n 	<li><a href=\"#array\">array()</a> - create a (shallow) copy of an array with different dimensions.</li>\r\n 	<li><a href=\"#flat\">flat()</a> - flatten an array to one dimension</li>\r\n 	<li><a href=\"#flip\">flip()</a> - flip an array along a dimension</li>\r\n 	<li><a href=\"#join\">join()</a> - join up to 4 arrays</li>\r\n 	<li><a href=\"#reorder\">reorder()</a> - changes the dimension order within the array</li>\r\n 	<li><a href=\"#shift\">shift()</a> - shifts data along a dimension</li>\r\n 	<li><a href=\"#tile\">tile()</a> - repeats an array along a dimension</li>\r\n 	<li><a href=\"#transpose\">transpose()</a> - performs a matrix transpose</li>\r\n 	<li><a href=\"#transpose\">T()</a> - transpose a matrix or vector (shorthand notation)</li>\r\n 	<li><a href=\"#transpose\">H()</a> - Hermitian Transpose (conjugate-transpose) a matrix</li>\r\n</ul>\r\nBelow we provide several examples of these functions and their use. However, if you come to this page far in the future, we suggest you <a href=\"http://arrayfire.org/docs/matrixmanipulation.htm\">visit the documentation on this topic</a> to see the latest information on these topics.\r\n<a name=\"flat\"></a>\r\n<h4>flat()</h4>\r\nThe flat() function flattens an array to one dimension:\r\n<pre class=\"lang:default decode:true \">a [3 3 1 1]\r\n1.0000 4.0000 7.0000\r\n2.0000 5.0000 8.0000\r\n3.0000 6.0000 9.0000\r\n\r\nflat(a) [9 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n6.0000\r\n7.0000\r\n8.0000\r\n9.0000</pre>\r\nThe flat function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_flat(af_array* out, const af_array in) \r\n– C interface for flat() function\r\n\r\narray af::flat(const array&amp; in)\r\n– C++ interface for flat() function</pre>\r\n<a name=\"flip\"></a>\r\n<h4>flip()</h4>\r\nThe flip() function flips the contents of an array along a chosen dimension. In the example below, we show the 5x2 array flipped along the zeroth (i.e. within a column) and first (e.g. across rows) axes:\r\n<pre class=\"lang:default decode:true \">a [5 2 1 1]\r\n1.0000 6.0000\r\n2.0000 7.0000\r\n3.0000 8.0000\r\n4.0000 9.0000\r\n5.0000 10.0000\r\n\r\nflip(a, 0) [5 2 1 1]\r\n5.0000 10.0000\r\n4.0000 9.0000\r\n3.0000 8.0000\r\n2.0000 7.0000\r\n1.0000 6.0000\r\n\r\nflip(a, 1) [5 2 1 1]\r\n6.0000 1.0000\r\n7.0000 2.0000\r\n8.0000 3.0000\r\n9.0000 4.0000\r\n10.0000 5.0000</pre>\r\nThe flip function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_flip(af_array *out, const af_array in, const unsigned dim) \r\n– C interface for flip()\r\n\r\narray af::flip(const array &amp;in, const unsigned dim) \r\n– C++ interface for flip()</pre>\r\n<a name=\"join\"></a>\r\n<h4>join()</h4>\r\nThe join() function joins arrays along a specific dimension. The C++ interface can join up to four arrays whereas the C interface supports up to 10 arrays. Here is an example of how to use join an array to itself:\r\n<pre class=\"lang:default decode:true \">a [5 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(0, a, a) [10 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n4.0000\r\n5.0000\r\n\r\njoin(1, a, a) [5 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n4.0000 4.0000\r\n5.0000 5.0000</pre>\r\nThe join function has several candidate functions in C:\r\n<pre class=\"lang:default decode:true\">af_err af_join(af_array *out, const int dim, const af_array first, const af_array second) \r\n– C interface function to join 2 arrays along a dimension\r\n\r\naf_err af_join_many(af_array *out, const int dim, const unsigned n_arrays, const af_array *inputs) \r\n– C interface function to join up to 10 arrays along a dimension</pre>\r\nand in C++:\r\n<pre class=\"lang:default decode:true\">array af::join(const int dim, const array &amp;first, const array &amp;second) \r\n– Joins 2 arrays along a dimension\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third) \r\n– Joins 3 arrays along a dimension.\r\n\r\narray af::join(const int dim, const array &amp;first, const array &amp;second, const array &amp;third, const array &amp;fourth) \r\n– Joins 4 arrays along a dimension</pre>\r\n<a name=\"join\"></a>\r\n\r\n<a name=\"moddims\"></a>\r\n<h4>moddims()</h4>\r\nThe moddims() function changes the dimensions of an array without changing its data or order. Note that this function modifies only the metadata associated with the array. It does not modify the content of the array. Here is an example of moddims() converting an 8x1 array into a 2x4 and then back to a 8x1:\r\n<pre class=\"lang:default decode:true\">a [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n\r\naf::dim4 new_dims(2, 4);\r\nmoddims(a, new_dims) [2 4 1 1]\r\n1.0000 1.0000 1.0000 1.0000\r\n2.0000 2.0000 2.0000 2.0000\r\n\r\nmoddims(a, a.elements(), 1, 1, 1) [8 1 1 1]\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000\r\n1.0000\r\n2.0000</pre>\r\nThe moddims function has a single form in the C API:\r\n<pre class=\"lang:default decode:true\">af_err af_moddims(af_array *out, const af_array in, const unsigned ndims, const dim_t *const dims) \r\n– C interface to mod dimensions of an array</pre>\r\nAnd several overloaded candidates in the C++ API:\r\n<pre class=\"lang:default decode:true\">array af::moddims(const array &amp;in, const unsigned ndims, const dim_t *const dims) \r\n– mods number of dimensions to match ndims as specidied in the array dims\r\n\r\narray af::moddims(const array &amp;in, const dim4 &amp;dims) \r\n– mods dimensions as specified by dims\r\n\r\narray af::moddims(const array &amp;in, const dim_t d0, const dim_t d1=1, const dim_t d2=1, const dim_t d3=1) \r\n– mods dimensions of an array</pre>\r\n<a name=\"moddims\"></a>\r\n\r\n<a name=\"reorder\"></a>\r\n<h4>reorder()</h4>\r\nThe reorder() function modifies the order of data within an array by exchanging data according to the change in dimensionality. The linear ordering of data within the array is preserved.\r\n<pre class=\"lang:default decode:true \">a [2 2 3 1]\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n1.0000 3.0000\r\n2.0000 4.0000\r\n\r\nreorder(a, 1, 0, 2) [2 2 3 1] //equivalent to a transpose\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n\r\nreorder(a, 2, 0, 1) [3 2 2 1]\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n1.0000 2.0000\r\n3.0000 4.0000\r\n3.0000 4.0000\r\n3.0000 4.0000</pre>\r\nThe reorder function has several candidates functions in the C/C++ APIs:\r\n<pre class=\"lang:default decode:true\">af_err af_reorder(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for reordering function\r\n\r\narray af::reorder(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=2, const unsigned w=3) \r\n– Reorders dimensions of an array</pre>\r\n<a name=\"reorder\"></a>\r\n\r\n<a name=\"shift\"></a>\r\n<h4>shift()</h4>\r\nThe shift() function shifts data in a circular buffer fashion along a chosen dimension. Consider the following example:\r\n<pre class=\"lang:default decode:true \">a [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n3.0000 4.0000 5.0000 1.0000 2.0000\r\n\r\nshift(a, 0, 2 ) [3 5 1 1]\r\n0.0000 0.0000 0.0000 0.0000 0.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n\r\nshift(a, -1, 2 ) [3 5 1 1]\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n1.0000 2.0000 3.0000 4.0000 5.0000\r\n0.0000 0.0000 0.0000 0.0000 0.0000</pre>\r\nThe shift function can be called from C and C++ as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_shift(af_array *out, const af_array in, const int x, const int y, const int z, const int w) \r\n– C interface for shifting an array\r\n\r\narray af::shift(const array &amp;in, const int x, const int y=0, const int z=0, const int w=0) \r\n– Shifts array along specified dimensions</pre>\r\n<a name=\"shift\"></a>\r\n\r\n<a name=\"tile\"></a>\r\n<h4>tile()</h4>\r\nThe tile() function repeats an array along the specified dimension. For example below we show how to tile an array along the zeroth and first dimensions of an array:\r\n<pre class=\"lang:default decode:true\">a [3 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice in the zeroth dimension\r\ntile(a, 2) [6 1 1 1]\r\n1.0000\r\n2.0000\r\n3.0000\r\n1.0000\r\n2.0000\r\n3.0000\r\n\r\n// Repeat array a twice along both the zeroth and first dimensions\r\ntile(a, 2, 2) [6 2 1 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n\r\n// Repeat array a twice along the first and three times along \r\n// the second dimension.\r\naf::dim4 tile_dims(1, 2, 3);\r\ntile(a, tile_dims) [3 2 3 1]\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000\r\n1.0000 1.0000\r\n2.0000 2.0000\r\n3.0000 3.0000</pre>\r\nThe C interface for tile is as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_tile(af_array *out, const af_array in, const unsigned x, const unsigned y, const unsigned z, const unsigned w) \r\n– C interface for tiling an array</pre>\r\nThe C++ interface has two overloads\r\n<pre class=\"lang:default decode:true\">array af::tile(const array &amp;in, const unsigned x, const unsigned y=1, const unsigned z=1, const unsigned w=1) \r\n– Tiles array along specified dimensions\r\n\r\narray af::tile(const array &amp;in, const dim4 &amp;dims) \r\n– Tile an array according to a dim4 object</pre>\r\n<a name=\"tile\"></a>\r\n\r\n<a name=\"transpose\"></a>\r\n<h4>transpose()</h4>\r\nThe transpose() function performs a standard matrix transpose. The input array must have the dimensions of a 2D-matrix.\r\n<pre class=\"lang:default decode:true\">a [3 3 1 1]\r\n1.0000 3.0000 3.0000\r\n2.0000 1.0000 3.0000\r\n2.0000 2.0000 1.0000\r\n\r\ntranspose(a) [3 3 1 1]\r\n1.0000 2.0000 2.0000\r\n3.0000 1.0000 2.0000\r\n3.0000 3.0000 1.0000</pre>\r\nThe C interfaces for transpose are as follows:\r\n<pre class=\"lang:default decode:true\">af_err af_transpose(af_array *out, af_array in, const bool conjugate) \r\n– C interface to transpose a matrix.\r\n\r\naf_err af_transpose_inplace(af_array in, const bool conjugate) \r\n– C interface to transpose a matrix in-place.</pre>\r\nThe C++ interface has two primary functions and two shorthand versions:\r\n<pre class=\"lang:default decode:true\">array af::transpose(const array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix.\r\n\r\nvoid af::transposeInPlace(array &amp;in, const bool conjugate=false) \r\n– Transposes a matrix in-place.\r\n\r\n__array af::T() \r\n– Transpose a matrix\r\n\r\n__array af::H() \r\n– Conjugate Transpose (Hermitian transpose) of a matrix</pre>\r\nHere is an example of how the shorthand versions might be used:\r\n<pre class=\"lang:default decode:true \">array x = randu(2, 2, f32);\r\naf_print(x.T()); // transpose (real)\r\narray c = randu(2, 2, c32);\r\naf_print(c.T()); // transpose (complex)\r\naf_print(c.H()); // Hermitian (conjugate) transpose</pre>\r\n<a name=\"transpose\"></a>\r\n\r\n<a name=\"array\"></a>\r\n<h4>array()</h4>\r\narray() can be used to create a (shallow) copy of a matrix with different dimensions. The total number of elements must remain the same. This function is a wrapper over the moddims() function discussed earlier.\r\n\r\nCombining re-ordering functions to enumerate grid coordinates\r\n\r\nBy using a combination of the array restructuring functions, one can quickly code complex manipulation patterns with a few lines of code. For example, consider generating (x,y) coordinates for a grid where each axis goes from 1 to n. Instead of using several loops to populate our arrays we can just use a small combination of the above functions.\r\n<pre class=\"lang:default decode:true  \">unsigned n=3;\r\naf::array xy = join(1,\r\n    tile(seq(1, n), n),\r\n    flat( transpose(tile(seq(1, n), 1, n)) )\r\n);\r\n\r\nxy [9 2 1 1]\r\n1.0000 1.0000\r\n2.0000 1.0000\r\n3.0000 1.0000\r\n1.0000 2.0000\r\n2.0000 2.0000\r\n3.0000 2.0000\r\n1.0000 3.0000\r\n2.0000 3.0000\r\n3.0000 3.0000</pre>\r\nWe hope you have found these instructions to be useful. As always, if you have questions about ArrayFire, feel free to drop us a line on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">Google Group</a>.','Manipulating and restructuring arrays','','inherit','closed','closed','','8633-revision-v1','','','2016-05-12 10:46:43','2016-05-12 14:46:43','',8633,'http://sandbox.arrayfire.com/8633-revision-v1/',0,'revision','',0),(8867,18528,'2016-05-16 11:55:45','2016-05-16 15:55:45','The fundamental primitive of the ArrayFire Library is our container object, the array. As the next post in our blog series, \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\", we will describe how to construct arrays, what datatypes arrays support, indexing, how to query an array for various properties (content, dimensions), and how to write mathematical expressions that involve arrays.\r\n\r\n<!--more-->\r\n\r\nArrayFire abstracts away much of the details of programming parallel architectures by providing a high-level container object, the <a class=\"el\" href=\"http://arrayfire.org/docs/group__array__mat.htm\">array</a>, that represents data stored on a CPU, GPU, FPGA, or other type of accelerator. This abstraction permits developers to write massively parallel applications in a high-level language where they need not be concerned about low-level optimizations that are frequently required to achieve high throughput on most parallel architectures.\r\n<h4>Creating ArrayFire Arrays</h4>\r\nArrays represent memory on a supported device. You can create arrays of uninitialized memory using the array constructor:\r\n<pre class=\"lang:c++ decode:true\">// Arrays may be created using the af::array constructor and dimensioned\r\n// as 1D, 2D, 3D; however, the values in these arrays will be undefined\r\narray undefined_1D = array(100);        // 1D array with 100 elements\r\narray undefined_2D = array(10, 100);    // 2D array of size 10 x 100\r\narray undefined_3D = array(10, 10, 10); // 3D array of size 10 x 10 x 10</pre>\r\nOr using one of many constructors that initialize memory:\r\n<pre class=\"lang:default decode:true\">// Create an array of zeros of length three:\r\narray zeros      = constant(0, 3);\r\n\r\n// Generate a 1x4 array of uniformly distributed [0,1] random numbe// using af::randu():\r\narray rand1      = randu(1, 4);\r\n    \r\n// Make a 2x2 array (or matrix, if you prefer) of random numbers\r\n// sampled from a normal distribution using af::randn():\r\narray rand2      = randn(2, 2);\r\n\r\n// Construct a 3x3 identity matrix. \r\narray iden       = af::identity(3, 3);</pre>\r\nLastly, arrays may be populated with data from the host using our copy constructor:\r\n<pre class=\"lang:default decode:true\">// Create a six-element array on the host\r\nfloat hA[] = {0, 1, 2, 3, 4, 5};\r\n    \r\n// Using the array copy constructor, we can create a 2x3\r\n// matrix from this data:\r\narray A(2, 3, hA);</pre>\r\nArrays can also be created from CUDA device pointers or OpenCL memory buffers. Please consult the <a href=\"http://arrayfire.org/docs/gettingstarted.htm\">documentation</a> on these aspects.\r\n<h4>Supported data types</h4>\r\nArrayFire arrays support standard integral and complex data types found in C/C++. The data type for an array is specified by providing an (optional) final parameter to any of the array constructors. The type field and supported types are as follows:\r\n<ul>\r\n 	<li>b8 8-bit boolean values (bool)</li>\r\n 	<li>f32 real single-precision (float)</li>\r\n 	<li>c32 complex single-precision (cfloat)</li>\r\n 	<li>s32 32-bit signed integer (int)</li>\r\n 	<li>u32 32-bit unsigned integer (unsigned)</li>\r\n 	<li>f64 real double-precision (double)</li>\r\n 	<li>c64 complex double-precision (cdouble)</li>\r\n 	<li>s64 64-bit signed integer (intl)</li>\r\n 	<li>u64 64-bit unsigned integer (uintl)</li>\r\n 	<li>s16 16-bit signed integer (short)</li>\r\n 	<li>u16 16-bit unsigned integer (unsigned short)</li>\r\n</ul>\r\nFor example, if you wanted to construct a 2x1 (column vector) of uniformly distributed 32-bit complex numbers (c32 data type), you would use the following code:\r\n<pre class=\"lang:default decode:true\">// Create a 2x1 column vector of uniformly distributed\r\n// 32-bit complex values:\r\narray randcplx   = randu(2, 1, c32);</pre>\r\n<h4>Indexing</h4>\r\nLike all functions in ArrayFire, indexing is also executed in parallel on the OpenCL/CUDA device. Because of this, indexing becomes part of a JIT operation and is accomplished using parentheses instead of square brackets (i.e. as A(0) instead of A[0]). To index af::arrays you may use one or a combination of the following functions:\r\n<ul>\r\n 	<li>integer scalars</li>\r\n 	<li>seq() representing a linear sequence</li>\r\n 	<li>end representing the last element of a dimension</li>\r\n 	<li>span representing the entire dimension</li>\r\n 	<li>row(i) or col(i) specifying a single row/column</li>\r\n 	<li>rows(first,last) or cols(first,last) specifying a span of rows or columns</li>\r\n</ul>\r\nHere are a few examples of these indexing functions in operation:\r\n<pre class=\"lang:default decode:true\">// Make an 3x3 array containing numbers 1-9:\r\narray A = array(seq(1,9), 3, 3);\r\n\r\nA(0);            // first element\r\nA(0,1);          // first row, second column\r\nA(end);          // last element\r\nA(-1);           // also last element\r\nA(end-1);        // second-to-last element\r\nA(1,span);       // second row\r\nA.row(end);      // last row\r\nA.cols(1,end);   // all but first column</pre>\r\nFor further examples, see the <a href=\"http://arrayfire.org/docs/indexing.htm\">documentation on indexing</a>.\r\n<h4>Querying existing arrays for their properties</h4>\r\nArrayFire array objects carry some ancillary information which can be quite useful when developing applications. For example, once you have an array <span class=\"lang:default decode:true crayon-inline \">A</span> , you can query for:\r\n<ul>\r\n 	<li>Number and size of dimensions via. <span class=\"lang:default decode:true crayon-inline \">A.numdims()</span>  and <span class=\"lang:default decode:true crayon-inline \">A.dims(int)</span>  functions.</li>\r\n 	<li>The size of the array in bytes with <span class=\"lang:default decode:true crayon-inline \">A.bytes()</span></li>\r\n 	<li>The underlying data type using <span class=\"lang:default decode:true crayon-inline \">A.type()</span> or one of many type-specific queries.</li>\r\n 	<li>Whether or not the array is complex or real using <span class=\"lang:default decode:true crayon-inline \">A.iscomplex()</span>  or <span class=\"lang:default decode:true crayon-inline \">A.isreal()</span></li>\r\n 	<li>If the data is scalar, <span class=\"lang:default decode:true crayon-inline \">A.isscalar()</span> , a vector, <span class=\"lang:default decode:true crayon-inline \">A.isvector()</span> , a row, <span class=\"lang:default decode:true crayon-inline \">A.isrow()</span> , or a column, <span class=\"lang:default decode:true crayon-inline \">A.iscolumn()</span> .</li>\r\n</ul>\r\n<h4>Writing mathematical expressions</h4>\r\nArrayFire features an intelligent Just-In-Time (JIT) compilation engine that converts expressions using arrays into the smallest number of CUDA/OpenCL kernels. For most operations on arrays, ArrayFire functions like a vector library. That means that an element-wise operation, like <span class=\"lang:default decode:true crayon-inline \">c[i] = a[i] + b[i]</span>  in C, would be written more concisely without indexing, like <span class=\"lang:default decode:true crayon-inline \">c = a + b</span> . When there are multiple expressions involving arrays, ArrayFire\'s JIT engine will merge them together. This \"kernel fusion\" technology not only decreases the number of kernel calls, but, more importantly, avoids extraneous global memory operations. Our JIT functionality extends across C/C++ function boundaries and only ends when a non-JIT function is encountered or a synchronization operation is explicitly called by the code. Thus writing mathematical functions in ArrayFire is as simple as writing the equations themselves!\r\n\r\nArrayFire provides <a class=\"el\" href=\"http://arrayfire.org/docs/group__arith__mat.htm\">hundreds of functions</a> for element-wise operations. All of the standard operators (e.g. +,-,*,/) are supported as are most transcendental functions (sin, cos, log, sqrt, etc.).\r\n\r\nIn addition to mathematical functions, ArrayFire also includes frequently used computer vision functions (FAST, ORB, SIFT), and image processing functions (colorspace conversion, filters, histograms, transformations, and morphological operations).\r\n\r\n&nbsp;','Introduction to the ArrayFire array','','inherit','closed','closed','','8831-revision-v1','','','2016-05-16 11:55:45','2016-05-16 15:55:45','',8831,'http://sandbox.arrayfire.com/8831-revision-v1/',0,'revision','',0),(8869,18528,'2016-05-31 10:00:11','2016-05-31 14:00:11','Although ArrayFire is quite extensive, there remain many cases in which you may want to write custom kernels in CUDA or OpenCL. For example, you may wish to add ArrayFire to an existing code base to increase your productivity, or you may need to supplement ArrayFire\'s functionality with your own custom implementation of specific algorithms. Today\'s \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\", blog post discusses how you can interface ArrayFire and CUDA.\r\n\r\n<!--more-->\r\n\r\nWhen it comes to interoperability with CUDA, the most important thing to remember about ArrayFire is that it manages its own memory, runs  in  its own CUDA stream, and  creates custom IDs for devices. As such, most of the interoperability functions focus on reducing potential synchronization conflicts between ArrayFire and CUDA.\r\n\r\n<strong>NOTE</strong>: This blog post was written against ArrayFire 3.3.x. We intend to implement additional convenience functions in ArrayFire 3.4 that should simplify this process further. Be sure to <a href=\"http://arrayfire.org/docs/interop_cuda.htm\">check the documentation</a> for any updates in future releases.\r\n<h4>Basics</h4>\r\nIt is fairly straightforward to interface ArrayFire with your own custom CUDA code. ArrayFire provides several functions to ease this process including:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td>af::array(...)</td>\r\n<td>Construct an ArrayFire Array from device memory</td>\r\n</tr>\r\n<tr>\r\n<td>af::array.device()</td>\r\n<td>Obtain a pointer to the device memory (implies lock()</td>\r\n</tr>\r\n<tr>\r\n<td>af::array.lock()</td>\r\n<td>Removes ArrayFire\'s control of a device memory pointer</td>\r\n</tr>\r\n<tr>\r\n<td>af::array.unlock()</td>\r\n<td>Restore\'s ArrayFire\'s control over a device memory pointer</td>\r\n</tr>\r\n<tr>\r\n<td>af::getDevice()</td>\r\n<td>Gets the current ArrayFire device ID</td>\r\n</tr>\r\n<tr>\r\n<td>af::setDevice()</td>\r\n<td>Switches ArrayFire to the specified device</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::getNativeId()</td>\r\n<td>Converts an ArrayFire device ID to a CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::setNativeId()</td>\r\n<td>Switches ArrayFire to the specified CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::getStream()</td>\r\n<td>Get the current CUDA stream used by ArrayFire</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nBelow we provide two worked examples on how ArrayFire can be integrated into new and existing projects.\r\n<h4>Adding custom CUDA kernels to an existing ArrayFire application</h4>\r\nBy default, ArrayFire manages its own memory and operates in its own CUDA stream. Thus there is a slight amount of bookkeeping that needs to be done in order to integrate your custom CUDA kernel.\r\n\r\nIf your kernels can share the ArrayFire CUDA stream, you should:\r\n<ol type=\"1\">\r\n 	<li>Include the \'af/afcuda.h\' header in your source code</li>\r\n 	<li>Use ArrayFire as normal</li>\r\n 	<li>Ensure any JIT kernels have executed using <code>af::eval()</code></li>\r\n 	<li>Obtain device pointers from ArrayFire array objects using</li>\r\n 	<li>Determine ArrayFire\'s CUDA stream</li>\r\n 	<li>Set arguments and run your kernel in ArrayFire\'s stream</li>\r\n 	<li>Return control of af::array memory to ArrayFire</li>\r\n 	<li>Compile with <code>nvcc</code>, linking with the <code>afcuda</code> library.</li>\r\n</ol>\r\nNotice that since ArrayFire and your kernels are sharing the same CUDA stream, there is no need to perform any synchronization operations as operations within a stream are executed in order.\r\n\r\nThis process is best illustrated with a fully worked example:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1. Add includes\r\n#include &lt;arrayfire.h&gt;\r\n#include &lt;af/cuda.h&gt;\r\n \r\nint main() {\r\n \r\n// 2. Use ArrayFire as normal\r\nsize_t num = 10;\r\naf::array x = af::constant(0, num);\r\n \r\n// ... many ArrayFire operaitons here\r\n \r\n// 3. Ensure any JIT kernels have executed\r\nx.eval();\r\naf_print(x);\r\n \r\n// Run a custom CUDA kernel in the ArrayFire CUDA stream\r\n \r\n// 4. Obtain device pointers from ArrayFire array objects using\r\n// the array::device() function:\r\nfloat *d_x = x.device&lt;float&gt;();\r\n \r\n// 5. Determine ArrayFire\'s CUDA stream\r\nint af_id = af::getDevice();\r\nint cuda_id = afcu::getNativeId(af_id);\r\ncudaStream_t af_cuda_stream = afcu::getStream(cuda_id);\r\n \r\n// 6. Set arguments and run your kernel in ArrayFire\'s stream\r\n// Here launch with 10 blocks of 10 threads\r\nincrement&lt;&lt;&lt;1, num, 0, af_cuda_stream&gt;&gt;&gt;(d_x);\r\n \r\n// 7. Return control of af::array memory to ArrayFire using\r\n// the array::unlock() function:\r\nx.unlock();\r\n \r\n// ... resume ArrayFire operations\r\naf_print(x);\r\n \r\n// Because the device pointers, d_x and d_y, were returned to ArrayFire\'s\r\n// control by the unlock function, there is no need to free them using\r\n// cudaFree()\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\nIf your kernels needs to operate in their own CUDA stream, the process is essentially identical, except you need to instruct ArrayFire to complete its computations using the af::sync() function prior to launching your own kernel and ensure your kernels are complete using <code>cudaDeviceSynchronize()</code> (or similar) commands prior to returning control of the memory to ArrayFire:\r\n<ol type=\"1\">\r\n 	<li>Include the \'af/afcuda.h\' header in your source code</li>\r\n 	<li>Use ArrayFire as normal</li>\r\n 	<li>Ensure any JIT kernels have executed using <code>af::eval()</code></li>\r\n 	<li>Instruct ArrayFire to finish operations using af::sync()</li>\r\n 	<li>Obtain device pointers from ArrayFire array objects using</li>\r\n 	<li>Determine ArrayFire\'s CUDA stream</li>\r\n 	<li>Set arguments and run your kernel in your custom stream</li>\r\n 	<li>Ensure CUDA operations have finished using <code>cudaDeviceSyncronize()</code> or similar commands.</li>\r\n 	<li>Return control of af::array memory to ArrayFire</li>\r\n 	<li>Compile with <code>nvcc</code>, linking with the <code>afcuda</code> library.</li>\r\n</ol>\r\n<h4>Adding ArrayFire to an existing CUDA application</h4>\r\nAdding ArrayFire to an existing CUDA application is slightly more involved and can be somewhat tricky due to several optimizations we implement. The most important are as follows:\r\n<ul>\r\n 	<li>ArrayFire assumes control of all memory provided to it.</li>\r\n 	<li>ArrayFire does not (in general) support in-place memory transactions.</li>\r\n</ul>\r\nWe will discuss the implications of these items below. To add ArrayFire to existing code you need to:\r\n<ol type=\"1\">\r\n 	<li>Include <code>arrayfire.h</code> and <code>af/cuda.h</code> in your source file</li>\r\n 	<li>Finish any pending CUDA operations (e.g. use cudaDeviceSynchronize() or similar stream functions)</li>\r\n 	<li>Create ArrayFire arrays from existing CUDA pointers</li>\r\n 	<li>Perform operations on ArrayFire arrays</li>\r\n 	<li>Instruct ArrayFire to finish operations using af::eval() and af::sync()</li>\r\n 	<li>Obtain pointers to important memory</li>\r\n 	<li>Continue your CUDA application.</li>\r\n 	<li>Free non-managed memory</li>\r\n 	<li>Compile and link with the appropriate paths and the <code>-lafcuda</code> flags.</li>\r\n</ol>\r\nTo create the af::array objects, you should use one of the following constructors with <code>src=afDevice</code>:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1D - 3D af::array constructors\r\naf::array (dim_t dim0, const T *pointer, af::source src=afHost)\r\naf::array (dim_t dim0, dim_t dim1, const T *pointer, af::source src=afHost)\r\naf::array (dim_t dim0, dim_t dim1, dim_t dim2, const T *pointer, af::source src=afHost)\r\naf::array (dim_t dim0, dim_t dim1, dim_t dim2, dim_t dim3, const T *pointer, af::source src=afHost)\r\n \r\n// af::array constructor using a dim4 object\r\naf::array (const dim4 &amp;dims, const T *pointer, af::source src=afHost)</pre>\r\n</div>\r\n</div>\r\n<em>NOTE</em>: With all of these constructors, ArrayFire\'s memory manager automatically assumes responsibility for any memory provided to it. Thus ArrayFire could free or reuse the memory at any later time. If this behavior is not desired, you may call<code>array::unlock()</code> and manage the memory yourself. However, if you do so, please be cautious not to free memory when ArrayFire might be using it!\r\n\r\nThe seven steps above are best illustrated using a fully-worked example:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1. Add includes\r\n#include &lt;arrayfire.h&gt;\r\n#include &lt;af/cuda.h&gt;\r\n \r\nusing namespace std;\r\n \r\nint main() {\r\n \r\n// Create and populate CUDA memory objects\r\nconst int elements = 100;\r\nsize_t size = elements * sizeof(float);\r\nfloat *cuda_A;\r\ncudaMalloc((void**) &amp;cuda_A, size);\r\n \r\n// ... perform many CUDA operations here\r\n \r\n// 2. Finish any pending CUDA operations\r\ncudaDeviceSynchronize();\r\n \r\n// 3. Create ArrayFire arrays from existing CUDA pointers.\r\n// Be sure to specify that the memory type is afDevice.\r\naf::array d_A(elements, cuda_A, afDevice);\r\n \r\n// NOTE: ArrayFire now manages cuda_A\r\n \r\n// 4. Perform operations on the ArrayFire Arrays.\r\nd_A = d_A * 2;\r\n \r\n// NOTE: ArrayFire does not perform the above transaction using\r\n// in-place memory, thus the pointers containing memory to d_A have\r\n// likely changed.\r\n \r\n// 5. Instruct ArrayFire to finish pending operations using eval and sync.\r\naf::eval(d_A);\r\naf::sync();\r\n \r\n// 6. Get pointers to important memory objects.\r\n// Once device is called, ArrayFire will not manage the memory.\r\nfloat * outputValue = d_A.device&lt;float&gt;();\r\n \r\n// 7. continue CUDA application as normal\r\n \r\n// 8. Free non-managed memory\r\n// We removed outputValue from ArrayFire\'s control, we need to free it\r\ncudaFree(outputValue);\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\n<h4>Using multiple devices</h4>\r\nIf you are using multiple devices with ArrayFire and CUDA kernels, there is one \"gotcha\" of which you should be aware. ArrayFire implements its own internal order of compute devices, thus a CUDA device ID may not be the same as an ArrayFire device ID. Thus when switching between devices it is important that you use our interoperability functions to get/set the correct device IDs. Below is a quick listing of the various functions needed to switch between devices along with some disambiguation as to the device identifiers used with each function:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>ID Type</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td>cudaGetDevice()</td>\r\n<td>CUDA</td>\r\n<td>Gets the current CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>cudaSetDevice()</td>\r\n<td>CUDA</td>\r\n<td>Sets the current CUDA device</td>\r\n</tr>\r\n<tr>\r\n<td>af::getDevice()</td>\r\n<td>AF</td>\r\n<td>Gets the current ArrayFire device ID</td>\r\n</tr>\r\n<tr>\r\n<td>af::setDevice()</td>\r\n<td>AF</td>\r\n<td>Sets the current ArrayFire device</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::getNativeId()</td>\r\n<td>AF -&gt; CUDA</td>\r\n<td>Convert an ArrayFire device ID to a CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::setNativeId()</td>\r\n<td>CUDA -&gt; AF</td>\r\n<td>Set the current ArrayFire device from a CUDA ID</td>\r\n</tr>\r\n</tbody>\r\n</table>','ArrayFire - CUDA Interoperability','','publish','open','closed','','arrayfire-cuda-interoperability','','','2016-05-18 13:49:39','2016-05-18 17:49:39','',0,'http://sandbox.arrayfire.com/?p=8869',0,'post','',2),(8870,18528,'2016-05-18 12:33:27','2016-05-18 16:33:27','&nbsp;\r\n\r\nAlthough ArrayFire is quite extensive, there remain many cases in which you may want to write custom kernels in CUDA or OpenCL. For example, you may wish to add ArrayFire to an existing code base to increase your productivity, or you may need to supplement ArrayFire\'s functionality with your own custom implementation of specific algorithms.\r\n\r\nArrayFire manages its own memory, runs within its own CUDA stream, and creates custom IDs for devices. As such, most of the interoperability functions focus on reducing potential synchronization conflicts between ArrayFire and CUDA.\r\n<h1>Basics</h1>\r\nIt is fairly straightforward to interface ArrayFire with your own custom CUDA code. ArrayFire provides several functions to ease this process including:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td>af::array(...)</td>\r\n<td>Construct an ArrayFire Array from device memory</td>\r\n</tr>\r\n<tr>\r\n<td>af::array.device()</td>\r\n<td>Obtain a pointer to the device memory (implies lock()</td>\r\n</tr>\r\n<tr>\r\n<td>af::array.lock()</td>\r\n<td>Removes ArrayFire\'s control of a device memory pointer</td>\r\n</tr>\r\n<tr>\r\n<td>af::array.unlock()</td>\r\n<td>Restore\'s ArrayFire\'s control over a device memory pointer</td>\r\n</tr>\r\n<tr>\r\n<td>af::getDevice()</td>\r\n<td>Gets the current ArrayFire device ID</td>\r\n</tr>\r\n<tr>\r\n<td>af::setDevice()</td>\r\n<td>Switches ArrayFire to the specified device</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::getNativeId()</td>\r\n<td>Converts an ArrayFire device ID to a CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::setNativeId()</td>\r\n<td>Switches ArrayFire to the specified CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::getStream()</td>\r\n<td>Get the current CUDA stream used by ArrayFire</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nBelow we provide two worked examples on how ArrayFire can be integrated into new and existing projects.\r\n<h4>Adding custom CUDA kernels to an existing ArrayFire application</h4>\r\nBy default, ArrayFire manages its own memory and operates in its own CUDA stream. Thus there is a slight amount of bookkeeping that needs to be done in order to integrate your custom CUDA kernel.\r\n\r\nIf your kernels can share the ArrayFire CUDA stream, you should:\r\n<ol type=\"1\">\r\n 	<li>Include the \'af/afcuda.h\' header in your source code</li>\r\n 	<li>Use ArrayFire as normal</li>\r\n 	<li>Ensure any JIT kernels have executed using `<code>af::eval()</code></li>\r\n 	<li>Obtain device pointers from ArrayFire array objects using</li>\r\n 	<li>Determine ArrayFire\'s CUDA stream</li>\r\n 	<li>Set arguments and run your kernel in ArrayFire\'s stream</li>\r\n 	<li>Return control of af::array memory to ArrayFire</li>\r\n 	<li>Compile with <code>nvcc</code>, linking with the <code>afcuda</code> library.</li>\r\n</ol>\r\nNotice that since ArrayFire and your kernels are sharing the same CUDA stream, there is no need to perform any synchronization operations as operations within a stream are executed in order.\r\n\r\nThis process is best illustrated with a fully worked example:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1. Add includes\r\n#include &lt;arrayfire.h&gt;\r\n#include &lt;af/cuda.h&gt;\r\n \r\nint main() {\r\n \r\n// 2. Use ArrayFire as normal\r\nsize_t num = 10;\r\naf::array x = af::constant(0, num);\r\n \r\n// ... many ArrayFire operaitons here\r\n \r\n// 3. Ensure any JIT kernels have executed\r\nx.eval();\r\naf_print(x);\r\n \r\n// Run a custom CUDA kernel in the ArrayFire CUDA stream\r\n \r\n// 4. Obtain device pointers from ArrayFire array objects using\r\n// the array::device() function:\r\nfloat *d_x = x.device&lt;float&gt;();\r\n \r\n// 5. Determine ArrayFire\'s CUDA stream\r\nint af_id = af::getDevice();\r\nint cuda_id = afcu::getNativeId(af_id);\r\ncudaStream_t af_cuda_stream = afcu::getStream(cuda_id);\r\n \r\n// 6. Set arguments and run your kernel in ArrayFire\'s stream\r\n// Here launch with 10 blocks of 10 threads\r\nincrement&lt;&lt;&lt;1, num, 0, af_cuda_stream&gt;&gt;&gt;(d_x);\r\n \r\n// 7. Return control of af::array memory to ArrayFire using\r\n// the array::unlock() function:\r\nx.unlock();\r\n \r\n// ... resume ArrayFire operations\r\naf_print(x);\r\n \r\n// Because the device pointers, d_x and d_y, were returned to ArrayFire\'s\r\n// control by the unlock function, there is no need to free them using\r\n// cudaFree()\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\nIf your kernels needs to operate in their own CUDA stream, the process is essentially identical, except you need to instruct ArrayFire to complete its computations using the af::sync() function prior to launching your own kernel and ensure your kernels are complete using <code>cudaDeviceSynchronize()</code> (or similar) commands prior to returning control of the memory to ArrayFire:\r\n<ol type=\"1\">\r\n 	<li>Include the \'af/afcuda.h\' header in your source code</li>\r\n 	<li>Use ArrayFire as normal</li>\r\n 	<li>Ensure any JIT kernels have executed using `<code>af::eval()</code></li>\r\n 	<li>Instruct ArrayFire to finish operations using af::sync()</li>\r\n 	<li>Obtain device pointers from ArrayFire array objects using</li>\r\n 	<li>Determine ArrayFire\'s CUDA stream</li>\r\n 	<li>Set arguments and run your kernel in your custom stream</li>\r\n 	<li>Ensure CUDA operations have finished using <code>cudaDeviceSyncronize()</code> or similar commands.</li>\r\n 	<li>Return control of af::array memory to ArrayFire</li>\r\n 	<li>Compile with <code>nvcc</code>, linking with the <code>afcuda</code> library.</li>\r\n</ol>\r\n<h4>Adding ArrayFire to an existing CUDA application</h4>\r\nAdding ArrayFire to an existing CUDA application is slightly more involved and can be somewhat tricky due to several optimizations we implement. The most important are as follows:\r\n<ul>\r\n 	<li>ArrayFire assumes control of all memory provided to it.</li>\r\n 	<li>ArrayFire does not (in general) support in-place memory transactions.</li>\r\n</ul>\r\nWe will discuss the implications of these items below. To add ArrayFire to existing code you need to:\r\n<ol type=\"1\">\r\n 	<li>Include <code>arrayfire.h</code> and <code>af/cuda.h</code> in your source file</li>\r\n 	<li>Finish any pending CUDA operations (e.g. use cudaDeviceSynchronize() or similar stream functions)</li>\r\n 	<li>Create ArrayFire arrays from existing CUDA pointers</li>\r\n 	<li>Perform operations on ArrayFire arrays</li>\r\n 	<li>Instruct ArrayFire to finish operations using af::eval() and af::sync()</li>\r\n 	<li>Obtain pointers to important memory</li>\r\n 	<li>Continue your CUDA application.</li>\r\n 	<li>Free non-managed memory</li>\r\n 	<li>Compile and link with the appropriate paths and the <code>-lafcuda</code> flags.</li>\r\n</ol>\r\nTo create the af::array objects, you should use one of the following constructors with <code>src=afDevice</code>:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1D - 3D af::array constructors\r\naf::array (dim_t dim0, const T *pointer, af::source src=afHost)\r\naf::array (dim_t dim0, dim_t dim1, const T *pointer, af::source src=afHost)\r\naf::array (dim_t dim0, dim_t dim1, dim_t dim2, const T *pointer, af::source src=afHost)\r\naf::array (dim_t dim0, dim_t dim1, dim_t dim2, dim_t dim3, const T *pointer, af::source src=afHost)\r\n \r\n// af::array constructor using a dim4 object\r\naf::array (const dim4 &amp;dims, const T *pointer, af::source src=afHost)</pre>\r\n</div>\r\n</div>\r\n<em>NOTE</em>: With all of these constructors, ArrayFire\'s memory manager automatically assumes responsibility for any memory provided to it. Thus ArrayFire could free or reuse the memory at any later time. If this behavior is not desired, you may call<code>array::unlock()</code> and manage the memory yourself. However, if you do so, please be cautious not to free memory when ArrayFire might be using it!\r\n\r\nThe seven steps above are best illustrated using a fully-worked example:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1. Add includes\r\n#include &lt;arrayfire.h&gt;\r\n#include &lt;af/cuda.h&gt;\r\n \r\nusing namespace std;\r\n \r\nint main() {\r\n \r\n// Create and populate CUDA memory objects\r\nconst int elements = 100;\r\nsize_t size = elements * sizeof(float);\r\nfloat *cuda_A;\r\ncudaMalloc((void**) &amp;cuda_A, size);\r\n \r\n// ... perform many CUDA operations here\r\n \r\n// 2. Finish any pending CUDA operations\r\ncudaDeviceSynchronize();\r\n \r\n// 3. Create ArrayFire arrays from existing CUDA pointers.\r\n// Be sure to specify that the memory type is afDevice.\r\naf::array d_A(elements, cuda_A, afDevice);\r\n \r\n// NOTE: ArrayFire now manages cuda_A\r\n \r\n// 4. Perform operations on the ArrayFire Arrays.\r\nd_A = d_A * 2;\r\n \r\n// NOTE: ArrayFire does not perform the above transaction using\r\n// in-place memory, thus the pointers containing memory to d_A have\r\n// likely changed.\r\n \r\n// 5. Instruct ArrayFire to finish pending operations using eval and sync.\r\naf::eval(d_A);\r\naf::sync();\r\n \r\n// 6. Get pointers to important memory objects.\r\n// Once device is called, ArrayFire will not manage the memory.\r\nfloat * outputValue = d_A.device&lt;float&gt;();\r\n \r\n// 7. continue CUDA application as normal\r\n \r\n// 8. Free non-managed memory\r\n// We removed outputValue from ArrayFire\'s control, we need to free it\r\ncudaFree(outputValue);\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\n<h4>Using multiple devices</h4>\r\nIf you are using multiple devices with ArrayFire and CUDA kernels, there is one \"gotcha\" of which you should be aware. ArrayFire implements its own internal order of compute devices, thus a CUDA device ID may not be the same as an ArrayFire device ID. Thus when switching between devices it is important that you use our interoperability functions to get/set the correct device IDs. Below is a quick listing of the various functions needed to switch between devices along with some disambiguation as to the device identifiers used with each function:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>ID Type</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td>cudaGetDevice()</td>\r\n<td>CUDA</td>\r\n<td>Gets the current CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>cudaSetDevice()</td>\r\n<td>CUDA</td>\r\n<td>Sets the current CUDA device</td>\r\n</tr>\r\n<tr>\r\n<td>af::getDevice()</td>\r\n<td>AF</td>\r\n<td>Gets the current ArrayFire device ID</td>\r\n</tr>\r\n<tr>\r\n<td>af::setDevice()</td>\r\n<td>AF</td>\r\n<td>Sets the current ArrayFire device</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::getNativeId()</td>\r\n<td>AF -&gt; CUDA</td>\r\n<td>Convert an ArrayFire device ID to a CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::setNativeId()</td>\r\n<td>CUDA -&gt; AF</td>\r\n<td>Set the current ArrayFire device from a CUDA ID</td>\r\n</tr>\r\n</tbody>\r\n</table>','ArrayFire - CUDA Interoperability','','inherit','closed','closed','','8869-revision-v1','','','2016-05-18 12:33:27','2016-05-18 16:33:27','',8869,'http://sandbox.arrayfire.com/8869-revision-v1/',0,'revision','',0),(8871,18528,'2016-05-18 12:42:16','2016-05-18 16:42:16','Although ArrayFire is quite extensive, there remain many cases in which you may want to write custom kernels in CUDA or OpenCL. For example, you may wish to add ArrayFire to an existing code base to increase your productivity, or you may need to supplement ArrayFire\'s functionality with your own custom implementation of specific algorithms. Today\'s \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\", blog post discusses how you can interface ArrayFire and CUDA.\r\n\r\n<!--more-->\r\n\r\nWhen it comes to interoperability with CUDA, the most important thing to remember about ArrayFire is that it manages its own memory, runs  in  its own CUDA stream, and  creates custom IDs for devices. As such, most of the interoperability functions focus on reducing potential synchronization conflicts between ArrayFire and CUDA.\r\n\r\n<strong>NOTE</strong>: This blog post was written against ArrayFire 3.3.x. We intend to implement additional convenience functions in ArrayFire 3.4 that should simplify this process further. Be sure to <a href=\"http://arrayfire.org/docs/interop_cuda.htm\">check the documentation</a> for any updates in future releases.\r\n<h4>Basics</h4>\r\nIt is fairly straightforward to interface ArrayFire with your own custom CUDA code. ArrayFire provides several functions to ease this process including:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td>af::array(...)</td>\r\n<td>Construct an ArrayFire Array from device memory</td>\r\n</tr>\r\n<tr>\r\n<td>af::array.device()</td>\r\n<td>Obtain a pointer to the device memory (implies lock()</td>\r\n</tr>\r\n<tr>\r\n<td>af::array.lock()</td>\r\n<td>Removes ArrayFire\'s control of a device memory pointer</td>\r\n</tr>\r\n<tr>\r\n<td>af::array.unlock()</td>\r\n<td>Restore\'s ArrayFire\'s control over a device memory pointer</td>\r\n</tr>\r\n<tr>\r\n<td>af::getDevice()</td>\r\n<td>Gets the current ArrayFire device ID</td>\r\n</tr>\r\n<tr>\r\n<td>af::setDevice()</td>\r\n<td>Switches ArrayFire to the specified device</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::getNativeId()</td>\r\n<td>Converts an ArrayFire device ID to a CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::setNativeId()</td>\r\n<td>Switches ArrayFire to the specified CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::getStream()</td>\r\n<td>Get the current CUDA stream used by ArrayFire</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nBelow we provide two worked examples on how ArrayFire can be integrated into new and existing projects.\r\n<h4>Adding custom CUDA kernels to an existing ArrayFire application</h4>\r\nBy default, ArrayFire manages its own memory and operates in its own CUDA stream. Thus there is a slight amount of bookkeeping that needs to be done in order to integrate your custom CUDA kernel.\r\n\r\nIf your kernels can share the ArrayFire CUDA stream, you should:\r\n<ol type=\"1\">\r\n 	<li>Include the \'af/afcuda.h\' header in your source code</li>\r\n 	<li>Use ArrayFire as normal</li>\r\n 	<li>Ensure any JIT kernels have executed using `<code>af::eval()</code></li>\r\n 	<li>Obtain device pointers from ArrayFire array objects using</li>\r\n 	<li>Determine ArrayFire\'s CUDA stream</li>\r\n 	<li>Set arguments and run your kernel in ArrayFire\'s stream</li>\r\n 	<li>Return control of af::array memory to ArrayFire</li>\r\n 	<li>Compile with <code>nvcc</code>, linking with the <code>afcuda</code> library.</li>\r\n</ol>\r\nNotice that since ArrayFire and your kernels are sharing the same CUDA stream, there is no need to perform any synchronization operations as operations within a stream are executed in order.\r\n\r\nThis process is best illustrated with a fully worked example:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1. Add includes\r\n#include &lt;arrayfire.h&gt;\r\n#include &lt;af/cuda.h&gt;\r\n \r\nint main() {\r\n \r\n// 2. Use ArrayFire as normal\r\nsize_t num = 10;\r\naf::array x = af::constant(0, num);\r\n \r\n// ... many ArrayFire operaitons here\r\n \r\n// 3. Ensure any JIT kernels have executed\r\nx.eval();\r\naf_print(x);\r\n \r\n// Run a custom CUDA kernel in the ArrayFire CUDA stream\r\n \r\n// 4. Obtain device pointers from ArrayFire array objects using\r\n// the array::device() function:\r\nfloat *d_x = x.device&lt;float&gt;();\r\n \r\n// 5. Determine ArrayFire\'s CUDA stream\r\nint af_id = af::getDevice();\r\nint cuda_id = afcu::getNativeId(af_id);\r\ncudaStream_t af_cuda_stream = afcu::getStream(cuda_id);\r\n \r\n// 6. Set arguments and run your kernel in ArrayFire\'s stream\r\n// Here launch with 10 blocks of 10 threads\r\nincrement&lt;&lt;&lt;1, num, 0, af_cuda_stream&gt;&gt;&gt;(d_x);\r\n \r\n// 7. Return control of af::array memory to ArrayFire using\r\n// the array::unlock() function:\r\nx.unlock();\r\n \r\n// ... resume ArrayFire operations\r\naf_print(x);\r\n \r\n// Because the device pointers, d_x and d_y, were returned to ArrayFire\'s\r\n// control by the unlock function, there is no need to free them using\r\n// cudaFree()\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\nIf your kernels needs to operate in their own CUDA stream, the process is essentially identical, except you need to instruct ArrayFire to complete its computations using the af::sync() function prior to launching your own kernel and ensure your kernels are complete using <code>cudaDeviceSynchronize()</code> (or similar) commands prior to returning control of the memory to ArrayFire:\r\n<ol type=\"1\">\r\n 	<li>Include the \'af/afcuda.h\' header in your source code</li>\r\n 	<li>Use ArrayFire as normal</li>\r\n 	<li>Ensure any JIT kernels have executed using `<code>af::eval()</code></li>\r\n 	<li>Instruct ArrayFire to finish operations using af::sync()</li>\r\n 	<li>Obtain device pointers from ArrayFire array objects using</li>\r\n 	<li>Determine ArrayFire\'s CUDA stream</li>\r\n 	<li>Set arguments and run your kernel in your custom stream</li>\r\n 	<li>Ensure CUDA operations have finished using <code>cudaDeviceSyncronize()</code> or similar commands.</li>\r\n 	<li>Return control of af::array memory to ArrayFire</li>\r\n 	<li>Compile with <code>nvcc</code>, linking with the <code>afcuda</code> library.</li>\r\n</ol>\r\n<h4>Adding ArrayFire to an existing CUDA application</h4>\r\nAdding ArrayFire to an existing CUDA application is slightly more involved and can be somewhat tricky due to several optimizations we implement. The most important are as follows:\r\n<ul>\r\n 	<li>ArrayFire assumes control of all memory provided to it.</li>\r\n 	<li>ArrayFire does not (in general) support in-place memory transactions.</li>\r\n</ul>\r\nWe will discuss the implications of these items below. To add ArrayFire to existing code you need to:\r\n<ol type=\"1\">\r\n 	<li>Include <code>arrayfire.h</code> and <code>af/cuda.h</code> in your source file</li>\r\n 	<li>Finish any pending CUDA operations (e.g. use cudaDeviceSynchronize() or similar stream functions)</li>\r\n 	<li>Create ArrayFire arrays from existing CUDA pointers</li>\r\n 	<li>Perform operations on ArrayFire arrays</li>\r\n 	<li>Instruct ArrayFire to finish operations using af::eval() and af::sync()</li>\r\n 	<li>Obtain pointers to important memory</li>\r\n 	<li>Continue your CUDA application.</li>\r\n 	<li>Free non-managed memory</li>\r\n 	<li>Compile and link with the appropriate paths and the <code>-lafcuda</code> flags.</li>\r\n</ol>\r\nTo create the af::array objects, you should use one of the following constructors with <code>src=afDevice</code>:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1D - 3D af::array constructors\r\naf::array (dim_t dim0, const T *pointer, af::source src=afHost)\r\naf::array (dim_t dim0, dim_t dim1, const T *pointer, af::source src=afHost)\r\naf::array (dim_t dim0, dim_t dim1, dim_t dim2, const T *pointer, af::source src=afHost)\r\naf::array (dim_t dim0, dim_t dim1, dim_t dim2, dim_t dim3, const T *pointer, af::source src=afHost)\r\n \r\n// af::array constructor using a dim4 object\r\naf::array (const dim4 &amp;dims, const T *pointer, af::source src=afHost)</pre>\r\n</div>\r\n</div>\r\n<em>NOTE</em>: With all of these constructors, ArrayFire\'s memory manager automatically assumes responsibility for any memory provided to it. Thus ArrayFire could free or reuse the memory at any later time. If this behavior is not desired, you may call<code>array::unlock()</code> and manage the memory yourself. However, if you do so, please be cautious not to free memory when ArrayFire might be using it!\r\n\r\nThe seven steps above are best illustrated using a fully-worked example:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1. Add includes\r\n#include &lt;arrayfire.h&gt;\r\n#include &lt;af/cuda.h&gt;\r\n \r\nusing namespace std;\r\n \r\nint main() {\r\n \r\n// Create and populate CUDA memory objects\r\nconst int elements = 100;\r\nsize_t size = elements * sizeof(float);\r\nfloat *cuda_A;\r\ncudaMalloc((void**) &amp;cuda_A, size);\r\n \r\n// ... perform many CUDA operations here\r\n \r\n// 2. Finish any pending CUDA operations\r\ncudaDeviceSynchronize();\r\n \r\n// 3. Create ArrayFire arrays from existing CUDA pointers.\r\n// Be sure to specify that the memory type is afDevice.\r\naf::array d_A(elements, cuda_A, afDevice);\r\n \r\n// NOTE: ArrayFire now manages cuda_A\r\n \r\n// 4. Perform operations on the ArrayFire Arrays.\r\nd_A = d_A * 2;\r\n \r\n// NOTE: ArrayFire does not perform the above transaction using\r\n// in-place memory, thus the pointers containing memory to d_A have\r\n// likely changed.\r\n \r\n// 5. Instruct ArrayFire to finish pending operations using eval and sync.\r\naf::eval(d_A);\r\naf::sync();\r\n \r\n// 6. Get pointers to important memory objects.\r\n// Once device is called, ArrayFire will not manage the memory.\r\nfloat * outputValue = d_A.device&lt;float&gt;();\r\n \r\n// 7. continue CUDA application as normal\r\n \r\n// 8. Free non-managed memory\r\n// We removed outputValue from ArrayFire\'s control, we need to free it\r\ncudaFree(outputValue);\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\n<h4>Using multiple devices</h4>\r\nIf you are using multiple devices with ArrayFire and CUDA kernels, there is one \"gotcha\" of which you should be aware. ArrayFire implements its own internal order of compute devices, thus a CUDA device ID may not be the same as an ArrayFire device ID. Thus when switching between devices it is important that you use our interoperability functions to get/set the correct device IDs. Below is a quick listing of the various functions needed to switch between devices along with some disambiguation as to the device identifiers used with each function:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>ID Type</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td>cudaGetDevice()</td>\r\n<td>CUDA</td>\r\n<td>Gets the current CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>cudaSetDevice()</td>\r\n<td>CUDA</td>\r\n<td>Sets the current CUDA device</td>\r\n</tr>\r\n<tr>\r\n<td>af::getDevice()</td>\r\n<td>AF</td>\r\n<td>Gets the current ArrayFire device ID</td>\r\n</tr>\r\n<tr>\r\n<td>af::setDevice()</td>\r\n<td>AF</td>\r\n<td>Sets the current ArrayFire device</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::getNativeId()</td>\r\n<td>AF -&gt; CUDA</td>\r\n<td>Convert an ArrayFire device ID to a CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::setNativeId()</td>\r\n<td>CUDA -&gt; AF</td>\r\n<td>Set the current ArrayFire device from a CUDA ID</td>\r\n</tr>\r\n</tbody>\r\n</table>','ArrayFire - CUDA Interoperability','','inherit','closed','closed','','8869-revision-v1','','','2016-05-18 12:42:16','2016-05-18 16:42:16','',8869,'http://sandbox.arrayfire.com/8869-revision-v1/',0,'revision','',0),(8872,18528,'2016-05-18 12:42:43','2016-05-18 16:42:43','Although ArrayFire is quite extensive, there remain many cases in which you may want to write custom kernels in CUDA or OpenCL. For example, you may wish to add ArrayFire to an existing code base to increase your productivity, or you may need to supplement ArrayFire\'s functionality with your own custom implementation of specific algorithms. Today\'s \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\", blog post discusses how you can interface ArrayFire and CUDA.\r\n\r\n<!--more-->\r\n\r\nWhen it comes to interoperability with CUDA, the most important thing to remember about ArrayFire is that it manages its own memory, runs  in  its own CUDA stream, and  creates custom IDs for devices. As such, most of the interoperability functions focus on reducing potential synchronization conflicts between ArrayFire and CUDA.\r\n\r\n<strong>NOTE</strong>: This blog post was written against ArrayFire 3.3.x. We intend to implement additional convenience functions in ArrayFire 3.4 that should simplify this process further. Be sure to <a href=\"http://arrayfire.org/docs/interop_cuda.htm\">check the documentation</a> for any updates in future releases.\r\n<h4>Basics</h4>\r\nIt is fairly straightforward to interface ArrayFire with your own custom CUDA code. ArrayFire provides several functions to ease this process including:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td>af::array(...)</td>\r\n<td>Construct an ArrayFire Array from device memory</td>\r\n</tr>\r\n<tr>\r\n<td>af::array.device()</td>\r\n<td>Obtain a pointer to the device memory (implies lock()</td>\r\n</tr>\r\n<tr>\r\n<td>af::array.lock()</td>\r\n<td>Removes ArrayFire\'s control of a device memory pointer</td>\r\n</tr>\r\n<tr>\r\n<td>af::array.unlock()</td>\r\n<td>Restore\'s ArrayFire\'s control over a device memory pointer</td>\r\n</tr>\r\n<tr>\r\n<td>af::getDevice()</td>\r\n<td>Gets the current ArrayFire device ID</td>\r\n</tr>\r\n<tr>\r\n<td>af::setDevice()</td>\r\n<td>Switches ArrayFire to the specified device</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::getNativeId()</td>\r\n<td>Converts an ArrayFire device ID to a CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::setNativeId()</td>\r\n<td>Switches ArrayFire to the specified CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::getStream()</td>\r\n<td>Get the current CUDA stream used by ArrayFire</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nBelow we provide two worked examples on how ArrayFire can be integrated into new and existing projects.\r\n<h4>Adding custom CUDA kernels to an existing ArrayFire application</h4>\r\nBy default, ArrayFire manages its own memory and operates in its own CUDA stream. Thus there is a slight amount of bookkeeping that needs to be done in order to integrate your custom CUDA kernel.\r\n\r\nIf your kernels can share the ArrayFire CUDA stream, you should:\r\n<ol type=\"1\">\r\n 	<li>Include the \'af/afcuda.h\' header in your source code</li>\r\n 	<li>Use ArrayFire as normal</li>\r\n 	<li>Ensure any JIT kernels have executed using <code>af::eval()</code></li>\r\n 	<li>Obtain device pointers from ArrayFire array objects using</li>\r\n 	<li>Determine ArrayFire\'s CUDA stream</li>\r\n 	<li>Set arguments and run your kernel in ArrayFire\'s stream</li>\r\n 	<li>Return control of af::array memory to ArrayFire</li>\r\n 	<li>Compile with <code>nvcc</code>, linking with the <code>afcuda</code> library.</li>\r\n</ol>\r\nNotice that since ArrayFire and your kernels are sharing the same CUDA stream, there is no need to perform any synchronization operations as operations within a stream are executed in order.\r\n\r\nThis process is best illustrated with a fully worked example:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1. Add includes\r\n#include &lt;arrayfire.h&gt;\r\n#include &lt;af/cuda.h&gt;\r\n \r\nint main() {\r\n \r\n// 2. Use ArrayFire as normal\r\nsize_t num = 10;\r\naf::array x = af::constant(0, num);\r\n \r\n// ... many ArrayFire operaitons here\r\n \r\n// 3. Ensure any JIT kernels have executed\r\nx.eval();\r\naf_print(x);\r\n \r\n// Run a custom CUDA kernel in the ArrayFire CUDA stream\r\n \r\n// 4. Obtain device pointers from ArrayFire array objects using\r\n// the array::device() function:\r\nfloat *d_x = x.device&lt;float&gt;();\r\n \r\n// 5. Determine ArrayFire\'s CUDA stream\r\nint af_id = af::getDevice();\r\nint cuda_id = afcu::getNativeId(af_id);\r\ncudaStream_t af_cuda_stream = afcu::getStream(cuda_id);\r\n \r\n// 6. Set arguments and run your kernel in ArrayFire\'s stream\r\n// Here launch with 10 blocks of 10 threads\r\nincrement&lt;&lt;&lt;1, num, 0, af_cuda_stream&gt;&gt;&gt;(d_x);\r\n \r\n// 7. Return control of af::array memory to ArrayFire using\r\n// the array::unlock() function:\r\nx.unlock();\r\n \r\n// ... resume ArrayFire operations\r\naf_print(x);\r\n \r\n// Because the device pointers, d_x and d_y, were returned to ArrayFire\'s\r\n// control by the unlock function, there is no need to free them using\r\n// cudaFree()\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\nIf your kernels needs to operate in their own CUDA stream, the process is essentially identical, except you need to instruct ArrayFire to complete its computations using the af::sync() function prior to launching your own kernel and ensure your kernels are complete using <code>cudaDeviceSynchronize()</code> (or similar) commands prior to returning control of the memory to ArrayFire:\r\n<ol type=\"1\">\r\n 	<li>Include the \'af/afcuda.h\' header in your source code</li>\r\n 	<li>Use ArrayFire as normal</li>\r\n 	<li>Ensure any JIT kernels have executed using `<code>af::eval()</code></li>\r\n 	<li>Instruct ArrayFire to finish operations using af::sync()</li>\r\n 	<li>Obtain device pointers from ArrayFire array objects using</li>\r\n 	<li>Determine ArrayFire\'s CUDA stream</li>\r\n 	<li>Set arguments and run your kernel in your custom stream</li>\r\n 	<li>Ensure CUDA operations have finished using <code>cudaDeviceSyncronize()</code> or similar commands.</li>\r\n 	<li>Return control of af::array memory to ArrayFire</li>\r\n 	<li>Compile with <code>nvcc</code>, linking with the <code>afcuda</code> library.</li>\r\n</ol>\r\n<h4>Adding ArrayFire to an existing CUDA application</h4>\r\nAdding ArrayFire to an existing CUDA application is slightly more involved and can be somewhat tricky due to several optimizations we implement. The most important are as follows:\r\n<ul>\r\n 	<li>ArrayFire assumes control of all memory provided to it.</li>\r\n 	<li>ArrayFire does not (in general) support in-place memory transactions.</li>\r\n</ul>\r\nWe will discuss the implications of these items below. To add ArrayFire to existing code you need to:\r\n<ol type=\"1\">\r\n 	<li>Include <code>arrayfire.h</code> and <code>af/cuda.h</code> in your source file</li>\r\n 	<li>Finish any pending CUDA operations (e.g. use cudaDeviceSynchronize() or similar stream functions)</li>\r\n 	<li>Create ArrayFire arrays from existing CUDA pointers</li>\r\n 	<li>Perform operations on ArrayFire arrays</li>\r\n 	<li>Instruct ArrayFire to finish operations using af::eval() and af::sync()</li>\r\n 	<li>Obtain pointers to important memory</li>\r\n 	<li>Continue your CUDA application.</li>\r\n 	<li>Free non-managed memory</li>\r\n 	<li>Compile and link with the appropriate paths and the <code>-lafcuda</code> flags.</li>\r\n</ol>\r\nTo create the af::array objects, you should use one of the following constructors with <code>src=afDevice</code>:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1D - 3D af::array constructors\r\naf::array (dim_t dim0, const T *pointer, af::source src=afHost)\r\naf::array (dim_t dim0, dim_t dim1, const T *pointer, af::source src=afHost)\r\naf::array (dim_t dim0, dim_t dim1, dim_t dim2, const T *pointer, af::source src=afHost)\r\naf::array (dim_t dim0, dim_t dim1, dim_t dim2, dim_t dim3, const T *pointer, af::source src=afHost)\r\n \r\n// af::array constructor using a dim4 object\r\naf::array (const dim4 &amp;dims, const T *pointer, af::source src=afHost)</pre>\r\n</div>\r\n</div>\r\n<em>NOTE</em>: With all of these constructors, ArrayFire\'s memory manager automatically assumes responsibility for any memory provided to it. Thus ArrayFire could free or reuse the memory at any later time. If this behavior is not desired, you may call<code>array::unlock()</code> and manage the memory yourself. However, if you do so, please be cautious not to free memory when ArrayFire might be using it!\r\n\r\nThe seven steps above are best illustrated using a fully-worked example:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1. Add includes\r\n#include &lt;arrayfire.h&gt;\r\n#include &lt;af/cuda.h&gt;\r\n \r\nusing namespace std;\r\n \r\nint main() {\r\n \r\n// Create and populate CUDA memory objects\r\nconst int elements = 100;\r\nsize_t size = elements * sizeof(float);\r\nfloat *cuda_A;\r\ncudaMalloc((void**) &amp;cuda_A, size);\r\n \r\n// ... perform many CUDA operations here\r\n \r\n// 2. Finish any pending CUDA operations\r\ncudaDeviceSynchronize();\r\n \r\n// 3. Create ArrayFire arrays from existing CUDA pointers.\r\n// Be sure to specify that the memory type is afDevice.\r\naf::array d_A(elements, cuda_A, afDevice);\r\n \r\n// NOTE: ArrayFire now manages cuda_A\r\n \r\n// 4. Perform operations on the ArrayFire Arrays.\r\nd_A = d_A * 2;\r\n \r\n// NOTE: ArrayFire does not perform the above transaction using\r\n// in-place memory, thus the pointers containing memory to d_A have\r\n// likely changed.\r\n \r\n// 5. Instruct ArrayFire to finish pending operations using eval and sync.\r\naf::eval(d_A);\r\naf::sync();\r\n \r\n// 6. Get pointers to important memory objects.\r\n// Once device is called, ArrayFire will not manage the memory.\r\nfloat * outputValue = d_A.device&lt;float&gt;();\r\n \r\n// 7. continue CUDA application as normal\r\n \r\n// 8. Free non-managed memory\r\n// We removed outputValue from ArrayFire\'s control, we need to free it\r\ncudaFree(outputValue);\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\n<h4>Using multiple devices</h4>\r\nIf you are using multiple devices with ArrayFire and CUDA kernels, there is one \"gotcha\" of which you should be aware. ArrayFire implements its own internal order of compute devices, thus a CUDA device ID may not be the same as an ArrayFire device ID. Thus when switching between devices it is important that you use our interoperability functions to get/set the correct device IDs. Below is a quick listing of the various functions needed to switch between devices along with some disambiguation as to the device identifiers used with each function:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>ID Type</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td>cudaGetDevice()</td>\r\n<td>CUDA</td>\r\n<td>Gets the current CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>cudaSetDevice()</td>\r\n<td>CUDA</td>\r\n<td>Sets the current CUDA device</td>\r\n</tr>\r\n<tr>\r\n<td>af::getDevice()</td>\r\n<td>AF</td>\r\n<td>Gets the current ArrayFire device ID</td>\r\n</tr>\r\n<tr>\r\n<td>af::setDevice()</td>\r\n<td>AF</td>\r\n<td>Sets the current ArrayFire device</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::getNativeId()</td>\r\n<td>AF -&gt; CUDA</td>\r\n<td>Convert an ArrayFire device ID to a CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::setNativeId()</td>\r\n<td>CUDA -&gt; AF</td>\r\n<td>Set the current ArrayFire device from a CUDA ID</td>\r\n</tr>\r\n</tbody>\r\n</table>','ArrayFire - CUDA Interoperability','','inherit','closed','closed','','8869-revision-v1','','','2016-05-18 12:42:43','2016-05-18 16:42:43','',8869,'http://sandbox.arrayfire.com/8869-revision-v1/',0,'revision','',0),(8873,18528,'2016-05-18 12:44:29','2016-05-18 16:44:29','Although ArrayFire is quite extensive, there remain many cases in which you may want to write custom kernels in CUDA or OpenCL. For example, you may wish to add ArrayFire to an existing code base to increase your productivity, or you may need to supplement ArrayFire\'s functionality with your own custom implementation of specific algorithms. Today\'s \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\", blog post discusses how you can interface ArrayFire and CUDA.\r\n\r\n<!--more-->\r\n\r\nWhen it comes to interoperability with CUDA, the most important thing to remember about ArrayFire is that it manages its own memory, runs  in  its own CUDA stream, and  creates custom IDs for devices. As such, most of the interoperability functions focus on reducing potential synchronization conflicts between ArrayFire and CUDA.\r\n\r\n<strong>NOTE</strong>: This blog post was written against ArrayFire 3.3.x. We intend to implement additional convenience functions in ArrayFire 3.4 that should simplify this process further. Be sure to <a href=\"http://arrayfire.org/docs/interop_cuda.htm\">check the documentation</a> for any updates in future releases.\r\n<h4>Basics</h4>\r\nIt is fairly straightforward to interface ArrayFire with your own custom CUDA code. ArrayFire provides several functions to ease this process including:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td>af::array(...)</td>\r\n<td>Construct an ArrayFire Array from device memory</td>\r\n</tr>\r\n<tr>\r\n<td>af::array.device()</td>\r\n<td>Obtain a pointer to the device memory (implies lock()</td>\r\n</tr>\r\n<tr>\r\n<td>af::array.lock()</td>\r\n<td>Removes ArrayFire\'s control of a device memory pointer</td>\r\n</tr>\r\n<tr>\r\n<td>af::array.unlock()</td>\r\n<td>Restore\'s ArrayFire\'s control over a device memory pointer</td>\r\n</tr>\r\n<tr>\r\n<td>af::getDevice()</td>\r\n<td>Gets the current ArrayFire device ID</td>\r\n</tr>\r\n<tr>\r\n<td>af::setDevice()</td>\r\n<td>Switches ArrayFire to the specified device</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::getNativeId()</td>\r\n<td>Converts an ArrayFire device ID to a CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::setNativeId()</td>\r\n<td>Switches ArrayFire to the specified CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::getStream()</td>\r\n<td>Get the current CUDA stream used by ArrayFire</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nBelow we provide two worked examples on how ArrayFire can be integrated into new and existing projects.\r\n<h4>Adding custom CUDA kernels to an existing ArrayFire application</h4>\r\nBy default, ArrayFire manages its own memory and operates in its own CUDA stream. Thus there is a slight amount of bookkeeping that needs to be done in order to integrate your custom CUDA kernel.\r\n\r\nIf your kernels can share the ArrayFire CUDA stream, you should:\r\n<ol type=\"1\">\r\n 	<li>Include the \'af/afcuda.h\' header in your source code</li>\r\n 	<li>Use ArrayFire as normal</li>\r\n 	<li>Ensure any JIT kernels have executed using <code>af::eval()</code></li>\r\n 	<li>Obtain device pointers from ArrayFire array objects using</li>\r\n 	<li>Determine ArrayFire\'s CUDA stream</li>\r\n 	<li>Set arguments and run your kernel in ArrayFire\'s stream</li>\r\n 	<li>Return control of af::array memory to ArrayFire</li>\r\n 	<li>Compile with <code>nvcc</code>, linking with the <code>afcuda</code> library.</li>\r\n</ol>\r\nNotice that since ArrayFire and your kernels are sharing the same CUDA stream, there is no need to perform any synchronization operations as operations within a stream are executed in order.\r\n\r\nThis process is best illustrated with a fully worked example:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1. Add includes\r\n#include &lt;arrayfire.h&gt;\r\n#include &lt;af/cuda.h&gt;\r\n \r\nint main() {\r\n \r\n// 2. Use ArrayFire as normal\r\nsize_t num = 10;\r\naf::array x = af::constant(0, num);\r\n \r\n// ... many ArrayFire operaitons here\r\n \r\n// 3. Ensure any JIT kernels have executed\r\nx.eval();\r\naf_print(x);\r\n \r\n// Run a custom CUDA kernel in the ArrayFire CUDA stream\r\n \r\n// 4. Obtain device pointers from ArrayFire array objects using\r\n// the array::device() function:\r\nfloat *d_x = x.device&lt;float&gt;();\r\n \r\n// 5. Determine ArrayFire\'s CUDA stream\r\nint af_id = af::getDevice();\r\nint cuda_id = afcu::getNativeId(af_id);\r\ncudaStream_t af_cuda_stream = afcu::getStream(cuda_id);\r\n \r\n// 6. Set arguments and run your kernel in ArrayFire\'s stream\r\n// Here launch with 10 blocks of 10 threads\r\nincrement&lt;&lt;&lt;1, num, 0, af_cuda_stream&gt;&gt;&gt;(d_x);\r\n \r\n// 7. Return control of af::array memory to ArrayFire using\r\n// the array::unlock() function:\r\nx.unlock();\r\n \r\n// ... resume ArrayFire operations\r\naf_print(x);\r\n \r\n// Because the device pointers, d_x and d_y, were returned to ArrayFire\'s\r\n// control by the unlock function, there is no need to free them using\r\n// cudaFree()\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\nIf your kernels needs to operate in their own CUDA stream, the process is essentially identical, except you need to instruct ArrayFire to complete its computations using the af::sync() function prior to launching your own kernel and ensure your kernels are complete using <code>cudaDeviceSynchronize()</code> (or similar) commands prior to returning control of the memory to ArrayFire:\r\n<ol type=\"1\">\r\n 	<li>Include the \'af/afcuda.h\' header in your source code</li>\r\n 	<li>Use ArrayFire as normal</li>\r\n 	<li>Ensure any JIT kernels have executed using <code>af::eval()</code></li>\r\n 	<li>Instruct ArrayFire to finish operations using af::sync()</li>\r\n 	<li>Obtain device pointers from ArrayFire array objects using</li>\r\n 	<li>Determine ArrayFire\'s CUDA stream</li>\r\n 	<li>Set arguments and run your kernel in your custom stream</li>\r\n 	<li>Ensure CUDA operations have finished using <code>cudaDeviceSyncronize()</code> or similar commands.</li>\r\n 	<li>Return control of af::array memory to ArrayFire</li>\r\n 	<li>Compile with <code>nvcc</code>, linking with the <code>afcuda</code> library.</li>\r\n</ol>\r\n<h4>Adding ArrayFire to an existing CUDA application</h4>\r\nAdding ArrayFire to an existing CUDA application is slightly more involved and can be somewhat tricky due to several optimizations we implement. The most important are as follows:\r\n<ul>\r\n 	<li>ArrayFire assumes control of all memory provided to it.</li>\r\n 	<li>ArrayFire does not (in general) support in-place memory transactions.</li>\r\n</ul>\r\nWe will discuss the implications of these items below. To add ArrayFire to existing code you need to:\r\n<ol type=\"1\">\r\n 	<li>Include <code>arrayfire.h</code> and <code>af/cuda.h</code> in your source file</li>\r\n 	<li>Finish any pending CUDA operations (e.g. use cudaDeviceSynchronize() or similar stream functions)</li>\r\n 	<li>Create ArrayFire arrays from existing CUDA pointers</li>\r\n 	<li>Perform operations on ArrayFire arrays</li>\r\n 	<li>Instruct ArrayFire to finish operations using af::eval() and af::sync()</li>\r\n 	<li>Obtain pointers to important memory</li>\r\n 	<li>Continue your CUDA application.</li>\r\n 	<li>Free non-managed memory</li>\r\n 	<li>Compile and link with the appropriate paths and the <code>-lafcuda</code> flags.</li>\r\n</ol>\r\nTo create the af::array objects, you should use one of the following constructors with <code>src=afDevice</code>:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1D - 3D af::array constructors\r\naf::array (dim_t dim0, const T *pointer, af::source src=afHost)\r\naf::array (dim_t dim0, dim_t dim1, const T *pointer, af::source src=afHost)\r\naf::array (dim_t dim0, dim_t dim1, dim_t dim2, const T *pointer, af::source src=afHost)\r\naf::array (dim_t dim0, dim_t dim1, dim_t dim2, dim_t dim3, const T *pointer, af::source src=afHost)\r\n \r\n// af::array constructor using a dim4 object\r\naf::array (const dim4 &amp;dims, const T *pointer, af::source src=afHost)</pre>\r\n</div>\r\n</div>\r\n<em>NOTE</em>: With all of these constructors, ArrayFire\'s memory manager automatically assumes responsibility for any memory provided to it. Thus ArrayFire could free or reuse the memory at any later time. If this behavior is not desired, you may call<code>array::unlock()</code> and manage the memory yourself. However, if you do so, please be cautious not to free memory when ArrayFire might be using it!\r\n\r\nThe seven steps above are best illustrated using a fully-worked example:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1. Add includes\r\n#include &lt;arrayfire.h&gt;\r\n#include &lt;af/cuda.h&gt;\r\n \r\nusing namespace std;\r\n \r\nint main() {\r\n \r\n// Create and populate CUDA memory objects\r\nconst int elements = 100;\r\nsize_t size = elements * sizeof(float);\r\nfloat *cuda_A;\r\ncudaMalloc((void**) &amp;cuda_A, size);\r\n \r\n// ... perform many CUDA operations here\r\n \r\n// 2. Finish any pending CUDA operations\r\ncudaDeviceSynchronize();\r\n \r\n// 3. Create ArrayFire arrays from existing CUDA pointers.\r\n// Be sure to specify that the memory type is afDevice.\r\naf::array d_A(elements, cuda_A, afDevice);\r\n \r\n// NOTE: ArrayFire now manages cuda_A\r\n \r\n// 4. Perform operations on the ArrayFire Arrays.\r\nd_A = d_A * 2;\r\n \r\n// NOTE: ArrayFire does not perform the above transaction using\r\n// in-place memory, thus the pointers containing memory to d_A have\r\n// likely changed.\r\n \r\n// 5. Instruct ArrayFire to finish pending operations using eval and sync.\r\naf::eval(d_A);\r\naf::sync();\r\n \r\n// 6. Get pointers to important memory objects.\r\n// Once device is called, ArrayFire will not manage the memory.\r\nfloat * outputValue = d_A.device&lt;float&gt;();\r\n \r\n// 7. continue CUDA application as normal\r\n \r\n// 8. Free non-managed memory\r\n// We removed outputValue from ArrayFire\'s control, we need to free it\r\ncudaFree(outputValue);\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\n<h4>Using multiple devices</h4>\r\nIf you are using multiple devices with ArrayFire and CUDA kernels, there is one \"gotcha\" of which you should be aware. ArrayFire implements its own internal order of compute devices, thus a CUDA device ID may not be the same as an ArrayFire device ID. Thus when switching between devices it is important that you use our interoperability functions to get/set the correct device IDs. Below is a quick listing of the various functions needed to switch between devices along with some disambiguation as to the device identifiers used with each function:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>ID Type</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td>cudaGetDevice()</td>\r\n<td>CUDA</td>\r\n<td>Gets the current CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>cudaSetDevice()</td>\r\n<td>CUDA</td>\r\n<td>Sets the current CUDA device</td>\r\n</tr>\r\n<tr>\r\n<td>af::getDevice()</td>\r\n<td>AF</td>\r\n<td>Gets the current ArrayFire device ID</td>\r\n</tr>\r\n<tr>\r\n<td>af::setDevice()</td>\r\n<td>AF</td>\r\n<td>Sets the current ArrayFire device</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::getNativeId()</td>\r\n<td>AF -&gt; CUDA</td>\r\n<td>Convert an ArrayFire device ID to a CUDA device ID</td>\r\n</tr>\r\n<tr>\r\n<td>afcu::setNativeId()</td>\r\n<td>CUDA -&gt; AF</td>\r\n<td>Set the current ArrayFire device from a CUDA ID</td>\r\n</tr>\r\n</tbody>\r\n</table>','ArrayFire - CUDA Interoperability','','inherit','closed','closed','','8869-revision-v1','','','2016-05-18 12:44:29','2016-05-18 16:44:29','',8869,'http://sandbox.arrayfire.com/8869-revision-v1/',0,'revision','',0),(8874,18528,'2016-06-07 10:00:00','2016-06-07 14:00:00','In last week\'s \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" post we discussed how to interface ArrayFire and CUDA to improve your productivity. This week we demonstrate how to mix ArrayFire and OpenCL in your application.\r\n\r\n<!--more-->\r\n\r\nMuch like with CUDA, ArrayFire controls almost all aspects of its execution on OpenCL platforms. ArrayFire manages its own context, queue, memory, and creates custom IDs for devices. As such, most of the interoperability functions focus on reducing potential synchronization conflicts between ArrayFire and OpenCL.\r\n\r\n<strong>NOTE</strong>: This blog post was written against ArrayFire 3.3.x. We intend to implement additional convenience functions in ArrayFire 3.4 that should simplify this process further. Be sure to <a href=\"http://arrayfire.org/docs/interop_cuda.htm\">check the documentation</a> for any updates in future releases.\r\n<h4>Basics</h4>\r\nIt is fairly straightforward to interface ArrayFire with your own custom OpenCL code. ArrayFire provides several functions to ease this process including:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td><code>af::array(...)</code></td>\r\n<td>Construct an ArrayFire array from <code>cl_mem</code> references or <code>cl::Buffer</code> objects</td>\r\n</tr>\r\n<tr>\r\n<td><code>af::array.device()</code></td>\r\n<td>Obtain a pointer to the <code>cl_mem</code> reference (implies lock())</td>\r\n</tr>\r\n<tr>\r\n<td><code>af::array.lock()</code></td>\r\n<td>Removes ArrayFire\'s control of a <code>cl_mem</code> buffer</td>\r\n</tr>\r\n<tr>\r\n<td><code>af::array.unlock()</code></td>\r\n<td>Restore\'s ArrayFire\'s control over a <code>cl_mem</code> buffer</td>\r\n</tr>\r\n<tr>\r\n<td><code>afcl::getPlatform()</code></td>\r\n<td>Get ArrayFire\'s current <code>cl_platform</code></td>\r\n</tr>\r\n<tr>\r\n<td><code>af::getDevice()</code></td>\r\n<td>Get the current ArrayFire Device ID</td>\r\n</tr>\r\n<tr>\r\n<td><code>afcl::getDeviceId()</code></td>\r\n<td>Get ArrayFire\'s current <code>cl_device_id</code></td>\r\n</tr>\r\n<tr>\r\n<td><code>af::setDevice()</code></td>\r\n<td>Set ArrayFire\'s device from an ArrayFire device ID</td>\r\n</tr>\r\n<tr>\r\n<td><code>afcl::setDeviceId()</code></td>\r\n<td>Set ArrayFire\'s device from a <code>cl_device_id</code></td>\r\n</tr>\r\n<tr>\r\n<td><code>afcl::setDevice()</code></td>\r\n<td>Set ArrayFire\'s device from a <code>cl_device_id</code> and <code>cl_context</code></td>\r\n</tr>\r\n<tr>\r\n<td><code>afcl::getContext()</code></td>\r\n<td>Get ArrayFire\'s current <code>cl_context</code></td>\r\n</tr>\r\n<tr>\r\n<td><code>afcl::getQueue()</code></td>\r\n<td>Get ArrayFire\'s current <code>cl_command_queue</code></td>\r\n</tr>\r\n<tr>\r\n<td><code>afcl::getDeviceType()</code></td>\r\n<td>Get the current <code>afcl_device_type</code></td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nAdditionally, the OpenCL backend permits the programmer to add and remove custom devices from the ArrayFire device manager. These permit you to attach ArrayFire directly to the OpenCL queue used by other portions of your application.\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td><code>afcl::addDevice()</code></td>\r\n<td>Add a new device to ArrayFire\'s device manager</td>\r\n</tr>\r\n<tr>\r\n<td><code>afcl::deleteDevice()</code></td>\r\n<td>Remove a device from ArrayFire\'s device manager</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nBelow we provide two worked examples on how ArrayFire can be integrated into new and existing projects.\r\n<h4>Adding custom OpenCL kernels to an existing ArrayFire application</h4>\r\nBy default, ArrayFire manages its own context, queue, memory, and creates custom IDs for devices. Thus there is some bookkeeping that needs to be done to integrate your custom OpenCL kernel.\r\n\r\nIf your kernels can share operate in the same queue as ArrayFire, you should:\r\n<ol type=\"1\">\r\n 	<li>Add an include for <code>af/opencl.h</code> to your project</li>\r\n 	<li>Obtain the OpenCL context, device, and queue used by ArrayFire</li>\r\n 	<li>Obtain <code>cl_mem</code> references to <code>af::array</code> objects</li>\r\n 	<li>Load, build, and use your kernels</li>\r\n 	<li>Return control of <code>af::array</code> memory to ArrayFire</li>\r\n</ol>\r\nNote, ArrayFire uses an in-order queue, thus when ArrayFire and your kernels are operating in the same queue, there is no need to perform any synchronization operations.\r\n\r\nThis process is best illustrated with a fully worked example:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">#include &lt;arrayfire.h&gt;\r\n// 1. Add the af/opencl.h include to your project\r\n#include &lt;af/opencl.h&gt;\r\n \r\nint main() {\r\nsize_t length = 10;\r\n \r\n// Create ArrayFire array objects:\r\naf::array A = af::randu(length, f32);\r\naf::array B = af::constant(0, length, f32);\r\n \r\n// ... additional ArrayFire operations here\r\n \r\n// 2. Obtain the device, context, and queue used by ArrayFire\r\nstatic cl_context af_context = afcl::getContext();\r\nstatic cl_device_id af_device_id = afcl::getDeviceId();\r\nstatic cl_command_queue af_queue = afcl::getQueue();\r\n \r\n// 3. Obtain cl_mem references to af::array objects\r\ncl_mem * d_A = A.device&lt;cl_mem&gt;();\r\ncl_mem * d_B = B.device&lt;cl_mem&gt;();\r\n \r\n// 4. Load, build, and use your kernels.\r\n// For the sake of readability, we have omitted error checking.\r\nint status = CL_SUCCESS;\r\n \r\n// A simple copy kernel, uses C++11 syntax for multi-line strings.\r\nconst char * kernel_name = \"copy_kernel\";\r\nconst char * source = R\"(\r\nvoid __kernel\r\ncopy_kernel(__global float * gA, __global float * gB)\r\n{\r\nint id = get_global_id(0);\r\ngB[id] = gA[id];\r\n}\r\n)\";\r\n \r\n// Create the program, build the executable, and extract the entry point\r\n// for the kernel.\r\ncl_program program = clCreateProgramWithSource(af_context, 1, &amp;source, NULL, &amp;status);\r\nstatus = clBuildProgram(program, 1, &amp;af_device_id, NULL, NULL, NULL);\r\ncl_kernel kernel = clCreateKernel(program, kernel_name, &amp;status);\r\n \r\n// Set arguments and launch your kernels\r\nclSetKernelArg(kernel, 0, sizeof(cl_mem), d_A);\r\nclSetKernelArg(kernel, 1, sizeof(cl_mem), d_B);\r\nclEnqueueNDRangeKernel(af_queue, kernel, 1, NULL, &amp;length, NULL, 0, NULL, NULL);\r\n \r\n// 5. Return control of af::array memory to ArrayFire\r\nA.unlock();\r\nB.unlock();\r\n \r\n// ... resume ArrayFire operations\r\n \r\n// Because the device pointers, d_x and d_y, were returned to ArrayFire\'s\r\n// control by the unlock function, there is no need to free them using\r\n// clReleaseMemObject()\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\nIf your kernels needs to operate in their own OpenCL queue, the process is essentially identical, except you need to instruct ArrayFire to complete its computations using the <code>af::sync()</code> function prior to launching your own kernel and ensure your kernels are complete using <code>clFinish</code> (or similar) commands prior to returning control of the memory to ArrayFire:\r\n<ol type=\"1\">\r\n 	<li>Add an include for <code>af/opencl.h</code> to your project</li>\r\n 	<li>Obtain the OpenCL context, device, and queue used by ArrayFire</li>\r\n 	<li>Obtain <code>cl_mem</code> references to <code>af::array</code> objects</li>\r\n 	<li>Instruct ArrayFire to finish operations using <code>af::sync()</code></li>\r\n 	<li>Load, build, and use your kernels</li>\r\n 	<li>Instruct OpenCL to finish operations using <code>clFinish()</code> or similar commands</li>\r\n        <li>Return control of <code>af::array</code> memory to ArrayFire</li>\r\n</ol>\r\n<h4>Adding ArrayFire to an existing OpenCL application</h4>\r\nAdding ArrayFire to an existing OpenCL application is slightly more involved and can be somewhat tricky due to several optimizations we implement. The most important are as follows:\r\n<ul>\r\n 	<li>ArrayFire assumes control of all memory provided to it.</li>\r\n 	<li>ArrayFire does not (in general) support in-place memory transactions.</li>\r\n</ul>\r\nWe will discuss the implications of these items below. To add ArrayFire to existing code you need to:\r\n<ol type=\"1\">\r\n 	<li>Add includes</li>\r\n 	<li>Instruct OpenCL to complete its operations using <code>clFinish</code> (or similar)</li>\r\n 	<li>Instruct ArrayFire to use the user-created OpenCL Context</li>\r\n 	<li>Create ArrayFire arrays from OpenCL memory objects</li>\r\n 	<li>Perform ArrayFire operations on the Arrays</li>\r\n 	<li>Instruct ArrayFire to finish operations using <code>af::sync()</code></li>\r\n 	<li>Obtain cl_mem references for important memory</li>\r\n 	<li>Continue your OpenCL application</li>\r\n</ol>\r\nTo create the af::array objects, you should use one of the following constructors:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1D - 3D af::array constructors\r\nstatic af::array array (dim_t dim0, cl_mem buf, af::dtype type, bool retain=false)\r\nstatic af::array array (dim_t dim0, dim_t dim1, cl_mem buf, af::dtype type, bool retain=false)\r\nstatic af::array array (dim_t dim0, dim_t dim1, dim_t dim2, cl_mem buf, af::dtype type, bool retain=false)\r\nstatic af::array array (dim_t dim0, dim_t dim1, dim_t dim2, dim_t dim3, cl_mem buf, af::dtype type, bool retain=false)\r\n \r\n// af::array constructor using a dim4 object\r\nstatic af::array array (af::dim4 idims, cl_mem buf, af::dtype type, bool retain=false)</pre>\r\n</div>\r\n</div>\r\n<em>NOTE</em>: With all of these constructors, ArrayFire\'s memory manager automatically assumes responsibility for any memory provided to it. If you are creating an array from a <code>cl::Buffer</code>, you should specify <code>retain=true</code> to ensure your memory is not deallocated if your <code>cl::Buffer</code> were to go out of scope. We use this technique in the example below. If you do not wish for ArrayFire to manage your memory, you may call the <code>array::unlock()</code> function and manage the memory yourself; however, if you do so, please be cautious not to call <code>clReleaseMemObj</code> on a <code>cl_mem</code> when ArrayFire might be using it!\r\n\r\nThe eight steps above are best illustrated using a fully-worked example. Below we use the OpenCL 2.0 C++ API and omit error checking to keep the code readable.\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">#include &lt;CL/cl2.hpp&gt;\r\n \r\n// 1. Add arrayfire.h and af/opencl.h to your application\r\n#include \"arrayfire.h\"\r\n#include \"af/opencl.h\"\r\n \r\n#include &lt;cstdio&gt;\r\n#include &lt;vector&gt;\r\n \r\nint main() {\r\n \r\n// Set up the OpenCL context, device, and queues\r\ncl::Context context(CL_DEVICE_TYPE_ALL);\r\nvector&lt;cl::Device&gt; devices = context.getInfo&lt;CL_CONTEXT_DEVICES&gt;();\r\ncl::Device device = devices[0];\r\ncl::CommandQueue queue(context, device);\r\n \r\n// Create a buffer of size 10 filled with ones, copy it to the device\r\nint length = 10;\r\nvector&lt;float&gt; h_A(length, 1);\r\ncl::Buffer cl_A(context, CL_MEM_READ_WRITE, length * sizeof(float), h_A.data());\r\n \r\n// 2. Instruct OpenCL to complete its operations using clFinish (or similar)\r\nqueue.finish();\r\n \r\n// 3. Instruct ArrayFire to use the user-created context\r\n// First, create a device from the current OpenCL device + context + queue\r\nafcl::addDevice(device(), context(), queue());\r\n// Next switch ArrayFire to the device using the device and context as\r\n// identifiers:\r\nafcl::setDevice(device(), context());\r\n \r\n// 4. Create ArrayFire arrays from OpenCL memory objects\r\naf::array af_A = afcl::array(length, cl_A(), f32, true);\r\n \r\n// 5. Perform ArrayFire operations on the Arrays\r\naf_A = af_A + af::randu(length);\r\n \r\n// NOTE: ArrayFire does not perform the above transaction using in-place memory,\r\n// thus the underlying OpenCL buffers containing the memory containing memory to\r\n// probably have changed\r\n \r\n// 6. Instruct ArrayFire to finish operations using af::sync\r\naf::sync();\r\n \r\n// 7. Obtain cl_mem references for important memory\r\ncl_A = *af_A.device&lt;cl_mem&gt;();\r\n \r\n// 8. Continue your OpenCL application\r\n \r\n// ...\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\n<h4>Using multiple devices</h4>\r\nIf you are using ArrayFire and OpenCL with multiple devices be sure to use <code>afcl::addDevice</code> to add your custom context + device + queue to ArrayFire\'s device manager. This will let you switch ArrayFire devices using your current<code>cl_device_id</code> and <code>cl_context</code>.','ArrayFire - OpenCL Interoperability','','publish','open','closed','','arrayfire-opencl-interoperability','','','2016-12-20 14:33:04','2016-12-20 19:33:04','',0,'http://sandbox.arrayfire.com/?p=8874',0,'post','',0),(8875,18528,'2016-05-18 12:46:27','2016-05-18 16:46:27','Although ArrayFire is quite extensive, there remain many cases in which you may want to write custom kernels in OpenCL or <a class=\"el\" href=\"interop_cuda.htm\">CUDA</a>. For example, you may wish to add ArrayFire to an existing code base to increase your productivity, or you may need to supplement ArrayFire\'s functionality with your own custom implementation of specific algorithms.\r\n\r\nArrayFire manages its own context, queue, memory, and creates custom IDs for devices. As such, most of the interoperability functions focus on reducing potential synchronization conflicts between ArrayFire and OpenCL.\r\n<h4>Basics</h4>\r\nIt is fairly straightforward to interface ArrayFire with your own custom OpenCL code. ArrayFire provides several functions to ease this process including:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"A multi dimensional data container. \" href=\"classaf_1_1array.htm\">af::array</a>(...)</td>\r\n<td>Construct an ArrayFire array from cl_mem references or cl::Buffer objects</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" href=\"group__device__func__device.htm#ga93c855ccd22d37cf90d32aef5ac75030\">af::array.device()</a></td>\r\n<td>Obtain a pointer to the cl_mem reference (implies lock())</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Locks the device buffer in the memory manager. \" href=\"classaf_1_1array.htm#adb935251a59a654ff19259005a8ed7f7\">af::array.lock()</a></td>\r\n<td>Removes ArrayFire\'s control of a cl_mem buffer</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Unlocks the device buffer in the memory manager. \" href=\"classaf_1_1array.htm#ab896fcbef7ce95ee1dc6a8c633240ee6\">af::array.unlock()</a></td>\r\n<td>Restore\'s ArrayFire\'s control over a cl_mem buffer</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get a vendor enumeration for the current platform. \" href=\"group__opencl__mat.htm#ga9c5a70a03d0d0bb31b4e7e5a0598752a\">afcl::getPlatform()</a></td>\r\n<td>Get ArrayFire\'s current cl_platform</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Gets the current device ID. \" href=\"group__device__func__get.htm#ga4dfe3f90475b735384f8b28cf2b19a11\">af::getDevice()</a></td>\r\n<td>Get the current ArrayFire Device ID</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get the device ID for ArrayFire\'s current active device. \" href=\"group__opencl__mat.htm#gae40668cc7d19273f449a1628ac438182\">afcl::getDeviceId()</a></td>\r\n<td>Get ArrayFire\'s current cl_device_id</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Sets the current device. \" href=\"group__device__func__set.htm#gafbb906ca5b89ec43fdb0e3a14d1df1e7\">af::setDevice()</a></td>\r\n<td>Set ArrayFire\'s device from an ArrayFire device ID</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Set ArrayFire\'s active device based on id of type cl_device_id. \" href=\"group__opencl__mat.htm#ga242cc7dc5dcebc9e695e4fc3faebb91e\">afcl::setDeviceId()</a></td>\r\n<td>Set ArrayFire\'s device from a cl_device_id</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Set active device using cl_context and cl_device_id. \" href=\"group__opencl__mat.htm#ga37969cfa49416bbdb25910d15c454d01\">afcl::setDevice()</a></td>\r\n<td>Set ArrayFire\'s device from a cl_device_id and cl_context</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get a handle to ArrayFire\'s OpenCL context. \" href=\"group__opencl__mat.htm#ga1984398db67a52977435e653bb842da7\">afcl::getContext()</a></td>\r\n<td>Get ArrayFire\'s current cl_context</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get a handle to ArrayFire\'s OpenCL command queue. \" href=\"group__opencl__mat.htm#ga4bdd87f7ee76ba2ac18a7e1719508d5d\">afcl::getQueue()</a></td>\r\n<td>Get ArrayFire\'s current cl_command_queue</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get the type of the current device. \" href=\"group__opencl__mat.htm#ga9f00565eb14e9cc9bf9568bac2072d70\">afcl::getDeviceType()</a></td>\r\n<td>Get the current afcl_device_type</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nAdditionally, the OpenCL backend permits the programmer to add and remove custom devices from the ArrayFire device manager. These permit you to attach ArrayFire directly to the OpenCL queue used by other portions of your application.\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Push user provided device control constructs into the ArrayFire device manager pool. \" href=\"group__opencl__mat.htm#ga52c81b7227b95ce05c3e8b8efed3a9dc\">afcl::addDevice()</a></td>\r\n<td>Add a new device to ArrayFire\'s device manager</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Remove the user provided device control constructs from the ArrayFire device manager pool...\" href=\"group__opencl__mat.htm#ga410026dc3d7b5e8b779c3505578cb097\">afcl::deleteDevice()</a></td>\r\n<td>Remove a device from ArrayFire\'s device manager</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nBelow we provide two worked examples on how ArrayFire can be integrated into new and existing projects.\r\n<h4>Adding custom OpenCL kernels to an existing ArrayFire application</h4>\r\nBy default, ArrayFire manages its own context, queue, memory, and creates custom IDs for devices. Thus there is some bookkeeping that needs to be done to integrate your custom OpenCL kernel.\r\n\r\nIf your kernels can share operate in the same queue as ArrayFire, you should:\r\n<ol type=\"1\">\r\n 	<li>Add an include for <code><a class=\"el\" href=\"opencl_8h.htm\">af/opencl.h</a></code> to your project</li>\r\n 	<li>Obtain the OpenCL context, device, and queue used by ArrayFire</li>\r\n 	<li>Obtain cl_mem references to <a class=\"el\" title=\"A multi dimensional data container. \" href=\"classaf_1_1array.htm\">af::array</a> objects</li>\r\n 	<li>Load, build, and use your kernels</li>\r\n 	<li>Return control of <a class=\"el\" title=\"A multi dimensional data container. \" href=\"classaf_1_1array.htm\">af::array</a> memory to ArrayFire</li>\r\n</ol>\r\nNote, ArrayFire uses an in-order queue, thus when ArrayFire and your kernels are operating in the same queue, there is no need to perform any synchronization operations.\r\n\r\nThis process is best illustrated with a fully worked example:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">#include &lt;arrayfire.h&gt;\r\n// 1. Add the af/opencl.h include to your project\r\n#include &lt;af/opencl.h&gt;\r\n \r\nint main() {\r\nsize_t length = 10;\r\n \r\n// Create ArrayFire array objects:\r\naf::array A = af::randu(length, f32);\r\naf::array B = af::constant(0, length, f32);\r\n \r\n// ... additional ArrayFire operations here\r\n \r\n// 2. Obtain the device, context, and queue used by ArrayFire\r\nstatic cl_context af_context = afcl::getContext();\r\nstatic cl_device_id af_device_id = afcl::getDeviceId();\r\nstatic cl_command_queue af_queue = afcl::getQueue();\r\n \r\n// 3. Obtain cl_mem references to af::array objects\r\ncl_mem * d_A = A.device&lt;cl_mem&gt;();\r\ncl_mem * d_B = B.device&lt;cl_mem&gt;();\r\n \r\n// 4. Load, build, and use your kernels.\r\n// For the sake of readability, we have omitted error checking.\r\nint status = CL_SUCCESS;\r\n \r\n// A simple copy kernel, uses C++11 syntax for multi-line strings.\r\nconst char * kernel_name = \"copy_kernel\";\r\nconst char * source = R\"(\r\nvoid __kernel\r\ncopy_kernel(__global float * gA, __global float * gB)\r\n{\r\nint id = get_global_id(0);\r\ngB[id] = gA[id];\r\n}\r\n)\";\r\n \r\n// Create the program, build the executable, and extract the entry point\r\n// for the kernel.\r\ncl_program program = clCreateProgramWithSource(af_context, 1, &amp;source, NULL, &amp;status);\r\nstatus = clBuildProgram(program, 1, &amp;af_device_id, NULL, NULL, NULL);\r\ncl_kernel kernel = clCreateKernel(program, kernel_name, &amp;status);\r\n \r\n// Set arguments and launch your kernels\r\nclSetKernelArg(kernel, 0, sizeof(cl_mem), d_A);\r\nclSetKernelArg(kernel, 1, sizeof(cl_mem), d_B);\r\nclEnqueueNDRangeKernel(af_queue, kernel, 1, NULL, &amp;length, NULL, 0, NULL, NULL);\r\n \r\n// 5. Return control of af::array memory to ArrayFire\r\nA.unlock();\r\nB.unlock();\r\n \r\n// ... resume ArrayFire operations\r\n \r\n// Because the device pointers, d_x and d_y, were returned to ArrayFire\'s\r\n// control by the unlock function, there is no need to free them using\r\n// clReleaseMemObject()\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\nIf your kernels needs to operate in their own OpenCL queue, the process is essentially identical, except you need to instruct ArrayFire to complete its computations using the <a class=\"el\" title=\"Blocks until the device is finished processing. \" href=\"group__device__func__sync.htm#ga8c5d51841cf4f2ddbdd6a3146cf2b390\">af::sync()</a> function prior to launching your own kernel and ensure your kernels are complete using <code>clFinish</code> (or similar) commands prior to returning control of the memory to ArrayFire:\r\n<ol type=\"1\">\r\n 	<li>Add an include for <code><a class=\"el\" href=\"opencl_8h.htm\">af/opencl.h</a></code> to your project</li>\r\n 	<li>Obtain the OpenCL context, device, and queue used by ArrayFire</li>\r\n 	<li>Obtain cl_mem references to <a class=\"el\" title=\"A multi dimensional data container. \" href=\"classaf_1_1array.htm\">af::array</a> objects</li>\r\n 	<li>Instruct ArrayFire to finish operations using <a class=\"el\" title=\"Blocks until the device is finished processing. \" href=\"group__device__func__sync.htm#ga8c5d51841cf4f2ddbdd6a3146cf2b390\">af::sync()</a></li>\r\n 	<li>Load, build, and use your kernels</li>\r\n 	<li>Instruct OpenCL to finish operations using clFinish() or similar commands.</li>\r\n</ol>\r\n<ol type=\"1\">\r\n 	<li>Return control of <a class=\"el\" title=\"A multi dimensional data container. \" href=\"classaf_1_1array.htm\">af::array</a> memory to ArrayFire</li>\r\n</ol>\r\n<h4>Adding ArrayFire to an existing OpenCL application</h4>\r\nAdding ArrayFire to an existing OpenCL application is slightly more involved and can be somewhat tricky due to several optimizations we implement. The most important are as follows:\r\n<ul>\r\n 	<li>ArrayFire assumes control of all memory provided to it.</li>\r\n 	<li>ArrayFire does not (in general) support in-place memory transactions.</li>\r\n</ul>\r\nWe will discuss the implications of these items below. To add ArrayFire to existing code you need to:\r\n<ol type=\"1\">\r\n 	<li>Add includes</li>\r\n 	<li>Instruct OpenCL to complete its operations using clFinish (or similar)</li>\r\n 	<li>Instruct ArrayFire to use the user-created OpenCL Context</li>\r\n 	<li>Create ArrayFire arrays from OpenCL memory objects</li>\r\n 	<li>Perform ArrayFire operations on the Arrays</li>\r\n 	<li>Instruct ArrayFire to finish operations using <a class=\"el\" title=\"Blocks until the device is finished processing. \" href=\"group__device__func__sync.htm#ga8c5d51841cf4f2ddbdd6a3146cf2b390\">af::sync()</a></li>\r\n 	<li>Obtain cl_mem references for important memory</li>\r\n 	<li>Continue your OpenCL application</li>\r\n</ol>\r\nTo create the <a class=\"el\" title=\"A multi dimensional data container. \" href=\"classaf_1_1array.htm\">af::array</a> objects, you should use one of the following constructors:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1D - 3D af::array constructors\r\nstatic af::array array (dim_t dim0, cl_mem buf, af::dtype type, bool retain=false)\r\nstatic af::array array (dim_t dim0, dim_t dim1, cl_mem buf, af::dtype type, bool retain=false)\r\nstatic af::array array (dim_t dim0, dim_t dim1, dim_t dim2, cl_mem buf, af::dtype type, bool retain=false)\r\nstatic af::array array (dim_t dim0, dim_t dim1, dim_t dim2, dim_t dim3, cl_mem buf, af::dtype type, bool retain=false)\r\n \r\n// af::array constructor using a dim4 object\r\nstatic af::array array (af::dim4 idims, cl_mem buf, af::dtype type, bool retain=false)</pre>\r\n</div>\r\n</div>\r\n<em>NOTE</em>: With all of these constructors, ArrayFire\'s memory manager automatically assumes responsibility for any memory provided to it. If you are creating an array from a <code>cl::Buffer</code>, you should specify <code>retain=true</code> to ensure your memory is not deallocated if your <code>cl::Buffer</code> were to go out of scope. We use this technique in the example below. If you do not wish for ArrayFire to manage your memory, you may call the <code>array::unlock()</code> function and manage the memory yourself; however, if you do so, please be cautious not to call <code>clReleaseMemObj</code> on a <code>cl_mem</code> when ArrayFire might be using it!\r\n\r\nThe eight steps above are best illustrated using a fully-worked example. Below we use the OpenCL 2.0 C++ API and omit error checking to keep the code readable.\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">#include &lt;CL/cl2.hpp&gt;\r\n \r\n// 1. Add arrayfire.h and af/opencl.h to your application\r\n#include \"arrayfire.h\"\r\n#include \"af/opencl.h\"\r\n \r\n#include &lt;cstdio&gt;\r\n#include &lt;vector&gt;\r\n \r\nint main() {\r\n \r\n// Set up the OpenCL context, device, and queues\r\ncl::Context context(CL_DEVICE_TYPE_ALL);\r\nvector&lt;cl::Device&gt; devices = context.getInfo&lt;CL_CONTEXT_DEVICES&gt;();\r\ncl::Device device = devices[0];\r\ncl::CommandQueue queue(context, device);\r\n \r\n// Create a buffer of size 10 filled with ones, copy it to the device\r\nint length = 10;\r\nvector&lt;float&gt; h_A(length, 1);\r\ncl::Buffer cl_A(context, CL_MEM_READ_WRITE, length * sizeof(float), h_A.data());\r\n \r\n// 2. Instruct OpenCL to complete its operations using clFinish (or similar)\r\nqueue.finish();\r\n \r\n// 3. Instruct ArrayFire to use the user-created context\r\n// First, create a device from the current OpenCL device + context + queue\r\nafcl::addDevice(device(), context(), queue());\r\n// Next switch ArrayFire to the device using the device and context as\r\n// identifiers:\r\nafcl::setDevice(device(), context());\r\n \r\n// 4. Create ArrayFire arrays from OpenCL memory objects\r\naf::array af_A = afcl::array(length, cl_A(), f32, true);\r\n \r\n// 5. Perform ArrayFire operations on the Arrays\r\naf_A = af_A + af::randu(length);\r\n \r\n// NOTE: ArrayFire does not perform the above transaction using in-place memory,\r\n// thus the underlying OpenCL buffers containing the memory containing memory to\r\n// probably have changed\r\n \r\n// 6. Instruct ArrayFire to finish operations using af::sync\r\naf::sync();\r\n \r\n// 7. Obtain cl_mem references for important memory\r\ncl_A = *af_A.device&lt;cl_mem&gt;();\r\n \r\n// 8. Continue your OpenCL application\r\n \r\n// ...\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\n<h4>Using multiple devices</h4>\r\nIf you are using ArrayFire and OpenCL with multiple devices be sure to use <code><a class=\"el\" title=\"Push user provided device control constructs into the ArrayFire device manager pool. \" href=\"group__opencl__mat.htm#ga52c81b7227b95ce05c3e8b8efed3a9dc\">afcl::addDevice</a></code> to add your custom context + device + queue to ArrayFire\'s device manager. This will let you switch ArrayFire devices using your current<code>cl_device_id</code> and <code>cl_context</code>.','ArrayFire - OpenCL Interoperability','','inherit','closed','closed','','8874-revision-v1','','','2016-05-18 12:46:27','2016-05-18 16:46:27','',8874,'http://sandbox.arrayfire.com/8874-revision-v1/',0,'revision','',0),(8876,18528,'2016-05-18 12:50:50','2016-05-18 16:50:50','In last week\'s \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" post we discussed how to interface ArrayFire and CUDA to improve your productivity. This week we demonstrate how to mix ArrayFire and OpenCL in your application.\r\n\r\n<!--more-->\r\n\r\nMuch like with CUDA, ArrayFire controls almost all aspects of its execution on OpenCL platforms. ArrayFire manages its own context, queue, memory, and creates custom IDs for devices. As such, most of the interoperability functions focus on reducing potential synchronization conflicts between ArrayFire and OpenCL.\r\n\r\n<strong>NOTE</strong>: This blog post was written against ArrayFire 3.3.x. We intend to implement additional convenience functions in ArrayFire 3.4 that should simplify this process further. Be sure to <a href=\"http://arrayfire.org/docs/interop_cuda.htm\">check the documentation</a> for any updates in future releases.\r\n<h4>Basics</h4>\r\nIt is fairly straightforward to interface ArrayFire with your own custom OpenCL code. ArrayFire provides several functions to ease this process including:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"A multi dimensional data container. \" href=\"classaf_1_1array.htm\">af::array</a>(...)</td>\r\n<td>Construct an ArrayFire array from cl_mem references or cl::Buffer objects</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" href=\"group__device__func__device.htm#ga93c855ccd22d37cf90d32aef5ac75030\">af::array.device()</a></td>\r\n<td>Obtain a pointer to the cl_mem reference (implies lock())</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Locks the device buffer in the memory manager. \" href=\"classaf_1_1array.htm#adb935251a59a654ff19259005a8ed7f7\">af::array.lock()</a></td>\r\n<td>Removes ArrayFire\'s control of a cl_mem buffer</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Unlocks the device buffer in the memory manager. \" href=\"classaf_1_1array.htm#ab896fcbef7ce95ee1dc6a8c633240ee6\">af::array.unlock()</a></td>\r\n<td>Restore\'s ArrayFire\'s control over a cl_mem buffer</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get a vendor enumeration for the current platform. \" href=\"group__opencl__mat.htm#ga9c5a70a03d0d0bb31b4e7e5a0598752a\">afcl::getPlatform()</a></td>\r\n<td>Get ArrayFire\'s current cl_platform</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Gets the current device ID. \" href=\"group__device__func__get.htm#ga4dfe3f90475b735384f8b28cf2b19a11\">af::getDevice()</a></td>\r\n<td>Get the current ArrayFire Device ID</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get the device ID for ArrayFire\'s current active device. \" href=\"group__opencl__mat.htm#gae40668cc7d19273f449a1628ac438182\">afcl::getDeviceId()</a></td>\r\n<td>Get ArrayFire\'s current cl_device_id</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Sets the current device. \" href=\"group__device__func__set.htm#gafbb906ca5b89ec43fdb0e3a14d1df1e7\">af::setDevice()</a></td>\r\n<td>Set ArrayFire\'s device from an ArrayFire device ID</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Set ArrayFire\'s active device based on id of type cl_device_id. \" href=\"group__opencl__mat.htm#ga242cc7dc5dcebc9e695e4fc3faebb91e\">afcl::setDeviceId()</a></td>\r\n<td>Set ArrayFire\'s device from a cl_device_id</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Set active device using cl_context and cl_device_id. \" href=\"group__opencl__mat.htm#ga37969cfa49416bbdb25910d15c454d01\">afcl::setDevice()</a></td>\r\n<td>Set ArrayFire\'s device from a cl_device_id and cl_context</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get a handle to ArrayFire\'s OpenCL context. \" href=\"group__opencl__mat.htm#ga1984398db67a52977435e653bb842da7\">afcl::getContext()</a></td>\r\n<td>Get ArrayFire\'s current cl_context</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get a handle to ArrayFire\'s OpenCL command queue. \" href=\"group__opencl__mat.htm#ga4bdd87f7ee76ba2ac18a7e1719508d5d\">afcl::getQueue()</a></td>\r\n<td>Get ArrayFire\'s current cl_command_queue</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get the type of the current device. \" href=\"group__opencl__mat.htm#ga9f00565eb14e9cc9bf9568bac2072d70\">afcl::getDeviceType()</a></td>\r\n<td>Get the current afcl_device_type</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nAdditionally, the OpenCL backend permits the programmer to add and remove custom devices from the ArrayFire device manager. These permit you to attach ArrayFire directly to the OpenCL queue used by other portions of your application.\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Push user provided device control constructs into the ArrayFire device manager pool. \" href=\"group__opencl__mat.htm#ga52c81b7227b95ce05c3e8b8efed3a9dc\">afcl::addDevice()</a></td>\r\n<td>Add a new device to ArrayFire\'s device manager</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Remove the user provided device control constructs from the ArrayFire device manager pool...\" href=\"group__opencl__mat.htm#ga410026dc3d7b5e8b779c3505578cb097\">afcl::deleteDevice()</a></td>\r\n<td>Remove a device from ArrayFire\'s device manager</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nBelow we provide two worked examples on how ArrayFire can be integrated into new and existing projects.\r\n<h4>Adding custom OpenCL kernels to an existing ArrayFire application</h4>\r\nBy default, ArrayFire manages its own context, queue, memory, and creates custom IDs for devices. Thus there is some bookkeeping that needs to be done to integrate your custom OpenCL kernel.\r\n\r\nIf your kernels can share operate in the same queue as ArrayFire, you should:\r\n<ol type=\"1\">\r\n 	<li>Add an include for <code><a class=\"el\" href=\"opencl_8h.htm\">af/opencl.h</a></code> to your project</li>\r\n 	<li>Obtain the OpenCL context, device, and queue used by ArrayFire</li>\r\n 	<li>Obtain cl_mem references to <a class=\"el\" title=\"A multi dimensional data container. \" href=\"classaf_1_1array.htm\">af::array</a> objects</li>\r\n 	<li>Load, build, and use your kernels</li>\r\n 	<li>Return control of <a class=\"el\" title=\"A multi dimensional data container. \" href=\"classaf_1_1array.htm\">af::array</a> memory to ArrayFire</li>\r\n</ol>\r\nNote, ArrayFire uses an in-order queue, thus when ArrayFire and your kernels are operating in the same queue, there is no need to perform any synchronization operations.\r\n\r\nThis process is best illustrated with a fully worked example:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">#include &lt;arrayfire.h&gt;\r\n// 1. Add the af/opencl.h include to your project\r\n#include &lt;af/opencl.h&gt;\r\n \r\nint main() {\r\nsize_t length = 10;\r\n \r\n// Create ArrayFire array objects:\r\naf::array A = af::randu(length, f32);\r\naf::array B = af::constant(0, length, f32);\r\n \r\n// ... additional ArrayFire operations here\r\n \r\n// 2. Obtain the device, context, and queue used by ArrayFire\r\nstatic cl_context af_context = afcl::getContext();\r\nstatic cl_device_id af_device_id = afcl::getDeviceId();\r\nstatic cl_command_queue af_queue = afcl::getQueue();\r\n \r\n// 3. Obtain cl_mem references to af::array objects\r\ncl_mem * d_A = A.device&lt;cl_mem&gt;();\r\ncl_mem * d_B = B.device&lt;cl_mem&gt;();\r\n \r\n// 4. Load, build, and use your kernels.\r\n// For the sake of readability, we have omitted error checking.\r\nint status = CL_SUCCESS;\r\n \r\n// A simple copy kernel, uses C++11 syntax for multi-line strings.\r\nconst char * kernel_name = \"copy_kernel\";\r\nconst char * source = R\"(\r\nvoid __kernel\r\ncopy_kernel(__global float * gA, __global float * gB)\r\n{\r\nint id = get_global_id(0);\r\ngB[id] = gA[id];\r\n}\r\n)\";\r\n \r\n// Create the program, build the executable, and extract the entry point\r\n// for the kernel.\r\ncl_program program = clCreateProgramWithSource(af_context, 1, &amp;source, NULL, &amp;status);\r\nstatus = clBuildProgram(program, 1, &amp;af_device_id, NULL, NULL, NULL);\r\ncl_kernel kernel = clCreateKernel(program, kernel_name, &amp;status);\r\n \r\n// Set arguments and launch your kernels\r\nclSetKernelArg(kernel, 0, sizeof(cl_mem), d_A);\r\nclSetKernelArg(kernel, 1, sizeof(cl_mem), d_B);\r\nclEnqueueNDRangeKernel(af_queue, kernel, 1, NULL, &amp;length, NULL, 0, NULL, NULL);\r\n \r\n// 5. Return control of af::array memory to ArrayFire\r\nA.unlock();\r\nB.unlock();\r\n \r\n// ... resume ArrayFire operations\r\n \r\n// Because the device pointers, d_x and d_y, were returned to ArrayFire\'s\r\n// control by the unlock function, there is no need to free them using\r\n// clReleaseMemObject()\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\nIf your kernels needs to operate in their own OpenCL queue, the process is essentially identical, except you need to instruct ArrayFire to complete its computations using the <a class=\"el\" title=\"Blocks until the device is finished processing. \" href=\"group__device__func__sync.htm#ga8c5d51841cf4f2ddbdd6a3146cf2b390\">af::sync()</a> function prior to launching your own kernel and ensure your kernels are complete using <code>clFinish</code> (or similar) commands prior to returning control of the memory to ArrayFire:\r\n<ol type=\"1\">\r\n 	<li>Add an include for <code><a class=\"el\" href=\"opencl_8h.htm\">af/opencl.h</a></code> to your project</li>\r\n 	<li>Obtain the OpenCL context, device, and queue used by ArrayFire</li>\r\n 	<li>Obtain cl_mem references to <a class=\"el\" title=\"A multi dimensional data container. \" href=\"classaf_1_1array.htm\">af::array</a> objects</li>\r\n 	<li>Instruct ArrayFire to finish operations using <a class=\"el\" title=\"Blocks until the device is finished processing. \" href=\"group__device__func__sync.htm#ga8c5d51841cf4f2ddbdd6a3146cf2b390\">af::sync()</a></li>\r\n 	<li>Load, build, and use your kernels</li>\r\n 	<li>Instruct OpenCL to finish operations using clFinish() or similar commands.</li>\r\n</ol>\r\n<ol type=\"1\">\r\n 	<li>Return control of <a class=\"el\" title=\"A multi dimensional data container. \" href=\"classaf_1_1array.htm\">af::array</a> memory to ArrayFire</li>\r\n</ol>\r\n<h4>Adding ArrayFire to an existing OpenCL application</h4>\r\nAdding ArrayFire to an existing OpenCL application is slightly more involved and can be somewhat tricky due to several optimizations we implement. The most important are as follows:\r\n<ul>\r\n 	<li>ArrayFire assumes control of all memory provided to it.</li>\r\n 	<li>ArrayFire does not (in general) support in-place memory transactions.</li>\r\n</ul>\r\nWe will discuss the implications of these items below. To add ArrayFire to existing code you need to:\r\n<ol type=\"1\">\r\n 	<li>Add includes</li>\r\n 	<li>Instruct OpenCL to complete its operations using clFinish (or similar)</li>\r\n 	<li>Instruct ArrayFire to use the user-created OpenCL Context</li>\r\n 	<li>Create ArrayFire arrays from OpenCL memory objects</li>\r\n 	<li>Perform ArrayFire operations on the Arrays</li>\r\n 	<li>Instruct ArrayFire to finish operations using <a class=\"el\" title=\"Blocks until the device is finished processing. \" href=\"group__device__func__sync.htm#ga8c5d51841cf4f2ddbdd6a3146cf2b390\">af::sync()</a></li>\r\n 	<li>Obtain cl_mem references for important memory</li>\r\n 	<li>Continue your OpenCL application</li>\r\n</ol>\r\nTo create the <a class=\"el\" title=\"A multi dimensional data container. \" href=\"classaf_1_1array.htm\">af::array</a> objects, you should use one of the following constructors:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1D - 3D af::array constructors\r\nstatic af::array array (dim_t dim0, cl_mem buf, af::dtype type, bool retain=false)\r\nstatic af::array array (dim_t dim0, dim_t dim1, cl_mem buf, af::dtype type, bool retain=false)\r\nstatic af::array array (dim_t dim0, dim_t dim1, dim_t dim2, cl_mem buf, af::dtype type, bool retain=false)\r\nstatic af::array array (dim_t dim0, dim_t dim1, dim_t dim2, dim_t dim3, cl_mem buf, af::dtype type, bool retain=false)\r\n \r\n// af::array constructor using a dim4 object\r\nstatic af::array array (af::dim4 idims, cl_mem buf, af::dtype type, bool retain=false)</pre>\r\n</div>\r\n</div>\r\n<em>NOTE</em>: With all of these constructors, ArrayFire\'s memory manager automatically assumes responsibility for any memory provided to it. If you are creating an array from a <code>cl::Buffer</code>, you should specify <code>retain=true</code> to ensure your memory is not deallocated if your <code>cl::Buffer</code> were to go out of scope. We use this technique in the example below. If you do not wish for ArrayFire to manage your memory, you may call the <code>array::unlock()</code> function and manage the memory yourself; however, if you do so, please be cautious not to call <code>clReleaseMemObj</code> on a <code>cl_mem</code> when ArrayFire might be using it!\r\n\r\nThe eight steps above are best illustrated using a fully-worked example. Below we use the OpenCL 2.0 C++ API and omit error checking to keep the code readable.\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">#include &lt;CL/cl2.hpp&gt;\r\n \r\n// 1. Add arrayfire.h and af/opencl.h to your application\r\n#include \"arrayfire.h\"\r\n#include \"af/opencl.h\"\r\n \r\n#include &lt;cstdio&gt;\r\n#include &lt;vector&gt;\r\n \r\nint main() {\r\n \r\n// Set up the OpenCL context, device, and queues\r\ncl::Context context(CL_DEVICE_TYPE_ALL);\r\nvector&lt;cl::Device&gt; devices = context.getInfo&lt;CL_CONTEXT_DEVICES&gt;();\r\ncl::Device device = devices[0];\r\ncl::CommandQueue queue(context, device);\r\n \r\n// Create a buffer of size 10 filled with ones, copy it to the device\r\nint length = 10;\r\nvector&lt;float&gt; h_A(length, 1);\r\ncl::Buffer cl_A(context, CL_MEM_READ_WRITE, length * sizeof(float), h_A.data());\r\n \r\n// 2. Instruct OpenCL to complete its operations using clFinish (or similar)\r\nqueue.finish();\r\n \r\n// 3. Instruct ArrayFire to use the user-created context\r\n// First, create a device from the current OpenCL device + context + queue\r\nafcl::addDevice(device(), context(), queue());\r\n// Next switch ArrayFire to the device using the device and context as\r\n// identifiers:\r\nafcl::setDevice(device(), context());\r\n \r\n// 4. Create ArrayFire arrays from OpenCL memory objects\r\naf::array af_A = afcl::array(length, cl_A(), f32, true);\r\n \r\n// 5. Perform ArrayFire operations on the Arrays\r\naf_A = af_A + af::randu(length);\r\n \r\n// NOTE: ArrayFire does not perform the above transaction using in-place memory,\r\n// thus the underlying OpenCL buffers containing the memory containing memory to\r\n// probably have changed\r\n \r\n// 6. Instruct ArrayFire to finish operations using af::sync\r\naf::sync();\r\n \r\n// 7. Obtain cl_mem references for important memory\r\ncl_A = *af_A.device&lt;cl_mem&gt;();\r\n \r\n// 8. Continue your OpenCL application\r\n \r\n// ...\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\n<h4>Using multiple devices</h4>\r\nIf you are using ArrayFire and OpenCL with multiple devices be sure to use <code><a class=\"el\" title=\"Push user provided device control constructs into the ArrayFire device manager pool. \" href=\"group__opencl__mat.htm#ga52c81b7227b95ce05c3e8b8efed3a9dc\">afcl::addDevice</a></code> to add your custom context + device + queue to ArrayFire\'s device manager. This will let you switch ArrayFire devices using your current<code>cl_device_id</code> and <code>cl_context</code>.','ArrayFire - OpenCL Interoperability','','inherit','closed','closed','','8874-revision-v1','','','2016-05-18 12:50:50','2016-05-18 16:50:50','',8874,'http://sandbox.arrayfire.com/8874-revision-v1/',0,'revision','',0),(8877,18528,'2016-05-18 12:51:54','2016-05-18 16:51:54','In last week\'s \"<a href=\"arrayfire.org/http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" post we discussed how to interface ArrayFire and CUDA to improve your productivity. This week we demonstrate how to mix ArrayFire and OpenCL in your application.\r\n\r\n<!--more-->\r\n\r\nMuch like with CUDA, ArrayFire controls almost all aspects of its execution on OpenCL platforms. ArrayFire manages its own context, queue, memory, and creates custom IDs for devices. As such, most of the interoperability functions focus on reducing potential synchronization conflicts between ArrayFire and OpenCL.\r\n\r\n<strong>NOTE</strong>: This blog post was written against ArrayFire 3.3.x. We intend to implement additional convenience functions in ArrayFire 3.4 that should simplify this process further. Be sure to <a href=\"arrayfire.org/http://arrayfire.org/docs/interop_cuda.htm\">check the documentation</a> for any updates in future releases.\r\n<h4>Basics</h4>\r\nIt is fairly straightforward to interface ArrayFire with your own custom OpenCL code. ArrayFire provides several functions to ease this process including:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"A multi dimensional data container. \" href=\"arrayfire.org/classaf_1_1array.htm\">af::array</a>(...)</td>\r\n<td>Construct an ArrayFire array from cl_mem references or cl::Buffer objects</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" href=\"arrayfire.org/group__device__func__device.htm#ga93c855ccd22d37cf90d32aef5ac75030\">af::array.device()</a></td>\r\n<td>Obtain a pointer to the cl_mem reference (implies lock())</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Locks the device buffer in the memory manager. \" href=\"arrayfire.org/classaf_1_1array.htm#adb935251a59a654ff19259005a8ed7f7\">af::array.lock()</a></td>\r\n<td>Removes ArrayFire\'s control of a cl_mem buffer</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Unlocks the device buffer in the memory manager. \" href=\"arrayfire.org/classaf_1_1array.htm#ab896fcbef7ce95ee1dc6a8c633240ee6\">af::array.unlock()</a></td>\r\n<td>Restore\'s ArrayFire\'s control over a cl_mem buffer</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get a vendor enumeration for the current platform. \" href=\"arrayfire.org/group__opencl__mat.htm#ga9c5a70a03d0d0bb31b4e7e5a0598752a\">afcl::getPlatform()</a></td>\r\n<td>Get ArrayFire\'s current cl_platform</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Gets the current device ID. \" href=\"arrayfire.org/group__device__func__get.htm#ga4dfe3f90475b735384f8b28cf2b19a11\">af::getDevice()</a></td>\r\n<td>Get the current ArrayFire Device ID</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get the device ID for ArrayFire\'s current active device. \" href=\"arrayfire.org/group__opencl__mat.htm#gae40668cc7d19273f449a1628ac438182\">afcl::getDeviceId()</a></td>\r\n<td>Get ArrayFire\'s current cl_device_id</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Sets the current device. \" href=\"arrayfire.org/group__device__func__set.htm#gafbb906ca5b89ec43fdb0e3a14d1df1e7\">af::setDevice()</a></td>\r\n<td>Set ArrayFire\'s device from an ArrayFire device ID</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Set ArrayFire\'s active device based on id of type cl_device_id. \" href=\"arrayfire.org/group__opencl__mat.htm#ga242cc7dc5dcebc9e695e4fc3faebb91e\">afcl::setDeviceId()</a></td>\r\n<td>Set ArrayFire\'s device from a cl_device_id</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Set active device using cl_context and cl_device_id. \" href=\"arrayfire.org/group__opencl__mat.htm#ga37969cfa49416bbdb25910d15c454d01\">afcl::setDevice()</a></td>\r\n<td>Set ArrayFire\'s device from a cl_device_id and cl_context</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get a handle to ArrayFire\'s OpenCL context. \" href=\"arrayfire.org/group__opencl__mat.htm#ga1984398db67a52977435e653bb842da7\">afcl::getContext()</a></td>\r\n<td>Get ArrayFire\'s current cl_context</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get a handle to ArrayFire\'s OpenCL command queue. \" href=\"arrayfire.org/group__opencl__mat.htm#ga4bdd87f7ee76ba2ac18a7e1719508d5d\">afcl::getQueue()</a></td>\r\n<td>Get ArrayFire\'s current cl_command_queue</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get the type of the current device. \" href=\"arrayfire.org/group__opencl__mat.htm#ga9f00565eb14e9cc9bf9568bac2072d70\">afcl::getDeviceType()</a></td>\r\n<td>Get the current afcl_device_type</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nAdditionally, the OpenCL backend permits the programmer to add and remove custom devices from the ArrayFire device manager. These permit you to attach ArrayFire directly to the OpenCL queue used by other portions of your application.\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Push user provided device control constructs into the ArrayFire device manager pool. \" href=\"arrayfire.org/group__opencl__mat.htm#ga52c81b7227b95ce05c3e8b8efed3a9dc\">afcl::addDevice()</a></td>\r\n<td>Add a new device to ArrayFire\'s device manager</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Remove the user provided device control constructs from the ArrayFire device manager pool...\" href=\"arrayfire.org/group__opencl__mat.htm#ga410026dc3d7b5e8b779c3505578cb097\">afcl::deleteDevice()</a></td>\r\n<td>Remove a device from ArrayFire\'s device manager</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nBelow we provide two worked examples on how ArrayFire can be integrated into new and existing projects.\r\n<h4>Adding custom OpenCL kernels to an existing ArrayFire application</h4>\r\nBy default, ArrayFire manages its own context, queue, memory, and creates custom IDs for devices. Thus there is some bookkeeping that needs to be done to integrate your custom OpenCL kernel.\r\n\r\nIf your kernels can share operate in the same queue as ArrayFire, you should:\r\n<ol type=\"1\">\r\n 	<li>Add an include for <code><a class=\"el\" href=\"arrayfire.org/opencl_8h.htm\">af/opencl.h</a></code> to your project</li>\r\n 	<li>Obtain the OpenCL context, device, and queue used by ArrayFire</li>\r\n 	<li>Obtain cl_mem references to <a class=\"el\" title=\"A multi dimensional data container. \" href=\"arrayfire.org/classaf_1_1array.htm\">af::array</a> objects</li>\r\n 	<li>Load, build, and use your kernels</li>\r\n 	<li>Return control of <a class=\"el\" title=\"A multi dimensional data container. \" href=\"arrayfire.org/classaf_1_1array.htm\">af::array</a> memory to ArrayFire</li>\r\n</ol>\r\nNote, ArrayFire uses an in-order queue, thus when ArrayFire and your kernels are operating in the same queue, there is no need to perform any synchronization operations.\r\n\r\nThis process is best illustrated with a fully worked example:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">#include &lt;arrayfire.h&gt;\r\n// 1. Add the af/opencl.h include to your project\r\n#include &lt;af/opencl.h&gt;\r\n \r\nint main() {\r\nsize_t length = 10;\r\n \r\n// Create ArrayFire array objects:\r\naf::array A = af::randu(length, f32);\r\naf::array B = af::constant(0, length, f32);\r\n \r\n// ... additional ArrayFire operations here\r\n \r\n// 2. Obtain the device, context, and queue used by ArrayFire\r\nstatic cl_context af_context = afcl::getContext();\r\nstatic cl_device_id af_device_id = afcl::getDeviceId();\r\nstatic cl_command_queue af_queue = afcl::getQueue();\r\n \r\n// 3. Obtain cl_mem references to af::array objects\r\ncl_mem * d_A = A.device&lt;cl_mem&gt;();\r\ncl_mem * d_B = B.device&lt;cl_mem&gt;();\r\n \r\n// 4. Load, build, and use your kernels.\r\n// For the sake of readability, we have omitted error checking.\r\nint status = CL_SUCCESS;\r\n \r\n// A simple copy kernel, uses C++11 syntax for multi-line strings.\r\nconst char * kernel_name = \"copy_kernel\";\r\nconst char * source = R\"(\r\nvoid __kernel\r\ncopy_kernel(__global float * gA, __global float * gB)\r\n{\r\nint id = get_global_id(0);\r\ngB[id] = gA[id];\r\n}\r\n)\";\r\n \r\n// Create the program, build the executable, and extract the entry point\r\n// for the kernel.\r\ncl_program program = clCreateProgramWithSource(af_context, 1, &amp;source, NULL, &amp;status);\r\nstatus = clBuildProgram(program, 1, &amp;af_device_id, NULL, NULL, NULL);\r\ncl_kernel kernel = clCreateKernel(program, kernel_name, &amp;status);\r\n \r\n// Set arguments and launch your kernels\r\nclSetKernelArg(kernel, 0, sizeof(cl_mem), d_A);\r\nclSetKernelArg(kernel, 1, sizeof(cl_mem), d_B);\r\nclEnqueueNDRangeKernel(af_queue, kernel, 1, NULL, &amp;length, NULL, 0, NULL, NULL);\r\n \r\n// 5. Return control of af::array memory to ArrayFire\r\nA.unlock();\r\nB.unlock();\r\n \r\n// ... resume ArrayFire operations\r\n \r\n// Because the device pointers, d_x and d_y, were returned to ArrayFire\'s\r\n// control by the unlock function, there is no need to free them using\r\n// clReleaseMemObject()\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\nIf your kernels needs to operate in their own OpenCL queue, the process is essentially identical, except you need to instruct ArrayFire to complete its computations using the <a class=\"el\" title=\"Blocks until the device is finished processing. \" href=\"arrayfire.org/group__device__func__sync.htm#ga8c5d51841cf4f2ddbdd6a3146cf2b390\">af::sync()</a> function prior to launching your own kernel and ensure your kernels are complete using <code>clFinish</code> (or similar) commands prior to returning control of the memory to ArrayFire:\r\n<ol type=\"1\">\r\n 	<li>Add an include for <code><a class=\"el\" href=\"arrayfire.org/opencl_8h.htm\">af/opencl.h</a></code> to your project</li>\r\n 	<li>Obtain the OpenCL context, device, and queue used by ArrayFire</li>\r\n 	<li>Obtain cl_mem references to <a class=\"el\" title=\"A multi dimensional data container. \" href=\"arrayfire.org/classaf_1_1array.htm\">af::array</a> objects</li>\r\n 	<li>Instruct ArrayFire to finish operations using <a class=\"el\" title=\"Blocks until the device is finished processing. \" href=\"arrayfire.org/group__device__func__sync.htm#ga8c5d51841cf4f2ddbdd6a3146cf2b390\">af::sync()</a></li>\r\n 	<li>Load, build, and use your kernels</li>\r\n 	<li>Instruct OpenCL to finish operations using clFinish() or similar commands.</li>\r\n</ol>\r\n<ol type=\"1\">\r\n 	<li>Return control of <a class=\"el\" title=\"A multi dimensional data container. \" href=\"arrayfire.org/classaf_1_1array.htm\">af::array</a> memory to ArrayFire</li>\r\n</ol>\r\n<h4>Adding ArrayFire to an existing OpenCL application</h4>\r\nAdding ArrayFire to an existing OpenCL application is slightly more involved and can be somewhat tricky due to several optimizations we implement. The most important are as follows:\r\n<ul>\r\n 	<li>ArrayFire assumes control of all memory provided to it.</li>\r\n 	<li>ArrayFire does not (in general) support in-place memory transactions.</li>\r\n</ul>\r\nWe will discuss the implications of these items below. To add ArrayFire to existing code you need to:\r\n<ol type=\"1\">\r\n 	<li>Add includes</li>\r\n 	<li>Instruct OpenCL to complete its operations using clFinish (or similar)</li>\r\n 	<li>Instruct ArrayFire to use the user-created OpenCL Context</li>\r\n 	<li>Create ArrayFire arrays from OpenCL memory objects</li>\r\n 	<li>Perform ArrayFire operations on the Arrays</li>\r\n 	<li>Instruct ArrayFire to finish operations using <a class=\"el\" title=\"Blocks until the device is finished processing. \" href=\"arrayfire.org/group__device__func__sync.htm#ga8c5d51841cf4f2ddbdd6a3146cf2b390\">af::sync()</a></li>\r\n 	<li>Obtain cl_mem references for important memory</li>\r\n 	<li>Continue your OpenCL application</li>\r\n</ol>\r\nTo create the <a class=\"el\" title=\"A multi dimensional data container. \" href=\"arrayfire.org/classaf_1_1array.htm\">af::array</a> objects, you should use one of the following constructors:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1D - 3D af::array constructors\r\nstatic af::array array (dim_t dim0, cl_mem buf, af::dtype type, bool retain=false)\r\nstatic af::array array (dim_t dim0, dim_t dim1, cl_mem buf, af::dtype type, bool retain=false)\r\nstatic af::array array (dim_t dim0, dim_t dim1, dim_t dim2, cl_mem buf, af::dtype type, bool retain=false)\r\nstatic af::array array (dim_t dim0, dim_t dim1, dim_t dim2, dim_t dim3, cl_mem buf, af::dtype type, bool retain=false)\r\n \r\n// af::array constructor using a dim4 object\r\nstatic af::array array (af::dim4 idims, cl_mem buf, af::dtype type, bool retain=false)</pre>\r\n</div>\r\n</div>\r\n<em>NOTE</em>: With all of these constructors, ArrayFire\'s memory manager automatically assumes responsibility for any memory provided to it. If you are creating an array from a <code>cl::Buffer</code>, you should specify <code>retain=true</code> to ensure your memory is not deallocated if your <code>cl::Buffer</code> were to go out of scope. We use this technique in the example below. If you do not wish for ArrayFire to manage your memory, you may call the <code>array::unlock()</code> function and manage the memory yourself; however, if you do so, please be cautious not to call <code>clReleaseMemObj</code> on a <code>cl_mem</code> when ArrayFire might be using it!\r\n\r\nThe eight steps above are best illustrated using a fully-worked example. Below we use the OpenCL 2.0 C++ API and omit error checking to keep the code readable.\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">#include &lt;CL/cl2.hpp&gt;\r\n \r\n// 1. Add arrayfire.h and af/opencl.h to your application\r\n#include \"arrayfire.h\"\r\n#include \"af/opencl.h\"\r\n \r\n#include &lt;cstdio&gt;\r\n#include &lt;vector&gt;\r\n \r\nint main() {\r\n \r\n// Set up the OpenCL context, device, and queues\r\ncl::Context context(CL_DEVICE_TYPE_ALL);\r\nvector&lt;cl::Device&gt; devices = context.getInfo&lt;CL_CONTEXT_DEVICES&gt;();\r\ncl::Device device = devices[0];\r\ncl::CommandQueue queue(context, device);\r\n \r\n// Create a buffer of size 10 filled with ones, copy it to the device\r\nint length = 10;\r\nvector&lt;float&gt; h_A(length, 1);\r\ncl::Buffer cl_A(context, CL_MEM_READ_WRITE, length * sizeof(float), h_A.data());\r\n \r\n// 2. Instruct OpenCL to complete its operations using clFinish (or similar)\r\nqueue.finish();\r\n \r\n// 3. Instruct ArrayFire to use the user-created context\r\n// First, create a device from the current OpenCL device + context + queue\r\nafcl::addDevice(device(), context(), queue());\r\n// Next switch ArrayFire to the device using the device and context as\r\n// identifiers:\r\nafcl::setDevice(device(), context());\r\n \r\n// 4. Create ArrayFire arrays from OpenCL memory objects\r\naf::array af_A = afcl::array(length, cl_A(), f32, true);\r\n \r\n// 5. Perform ArrayFire operations on the Arrays\r\naf_A = af_A + af::randu(length);\r\n \r\n// NOTE: ArrayFire does not perform the above transaction using in-place memory,\r\n// thus the underlying OpenCL buffers containing the memory containing memory to\r\n// probably have changed\r\n \r\n// 6. Instruct ArrayFire to finish operations using af::sync\r\naf::sync();\r\n \r\n// 7. Obtain cl_mem references for important memory\r\ncl_A = *af_A.device&lt;cl_mem&gt;();\r\n \r\n// 8. Continue your OpenCL application\r\n \r\n// ...\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\n<h4>Using multiple devices</h4>\r\nIf you are using ArrayFire and OpenCL with multiple devices be sure to use <code><a class=\"el\" title=\"Push user provided device control constructs into the ArrayFire device manager pool. \" href=\"arrayfire.org/group__opencl__mat.htm#ga52c81b7227b95ce05c3e8b8efed3a9dc\">afcl::addDevice</a></code> to add your custom context + device + queue to ArrayFire\'s device manager. This will let you switch ArrayFire devices using your current<code>cl_device_id</code> and <code>cl_context</code>.','ArrayFire - OpenCL Interoperability','','inherit','closed','closed','','8874-revision-v1','','','2016-05-18 12:51:54','2016-05-18 16:51:54','',8874,'http://sandbox.arrayfire.com/8874-revision-v1/',0,'revision','',0),(8878,18528,'2016-05-18 12:53:06','2016-05-18 16:53:06','In last week\'s \"<a href=\"http://arrayfire.org/http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" post we discussed how to interface ArrayFire and CUDA to improve your productivity. This week we demonstrate how to mix ArrayFire and OpenCL in your application.\r\n\r\n<!--more-->\r\n\r\nMuch like with CUDA, ArrayFire controls almost all aspects of its execution on OpenCL platforms. ArrayFire manages its own context, queue, memory, and creates custom IDs for devices. As such, most of the interoperability functions focus on reducing potential synchronization conflicts between ArrayFire and OpenCL.\r\n\r\n<strong>NOTE</strong>: This blog post was written against ArrayFire 3.3.x. We intend to implement additional convenience functions in ArrayFire 3.4 that should simplify this process further. Be sure to <a href=\"http://arrayfire.org/http://arrayfire.org/docs/interop_cuda.htm\">check the documentation</a> for any updates in future releases.\r\n<h4>Basics</h4>\r\nIt is fairly straightforward to interface ArrayFire with your own custom OpenCL code. ArrayFire provides several functions to ease this process including:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"A multi dimensional data container. \" href=\"http://arrayfire.org/classaf_1_1array.htm\">af::array</a>(...)</td>\r\n<td>Construct an ArrayFire array from cl_mem references or cl::Buffer objects</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" href=\"http://arrayfire.org/group__device__func__device.htm#ga93c855ccd22d37cf90d32aef5ac75030\">af::array.device()</a></td>\r\n<td>Obtain a pointer to the cl_mem reference (implies lock())</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Locks the device buffer in the memory manager. \" href=\"http://arrayfire.org/classaf_1_1array.htm#adb935251a59a654ff19259005a8ed7f7\">af::array.lock()</a></td>\r\n<td>Removes ArrayFire\'s control of a cl_mem buffer</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Unlocks the device buffer in the memory manager. \" href=\"http://arrayfire.org/classaf_1_1array.htm#ab896fcbef7ce95ee1dc6a8c633240ee6\">af::array.unlock()</a></td>\r\n<td>Restore\'s ArrayFire\'s control over a cl_mem buffer</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get a vendor enumeration for the current platform. \" href=\"http://arrayfire.org/group__opencl__mat.htm#ga9c5a70a03d0d0bb31b4e7e5a0598752a\">afcl::getPlatform()</a></td>\r\n<td>Get ArrayFire\'s current cl_platform</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Gets the current device ID. \" href=\"http://arrayfire.org/group__device__func__get.htm#ga4dfe3f90475b735384f8b28cf2b19a11\">af::getDevice()</a></td>\r\n<td>Get the current ArrayFire Device ID</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get the device ID for ArrayFire\'s current active device. \" href=\"http://arrayfire.org/group__opencl__mat.htm#gae40668cc7d19273f449a1628ac438182\">afcl::getDeviceId()</a></td>\r\n<td>Get ArrayFire\'s current cl_device_id</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Sets the current device. \" href=\"http://arrayfire.org/group__device__func__set.htm#gafbb906ca5b89ec43fdb0e3a14d1df1e7\">af::setDevice()</a></td>\r\n<td>Set ArrayFire\'s device from an ArrayFire device ID</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Set ArrayFire\'s active device based on id of type cl_device_id. \" href=\"http://arrayfire.org/group__opencl__mat.htm#ga242cc7dc5dcebc9e695e4fc3faebb91e\">afcl::setDeviceId()</a></td>\r\n<td>Set ArrayFire\'s device from a cl_device_id</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Set active device using cl_context and cl_device_id. \" href=\"http://arrayfire.org/group__opencl__mat.htm#ga37969cfa49416bbdb25910d15c454d01\">afcl::setDevice()</a></td>\r\n<td>Set ArrayFire\'s device from a cl_device_id and cl_context</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get a handle to ArrayFire\'s OpenCL context. \" href=\"http://arrayfire.org/group__opencl__mat.htm#ga1984398db67a52977435e653bb842da7\">afcl::getContext()</a></td>\r\n<td>Get ArrayFire\'s current cl_context</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get a handle to ArrayFire\'s OpenCL command queue. \" href=\"http://arrayfire.org/group__opencl__mat.htm#ga4bdd87f7ee76ba2ac18a7e1719508d5d\">afcl::getQueue()</a></td>\r\n<td>Get ArrayFire\'s current cl_command_queue</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Get the type of the current device. \" href=\"http://arrayfire.org/group__opencl__mat.htm#ga9f00565eb14e9cc9bf9568bac2072d70\">afcl::getDeviceType()</a></td>\r\n<td>Get the current afcl_device_type</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nAdditionally, the OpenCL backend permits the programmer to add and remove custom devices from the ArrayFire device manager. These permit you to attach ArrayFire directly to the OpenCL queue used by other portions of your application.\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Push user provided device control constructs into the ArrayFire device manager pool. \" href=\"http://arrayfire.org/group__opencl__mat.htm#ga52c81b7227b95ce05c3e8b8efed3a9dc\">afcl::addDevice()</a></td>\r\n<td>Add a new device to ArrayFire\'s device manager</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Remove the user provided device control constructs from the ArrayFire device manager pool...\" href=\"http://arrayfire.org/group__opencl__mat.htm#ga410026dc3d7b5e8b779c3505578cb097\">afcl::deleteDevice()</a></td>\r\n<td>Remove a device from ArrayFire\'s device manager</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nBelow we provide two worked examples on how ArrayFire can be integrated into new and existing projects.\r\n<h4>Adding custom OpenCL kernels to an existing ArrayFire application</h4>\r\nBy default, ArrayFire manages its own context, queue, memory, and creates custom IDs for devices. Thus there is some bookkeeping that needs to be done to integrate your custom OpenCL kernel.\r\n\r\nIf your kernels can share operate in the same queue as ArrayFire, you should:\r\n<ol type=\"1\">\r\n 	<li>Add an include for <code><a class=\"el\" href=\"http://arrayfire.org/opencl_8h.htm\">af/opencl.h</a></code> to your project</li>\r\n 	<li>Obtain the OpenCL context, device, and queue used by ArrayFire</li>\r\n 	<li>Obtain cl_mem references to <a class=\"el\" title=\"A multi dimensional data container. \" href=\"http://arrayfire.org/classaf_1_1array.htm\">af::array</a> objects</li>\r\n 	<li>Load, build, and use your kernels</li>\r\n 	<li>Return control of <a class=\"el\" title=\"A multi dimensional data container. \" href=\"http://arrayfire.org/classaf_1_1array.htm\">af::array</a> memory to ArrayFire</li>\r\n</ol>\r\nNote, ArrayFire uses an in-order queue, thus when ArrayFire and your kernels are operating in the same queue, there is no need to perform any synchronization operations.\r\n\r\nThis process is best illustrated with a fully worked example:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">#include &lt;arrayfire.h&gt;\r\n// 1. Add the af/opencl.h include to your project\r\n#include &lt;af/opencl.h&gt;\r\n \r\nint main() {\r\nsize_t length = 10;\r\n \r\n// Create ArrayFire array objects:\r\naf::array A = af::randu(length, f32);\r\naf::array B = af::constant(0, length, f32);\r\n \r\n// ... additional ArrayFire operations here\r\n \r\n// 2. Obtain the device, context, and queue used by ArrayFire\r\nstatic cl_context af_context = afcl::getContext();\r\nstatic cl_device_id af_device_id = afcl::getDeviceId();\r\nstatic cl_command_queue af_queue = afcl::getQueue();\r\n \r\n// 3. Obtain cl_mem references to af::array objects\r\ncl_mem * d_A = A.device&lt;cl_mem&gt;();\r\ncl_mem * d_B = B.device&lt;cl_mem&gt;();\r\n \r\n// 4. Load, build, and use your kernels.\r\n// For the sake of readability, we have omitted error checking.\r\nint status = CL_SUCCESS;\r\n \r\n// A simple copy kernel, uses C++11 syntax for multi-line strings.\r\nconst char * kernel_name = \"copy_kernel\";\r\nconst char * source = R\"(\r\nvoid __kernel\r\ncopy_kernel(__global float * gA, __global float * gB)\r\n{\r\nint id = get_global_id(0);\r\ngB[id] = gA[id];\r\n}\r\n)\";\r\n \r\n// Create the program, build the executable, and extract the entry point\r\n// for the kernel.\r\ncl_program program = clCreateProgramWithSource(af_context, 1, &amp;source, NULL, &amp;status);\r\nstatus = clBuildProgram(program, 1, &amp;af_device_id, NULL, NULL, NULL);\r\ncl_kernel kernel = clCreateKernel(program, kernel_name, &amp;status);\r\n \r\n// Set arguments and launch your kernels\r\nclSetKernelArg(kernel, 0, sizeof(cl_mem), d_A);\r\nclSetKernelArg(kernel, 1, sizeof(cl_mem), d_B);\r\nclEnqueueNDRangeKernel(af_queue, kernel, 1, NULL, &amp;length, NULL, 0, NULL, NULL);\r\n \r\n// 5. Return control of af::array memory to ArrayFire\r\nA.unlock();\r\nB.unlock();\r\n \r\n// ... resume ArrayFire operations\r\n \r\n// Because the device pointers, d_x and d_y, were returned to ArrayFire\'s\r\n// control by the unlock function, there is no need to free them using\r\n// clReleaseMemObject()\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\nIf your kernels needs to operate in their own OpenCL queue, the process is essentially identical, except you need to instruct ArrayFire to complete its computations using the <a class=\"el\" title=\"Blocks until the device is finished processing. \" href=\"http://arrayfire.org/group__device__func__sync.htm#ga8c5d51841cf4f2ddbdd6a3146cf2b390\">af::sync()</a> function prior to launching your own kernel and ensure your kernels are complete using <code>clFinish</code> (or similar) commands prior to returning control of the memory to ArrayFire:\r\n<ol type=\"1\">\r\n 	<li>Add an include for <code><a class=\"el\" href=\"http://arrayfire.org/opencl_8h.htm\">af/opencl.h</a></code> to your project</li>\r\n 	<li>Obtain the OpenCL context, device, and queue used by ArrayFire</li>\r\n 	<li>Obtain cl_mem references to <a class=\"el\" title=\"A multi dimensional data container. \" href=\"http://arrayfire.org/classaf_1_1array.htm\">af::array</a> objects</li>\r\n 	<li>Instruct ArrayFire to finish operations using <a class=\"el\" title=\"Blocks until the device is finished processing. \" href=\"http://arrayfire.org/group__device__func__sync.htm#ga8c5d51841cf4f2ddbdd6a3146cf2b390\">af::sync()</a></li>\r\n 	<li>Load, build, and use your kernels</li>\r\n 	<li>Instruct OpenCL to finish operations using clFinish() or similar commands.</li>\r\n</ol>\r\n<ol type=\"1\">\r\n 	<li>Return control of <a class=\"el\" title=\"A multi dimensional data container. \" href=\"http://arrayfire.org/classaf_1_1array.htm\">af::array</a> memory to ArrayFire</li>\r\n</ol>\r\n<h4>Adding ArrayFire to an existing OpenCL application</h4>\r\nAdding ArrayFire to an existing OpenCL application is slightly more involved and can be somewhat tricky due to several optimizations we implement. The most important are as follows:\r\n<ul>\r\n 	<li>ArrayFire assumes control of all memory provided to it.</li>\r\n 	<li>ArrayFire does not (in general) support in-place memory transactions.</li>\r\n</ul>\r\nWe will discuss the implications of these items below. To add ArrayFire to existing code you need to:\r\n<ol type=\"1\">\r\n 	<li>Add includes</li>\r\n 	<li>Instruct OpenCL to complete its operations using clFinish (or similar)</li>\r\n 	<li>Instruct ArrayFire to use the user-created OpenCL Context</li>\r\n 	<li>Create ArrayFire arrays from OpenCL memory objects</li>\r\n 	<li>Perform ArrayFire operations on the Arrays</li>\r\n 	<li>Instruct ArrayFire to finish operations using <a class=\"el\" title=\"Blocks until the device is finished processing. \" href=\"http://arrayfire.org/group__device__func__sync.htm#ga8c5d51841cf4f2ddbdd6a3146cf2b390\">af::sync()</a></li>\r\n 	<li>Obtain cl_mem references for important memory</li>\r\n 	<li>Continue your OpenCL application</li>\r\n</ol>\r\nTo create the <a class=\"el\" title=\"A multi dimensional data container. \" href=\"http://arrayfire.org/classaf_1_1array.htm\">af::array</a> objects, you should use one of the following constructors:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1D - 3D af::array constructors\r\nstatic af::array array (dim_t dim0, cl_mem buf, af::dtype type, bool retain=false)\r\nstatic af::array array (dim_t dim0, dim_t dim1, cl_mem buf, af::dtype type, bool retain=false)\r\nstatic af::array array (dim_t dim0, dim_t dim1, dim_t dim2, cl_mem buf, af::dtype type, bool retain=false)\r\nstatic af::array array (dim_t dim0, dim_t dim1, dim_t dim2, dim_t dim3, cl_mem buf, af::dtype type, bool retain=false)\r\n \r\n// af::array constructor using a dim4 object\r\nstatic af::array array (af::dim4 idims, cl_mem buf, af::dtype type, bool retain=false)</pre>\r\n</div>\r\n</div>\r\n<em>NOTE</em>: With all of these constructors, ArrayFire\'s memory manager automatically assumes responsibility for any memory provided to it. If you are creating an array from a <code>cl::Buffer</code>, you should specify <code>retain=true</code> to ensure your memory is not deallocated if your <code>cl::Buffer</code> were to go out of scope. We use this technique in the example below. If you do not wish for ArrayFire to manage your memory, you may call the <code>array::unlock()</code> function and manage the memory yourself; however, if you do so, please be cautious not to call <code>clReleaseMemObj</code> on a <code>cl_mem</code> when ArrayFire might be using it!\r\n\r\nThe eight steps above are best illustrated using a fully-worked example. Below we use the OpenCL 2.0 C++ API and omit error checking to keep the code readable.\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">#include &lt;CL/cl2.hpp&gt;\r\n \r\n// 1. Add arrayfire.h and af/opencl.h to your application\r\n#include \"arrayfire.h\"\r\n#include \"af/opencl.h\"\r\n \r\n#include &lt;cstdio&gt;\r\n#include &lt;vector&gt;\r\n \r\nint main() {\r\n \r\n// Set up the OpenCL context, device, and queues\r\ncl::Context context(CL_DEVICE_TYPE_ALL);\r\nvector&lt;cl::Device&gt; devices = context.getInfo&lt;CL_CONTEXT_DEVICES&gt;();\r\ncl::Device device = devices[0];\r\ncl::CommandQueue queue(context, device);\r\n \r\n// Create a buffer of size 10 filled with ones, copy it to the device\r\nint length = 10;\r\nvector&lt;float&gt; h_A(length, 1);\r\ncl::Buffer cl_A(context, CL_MEM_READ_WRITE, length * sizeof(float), h_A.data());\r\n \r\n// 2. Instruct OpenCL to complete its operations using clFinish (or similar)\r\nqueue.finish();\r\n \r\n// 3. Instruct ArrayFire to use the user-created context\r\n// First, create a device from the current OpenCL device + context + queue\r\nafcl::addDevice(device(), context(), queue());\r\n// Next switch ArrayFire to the device using the device and context as\r\n// identifiers:\r\nafcl::setDevice(device(), context());\r\n \r\n// 4. Create ArrayFire arrays from OpenCL memory objects\r\naf::array af_A = afcl::array(length, cl_A(), f32, true);\r\n \r\n// 5. Perform ArrayFire operations on the Arrays\r\naf_A = af_A + af::randu(length);\r\n \r\n// NOTE: ArrayFire does not perform the above transaction using in-place memory,\r\n// thus the underlying OpenCL buffers containing the memory containing memory to\r\n// probably have changed\r\n \r\n// 6. Instruct ArrayFire to finish operations using af::sync\r\naf::sync();\r\n \r\n// 7. Obtain cl_mem references for important memory\r\ncl_A = *af_A.device&lt;cl_mem&gt;();\r\n \r\n// 8. Continue your OpenCL application\r\n \r\n// ...\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\n<h4>Using multiple devices</h4>\r\nIf you are using ArrayFire and OpenCL with multiple devices be sure to use <code><a class=\"el\" title=\"Push user provided device control constructs into the ArrayFire device manager pool. \" href=\"http://arrayfire.org/group__opencl__mat.htm#ga52c81b7227b95ce05c3e8b8efed3a9dc\">afcl::addDevice</a></code> to add your custom context + device + queue to ArrayFire\'s device manager. This will let you switch ArrayFire devices using your current<code>cl_device_id</code> and <code>cl_context</code>.','ArrayFire - OpenCL Interoperability','','inherit','closed','closed','','8874-revision-v1','','','2016-05-18 12:53:06','2016-05-18 16:53:06','',8874,'http://sandbox.arrayfire.com/8874-revision-v1/',0,'revision','',0),(8879,18528,'2016-05-18 12:53:55','2016-05-18 16:53:55','In last week\'s \"<a href=\"http://arrayfire.org/http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" post we discussed how to interface ArrayFire and CUDA to improve your productivity. This week we demonstrate how to mix ArrayFire and OpenCL in your application.\r\n\r\n<!--more-->\r\n\r\nMuch like with CUDA, ArrayFire controls almost all aspects of its execution on OpenCL platforms. ArrayFire manages its own context, queue, memory, and creates custom IDs for devices. As such, most of the interoperability functions focus on reducing potential synchronization conflicts between ArrayFire and OpenCL.\r\n\r\n<strong>NOTE</strong>: This blog post was written against ArrayFire 3.3.x. We intend to implement additional convenience functions in ArrayFire 3.4 that should simplify this process further. Be sure to <a href=\"http://arrayfire.org/http://arrayfire.org/docs/interop_cuda.htm\">check the documentation</a> for any updates in future releases.\r\n<h4>Basics</h4>\r\nIt is fairly straightforward to interface ArrayFire with your own custom OpenCL code. ArrayFire provides several functions to ease this process including:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td>af::array(...)</td>\r\n<td>Construct an ArrayFire array from cl_mem references or cl::Buffer objects</td>\r\n</tr>\r\n<tr>\r\n<td>af::array.device()</td>\r\n<td>Obtain a pointer to the cl_mem reference (implies lock())</td>\r\n</tr>\r\n<tr>\r\n<td>af::array.lock()</td>\r\n<td>Removes ArrayFire\'s control of a cl_mem buffer</td>\r\n</tr>\r\n<tr>\r\n<td>af::array.unlock()</td>\r\n<td>Restore\'s ArrayFire\'s control over a cl_mem buffer</td>\r\n</tr>\r\n<tr>\r\n<td>afcl::getPlatform()</td>\r\n<td>Get ArrayFire\'s current cl_platform</td>\r\n</tr>\r\n<tr>\r\n<td>af::getDevice()</td>\r\n<td>Get the current ArrayFire Device ID</td>\r\n</tr>\r\n<tr>\r\n<td>afcl::getDeviceId()</td>\r\n<td>Get ArrayFire\'s current cl_device_id</td>\r\n</tr>\r\n<tr>\r\n<td>af::setDevice()</td>\r\n<td>Set ArrayFire\'s device from an ArrayFire device ID</td>\r\n</tr>\r\n<tr>\r\n<td>afcl::setDeviceId()</td>\r\n<td>Set ArrayFire\'s device from a cl_device_id</td>\r\n</tr>\r\n<tr>\r\n<td>afcl::setDevice()</td>\r\n<td>Set ArrayFire\'s device from a cl_device_id and cl_context</td>\r\n</tr>\r\n<tr>\r\n<td>afcl::getContext()</td>\r\n<td>Get ArrayFire\'s current cl_context</td>\r\n</tr>\r\n<tr>\r\n<td>afcl::getQueue()</td>\r\n<td>Get ArrayFire\'s current cl_command_queue</td>\r\n</tr>\r\n<tr>\r\n<td>afcl::getDeviceType()</td>\r\n<td>Get the current afcl_device_type</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nAdditionally, the OpenCL backend permits the programmer to add and remove custom devices from the ArrayFire device manager. These permit you to attach ArrayFire directly to the OpenCL queue used by other portions of your application.\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Purpose</th>\r\n</tr>\r\n<tr>\r\n<td>afcl::addDevice()</td>\r\n<td>Add a new device to ArrayFire\'s device manager</td>\r\n</tr>\r\n<tr>\r\n<td>afcl::deleteDevice()</td>\r\n<td>Remove a device from ArrayFire\'s device manager</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nBelow we provide two worked examples on how ArrayFire can be integrated into new and existing projects.\r\n<h4>Adding custom OpenCL kernels to an existing ArrayFire application</h4>\r\nBy default, ArrayFire manages its own context, queue, memory, and creates custom IDs for devices. Thus there is some bookkeeping that needs to be done to integrate your custom OpenCL kernel.\r\n\r\nIf your kernels can share operate in the same queue as ArrayFire, you should:\r\n<ol type=\"1\">\r\n 	<li>Add an include for <code>af/opencl.h</code> to your project</li>\r\n 	<li>Obtain the OpenCL context, device, and queue used by ArrayFire</li>\r\n 	<li>Obtain cl_mem references to af::array objects</li>\r\n 	<li>Load, build, and use your kernels</li>\r\n 	<li>Return control of af::array memory to ArrayFire</li>\r\n</ol>\r\nNote, ArrayFire uses an in-order queue, thus when ArrayFire and your kernels are operating in the same queue, there is no need to perform any synchronization operations.\r\n\r\nThis process is best illustrated with a fully worked example:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">#include &lt;arrayfire.h&gt;\r\n// 1. Add the af/opencl.h include to your project\r\n#include &lt;af/opencl.h&gt;\r\n \r\nint main() {\r\nsize_t length = 10;\r\n \r\n// Create ArrayFire array objects:\r\naf::array A = af::randu(length, f32);\r\naf::array B = af::constant(0, length, f32);\r\n \r\n// ... additional ArrayFire operations here\r\n \r\n// 2. Obtain the device, context, and queue used by ArrayFire\r\nstatic cl_context af_context = afcl::getContext();\r\nstatic cl_device_id af_device_id = afcl::getDeviceId();\r\nstatic cl_command_queue af_queue = afcl::getQueue();\r\n \r\n// 3. Obtain cl_mem references to af::array objects\r\ncl_mem * d_A = A.device&lt;cl_mem&gt;();\r\ncl_mem * d_B = B.device&lt;cl_mem&gt;();\r\n \r\n// 4. Load, build, and use your kernels.\r\n// For the sake of readability, we have omitted error checking.\r\nint status = CL_SUCCESS;\r\n \r\n// A simple copy kernel, uses C++11 syntax for multi-line strings.\r\nconst char * kernel_name = \"copy_kernel\";\r\nconst char * source = R\"(\r\nvoid __kernel\r\ncopy_kernel(__global float * gA, __global float * gB)\r\n{\r\nint id = get_global_id(0);\r\ngB[id] = gA[id];\r\n}\r\n)\";\r\n \r\n// Create the program, build the executable, and extract the entry point\r\n// for the kernel.\r\ncl_program program = clCreateProgramWithSource(af_context, 1, &amp;source, NULL, &amp;status);\r\nstatus = clBuildProgram(program, 1, &amp;af_device_id, NULL, NULL, NULL);\r\ncl_kernel kernel = clCreateKernel(program, kernel_name, &amp;status);\r\n \r\n// Set arguments and launch your kernels\r\nclSetKernelArg(kernel, 0, sizeof(cl_mem), d_A);\r\nclSetKernelArg(kernel, 1, sizeof(cl_mem), d_B);\r\nclEnqueueNDRangeKernel(af_queue, kernel, 1, NULL, &amp;length, NULL, 0, NULL, NULL);\r\n \r\n// 5. Return control of af::array memory to ArrayFire\r\nA.unlock();\r\nB.unlock();\r\n \r\n// ... resume ArrayFire operations\r\n \r\n// Because the device pointers, d_x and d_y, were returned to ArrayFire\'s\r\n// control by the unlock function, there is no need to free them using\r\n// clReleaseMemObject()\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\nIf your kernels needs to operate in their own OpenCL queue, the process is essentially identical, except you need to instruct ArrayFire to complete its computations using the af::sync() function prior to launching your own kernel and ensure your kernels are complete using <code>clFinish</code> (or similar) commands prior to returning control of the memory to ArrayFire:\r\n<ol type=\"1\">\r\n 	<li>Add an include for <code>af/opencl.h</code> to your project</li>\r\n 	<li>Obtain the OpenCL context, device, and queue used by ArrayFire</li>\r\n 	<li>Obtain cl_mem references to af::array objects</li>\r\n 	<li>Instruct ArrayFire to finish operations using af::sync()</li>\r\n 	<li>Load, build, and use your kernels</li>\r\n 	<li>Instruct OpenCL to finish operations using clFinish() or similar commands.</li>\r\n</ol>\r\n<ol type=\"1\">\r\n 	<li>Return control of af::array memory to ArrayFire</li>\r\n</ol>\r\n<h4>Adding ArrayFire to an existing OpenCL application</h4>\r\nAdding ArrayFire to an existing OpenCL application is slightly more involved and can be somewhat tricky due to several optimizations we implement. The most important are as follows:\r\n<ul>\r\n 	<li>ArrayFire assumes control of all memory provided to it.</li>\r\n 	<li>ArrayFire does not (in general) support in-place memory transactions.</li>\r\n</ul>\r\nWe will discuss the implications of these items below. To add ArrayFire to existing code you need to:\r\n<ol type=\"1\">\r\n 	<li>Add includes</li>\r\n 	<li>Instruct OpenCL to complete its operations using clFinish (or similar)</li>\r\n 	<li>Instruct ArrayFire to use the user-created OpenCL Context</li>\r\n 	<li>Create ArrayFire arrays from OpenCL memory objects</li>\r\n 	<li>Perform ArrayFire operations on the Arrays</li>\r\n 	<li>Instruct ArrayFire to finish operations using af::sync()</li>\r\n 	<li>Obtain cl_mem references for important memory</li>\r\n 	<li>Continue your OpenCL application</li>\r\n</ol>\r\nTo create the af::array objects, you should use one of the following constructors:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// 1D - 3D af::array constructors\r\nstatic af::array array (dim_t dim0, cl_mem buf, af::dtype type, bool retain=false)\r\nstatic af::array array (dim_t dim0, dim_t dim1, cl_mem buf, af::dtype type, bool retain=false)\r\nstatic af::array array (dim_t dim0, dim_t dim1, dim_t dim2, cl_mem buf, af::dtype type, bool retain=false)\r\nstatic af::array array (dim_t dim0, dim_t dim1, dim_t dim2, dim_t dim3, cl_mem buf, af::dtype type, bool retain=false)\r\n \r\n// af::array constructor using a dim4 object\r\nstatic af::array array (af::dim4 idims, cl_mem buf, af::dtype type, bool retain=false)</pre>\r\n</div>\r\n</div>\r\n<em>NOTE</em>: With all of these constructors, ArrayFire\'s memory manager automatically assumes responsibility for any memory provided to it. If you are creating an array from a <code>cl::Buffer</code>, you should specify <code>retain=true</code> to ensure your memory is not deallocated if your <code>cl::Buffer</code> were to go out of scope. We use this technique in the example below. If you do not wish for ArrayFire to manage your memory, you may call the <code>array::unlock()</code> function and manage the memory yourself; however, if you do so, please be cautious not to call <code>clReleaseMemObj</code> on a <code>cl_mem</code> when ArrayFire might be using it!\r\n\r\nThe eight steps above are best illustrated using a fully-worked example. Below we use the OpenCL 2.0 C++ API and omit error checking to keep the code readable.\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">#include &lt;CL/cl2.hpp&gt;\r\n \r\n// 1. Add arrayfire.h and af/opencl.h to your application\r\n#include \"arrayfire.h\"\r\n#include \"af/opencl.h\"\r\n \r\n#include &lt;cstdio&gt;\r\n#include &lt;vector&gt;\r\n \r\nint main() {\r\n \r\n// Set up the OpenCL context, device, and queues\r\ncl::Context context(CL_DEVICE_TYPE_ALL);\r\nvector&lt;cl::Device&gt; devices = context.getInfo&lt;CL_CONTEXT_DEVICES&gt;();\r\ncl::Device device = devices[0];\r\ncl::CommandQueue queue(context, device);\r\n \r\n// Create a buffer of size 10 filled with ones, copy it to the device\r\nint length = 10;\r\nvector&lt;float&gt; h_A(length, 1);\r\ncl::Buffer cl_A(context, CL_MEM_READ_WRITE, length * sizeof(float), h_A.data());\r\n \r\n// 2. Instruct OpenCL to complete its operations using clFinish (or similar)\r\nqueue.finish();\r\n \r\n// 3. Instruct ArrayFire to use the user-created context\r\n// First, create a device from the current OpenCL device + context + queue\r\nafcl::addDevice(device(), context(), queue());\r\n// Next switch ArrayFire to the device using the device and context as\r\n// identifiers:\r\nafcl::setDevice(device(), context());\r\n \r\n// 4. Create ArrayFire arrays from OpenCL memory objects\r\naf::array af_A = afcl::array(length, cl_A(), f32, true);\r\n \r\n// 5. Perform ArrayFire operations on the Arrays\r\naf_A = af_A + af::randu(length);\r\n \r\n// NOTE: ArrayFire does not perform the above transaction using in-place memory,\r\n// thus the underlying OpenCL buffers containing the memory containing memory to\r\n// probably have changed\r\n \r\n// 6. Instruct ArrayFire to finish operations using af::sync\r\naf::sync();\r\n \r\n// 7. Obtain cl_mem references for important memory\r\ncl_A = *af_A.device&lt;cl_mem&gt;();\r\n \r\n// 8. Continue your OpenCL application\r\n \r\n// ...\r\n \r\nreturn 0;\r\n}</pre>\r\n</div>\r\n</div>\r\n<h4>Using multiple devices</h4>\r\nIf you are using ArrayFire and OpenCL with multiple devices be sure to use <code>afcl::addDevice</code> to add your custom context + device + queue to ArrayFire\'s device manager. This will let you switch ArrayFire devices using your current<code>cl_device_id</code> and <code>cl_context</code>.','ArrayFire - OpenCL Interoperability','','inherit','closed','closed','','8874-revision-v1','','','2016-05-18 12:53:55','2016-05-18 16:53:55','',8874,'http://sandbox.arrayfire.com/8874-revision-v1/',0,'revision','',0),(8881,18528,'2016-05-18 15:52:41','2016-05-18 19:52:41','The ArrayFire library attempts to make high performance computing as easy as possible for scientists and engineers. Because many tasks need to be visualized, ArrayFire also provides a high-level interface to our <a href=\"https://github.com/arrayfire/forge\">Forge visualization library</a>. In today\'s \"<a href=\"http://arrayfire.org/http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" post we present an overview of ArrayFire\'s visualization functionality and demonstrate how to use Forge to display data contained in af::array objects.\n\n<!--more-->\n\nThe Forge library is a general-purpose visualization tool for data stored on the GPU or related accelerator devices. By default, ArrayFire ships with Forge built in. However; if you or your system administrator installed the \"no-graphics\" version of ArrayFire, Forge won\'t be included.\n\nArrayFire provides several wrapper functions that simplify Forge\'s interface when used with <a class=\"el\" title=\"A multi dimensional data container. \" href=\"classaf_1_1array.htm\">af::array</a> objects. These functions primarily perform interop tasks including visualization range setting, copying data into OpenGL data structures, and generating an OpenGL window for display.\n<h4><a id=\"setup\" class=\"anchor\"></a>Setup</h4>\nBefore we can use Forge, we must create an window containing an OpenGL context. Creating an instance of the<code><a class=\"el\" title=\"Window object to render af::arrays. \" href=\"classaf_1_1Window.htm\">af::Window</a></code> class will accomplish both of these tasks. Note, at present Forge must create and manage its own OpenGL context; however, we hope to change this in a future release. Once the window is created, you can use Forge\'s drawing functions to visualize your data. Here is a basic example of how to create a window, set its title, and enter into a drawing loop:\n<div class=\"fragment\">\n<div class=\"line\">\n<pre class=\"lang:default decode:true \">const static int width = 512, height = 512;\naf::Window window(width, height, \"2D plot example title\");\n \ndo{\n \n//drawing functions here\n \n} while( !window.close() );</pre>\n</div>\n</div>\n<h4><a id=\"render_func\" class=\"anchor\"></a>Rendering Functions</h4>\nAs included in ArrayFire 3.3, Forge provides the following plotting capabilities:\n<table class=\"doxtable\">\n<tbody>\n<tr>\n<th>Function</th>\n<th>Description</th>\n</tr>\n<tr>\n<td><a class=\"el\" title=\"Renders the input array as a histogram to the window. \" href=\"group__gfx__func__draw.htm#gafd7d94aa8f5fd37fee0662a4906a38d7\">af::Window::hist()</a></td>\n<td>Creates a histogram plot from input data and bins</td>\n</tr>\n<tr>\n<td><a class=\"el\" title=\"Renders the input array as an image to the window. \" href=\"group__gfx__func__draw.htm#gaed174450be6db4dfa5ef65b7baccbe57\">af::Window::image()</a></td>\n<td>Display an image</td>\n</tr>\n<tr>\n<td><a class=\"el\" title=\"Renders the input arrays as a 2D plot to the window. \" href=\"group__gfx__func__draw.htm#ga8e01736df3d805a5488c609e2573818b\">af::Window::plot()</a></td>\n<td>2D Line plot</td>\n</tr>\n<tr>\n<td><a class=\"el\" title=\"Renders the input array as an 3d line plot to the window. \" href=\"group__gfx__func__draw.htm#ga8e04ec129034e9fe769f3e6b14cd087f\">af::Window::plot3()</a></td>\n<td>3D line plot</td>\n</tr>\n<tr>\n<td><a class=\"el\" title=\"Renders the input arrays as a 2D scatter-plot to the window. \" href=\"group__gfx__func__draw.htm#ga73406db589e5090c051baae0af175df9\">af::Window::scatter()</a></td>\n<td>2D scatter plot</td>\n</tr>\n<tr>\n<td><a class=\"el\" title=\"Renders the input arrays as a 3D scatter-plot to the window. \" href=\"group__gfx__func__draw.htm#ga3bbfbe1b60741a259d2146b3ab50ace3\">af::Window::scatter3()</a></td>\n<td>3D scatter plot</td>\n</tr>\n<tr>\n<td><a class=\"el\" title=\"Renders the input arrays as a 3D surface plot to the window. \" href=\"group__gfx__func__draw.htm#ga1cdb8c3205d70d8feaddd8c30245393f\">af::Window::surface()</a></td>\n<td>Visualize a 3D surface</td>\n</tr>\n</tbody>\n</table>\nFull documentation on all plotting functions can be found in the <a class=\"el\" href=\"group__gfx__func__draw.htm\">rendering functions</a> portion of the documentation.\n<h5><a id=\"Image_38\"></a>Image</h5>\nThe af::Window::image() function can be used to plot grayscale or color images. To plot a grayscale image a 2d array should be passed into the function.\nLet’s see this on a static noise example:\n<pre><code class=\"language-{.cpp}\">array img = constant(0, width, height);   //make a black image\narray random = randu(width, height);      //make random [0,1] distribution\n\nwindow.image(img);</code></pre>\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/noise.png\"><img class=\"aligncenter size-medium wp-image-8710\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/noise-262x300.png\" alt=\"Forge image plot of noise\" width=\"262\" height=\"300\" /></a>\n\nTweaking the previous example by giving our image a depth of 3 for the RGB values allows us to generate colorful noise:\n<pre><code class=\"language-{.cpp}\">array img = 255 * randu(width, height, 3);      //make random [0, 255] distribution\nwindow.image( img.as(u8) );</code></pre>\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/color_noise.png\"><img class=\"aligncenter size-medium wp-image-8708\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/color_noise-262x300.png\" alt=\"Forge image plot of color noise\" width=\"262\" height=\"300\" /></a>\n\nNote that Forge automatically handles any af::array type passed from Arrayfire. In the first example we passed in an image of floats in the range [0, 1]. In the last example we cast our array to an unsigned byte array with the range\n[0, 255]. The type-handling properties are consistent for all Forge drawing functions.\n<h5><a id=\"Plot_63\"></a>Plot</h5>\nThe af::Window::plot() function visualizes an array as a 2d-line plot. Let’s see a simple example:\n<pre><code class=\"language-{.cpp}\">array X = seq(-af::Pi, af::Pi, 0.01);\narray Y = sin(X);\nwindow.plot(X, Y);</code></pre>\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_plot.png\"><img class=\"aligncenter size-medium wp-image-8714\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_plot-296x300.png\" alt=\"Forge 2d line plot of sin() function\" width=\"296\" height=\"300\" /></a>\nThe plot function has the signature:\n\n<code><strong>void plot( const array &amp;X, const array &amp;Y, const char * const title = NULL );</strong></code>\n\nBoth the x and y coordinates of the points are required to plot. This allows for non-uniform, or parametric plots:\n<pre><code class=\"language-{.cpp}\">array t = seq(0, 100, 0.01);\narray X = sin(t) * (exp(cos(t)) - 2 * cos(4 * t) - pow(sin(t / 12), 5));\narray Y = cos(t) * (exp(cos(t)) - 2 * cos(4 * t) - pow(sin(t / 12), 5));\nwindow.plot(X, Y);</code></pre>\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/butterfly_plot.png\"><img class=\"aligncenter size-medium wp-image-8707\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/butterfly_plot-290x300.png\" alt=\"\" width=\"290\" height=\"300\" /></a>\n<h5><a id=\"Scatter_88\"></a>Scatter</h5>\nThe af::Window::scatter() function visualizes an array as a 2d-scatter plot. Let’s see a example:\n<pre><code class=\"language-{.cpp}\">array X = seq(-af::Pi, af::Pi, 0.01);\narray noise = randn(X.dims(0)) /3.0f;\narray Y = sin(X) + noise;\nwindow.scatter(X, Y);</code></pre>\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_scatter.png\"><img class=\"aligncenter size-medium wp-image-8715\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_scatter-300x228.png\" alt=\"Forge 2d scatter plot\" width=\"300\" height=\"228\" /></a>\n\nThe scatter function has the signature:\n\n<code><strong>void scatter( const array &amp;X, const array &amp;Y, af::markerType marker=AF_MARKER_POINT, const char * const title = NULL);</strong></code>\n\nThe <strong>af::markerType</strong> enum determines which marker will be drawn at each point.\nIt can take on the values of:\n<pre><code class=\"language-{.cpp}\">enum af::markerType {\n    AF_MARKER_POINT\n    AF_MARKER_CIRCLE\n    AF_MARKER_SQUARE\n    AF_MARKER_TRIANGLE\n    AF_MARKER_CROSS\n    AF_MARKER_PLUS\n    AF_MARKER_STAR\n};</code></pre>\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\"><img class=\"aligncenter size-full wp-image-8709\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\" alt=\"Different types of markers in Forge.\" width=\"1846\" height=\"326\" /></a>\n<h3><a id=\"Plot3_118\"></a>Plot3</h3>\nThe af::Window::plot3() function will plot a curve in 3d-space.\nIts signature is:\n\n<code><strong>void plot3 (const array &amp;in, const char * title = NULL);</strong></code>\n\nThe input array expects xyz-triplets in sequential order. The points can be in a flattened one dimensional (<em>3n x 1</em>) array, or in one of the (<em>3 x n</em>), (<em>n x 3</em>) matrix forms.\n<pre><code class=\"language-{.cpp}\">array Z = seq(0.1f, 10.f, 0.01);\narray Y = sin(10 * Z) / Z;\narray X = cos(10 * Z) / Z;\n\narray Pts = join(1, X, Y, Z);\n//Pts can be passed in as a matrix in the from n x 3, 3 x n\n//or in the flattened xyz-triplet array with size 3n x 1\nwindow.plot3(Pts);\n//both of the following are equally valid\n//window.plot3(transpose(Pts));\n//window.plot3(flat(Pts));</code></pre>\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/spiral_plot3.png\"><img class=\"aligncenter size-medium wp-image-8716\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/spiral_plot3-300x211.png\" alt=\"Forge 3d line plot\" width=\"300\" height=\"211\" /></a>\n<h3><a id=\"Histogram_140\"></a>Histogram</h3>\nThe af::Window::hist() function renders an input array as a histogram. In our example, the input array will be created with Arrayfire’s histogram() function, which actually counts and bins each sample. The output from histogram() can directly be fed into the af::Window::hist() rendering function.\n<pre><code class=\"language-{.cpp}\">const int BINS = 128; SAMPLES = 9162;\narray norm = randn(SAMPLES);\narray hist_arr = histogram(norm, BINS);\n\nwin.hist(hist_arr, 0, BINS);</code></pre>\nIn addition to the histogram array with the number of samples in each bin, the af::Window::hist() function takes two additional parameters – the minimum and maximum values of all datapoints in the histogram array. This effectively sets the range of the binned data. The full signature of af::Window::hist() is:\n\n<code><strong>void hist(const array &amp; X, const double minval, const double maxval, const char * const title = NULL);</strong></code>\n\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_histogram.png\"><img class=\"aligncenter size-medium wp-image-8711\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_histogram-300x256.png\" alt=\"Forge histogram plot\" width=\"300\" height=\"256\" /></a>\n<h3><a id=\"Scatter3_162\"></a>Scatter3</h3>\nThe af::Window::scatter3() function visualizes an array as a 3d-scatter plot.\nIts signature is:\n\n<code><strong>void scatter3 (const array &amp;in, af::markerType marker=AF_MARKER_POINT, const char * title = NULL);</strong></code>\n\nThe input array expects xyz-triplets in sequential order. The points can be in a flattened one dimensional (<em>3n x 1</em>) array, or in one of the (<em>3 x n</em>), (<em>n x 3</em>) matrix forms.\n\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_scatter3.png\"><img class=\"aligncenter size-medium wp-image-8712\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_scatter3-300x208.png\" alt=\"Forge 3d scatter plot\" width=\"300\" height=\"208\" /></a>\n<pre><code class=\"language-{.cpp}\">array X = randn(300);\narray Y = randn(300);\narray Z = randn(300);\n\narray Pts = join(1, X, Y, Z);\nwindow.scatter3(Pts);</code></pre>\nThe <strong>af::markerType</strong> enum determines which marker will be drawn at each point. It can take on the values of:\n<pre><code class=\"language-{.cpp}\">enum af::markerType {\n    AF_MARKER_POINT\n    AF_MARKER_CIRCLE\n    AF_MARKER_SQUARE\n    AF_MARKER_TRIANGLE\n    AF_MARKER_CROSS\n    AF_MARKER_PLUS\n    AF_MARKER_STAR\n};</code></pre>\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\"><img class=\"aligncenter size-full wp-image-8709\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\" alt=\"Different types of markers in Forge.\" width=\"1846\" height=\"326\" /></a>\n<h3><a id=\"Surface_195\"></a>Surface</h3>\nThe af::Window::surface() function will plot af::arrays as a 3d surface.\n<pre><code class=\"language-{.cpp}\">array Z = randu(21, 21);\nwindow.surface(Z, \"Random Surface\");    //equal to next function call\n//window.surface( seq(-1, 1, 0.1), seq(-1, 1, 0.1), Z, \"Random Surface\");</code></pre>\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/rand_surface.png\"><img class=\"aligncenter size-medium wp-image-8713\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/rand_surface-300x269.png\" alt=\"Forge 3d surface() plot\" width=\"300\" height=\"269\" /></a>\nThere are two overloads for the af::Window::surface() function:\n\n<code><strong>void surface (const array &amp; S, const char * const title )</strong>\n// Accepts a 2d matrix with the z values of the surface</code>\n\n<code><strong>void surface (const array &amp;xVals, const array &amp;yVals, const array &amp;S, const char * const title)</strong>\n// accepts additional vectors that define the x,y coordinates for the surface points.</code>\n\nThe second overload has two options for the x, y coordinate vectors. Assuming a surface grid of size <strong>m x n</strong>:\n<ol>\n 	<li>Short vectors defining the spacing along each axis. Vectors will have sizes <strong>m x 1</strong> and <strong>n x 1</strong>.</li>\n 	<li>Vectors containing the coordinates of each and every point. Each of the vectors will have length <strong>mn x 1</strong>. This can be used for completely non-uniform or parametric surfaces.</li>\n</ol>\n<h2><a id=\"Conclusion_216\"></a>Conclusion</h2>\nThere is a fairly comprehensive collection of methods to visualize data in Arrayfire. Thanks to the high-performance gpu plotting library Forge, the provided Arrayfire functions not only make visualizations as simple as possible, but keep them as robust as the rest of the Arrayfire library.','Visualizing af::array with Forge','','inherit','closed','closed','','8698-autosave-v1','','','2016-05-18 15:52:41','2016-05-18 19:52:41','',8698,'http://sandbox.arrayfire.com/8698-autosave-v1/',0,'revision','',0),(8882,18528,'2016-05-18 15:42:12','2016-05-18 19:42:12','Whereas the ArrayFire library aims to provide a robust and easy to use platform for high-performance, parallel and GPU computing, ArrayFire\'s <a href=\"https://github.com/arrayfire/forge\">Forge</a> library attempts to provide an equally powerful and performant methods to visualize data stored on accelerators (most often GPUs) using an OpenGL context. By default, ArrayFire ships with the Forge visualization library built in . Unless you or your system administrator have installed the \"no-graphics\" version, ArrayFire already includes everything you need to use Forge.\r\n\r\nArrayFire provides several wrapper functions that simplify Forge\'s interface when used with <a class=\"el\" title=\"A multi dimensional data container. \" href=\"classaf_1_1array.htm\">af::array</a> objects. These functions primarily perform interop tasks including visualization range setting, copying data into OpenGL data structures, and generating an OpenGL window for display.\r\n<h1><a id=\"setup\" class=\"anchor\"></a>Setup</h1>\r\nBefore we can use Forge, we must create an window containing an OpenGL context. Creating an instance of the<code><a class=\"el\" title=\"Window object to render af::arrays. \" href=\"classaf_1_1Window.htm\">af::Window</a></code> class will accomplish both of these tasks. Note, at present Forge must create and manage its own OpenGL context; however, we hope to change this in a future release. Once the window is created, you can use Forge\'s drawing functions to visualize your data. Here is a basic example of how to create a window, set its title, and enter into a drawing loop:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">const static int width = 512, height = 512;\r\naf::Window window(width, height, \"2D plot example title\");\r\n \r\ndo{\r\n \r\n//drawing functions here\r\n \r\n} while( !window.close() );</pre>\r\n</div>\r\n</div>\r\n<h1><a id=\"render_func\" class=\"anchor\"></a>Rendering Functions</h1>\r\nAs included in ArrayFire 3.3, Forge provides the following plotting capabilities:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Description</th>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input array as a histogram to the window. \" href=\"group__gfx__func__draw.htm#gafd7d94aa8f5fd37fee0662a4906a38d7\">af::Window::hist()</a></td>\r\n<td>Creates a histogram plot from input data and bins</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input array as an image to the window. \" href=\"group__gfx__func__draw.htm#gaed174450be6db4dfa5ef65b7baccbe57\">af::Window::image()</a></td>\r\n<td>Display an image</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input arrays as a 2D plot to the window. \" href=\"group__gfx__func__draw.htm#ga8e01736df3d805a5488c609e2573818b\">af::Window::plot()</a></td>\r\n<td>2D Line plot</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input array as an 3d line plot to the window. \" href=\"group__gfx__func__draw.htm#ga8e04ec129034e9fe769f3e6b14cd087f\">af::Window::plot3()</a></td>\r\n<td>3D line plot</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input arrays as a 2D scatter-plot to the window. \" href=\"group__gfx__func__draw.htm#ga73406db589e5090c051baae0af175df9\">af::Window::scatter()</a></td>\r\n<td>2D scatter plot</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input arrays as a 3D scatter-plot to the window. \" href=\"group__gfx__func__draw.htm#ga3bbfbe1b60741a259d2146b3ab50ace3\">af::Window::scatter3()</a></td>\r\n<td>3D scatter plot</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input arrays as a 3D surface plot to the window. \" href=\"group__gfx__func__draw.htm#ga1cdb8c3205d70d8feaddd8c30245393f\">af::Window::surface()</a></td>\r\n<td>Visualize a 3D surface</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nFull documentation on all plotting functions can be found in the <a class=\"el\" href=\"group__gfx__func__draw.htm\">rendering functions</a> portion of the documentation.\r\n<h3><a id=\"Image_38\"></a>Image</h3>\r\nThe af::Window::image() function can be used to plot grayscale or color images. To plot a grayscale image a 2d array should be passed into the function.\r\nLet’s see this on a static noise example:\r\n<pre><code class=\"language-{.cpp}\">array img = constant(0, width, height);   //make a black image\r\narray random = randu(width, height);      //make random [0,1] distribution\r\n\r\nwindow.image(img);</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/noise.png\"><img class=\"aligncenter size-medium wp-image-8710\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/noise-262x300.png\" alt=\"Forge image plot of noise\" width=\"262\" height=\"300\" /></a>\r\n\r\nTweaking the previous example by giving our image a depth of 3 for the RGB values allows us to generate colorful noise:\r\n<pre><code class=\"language-{.cpp}\">array img = 255 * randu(width, height, 3);      //make random [0, 255] distribution\r\nwindow.image( img.as(u8) );</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/color_noise.png\"><img class=\"aligncenter size-medium wp-image-8708\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/color_noise-262x300.png\" alt=\"Forge image plot of color noise\" width=\"262\" height=\"300\" /></a>\r\n\r\nNote that Forge automatically handles any af::array type passed from Arrayfire. In the first example we passed in an image of floats in the range [0, 1]. In the last example we cast our array to an unsigned byte array with the range\r\n[0, 255]. The type-handling properties are consistent for all Forge drawing functions.\r\n<h3><a id=\"Plot_63\"></a>Plot</h3>\r\nThe af::Window::plot() function visualizes an array as a 2d-line plot. Let’s see a simple example:\r\n<pre><code class=\"language-{.cpp}\">array X = seq(-af::Pi, af::Pi, 0.01);\r\narray Y = sin(X);\r\nwindow.plot(X, Y);</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_plot.png\"><img class=\"aligncenter size-medium wp-image-8714\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_plot-296x300.png\" alt=\"Forge 2d line plot of sin() function\" width=\"296\" height=\"300\" /></a>\r\nThe plot function has the signature:\r\n\r\n<code><strong>void plot( const array &amp;X, const array &amp;Y, const char * const title = NULL );</strong></code>\r\n\r\nBoth the x and y coordinates of the points are required to plot. This allows for non-uniform, or parametric plots:\r\n<pre><code class=\"language-{.cpp}\">array t = seq(0, 100, 0.01);\r\narray X = sin(t) * (exp(cos(t)) - 2 * cos(4 * t) - pow(sin(t / 12), 5));\r\narray Y = cos(t) * (exp(cos(t)) - 2 * cos(4 * t) - pow(sin(t / 12), 5));\r\nwindow.plot(X, Y);</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/butterfly_plot.png\"><img class=\"aligncenter size-medium wp-image-8707\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/butterfly_plot-290x300.png\" alt=\"\" width=\"290\" height=\"300\" /></a>\r\n<h3><a id=\"Scatter_88\"></a>Scatter</h3>\r\nThe af::Window::scatter() function visualizes an array as a 2d-scatter plot. Let’s see a example:\r\n<pre><code class=\"language-{.cpp}\">array X = seq(-af::Pi, af::Pi, 0.01);\r\narray noise = randn(X.dims(0)) /3.0f;\r\narray Y = sin(X) + noise;\r\nwindow.scatter(X, Y);</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_scatter.png\"><img class=\"aligncenter size-medium wp-image-8715\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_scatter-300x228.png\" alt=\"Forge 2d scatter plot\" width=\"300\" height=\"228\" /></a>\r\n\r\nThe scatter function has the signature:\r\n\r\n<code><strong>void scatter( const array &amp;X, const array &amp;Y, af::markerType marker=AF_MARKER_POINT, const char * const title = NULL);</strong></code>\r\n\r\nThe <strong>af::markerType</strong> enum determines which marker will be drawn at each point.\r\nIt can take on the values of:\r\n<pre><code class=\"language-{.cpp}\">enum af::markerType {\r\n    AF_MARKER_POINT\r\n    AF_MARKER_CIRCLE\r\n    AF_MARKER_SQUARE\r\n    AF_MARKER_TRIANGLE\r\n    AF_MARKER_CROSS\r\n    AF_MARKER_PLUS\r\n    AF_MARKER_STAR\r\n};</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\"><img class=\"aligncenter size-full wp-image-8709\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\" alt=\"Different types of markers in Forge.\" width=\"1846\" height=\"326\" /></a>\r\n<h3><a id=\"Plot3_118\"></a>Plot3</h3>\r\nThe af::Window::plot3() function will plot a curve in 3d-space.\r\nIts signature is:\r\n\r\n<code><strong>void plot3 (const array &amp;in, const char * title = NULL);</strong></code>\r\n\r\nThe input array expects xyz-triplets in sequential order. The points can be in a flattened one dimensional (<em>3n x 1</em>) array, or in one of the (<em>3 x n</em>), (<em>n x 3</em>) matrix forms.\r\n<pre><code class=\"language-{.cpp}\">array Z = seq(0.1f, 10.f, 0.01);\r\narray Y = sin(10 * Z) / Z;\r\narray X = cos(10 * Z) / Z;\r\n\r\narray Pts = join(1, X, Y, Z);\r\n//Pts can be passed in as a matrix in the from n x 3, 3 x n\r\n//or in the flattened xyz-triplet array with size 3n x 1\r\nwindow.plot3(Pts);\r\n//both of the following are equally valid\r\n//window.plot3(transpose(Pts));\r\n//window.plot3(flat(Pts));</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/spiral_plot3.png\"><img class=\"aligncenter size-medium wp-image-8716\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/spiral_plot3-300x211.png\" alt=\"Forge 3d line plot\" width=\"300\" height=\"211\" /></a>\r\n<h3><a id=\"Histogram_140\"></a>Histogram</h3>\r\nThe af::Window::hist() function renders an input array as a histogram. In our example, the input array will be created with Arrayfire’s histogram() function, which actually counts and bins each sample. The output from histogram() can directly be fed into the af::Window::hist() rendering function.\r\n<pre><code class=\"language-{.cpp}\">const int BINS = 128; SAMPLES = 9162;\r\narray norm = randn(SAMPLES);\r\narray hist_arr = histogram(norm, BINS);\r\n\r\nwin.hist(hist_arr, 0, BINS);</code></pre>\r\nIn addition to the histogram array with the number of samples in each bin, the af::Window::hist() function takes two additional parameters – the minimum and maximum values of all datapoints in the histogram array. This effectively sets the range of the binned data. The full signature of af::Window::hist() is:\r\n\r\n<code><strong>void hist(const array &amp; X, const double minval, const double maxval, const char * const title = NULL);</strong></code>\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_histogram.png\"><img class=\"aligncenter size-medium wp-image-8711\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_histogram-300x256.png\" alt=\"Forge histogram plot\" width=\"300\" height=\"256\" /></a>\r\n<h3><a id=\"Scatter3_162\"></a>Scatter3</h3>\r\nThe af::Window::scatter3() function visualizes an array as a 3d-scatter plot.\r\nIts signature is:\r\n\r\n<code><strong>void scatter3 (const array &amp;in, af::markerType marker=AF_MARKER_POINT, const char * title = NULL);</strong></code>\r\n\r\nThe input array expects xyz-triplets in sequential order. The points can be in a flattened one dimensional (<em>3n x 1</em>) array, or in one of the (<em>3 x n</em>), (<em>n x 3</em>) matrix forms.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_scatter3.png\"><img class=\"aligncenter size-medium wp-image-8712\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_scatter3-300x208.png\" alt=\"Forge 3d scatter plot\" width=\"300\" height=\"208\" /></a>\r\n<pre><code class=\"language-{.cpp}\">array X = randn(300);\r\narray Y = randn(300);\r\narray Z = randn(300);\r\n\r\narray Pts = join(1, X, Y, Z);\r\nwindow.scatter3(Pts);</code></pre>\r\nThe <strong>af::markerType</strong> enum determines which marker will be drawn at each point. It can take on the values of:\r\n<pre><code class=\"language-{.cpp}\">enum af::markerType {\r\n    AF_MARKER_POINT\r\n    AF_MARKER_CIRCLE\r\n    AF_MARKER_SQUARE\r\n    AF_MARKER_TRIANGLE\r\n    AF_MARKER_CROSS\r\n    AF_MARKER_PLUS\r\n    AF_MARKER_STAR\r\n};</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\"><img class=\"aligncenter size-full wp-image-8709\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\" alt=\"Different types of markers in Forge.\" width=\"1846\" height=\"326\" /></a>\r\n<h3><a id=\"Surface_195\"></a>Surface</h3>\r\nThe af::Window::surface() function will plot af::arrays as a 3d surface.\r\n<pre><code class=\"language-{.cpp}\">array Z = randu(21, 21);\r\nwindow.surface(Z, \"Random Surface\");    //equal to next function call\r\n//window.surface( seq(-1, 1, 0.1), seq(-1, 1, 0.1), Z, \"Random Surface\");</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/rand_surface.png\"><img class=\"aligncenter size-medium wp-image-8713\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/rand_surface-300x269.png\" alt=\"Forge 3d surface() plot\" width=\"300\" height=\"269\" /></a>\r\nThere are two overloads for the af::Window::surface() function:\r\n\r\n<code><strong>void surface (const array &amp; S, const char * const title )</strong>\r\n// Accepts a 2d matrix with the z values of the surface</code>\r\n\r\n<code><strong>void surface (const array &amp;xVals, const array &amp;yVals, const array &amp;S, const char * const title)</strong>\r\n// accepts additional vectors that define the x,y coordinates for the surface points.</code>\r\n\r\nThe second overload has two options for the x, y coordinate vectors. Assuming a surface grid of size <strong>m x n</strong>:\r\n<ol>\r\n 	<li>Short vectors defining the spacing along each axis. Vectors will have sizes <strong>m x 1</strong> and <strong>n x 1</strong>.</li>\r\n 	<li>Vectors containing the coordinates of each and every point. Each of the vectors will have length <strong>mn x 1</strong>. This can be used for completely non-uniform or parametric surfaces.</li>\r\n</ol>\r\n<h2><a id=\"Conclusion_216\"></a>Conclusion</h2>\r\nThere is a fairly comprehensive collection of methods to visualize data in Arrayfire. Thanks to the high-performance gpu plotting library Forge, the provided Arrayfire functions not only make visualizations as simple as possible, but keep them as robust as the rest of the Arrayfire library.','Visualizing af::array with Forge','','inherit','closed','closed','','8698-revision-v1','','','2016-05-18 15:42:12','2016-05-18 19:42:12','',8698,'http://sandbox.arrayfire.com/8698-revision-v1/',0,'revision','',0),(8883,18528,'2016-05-18 15:51:01','2016-05-18 19:51:01','The ArrayFire library attempts to make high performance computing as easy as possible for scientists and engineers. Because many tasks need to be visualized, ArrayFire also provides a high-level interface to our <a href=\"https://github.com/arrayfire/forge\">Forge visualization library</a>. In today\'s \"<a href=\"http://arrayfire.org/http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" post we present an overview of ArrayFire\'s visualization functionality and demonstrate how to use Forge to display data contained in af::array objects.\r\n\r\n<!--more-->\r\n\r\nThe Forge library is a general-purpose visualization tool for data stored on the GPU or related accelerator devices. By default, ArrayFire ships with Forge built in. However; if you or your system administrator installed the \"no-graphics\" version of ArrayFire, Forge won\'t be included.\r\n\r\nArrayFire provides several wrapper functions that simplify Forge\'s interface when used with <a class=\"el\" title=\"A multi dimensional data container. \" href=\"classaf_1_1array.htm\">af::array</a> objects. These functions primarily perform interop tasks including visualization range setting, copying data into OpenGL data structures, and generating an OpenGL window for display.\r\n<h1><a id=\"setup\" class=\"anchor\"></a>Setup</h1>\r\nBefore we can use Forge, we must create an window containing an OpenGL context. Creating an instance of the<code><a class=\"el\" title=\"Window object to render af::arrays. \" href=\"classaf_1_1Window.htm\">af::Window</a></code> class will accomplish both of these tasks. Note, at present Forge must create and manage its own OpenGL context; however, we hope to change this in a future release. Once the window is created, you can use Forge\'s drawing functions to visualize your data. Here is a basic example of how to create a window, set its title, and enter into a drawing loop:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">const static int width = 512, height = 512;\r\naf::Window window(width, height, \"2D plot example title\");\r\n \r\ndo{\r\n \r\n//drawing functions here\r\n \r\n} while( !window.close() );</pre>\r\n</div>\r\n</div>\r\n<h1><a id=\"render_func\" class=\"anchor\"></a>Rendering Functions</h1>\r\nAs included in ArrayFire 3.3, Forge provides the following plotting capabilities:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Description</th>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input array as a histogram to the window. \" href=\"group__gfx__func__draw.htm#gafd7d94aa8f5fd37fee0662a4906a38d7\">af::Window::hist()</a></td>\r\n<td>Creates a histogram plot from input data and bins</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input array as an image to the window. \" href=\"group__gfx__func__draw.htm#gaed174450be6db4dfa5ef65b7baccbe57\">af::Window::image()</a></td>\r\n<td>Display an image</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input arrays as a 2D plot to the window. \" href=\"group__gfx__func__draw.htm#ga8e01736df3d805a5488c609e2573818b\">af::Window::plot()</a></td>\r\n<td>2D Line plot</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input array as an 3d line plot to the window. \" href=\"group__gfx__func__draw.htm#ga8e04ec129034e9fe769f3e6b14cd087f\">af::Window::plot3()</a></td>\r\n<td>3D line plot</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input arrays as a 2D scatter-plot to the window. \" href=\"group__gfx__func__draw.htm#ga73406db589e5090c051baae0af175df9\">af::Window::scatter()</a></td>\r\n<td>2D scatter plot</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input arrays as a 3D scatter-plot to the window. \" href=\"group__gfx__func__draw.htm#ga3bbfbe1b60741a259d2146b3ab50ace3\">af::Window::scatter3()</a></td>\r\n<td>3D scatter plot</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input arrays as a 3D surface plot to the window. \" href=\"group__gfx__func__draw.htm#ga1cdb8c3205d70d8feaddd8c30245393f\">af::Window::surface()</a></td>\r\n<td>Visualize a 3D surface</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nFull documentation on all plotting functions can be found in the <a class=\"el\" href=\"group__gfx__func__draw.htm\">rendering functions</a> portion of the documentation.\r\n<h3><a id=\"Image_38\"></a>Image</h3>\r\nThe af::Window::image() function can be used to plot grayscale or color images. To plot a grayscale image a 2d array should be passed into the function.\r\nLet’s see this on a static noise example:\r\n<pre><code class=\"language-{.cpp}\">array img = constant(0, width, height);   //make a black image\r\narray random = randu(width, height);      //make random [0,1] distribution\r\n\r\nwindow.image(img);</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/noise.png\"><img class=\"aligncenter size-medium wp-image-8710\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/noise-262x300.png\" alt=\"Forge image plot of noise\" width=\"262\" height=\"300\" /></a>\r\n\r\nTweaking the previous example by giving our image a depth of 3 for the RGB values allows us to generate colorful noise:\r\n<pre><code class=\"language-{.cpp}\">array img = 255 * randu(width, height, 3);      //make random [0, 255] distribution\r\nwindow.image( img.as(u8) );</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/color_noise.png\"><img class=\"aligncenter size-medium wp-image-8708\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/color_noise-262x300.png\" alt=\"Forge image plot of color noise\" width=\"262\" height=\"300\" /></a>\r\n\r\nNote that Forge automatically handles any af::array type passed from Arrayfire. In the first example we passed in an image of floats in the range [0, 1]. In the last example we cast our array to an unsigned byte array with the range\r\n[0, 255]. The type-handling properties are consistent for all Forge drawing functions.\r\n<h3><a id=\"Plot_63\"></a>Plot</h3>\r\nThe af::Window::plot() function visualizes an array as a 2d-line plot. Let’s see a simple example:\r\n<pre><code class=\"language-{.cpp}\">array X = seq(-af::Pi, af::Pi, 0.01);\r\narray Y = sin(X);\r\nwindow.plot(X, Y);</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_plot.png\"><img class=\"aligncenter size-medium wp-image-8714\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_plot-296x300.png\" alt=\"Forge 2d line plot of sin() function\" width=\"296\" height=\"300\" /></a>\r\nThe plot function has the signature:\r\n\r\n<code><strong>void plot( const array &amp;X, const array &amp;Y, const char * const title = NULL );</strong></code>\r\n\r\nBoth the x and y coordinates of the points are required to plot. This allows for non-uniform, or parametric plots:\r\n<pre><code class=\"language-{.cpp}\">array t = seq(0, 100, 0.01);\r\narray X = sin(t) * (exp(cos(t)) - 2 * cos(4 * t) - pow(sin(t / 12), 5));\r\narray Y = cos(t) * (exp(cos(t)) - 2 * cos(4 * t) - pow(sin(t / 12), 5));\r\nwindow.plot(X, Y);</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/butterfly_plot.png\"><img class=\"aligncenter size-medium wp-image-8707\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/butterfly_plot-290x300.png\" alt=\"\" width=\"290\" height=\"300\" /></a>\r\n<h3><a id=\"Scatter_88\"></a>Scatter</h3>\r\nThe af::Window::scatter() function visualizes an array as a 2d-scatter plot. Let’s see a example:\r\n<pre><code class=\"language-{.cpp}\">array X = seq(-af::Pi, af::Pi, 0.01);\r\narray noise = randn(X.dims(0)) /3.0f;\r\narray Y = sin(X) + noise;\r\nwindow.scatter(X, Y);</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_scatter.png\"><img class=\"aligncenter size-medium wp-image-8715\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_scatter-300x228.png\" alt=\"Forge 2d scatter plot\" width=\"300\" height=\"228\" /></a>\r\n\r\nThe scatter function has the signature:\r\n\r\n<code><strong>void scatter( const array &amp;X, const array &amp;Y, af::markerType marker=AF_MARKER_POINT, const char * const title = NULL);</strong></code>\r\n\r\nThe <strong>af::markerType</strong> enum determines which marker will be drawn at each point.\r\nIt can take on the values of:\r\n<pre><code class=\"language-{.cpp}\">enum af::markerType {\r\n    AF_MARKER_POINT\r\n    AF_MARKER_CIRCLE\r\n    AF_MARKER_SQUARE\r\n    AF_MARKER_TRIANGLE\r\n    AF_MARKER_CROSS\r\n    AF_MARKER_PLUS\r\n    AF_MARKER_STAR\r\n};</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\"><img class=\"aligncenter size-full wp-image-8709\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\" alt=\"Different types of markers in Forge.\" width=\"1846\" height=\"326\" /></a>\r\n<h3><a id=\"Plot3_118\"></a>Plot3</h3>\r\nThe af::Window::plot3() function will plot a curve in 3d-space.\r\nIts signature is:\r\n\r\n<code><strong>void plot3 (const array &amp;in, const char * title = NULL);</strong></code>\r\n\r\nThe input array expects xyz-triplets in sequential order. The points can be in a flattened one dimensional (<em>3n x 1</em>) array, or in one of the (<em>3 x n</em>), (<em>n x 3</em>) matrix forms.\r\n<pre><code class=\"language-{.cpp}\">array Z = seq(0.1f, 10.f, 0.01);\r\narray Y = sin(10 * Z) / Z;\r\narray X = cos(10 * Z) / Z;\r\n\r\narray Pts = join(1, X, Y, Z);\r\n//Pts can be passed in as a matrix in the from n x 3, 3 x n\r\n//or in the flattened xyz-triplet array with size 3n x 1\r\nwindow.plot3(Pts);\r\n//both of the following are equally valid\r\n//window.plot3(transpose(Pts));\r\n//window.plot3(flat(Pts));</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/spiral_plot3.png\"><img class=\"aligncenter size-medium wp-image-8716\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/spiral_plot3-300x211.png\" alt=\"Forge 3d line plot\" width=\"300\" height=\"211\" /></a>\r\n<h3><a id=\"Histogram_140\"></a>Histogram</h3>\r\nThe af::Window::hist() function renders an input array as a histogram. In our example, the input array will be created with Arrayfire’s histogram() function, which actually counts and bins each sample. The output from histogram() can directly be fed into the af::Window::hist() rendering function.\r\n<pre><code class=\"language-{.cpp}\">const int BINS = 128; SAMPLES = 9162;\r\narray norm = randn(SAMPLES);\r\narray hist_arr = histogram(norm, BINS);\r\n\r\nwin.hist(hist_arr, 0, BINS);</code></pre>\r\nIn addition to the histogram array with the number of samples in each bin, the af::Window::hist() function takes two additional parameters – the minimum and maximum values of all datapoints in the histogram array. This effectively sets the range of the binned data. The full signature of af::Window::hist() is:\r\n\r\n<code><strong>void hist(const array &amp; X, const double minval, const double maxval, const char * const title = NULL);</strong></code>\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_histogram.png\"><img class=\"aligncenter size-medium wp-image-8711\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_histogram-300x256.png\" alt=\"Forge histogram plot\" width=\"300\" height=\"256\" /></a>\r\n<h3><a id=\"Scatter3_162\"></a>Scatter3</h3>\r\nThe af::Window::scatter3() function visualizes an array as a 3d-scatter plot.\r\nIts signature is:\r\n\r\n<code><strong>void scatter3 (const array &amp;in, af::markerType marker=AF_MARKER_POINT, const char * title = NULL);</strong></code>\r\n\r\nThe input array expects xyz-triplets in sequential order. The points can be in a flattened one dimensional (<em>3n x 1</em>) array, or in one of the (<em>3 x n</em>), (<em>n x 3</em>) matrix forms.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_scatter3.png\"><img class=\"aligncenter size-medium wp-image-8712\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_scatter3-300x208.png\" alt=\"Forge 3d scatter plot\" width=\"300\" height=\"208\" /></a>\r\n<pre><code class=\"language-{.cpp}\">array X = randn(300);\r\narray Y = randn(300);\r\narray Z = randn(300);\r\n\r\narray Pts = join(1, X, Y, Z);\r\nwindow.scatter3(Pts);</code></pre>\r\nThe <strong>af::markerType</strong> enum determines which marker will be drawn at each point. It can take on the values of:\r\n<pre><code class=\"language-{.cpp}\">enum af::markerType {\r\n    AF_MARKER_POINT\r\n    AF_MARKER_CIRCLE\r\n    AF_MARKER_SQUARE\r\n    AF_MARKER_TRIANGLE\r\n    AF_MARKER_CROSS\r\n    AF_MARKER_PLUS\r\n    AF_MARKER_STAR\r\n};</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\"><img class=\"aligncenter size-full wp-image-8709\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\" alt=\"Different types of markers in Forge.\" width=\"1846\" height=\"326\" /></a>\r\n<h3><a id=\"Surface_195\"></a>Surface</h3>\r\nThe af::Window::surface() function will plot af::arrays as a 3d surface.\r\n<pre><code class=\"language-{.cpp}\">array Z = randu(21, 21);\r\nwindow.surface(Z, \"Random Surface\");    //equal to next function call\r\n//window.surface( seq(-1, 1, 0.1), seq(-1, 1, 0.1), Z, \"Random Surface\");</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/rand_surface.png\"><img class=\"aligncenter size-medium wp-image-8713\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/rand_surface-300x269.png\" alt=\"Forge 3d surface() plot\" width=\"300\" height=\"269\" /></a>\r\nThere are two overloads for the af::Window::surface() function:\r\n\r\n<code><strong>void surface (const array &amp; S, const char * const title )</strong>\r\n// Accepts a 2d matrix with the z values of the surface</code>\r\n\r\n<code><strong>void surface (const array &amp;xVals, const array &amp;yVals, const array &amp;S, const char * const title)</strong>\r\n// accepts additional vectors that define the x,y coordinates for the surface points.</code>\r\n\r\nThe second overload has two options for the x, y coordinate vectors. Assuming a surface grid of size <strong>m x n</strong>:\r\n<ol>\r\n 	<li>Short vectors defining the spacing along each axis. Vectors will have sizes <strong>m x 1</strong> and <strong>n x 1</strong>.</li>\r\n 	<li>Vectors containing the coordinates of each and every point. Each of the vectors will have length <strong>mn x 1</strong>. This can be used for completely non-uniform or parametric surfaces.</li>\r\n</ol>\r\n<h2><a id=\"Conclusion_216\"></a>Conclusion</h2>\r\nThere is a fairly comprehensive collection of methods to visualize data in Arrayfire. Thanks to the high-performance gpu plotting library Forge, the provided Arrayfire functions not only make visualizations as simple as possible, but keep them as robust as the rest of the Arrayfire library.','Visualizing af::array with Forge','','inherit','closed','closed','','8698-revision-v1','','','2016-05-18 15:51:01','2016-05-18 19:51:01','',8698,'http://sandbox.arrayfire.com/8698-revision-v1/',0,'revision','',0),(8884,18528,'2016-05-18 15:53:02','2016-05-18 19:53:02','The ArrayFire library attempts to make high performance computing as easy as possible for scientists and engineers. Because many tasks need to be visualized, ArrayFire also provides a high-level interface to our <a href=\"https://github.com/arrayfire/forge\">Forge visualization library</a>. In today\'s \"<a href=\"http://arrayfire.org/http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" post we present an overview of ArrayFire\'s visualization functionality and demonstrate how to use Forge to display data contained in af::array objects.\r\n\r\n<!--more-->\r\n\r\nThe Forge library is a general-purpose visualization tool for data stored on the GPU or related accelerator devices. By default, ArrayFire ships with Forge built in. However; if you or your system administrator installed the \"no-graphics\" version of ArrayFire, Forge won\'t be included.\r\n\r\nArrayFire provides several wrapper functions that simplify Forge\'s interface when used with <a class=\"el\" title=\"A multi dimensional data container. \" href=\"classaf_1_1array.htm\">af::array</a> objects. These functions primarily perform interop tasks including visualization range setting, copying data into OpenGL data structures, and generating an OpenGL window for display.\r\n<h4><a id=\"setup\" class=\"anchor\"></a>Setup</h4>\r\nBefore we can use Forge, we must create an window containing an OpenGL context. Creating an instance of the<code><a class=\"el\" title=\"Window object to render af::arrays. \" href=\"classaf_1_1Window.htm\">af::Window</a></code> class will accomplish both of these tasks. Note, at present Forge must create and manage its own OpenGL context; however, we hope to change this in a future release. Once the window is created, you can use Forge\'s drawing functions to visualize your data. Here is a basic example of how to create a window, set its title, and enter into a drawing loop:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">const static int width = 512, height = 512;\r\naf::Window window(width, height, \"2D plot example title\");\r\n \r\ndo{\r\n \r\n//drawing functions here\r\n \r\n} while( !window.close() );</pre>\r\n</div>\r\n</div>\r\n<h4><a id=\"render_func\" class=\"anchor\"></a>Rendering Functions</h4>\r\nAs included in ArrayFire 3.3, Forge provides the following plotting capabilities:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Description</th>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input array as a histogram to the window. \" href=\"group__gfx__func__draw.htm#gafd7d94aa8f5fd37fee0662a4906a38d7\">af::Window::hist()</a></td>\r\n<td>Creates a histogram plot from input data and bins</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input array as an image to the window. \" href=\"group__gfx__func__draw.htm#gaed174450be6db4dfa5ef65b7baccbe57\">af::Window::image()</a></td>\r\n<td>Display an image</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input arrays as a 2D plot to the window. \" href=\"group__gfx__func__draw.htm#ga8e01736df3d805a5488c609e2573818b\">af::Window::plot()</a></td>\r\n<td>2D Line plot</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input array as an 3d line plot to the window. \" href=\"group__gfx__func__draw.htm#ga8e04ec129034e9fe769f3e6b14cd087f\">af::Window::plot3()</a></td>\r\n<td>3D line plot</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input arrays as a 2D scatter-plot to the window. \" href=\"group__gfx__func__draw.htm#ga73406db589e5090c051baae0af175df9\">af::Window::scatter()</a></td>\r\n<td>2D scatter plot</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input arrays as a 3D scatter-plot to the window. \" href=\"group__gfx__func__draw.htm#ga3bbfbe1b60741a259d2146b3ab50ace3\">af::Window::scatter3()</a></td>\r\n<td>3D scatter plot</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input arrays as a 3D surface plot to the window. \" href=\"group__gfx__func__draw.htm#ga1cdb8c3205d70d8feaddd8c30245393f\">af::Window::surface()</a></td>\r\n<td>Visualize a 3D surface</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nFull documentation on all plotting functions can be found in the <a class=\"el\" href=\"group__gfx__func__draw.htm\">rendering functions</a> portion of the documentation.\r\n<h5><a id=\"Image_38\"></a>Image</h5>\r\nThe af::Window::image() function can be used to plot grayscale or color images. To plot a grayscale image a 2d array should be passed into the function.\r\nLet’s see this on a static noise example:\r\n<pre><code class=\"language-{.cpp}\">array img = constant(0, width, height);   //make a black image\r\narray random = randu(width, height);      //make random [0,1] distribution\r\n\r\nwindow.image(img);</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/noise.png\"><img class=\"aligncenter size-medium wp-image-8710\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/noise-262x300.png\" alt=\"Forge image plot of noise\" width=\"262\" height=\"300\" /></a>\r\n\r\nTweaking the previous example by giving our image a depth of 3 for the RGB values allows us to generate colorful noise:\r\n<pre><code class=\"language-{.cpp}\">array img = 255 * randu(width, height, 3);      //make random [0, 255] distribution\r\nwindow.image( img.as(u8) );</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/color_noise.png\"><img class=\"aligncenter size-medium wp-image-8708\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/color_noise-262x300.png\" alt=\"Forge image plot of color noise\" width=\"262\" height=\"300\" /></a>\r\n\r\nNote that Forge automatically handles any af::array type passed from Arrayfire. In the first example we passed in an image of floats in the range [0, 1]. In the last example we cast our array to an unsigned byte array with the range\r\n[0, 255]. The type-handling properties are consistent for all Forge drawing functions.\r\n<h5><a id=\"Plot_63\"></a>Plot</h5>\r\nThe af::Window::plot() function visualizes an array as a 2d-line plot. Let’s see a simple example:\r\n<pre><code class=\"language-{.cpp}\">array X = seq(-af::Pi, af::Pi, 0.01);\r\narray Y = sin(X);\r\nwindow.plot(X, Y);</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_plot.png\"><img class=\"aligncenter size-medium wp-image-8714\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_plot-296x300.png\" alt=\"Forge 2d line plot of sin() function\" width=\"296\" height=\"300\" /></a>\r\nThe plot function has the signature:\r\n\r\n<code><strong>void plot( const array &amp;X, const array &amp;Y, const char * const title = NULL );</strong></code>\r\n\r\nBoth the x and y coordinates of the points are required to plot. This allows for non-uniform, or parametric plots:\r\n<pre><code class=\"language-{.cpp}\">array t = seq(0, 100, 0.01);\r\narray X = sin(t) * (exp(cos(t)) - 2 * cos(4 * t) - pow(sin(t / 12), 5));\r\narray Y = cos(t) * (exp(cos(t)) - 2 * cos(4 * t) - pow(sin(t / 12), 5));\r\nwindow.plot(X, Y);</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/butterfly_plot.png\"><img class=\"aligncenter size-medium wp-image-8707\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/butterfly_plot-290x300.png\" alt=\"\" width=\"290\" height=\"300\" /></a>\r\n<h5><a id=\"Scatter_88\"></a>Scatter</h5>\r\nThe af::Window::scatter() function visualizes an array as a 2d-scatter plot. Let’s see a example:\r\n<pre><code class=\"language-{.cpp}\">array X = seq(-af::Pi, af::Pi, 0.01);\r\narray noise = randn(X.dims(0)) /3.0f;\r\narray Y = sin(X) + noise;\r\nwindow.scatter(X, Y);</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_scatter.png\"><img class=\"aligncenter size-medium wp-image-8715\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_scatter-300x228.png\" alt=\"Forge 2d scatter plot\" width=\"300\" height=\"228\" /></a>\r\n\r\nThe scatter function has the signature:\r\n\r\n<code><strong>void scatter( const array &amp;X, const array &amp;Y, af::markerType marker=AF_MARKER_POINT, const char * const title = NULL);</strong></code>\r\n\r\nThe <strong>af::markerType</strong> enum determines which marker will be drawn at each point.\r\nIt can take on the values of:\r\n<pre><code class=\"language-{.cpp}\">enum af::markerType {\r\n    AF_MARKER_POINT\r\n    AF_MARKER_CIRCLE\r\n    AF_MARKER_SQUARE\r\n    AF_MARKER_TRIANGLE\r\n    AF_MARKER_CROSS\r\n    AF_MARKER_PLUS\r\n    AF_MARKER_STAR\r\n};</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\"><img class=\"aligncenter size-full wp-image-8709\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\" alt=\"Different types of markers in Forge.\" width=\"1846\" height=\"326\" /></a>\r\n<h5><a id=\"Plot3_118\"></a>Plot3</h5>\r\nThe af::Window::plot3() function will plot a curve in 3d-space.\r\nIts signature is:\r\n\r\n<code><strong>void plot3 (const array &amp;in, const char * title = NULL);</strong></code>\r\n\r\nThe input array expects xyz-triplets in sequential order. The points can be in a flattened one dimensional (<em>3n x 1</em>) array, or in one of the (<em>3 x n</em>), (<em>n x 3</em>) matrix forms.\r\n<pre><code class=\"language-{.cpp}\">array Z = seq(0.1f, 10.f, 0.01);\r\narray Y = sin(10 * Z) / Z;\r\narray X = cos(10 * Z) / Z;\r\n\r\narray Pts = join(1, X, Y, Z);\r\n//Pts can be passed in as a matrix in the from n x 3, 3 x n\r\n//or in the flattened xyz-triplet array with size 3n x 1\r\nwindow.plot3(Pts);\r\n//both of the following are equally valid\r\n//window.plot3(transpose(Pts));\r\n//window.plot3(flat(Pts));</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/spiral_plot3.png\"><img class=\"aligncenter size-medium wp-image-8716\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/spiral_plot3-300x211.png\" alt=\"Forge 3d line plot\" width=\"300\" height=\"211\" /></a>\r\n<h5><a id=\"Histogram_140\"></a>Histogram</h5>\r\nThe af::Window::hist() function renders an input array as a histogram. In our example, the input array will be created with Arrayfire’s histogram() function, which actually counts and bins each sample. The output from histogram() can directly be fed into the af::Window::hist() rendering function.\r\n<pre><code class=\"language-{.cpp}\">const int BINS = 128; SAMPLES = 9162;\r\narray norm = randn(SAMPLES);\r\narray hist_arr = histogram(norm, BINS);\r\n\r\nwin.hist(hist_arr, 0, BINS);</code></pre>\r\nIn addition to the histogram array with the number of samples in each bin, the af::Window::hist() function takes two additional parameters – the minimum and maximum values of all datapoints in the histogram array. This effectively sets the range of the binned data. The full signature of af::Window::hist() is:\r\n\r\n<code><strong>void hist(const array &amp; X, const double minval, const double maxval, const char * const title = NULL);</strong></code>\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_histogram.png\"><img class=\"aligncenter size-medium wp-image-8711\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_histogram-300x256.png\" alt=\"Forge histogram plot\" width=\"300\" height=\"256\" /></a>\r\n<h5><a id=\"Scatter3_162\"></a>Scatter3</h5>\r\nThe af::Window::scatter3() function visualizes an array as a 3d-scatter plot.\r\nIts signature is:\r\n\r\n<code><strong>void scatter3 (const array &amp;in, af::markerType marker=AF_MARKER_POINT, const char * title = NULL);</strong></code>\r\n\r\nThe input array expects xyz-triplets in sequential order. The points can be in a flattened one dimensional (<em>3n x 1</em>) array, or in one of the (<em>3 x n</em>), (<em>n x 3</em>) matrix forms.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_scatter3.png\"><img class=\"aligncenter size-medium wp-image-8712\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_scatter3-300x208.png\" alt=\"Forge 3d scatter plot\" width=\"300\" height=\"208\" /></a>\r\n<pre><code class=\"language-{.cpp}\">array X = randn(300);\r\narray Y = randn(300);\r\narray Z = randn(300);\r\n\r\narray Pts = join(1, X, Y, Z);\r\nwindow.scatter3(Pts);</code></pre>\r\nThe <strong>af::markerType</strong> enum determines which marker will be drawn at each point. It can take on the values of:\r\n<pre><code class=\"language-{.cpp}\">enum af::markerType {\r\n    AF_MARKER_POINT\r\n    AF_MARKER_CIRCLE\r\n    AF_MARKER_SQUARE\r\n    AF_MARKER_TRIANGLE\r\n    AF_MARKER_CROSS\r\n    AF_MARKER_PLUS\r\n    AF_MARKER_STAR\r\n};</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\"><img class=\"aligncenter size-full wp-image-8709\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\" alt=\"Different types of markers in Forge.\" width=\"1846\" height=\"326\" /></a>\r\n<h5><a id=\"Surface_195\"></a>Surface</h5>\r\nThe af::Window::surface() function will plot af::arrays as a 3d surface.\r\n<pre><code class=\"language-{.cpp}\">array Z = randu(21, 21);\r\nwindow.surface(Z, \"Random Surface\");    //equal to next function call\r\n//window.surface( seq(-1, 1, 0.1), seq(-1, 1, 0.1), Z, \"Random Surface\");</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/rand_surface.png\"><img class=\"aligncenter size-medium wp-image-8713\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/rand_surface-300x269.png\" alt=\"Forge 3d surface() plot\" width=\"300\" height=\"269\" /></a>\r\nThere are two overloads for the af::Window::surface() function:\r\n\r\n<code><strong>void surface (const array &amp; S, const char * const title )</strong>\r\n// Accepts a 2d matrix with the z values of the surface</code>\r\n\r\n<code><strong>void surface (const array &amp;xVals, const array &amp;yVals, const array &amp;S, const char * const title)</strong>\r\n// accepts additional vectors that define the x,y coordinates for the surface points.</code>\r\n\r\nThe second overload has two options for the x, y coordinate vectors. Assuming a surface grid of size <strong>m x n</strong>:\r\n<ol>\r\n 	<li>Short vectors defining the spacing along each axis. Vectors will have sizes <strong>m x 1</strong> and <strong>n x 1</strong>.</li>\r\n 	<li>Vectors containing the coordinates of each and every point. Each of the vectors will have length <strong>mn x 1</strong>. This can be used for completely non-uniform or parametric surfaces.</li>\r\n</ol>\r\n<h4><a id=\"Conclusion_216\"></a>Conclusion</h4>\r\nThere is a fairly comprehensive collection of methods to visualize data in Arrayfire. Thanks to the high-performance gpu plotting library Forge, the provided Arrayfire functions not only make visualizations as simple as possible, but keep them as robust as the rest of the Arrayfire library.','Visualizing af::array with Forge','','inherit','closed','closed','','8698-revision-v1','','','2016-05-18 15:53:02','2016-05-18 19:53:02','',8698,'http://sandbox.arrayfire.com/8698-revision-v1/',0,'revision','',0),(8885,18528,'2016-05-18 15:53:19','2016-05-18 19:53:19','The ArrayFire library attempts to make high performance computing as easy as possible for scientists and engineers. Because many tasks need to be visualized, ArrayFire also provides a high-level interface to our <a href=\"https://github.com/arrayfire/forge\">Forge visualization library</a>. In today\'s \"<a href=\"http://arrayfire.org/http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\" post we present an overview of ArrayFire\'s visualization functionality and demonstrate how to use Forge to display data contained in af::array objects.\r\n\r\n<!--more-->\r\n\r\nThe Forge library is a general-purpose visualization tool for data stored on the GPU or related accelerator devices. By default, ArrayFire ships with Forge built in. However; if you or your system administrator installed the \"no-graphics\" version of ArrayFire, Forge won\'t be included.\r\n\r\nArrayFire provides several wrapper functions that simplify Forge\'s interface when used with <a class=\"el\" title=\"A multi dimensional data container. \" href=\"classaf_1_1array.htm\">af::array</a> objects. These functions primarily perform interop tasks including visualization range setting, copying data into OpenGL data structures, and generating an OpenGL window for display.\r\n<h4><a id=\"setup\" class=\"anchor\"></a>Setup</h4>\r\nBefore we can use Forge, we must create an window containing an OpenGL context. Creating an instance of the<code><a class=\"el\" title=\"Window object to render af::arrays. \" href=\"classaf_1_1Window.htm\">af::Window</a></code> class will accomplish both of these tasks. Note, at present Forge must create and manage its own OpenGL context; however, we hope to change this in a future release. Once the window is created, you can use Forge\'s drawing functions to visualize your data. Here is a basic example of how to create a window, set its title, and enter into a drawing loop:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">const static int width = 512, height = 512;\r\naf::Window window(width, height, \"2D plot example title\");\r\n \r\ndo{\r\n \r\n//drawing functions here\r\n \r\n} while( !window.close() );</pre>\r\n</div>\r\n</div>\r\n<h4><a id=\"render_func\" class=\"anchor\"></a>Rendering Functions</h4>\r\nAs included in ArrayFire 3.3, Forge provides the following plotting capabilities:\r\n<table class=\"doxtable\">\r\n<tbody>\r\n<tr>\r\n<th>Function</th>\r\n<th>Description</th>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input array as a histogram to the window. \" href=\"group__gfx__func__draw.htm#gafd7d94aa8f5fd37fee0662a4906a38d7\">af::Window::hist()</a></td>\r\n<td>Creates a histogram plot from input data and bins</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input array as an image to the window. \" href=\"group__gfx__func__draw.htm#gaed174450be6db4dfa5ef65b7baccbe57\">af::Window::image()</a></td>\r\n<td>Display an image</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input arrays as a 2D plot to the window. \" href=\"group__gfx__func__draw.htm#ga8e01736df3d805a5488c609e2573818b\">af::Window::plot()</a></td>\r\n<td>2D Line plot</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input array as an 3d line plot to the window. \" href=\"group__gfx__func__draw.htm#ga8e04ec129034e9fe769f3e6b14cd087f\">af::Window::plot3()</a></td>\r\n<td>3D line plot</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input arrays as a 2D scatter-plot to the window. \" href=\"group__gfx__func__draw.htm#ga73406db589e5090c051baae0af175df9\">af::Window::scatter()</a></td>\r\n<td>2D scatter plot</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input arrays as a 3D scatter-plot to the window. \" href=\"group__gfx__func__draw.htm#ga3bbfbe1b60741a259d2146b3ab50ace3\">af::Window::scatter3()</a></td>\r\n<td>3D scatter plot</td>\r\n</tr>\r\n<tr>\r\n<td><a class=\"el\" title=\"Renders the input arrays as a 3D surface plot to the window. \" href=\"group__gfx__func__draw.htm#ga1cdb8c3205d70d8feaddd8c30245393f\">af::Window::surface()</a></td>\r\n<td>Visualize a 3D surface</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\nFull documentation on all plotting functions can be found in the <a class=\"el\" href=\"group__gfx__func__draw.htm\">rendering functions</a> portion of the documentation.\r\n<h5><a id=\"Image_38\"></a>Image</h5>\r\nThe af::Window::image() function can be used to plot grayscale or color images. To plot a grayscale image a 2d array should be passed into the function.\r\nLet’s see this on a static noise example:\r\n<pre><code class=\"language-{.cpp}\">array img = constant(0, width, height);   //make a black image\r\narray random = randu(width, height);      //make random [0,1] distribution\r\n\r\nwindow.image(img);</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/noise.png\"><img class=\"aligncenter size-medium wp-image-8710\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/noise-262x300.png\" alt=\"Forge image plot of noise\" width=\"262\" height=\"300\" /></a>\r\n\r\nTweaking the previous example by giving our image a depth of 3 for the RGB values allows us to generate colorful noise:\r\n<pre><code class=\"language-{.cpp}\">array img = 255 * randu(width, height, 3);      //make random [0, 255] distribution\r\nwindow.image( img.as(u8) );</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/color_noise.png\"><img class=\"aligncenter size-medium wp-image-8708\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/color_noise-262x300.png\" alt=\"Forge image plot of color noise\" width=\"262\" height=\"300\" /></a>\r\n\r\nNote that Forge automatically handles any af::array type passed from Arrayfire. In the first example we passed in an image of floats in the range [0, 1]. In the last example we cast our array to an unsigned byte array with the range\r\n[0, 255]. The type-handling properties are consistent for all Forge drawing functions.\r\n<h5><a id=\"Plot_63\"></a>Plot</h5>\r\nThe af::Window::plot() function visualizes an array as a 2d-line plot. Let’s see a simple example:\r\n<pre><code class=\"language-{.cpp}\">array X = seq(-af::Pi, af::Pi, 0.01);\r\narray Y = sin(X);\r\nwindow.plot(X, Y);</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_plot.png\"><img class=\"aligncenter size-medium wp-image-8714\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_plot-296x300.png\" alt=\"Forge 2d line plot of sin() function\" width=\"296\" height=\"300\" /></a>\r\nThe plot function has the signature:\r\n\r\n<code><strong>void plot( const array &amp;X, const array &amp;Y, const char * const title = NULL );</strong></code>\r\n\r\nBoth the x and y coordinates of the points are required to plot. This allows for non-uniform, or parametric plots:\r\n<pre><code class=\"language-{.cpp}\">array t = seq(0, 100, 0.01);\r\narray X = sin(t) * (exp(cos(t)) - 2 * cos(4 * t) - pow(sin(t / 12), 5));\r\narray Y = cos(t) * (exp(cos(t)) - 2 * cos(4 * t) - pow(sin(t / 12), 5));\r\nwindow.plot(X, Y);</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/butterfly_plot.png\"><img class=\"aligncenter size-medium wp-image-8707\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/butterfly_plot-290x300.png\" alt=\"\" width=\"290\" height=\"300\" /></a>\r\n<h5><a id=\"Scatter_88\"></a>Scatter</h5>\r\nThe af::Window::scatter() function visualizes an array as a 2d-scatter plot. Let’s see a example:\r\n<pre><code class=\"language-{.cpp}\">array X = seq(-af::Pi, af::Pi, 0.01);\r\narray noise = randn(X.dims(0)) /3.0f;\r\narray Y = sin(X) + noise;\r\nwindow.scatter(X, Y);</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_scatter.png\"><img class=\"aligncenter size-medium wp-image-8715\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/sin_scatter-300x228.png\" alt=\"Forge 2d scatter plot\" width=\"300\" height=\"228\" /></a>\r\n\r\nThe scatter function has the signature:\r\n\r\n<code><strong>void scatter( const array &amp;X, const array &amp;Y, af::markerType marker=AF_MARKER_POINT, const char * const title = NULL);</strong></code>\r\n\r\nThe <strong>af::markerType</strong> enum determines which marker will be drawn at each point.\r\nIt can take on the values of:\r\n<pre><code class=\"language-{.cpp}\">enum af::markerType {\r\n    AF_MARKER_POINT\r\n    AF_MARKER_CIRCLE\r\n    AF_MARKER_SQUARE\r\n    AF_MARKER_TRIANGLE\r\n    AF_MARKER_CROSS\r\n    AF_MARKER_PLUS\r\n    AF_MARKER_STAR\r\n};</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\"><img class=\"aligncenter size-full wp-image-8709\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\" alt=\"Different types of markers in Forge.\" width=\"1846\" height=\"326\" /></a>\r\n<h5><a id=\"Plot3_118\"></a>Plot3</h5>\r\nThe af::Window::plot3() function will plot a curve in 3d-space.\r\nIts signature is:\r\n\r\n<code><strong>void plot3 (const array &amp;in, const char * title = NULL);</strong></code>\r\n\r\nThe input array expects xyz-triplets in sequential order. The points can be in a flattened one dimensional (<em>3n x 1</em>) array, or in one of the (<em>3 x n</em>), (<em>n x 3</em>) matrix forms.\r\n<pre><code class=\"language-{.cpp}\">array Z = seq(0.1f, 10.f, 0.01);\r\narray Y = sin(10 * Z) / Z;\r\narray X = cos(10 * Z) / Z;\r\n\r\narray Pts = join(1, X, Y, Z);\r\n//Pts can be passed in as a matrix in the from n x 3, 3 x n\r\n//or in the flattened xyz-triplet array with size 3n x 1\r\nwindow.plot3(Pts);\r\n//both of the following are equally valid\r\n//window.plot3(transpose(Pts));\r\n//window.plot3(flat(Pts));</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/spiral_plot3.png\"><img class=\"aligncenter size-medium wp-image-8716\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/spiral_plot3-300x211.png\" alt=\"Forge 3d line plot\" width=\"300\" height=\"211\" /></a>\r\n<h5><a id=\"Histogram_140\"></a>Histogram</h5>\r\nThe af::Window::hist() function renders an input array as a histogram. In our example, the input array will be created with Arrayfire’s histogram() function, which actually counts and bins each sample. The output from histogram() can directly be fed into the af::Window::hist() rendering function.\r\n<pre><code class=\"language-{.cpp}\">const int BINS = 128; SAMPLES = 9162;\r\narray norm = randn(SAMPLES);\r\narray hist_arr = histogram(norm, BINS);\r\n\r\nwin.hist(hist_arr, 0, BINS);</code></pre>\r\nIn addition to the histogram array with the number of samples in each bin, the af::Window::hist() function takes two additional parameters – the minimum and maximum values of all datapoints in the histogram array. This effectively sets the range of the binned data. The full signature of af::Window::hist() is:\r\n\r\n<code><strong>void hist(const array &amp; X, const double minval, const double maxval, const char * const title = NULL);</strong></code>\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_histogram.png\"><img class=\"aligncenter size-medium wp-image-8711\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_histogram-300x256.png\" alt=\"Forge histogram plot\" width=\"300\" height=\"256\" /></a>\r\n<h5><a id=\"Scatter3_162\"></a>Scatter3</h5>\r\nThe af::Window::scatter3() function visualizes an array as a 3d-scatter plot.\r\nIts signature is:\r\n\r\n<code><strong>void scatter3 (const array &amp;in, af::markerType marker=AF_MARKER_POINT, const char * title = NULL);</strong></code>\r\n\r\nThe input array expects xyz-triplets in sequential order. The points can be in a flattened one dimensional (<em>3n x 1</em>) array, or in one of the (<em>3 x n</em>), (<em>n x 3</em>) matrix forms.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_scatter3.png\"><img class=\"aligncenter size-medium wp-image-8712\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/norm_scatter3-300x208.png\" alt=\"Forge 3d scatter plot\" width=\"300\" height=\"208\" /></a>\r\n<pre><code class=\"language-{.cpp}\">array X = randn(300);\r\narray Y = randn(300);\r\narray Z = randn(300);\r\n\r\narray Pts = join(1, X, Y, Z);\r\nwindow.scatter3(Pts);</code></pre>\r\nThe <strong>af::markerType</strong> enum determines which marker will be drawn at each point. It can take on the values of:\r\n<pre><code class=\"language-{.cpp}\">enum af::markerType {\r\n    AF_MARKER_POINT\r\n    AF_MARKER_CIRCLE\r\n    AF_MARKER_SQUARE\r\n    AF_MARKER_TRIANGLE\r\n    AF_MARKER_CROSS\r\n    AF_MARKER_PLUS\r\n    AF_MARKER_STAR\r\n};</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\"><img class=\"aligncenter size-full wp-image-8709\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/marker_types.png\" alt=\"Different types of markers in Forge.\" width=\"1846\" height=\"326\" /></a>\r\n<h5><a id=\"Surface_195\"></a>Surface</h5>\r\nThe af::Window::surface() function will plot af::arrays as a 3d surface.\r\n<pre><code class=\"language-{.cpp}\">array Z = randu(21, 21);\r\nwindow.surface(Z, \"Random Surface\");    //equal to next function call\r\n//window.surface( seq(-1, 1, 0.1), seq(-1, 1, 0.1), Z, \"Random Surface\");</code></pre>\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/rand_surface.png\"><img class=\"aligncenter size-medium wp-image-8713\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2015/12/rand_surface-300x269.png\" alt=\"Forge 3d surface() plot\" width=\"300\" height=\"269\" /></a>\r\nThere are two overloads for the af::Window::surface() function:\r\n\r\n<code><strong>void surface (const array &amp; S, const char * const title )</strong>\r\n// Accepts a 2d matrix with the z values of the surface</code>\r\n\r\n<code><strong>void surface (const array &amp;xVals, const array &amp;yVals, const array &amp;S, const char * const title)</strong>\r\n// accepts additional vectors that define the x,y coordinates for the surface points.</code>\r\n\r\nThe second overload has two options for the x, y coordinate vectors. Assuming a surface grid of size <strong>m x n</strong>:\r\n<ol>\r\n 	<li>Short vectors defining the spacing along each axis. Vectors will have sizes <strong>m x 1</strong> and <strong>n x 1</strong>.</li>\r\n 	<li>Vectors containing the coordinates of each and every point. Each of the vectors will have length <strong>mn x 1</strong>. This can be used for completely non-uniform or parametric surfaces.</li>\r\n</ol>\r\n<h4><a id=\"Conclusion_216\"></a>Conclusion</h4>\r\nThere is a fairly comprehensive collection of methods to visualize data in Arrayfire. Thanks to the high-performance gpu plotting library Forge, the provided Arrayfire functions not only make visualizations as simple as possible, but keep them as robust as the rest of the Arrayfire library.','Visualizing the af::array with Forge','','inherit','closed','closed','','8698-revision-v1','','','2016-05-18 15:53:19','2016-05-18 19:53:19','',8698,'http://sandbox.arrayfire.com/8698-revision-v1/',0,'revision','',0),(8893,18528,'2016-05-23 11:26:41','2016-05-23 15:26:41','Yes, you read that right! ArrayFire is open source—it’s all there and it’s all free. This is big, and you and the rest of the parallel computing community are going to love it!\n\nYou can <a href=\"http://sandbox.arrayfire.com/download/\">download our pre-compiled binary installers</a> \\which are optimized for a wide variety of systems or you can <a href=\"https://github.com/arrayfire/arrayfire\">get a copy of the ArrayFire source code</a> from our GitHub page. ArrayFire is being released under the BSD 3-Clause License, which will enable unencumbered deployment and portability of ArrayFire for commercial use.\n\nSo go check it out! We welcome your feedback and look forward to your future contributions to ArrayFire.\n\nThe move to open source isn\'t our only news—we\'ve also made ArrayFire better than ever. Check out our recent post (now updated) to learn more about the <a href=\"http://sandbox.arrayfire.com/new-features-arrayfire/\">new features</a> we\'ve added to ArrayFire. Be sure to also check out all of the ArrayFire functions (and a lot more!) in our <a href=\"http://www.sandbox.arrayfire.com/docs/index.htm\">documentation</a>.\n\n<strong>You\'ve got the source. Now join the community.</strong>\n\nNow for the most important part. We want you to be an integral part of the ArrayFire community. We’re big fans of freedom, collaboration, and perpetual motion. Adapt ArrayFire to meet your needs, watch it blaze, and tell us all about it!\n\nHere\'s how to get started.\n<ul>\n 	<li>Join the <a href=\"https://github.com/arrayfire\">ArrayFire GitHub community</a> and <a href=\"https://github.com/arrayfire/arrayfire\">download</a> the source.</li>\n 	<li>Visit our <a href=\"http://sandbox.arrayfire.com/forums/\">forums</a> to pick up useful tips and learn about best practices.</li>\n 	<li>Join our growing community on <a href=\"https://plus.google.com/+Arrayfire/posts\">Google+</a>.</li>\n 	<li><a href=\"https://twitter.com/arrayfire\">Follow us</a> and give a friendly shout-out!</li>\n</ul>\nWe\'ll also be organizing webinars, meetups, and other networking opportunities to get feedback from the community and collaborate on future updates to ArrayFire. We strongly encourage your participation and contributions—and brownie points will be awarded to top contributors!\n\n<strong>Need additional help?</strong>\n\nEveryone could use a hand now and then. Dedicated technical support is now available from our team of ArrayFire developers. Choose from among our three ArrayFire <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a>, or simply go hour-by-hour. Whatever your level of need, the ArrayFire team is here for you.\n\nHow about custom developer services? We\'ve got you covered there, too! <a href=\"http://sandbox.arrayfire.com/consulting/\">Hire us</a> to accelerate your code, write custom code for your organization, or even <a href=\"http://sandbox.arrayfire.com/training/\">train your pros</a>.\n\nFor more information check out our new and improved <a href=\"http://sandbox.arrayfire.com/\">website</a> or contact us at sales@arrayfire.com.\n\nLooking forward to having you join us in this exciting venture!','ArrayFire is Now Open Source','','inherit','closed','closed','','7399-autosave-v1','','','2016-05-23 11:26:41','2016-05-23 15:26:41','',7399,'http://sandbox.arrayfire.com/7399-autosave-v1/',0,'revision','',0),(8894,18528,'2016-05-23 11:23:34','2016-05-23 15:23:34','Yes, you read that right! ArrayFire is open source—it’s all there and it’s all free. This is big, and you and the rest of the parallel computing community are going to love it!\r\n\r\nYou can <a href=\"http://sandbox.arrayfire.com/download/\">download our pre-compiled binary installers</a> which are optimized for a wide variety of systems or you can <a href=\"https://github.com/arrayfire/arrayfire\">get a copy of the ArrayFire source code</a> from our GitHub page. ArrayFire is being released under the BSD 3-Clause License, which will enable unencumbered deployment and portability of ArrayFire for commercial use.\r\n\r\nSo go check it out! We welcome your feedback and look forward to your future contributions to ArrayFire.\r\n\r\nThe move to open source isn\'t our only news—we\'ve also made ArrayFire better than ever. Check out our recent post (now updated) to learn more about the <a href=\"http://sandbox.arrayfire.com/new-features-arrayfire/\">new features</a> we\'ve added to ArrayFire. Be sure to also check out all of the ArrayFire functions (and a lot more!) in our <a href=\"http://www.sandbox.arrayfire.com/docs/index.htm\">documentation</a>.\r\n\r\n<strong>You\'ve got the source. Now join the community.</strong>\r\n\r\nNow for the most important part. We want you to be an integral part of the ArrayFire community. We’re big fans of freedom, collaboration, and perpetual motion. Adapt ArrayFire to meet your needs, watch it blaze, and tell us all about it!\r\n\r\nHere\'s how to get started.\r\n<ul>\r\n 	<li>Join the <a href=\"https://github.com/arrayfire\">ArrayFire GitHub community</a> and <a href=\"https://github.com/arrayfire/arrayfire\">download</a> the source.</li>\r\n 	<li>Visit our <a href=\"http://sandbox.arrayfire.com/forums/\">forums</a> to pick up useful tips and learn about best practices.</li>\r\n 	<li>Join our growing community on <a href=\"https://plus.google.com/+Arrayfire/posts\">Google+</a>.</li>\r\n 	<li><a href=\"https://twitter.com/arrayfire\">Follow us</a> and give a friendly shout-out!</li>\r\n</ul>\r\nWe\'ll also be organizing webinars, meetups, and other networking opportunities to get feedback from the community and collaborate on future updates to ArrayFire. We strongly encourage your participation and contributions—and brownie points will be awarded to top contributors!\r\n\r\n<strong>Need additional help?</strong>\r\n\r\nEveryone could use a hand now and then. Dedicated technical support is now available from our team of ArrayFire developers. Choose from among our three ArrayFire <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a>, or simply go hour-by-hour. Whatever your level of need, the ArrayFire team is here for you.\r\n\r\nHow about custom developer services? We\'ve got you covered there, too! <a href=\"http://sandbox.arrayfire.com/consulting/\">Hire us</a> to accelerate your code, write custom code for your organization, or even <a href=\"http://sandbox.arrayfire.com/training/\">train your pros</a>.\r\n\r\nFor more information check out our new and improved <a href=\"http://sandbox.arrayfire.com/\">website</a> or contact us at sales@arrayfire.com.\r\n\r\nLooking forward to having you join us in this exciting venture!','ArrayFire is Now Open Source','','inherit','closed','closed','','7399-revision-v1','','','2016-05-23 11:23:34','2016-05-23 15:23:34','',7399,'http://sandbox.arrayfire.com/7399-revision-v1/',0,'revision','',0),(8895,18528,'2016-05-25 13:30:04','2016-05-25 17:30:04','Programmers and Data Scientists want to take advantage of fast and parallel computational devices. One of the best ways of doing this is to write vectorized code; however, this is often easier said than done. In today\'s continuation of the blog series \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\", we will discuss the various methods by which you can maximize the performance of your code by using ArrayFire\'s built-in vectorization features.\r\n\r\n<!--more-->\r\n\r\nArrayFire provides many ways to vectorize a given code segment. In this tutorial, we present several methods to vectorize code using ArrayFire and discuss the benefits and drawbacks associated with each method.\r\n<h4><a id=\"GenericDefault_vectorization_10\"></a>Generic/Default vectorization</h4>\r\nBy its very nature, ArrayFire is a vectorized library. Most functions operate on arrays as a whole – on all elements in parallel. Wherever possible, existing vectorized functions should be used opposed to manually indexing into arrays. For example consider the following code:\r\n<pre class=\"lang:default decode:true \">af::array a = af::range(10); // [0,  9]\r\nfor(int i = 0; i &lt; a.dims(0); ++i)\r\n{\r\n    a(i) = a(i) + 1;         // [1, 10]\r\n}</pre>\r\nAlthough completely valid, the code is very inefficient as it results in a kernel kernels that operate on one datum. Instead, the developer should have used ArrayFire\'s overload of the + operator:\r\n<pre><code class=\"language-{.cpp}\">\r\naf::array a = af::range(10);  // [0,  9]\r\na = a + 1;                    // [1, 10]\r\n</code></pre>\r\nThis code will result in a single kernel that operates on all 10 elements of <code>a</code> in parallel.\r\n\r\nMost ArrayFire functions are vectorized. A small subset of these include:\r\n\r\n<strong>Arithmetic operations:</strong> +, -, *, / , %, &gt;&gt;, &lt;&lt;\r\n<strong>Logical operations:</strong> &amp;&amp;, ||, &lt;, &gt;, ==, !=\r\n<strong>Numeric functions:</strong> abs(), floor(), round(), min(), max()…\r\n<strong>Complex operations:</strong> real(), imag(), conj()…\r\n<strong>Exponential and logarithmic functions:</strong> exp(), log(), expm1(), log1p()…\r\n<strong>Trigonometric functions:</strong> sin(), cos(), tan()…\r\n<strong>Hyperbolic functions:</strong> sinh(), cosh(), tanh()…\r\n\r\nIn addition to element-wise operations, many other functions are also vectorized in ArrayFire.\r\n\r\nNotice that even that perform some form of aggregation (e.g. <code>sum()</code> or <code>min()</code>), signal processing (like <code>convolve()</code>), and even image processing functions (i.e. <code>rotate()</code>) all support vectorization on different columns or images. For example, if we have <code>NUM</code> images of size <code>WIDTH</code> by <code>HEIGHT</code>, one could convolve each image in a vector fashion as follows:\r\n<pre class=\"lang:default decode:true \">float g_coef[] = { 1, 2, 1,\r\n                   2, 4, 2,\r\n                   1, 2, 1 };\r\naf::array filter = 1.f/16 * af::array(3, 3, f_coef);\r\naf::array signal = randu(WIDTH, HEIGHT, NUM);\r\naf::array conv = convolve2(signal, filter);</pre>\r\nSimilarly, one can rotate 100 images by 45 degrees in a single call using code like the following:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// Construct an array of 100 WIDTH x HEIGHT images of random numbers\r\naf::array imgs = randu(WIDTH, HEIGHT, 100);\r\n// Rotate all of the images in a single command\r\naf::array rot_imgs = rotate(imgs, 45);</pre>\r\n</div>\r\n</div>\r\nAlthough <em>most</em> functions in ArrayFire do support vectorization, some do not. Most notably, all linear algebra functions. Even though they are not vectorized linear algebra operations still execute in parallel on your hardware.\r\n\r\nUsing the built in vectorized operations should be the first and preferred method of vectorizing any code written with ArrayFire.\r\n<h4><a id=\"GFOR_Parallel_forloops_76\"></a>GFOR: Parallel for-loops</h4>\r\nAnother novel method of vectorization present in ArrayFire is the GFOR loop replacement construct. GFOR allows launching all iterations of a loop in parallel on the GPU or device, as long as the iterations are independent. While the standard for-loop performs each iteration sequentially, ArrayFire\'s gfor-loop performs each iteration at the same time (in parallel). ArrayFire does this by tiling out the values of all loop iterations and then performing computation on those tiles in one pass. You can think of gfor as performing auto-vectorization of your code, e.g. you write a gfor-loop that increments every element of a vector but behind the scenes ArrayFire rewrites it to operate on the entire vector in parallel.\r\n\r\nThe original for-loop example at the beginning of this document could be rewritten using GFOR as follows:\r\n<pre><code class=\"language-{.cpp}\">af::array a = af::range(10);\r\ngfor(seq i, n)\r\n    a(i) = a(i) + 1;</code></pre>\r\nIn this case, each instance of the gfor loop is independent, thus ArrayFire will automatically tile out the <code>a</code> array in device memory and execute the increment kernels in parallel.\r\n\r\nTo see another example, you could run an <a class=\"el\" title=\"C++ Interface exclusive sum (cumulative sum) of an array. \" href=\"group__scan__func__accum.htm#gae450135c4ae1bdaa4489804a215f3214\">accum()</a> on every slice of a matrix in a for-loop, or you could \"vectorize\" and simply do it all in one gfor-loop operation:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// runs each accum() in sequence\r\nfor (int i = 0; i &lt; N; ++i)\r\n    B(span,i) = accum(A(span,i));\r\n \r\n// runs N accums in parallel\r\ngfor (seq i, N)\r\n    B(span,i) = accum(A(span,i));</pre>\r\n</div>\r\n</div>\r\nHowever, returning to our previous vectorization technique, <a class=\"el\" title=\"C++ Interface exclusive sum (cumulative sum) of an array. \" href=\"group__scan__func__accum.htm#gae450135c4ae1bdaa4489804a215f3214\">accum()</a> is already vectorized and the operation could be completely replaced with merely:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">B = accum(A);</pre>\r\n</div>\r\n</div>\r\nIt is best to vectorize computation as much as possible to avoid the overhead in both for-loops and gfor-loops. However, the gfor-loop construct is most effective in the narrow case of broadcast-style operations. Consider the case when we have a vector of constants that we wish to apply to a collection of variables, such as expressing the values of a linear combination for multiple vectors. The broadcast of one set of constants to many vectors works well with gfor-loops:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">const static int p=4, n=1000;\r\naf::array consts = af::randu(p);\r\naf::array var_terms = randn(p, n);\r\n \r\ngfor(seq i, n)\r\n    combination(span, i) = consts * var_terms(span, i);</pre>\r\n</div>\r\n</div>\r\nUsing GFOR requires following several rules and multiple guidelines for optimal performance. The details of this vectorization method can be found in the <a class=\"el\" href=\"page_gfor.htm#gfor\">GFOR documentation</a>.\r\n<h4><a id=\"Batching_127\"></a>Batching</h4>\r\nThe <a class=\"el\" href=\"namespaceaf.htm#aa0eb9e160f5be4b95234543e5c47934b\">batchFunc()</a> function allows the broad application of existing ArrayFire functions to multiple sets of data. Effectively,<a class=\"el\" href=\"namespaceaf.htm#aa0eb9e160f5be4b95234543e5c47934b\">batchFunc()</a> allows ArrayFire functions to execute in \"batch processing\" mode. In this mode, functions will find a dimension which contains \"batches\" of data to be processed and will parallelize the procedure.\r\n\r\nConsider the following example. Here we create a filter which we would like to apply to each of the weight vectors. The naive solution would be using a for-loop as we have seen previously:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// Create the filter and the weight vectors\r\naf::array filter = randn(1, 5);\r\naf::array weights = randu(5, 5);\r\n \r\n// Apply the filter using a for-loop\r\naf::array filtered_weights = constant(0, 5, 5);\r\nfor(int i=0; i&lt;weights.dims(1); ++i){\r\n    filtered_weights.col(i) = filter * weights.col(i);\r\n}</pre>\r\n</div>\r\n</div>\r\nHowever, as we have discussed above, this solution will be very inefficient. One may be tempted to implement a vectorized solution as follows:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// Create the filter and the weight vectors\r\naf::array filter = randn(1, 5);\r\naf::array weights = randu(5, 5);\r\n \r\naf::array filtered_weights = filter * weights; // fails due to dimension mismatch</pre>\r\n</div>\r\n</div>\r\nHowever, the dimensions of <code>filter</code> and <code>weights</code> do not match, thus ArrayFire will generate a runtime error.\r\n\r\n<code>batchfunc()</code> was created to solve this specific problem. The signature of the function is as follows:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">array batchFunc(const array &amp;lhs, const array &amp;rhs, batchFunc_t func);</pre>\r\n</div>\r\n</div>\r\nwhere <code>__batchFunc_t__</code> is a function pointer of the form:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">typedef array (*batchFunc_t) (const array &amp;lhs, const array &amp;rhs);</pre>\r\n</div>\r\n</div>\r\nSo, to use <a class=\"el\" href=\"namespaceaf.htm#aa0eb9e160f5be4b95234543e5c47934b\">batchFunc()</a>, we need to provide the function we wish to apply as a batch operation. For illustration\'s sake, let\'s \"implement\" a multiplication function following the format.\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">af::array my_mult (const af::array &amp;lhs, const af::array &amp;rhs){\r\nreturn lhs * rhs;\r\n}</pre>\r\n</div>\r\n</div>\r\nOur final batch call is not much more difficult than the ideal syntax we imagined.\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// Create the filter and the weight vectors\r\naf::array filter = randn(1, 5);\r\naf::array weights = randu(5, 5);\r\n \r\n// Apply the batch function\r\naf::array filtered_weights = batchFunc( filter, weights, my_mult );</pre>\r\n</div>\r\n</div>\r\nThe batch function will work with many previously mentioned vectorized ArrayFire functions. It can even work with a combination of those functions if they are wrapped inside a helper function matching the <code>__batchFunc_t__</code> signature. One limitation of <code>batchfunc()</code> is that it cannot be used from within a <code><a class=\"el\" href=\"gfor_8h.htm#a6d6cd11d53daad217fd0b92f5a7ceec6\">gfor()</a></code> loop at the present time.\r\n<h4><a id=\"Advanced_Vectorization_181\"></a>Advanced Vectorization</h4>\r\nWe have seen the different methods ArrayFire provides to vectorize our code. Tying them all together is a slightly more involved process that needs to consider data dimensionality and layout, memory usage, nesting order, etc. An excellent example and discussion of these factors can be found in another blog post:\r\n\r\n<a href=\"http://sandbox.arrayfire.com/how-to-write-vectorized-code/\">http://sandbox.arrayfire.com/how-to-write-vectorized-code/</a>\r\n\r\nIt’s worth noting that the whole implementation discussed in the blog has since been transformed into a convenient <strong>af::nearestNeighbour()</strong> function. Before writing something from scratch, check that ArrayFire doesn’t already have an implementation. The default vectorized nature of ArrayFire and an extensive collection of functions will speed things up in addition to replacing dozens of lines of code!','Introduction to Vectorization in ArrayFire','','inherit','closed','closed','','8735-revision-v1','','','2016-05-25 13:30:04','2016-05-25 17:30:04','',8735,'http://sandbox.arrayfire.com/8735-revision-v1/',0,'revision','',0),(8896,18528,'2016-05-25 13:36:20','2016-05-25 17:36:20','Programmers and Data Scientists want to take advantage of fast and parallel computational devices. One of the best ways of doing this is to write vectorized code; however, this is often easier said than done. In today\'s continuation of the blog series \"<a href=\"http://sandbox.arrayfire.com/tag/learning-arrayfire-from-scratch/\">Learning ArrayFire from scratch</a>\", we will discuss the various methods by which you can maximize the performance of your code by using ArrayFire\'s built-in vectorization features.\r\n\r\n<!--more-->\r\n\r\nArrayFire provides many ways to vectorize a given code segment. In this tutorial, we present several methods to vectorize code using ArrayFire and discuss the benefits and drawbacks associated with each method.\r\n<h4><a id=\"GenericDefault_vectorization_10\"></a>Generic/Default vectorization</h4>\r\nBy its very nature, ArrayFire is a vectorized library. Most functions operate on arrays as a whole – on all elements in parallel. Wherever possible, existing vectorized functions should be used opposed to manually indexing into arrays. For example consider the following code:\r\n<pre class=\"lang:default decode:true \">af::array a = af::range(10); // [0,  9]\r\nfor(int i = 0; i &lt; a.dims(0); ++i)\r\n{\r\n    a(i) = a(i) + 1;         // [1, 10]\r\n}</pre>\r\nAlthough completely valid, the code is very inefficient as it results in a kernel that operate on one datum. Instead, the developer should have used ArrayFire\'s overload of the + operator:\r\n<pre><code class=\"language-{.cpp}\">\r\naf::array a = af::range(10);  // [0,  9]\r\na = a + 1;                    // [1, 10]\r\n</code></pre>\r\nThis code will result in a single kernel that operates on all 10 elements of <code>a</code> in parallel.\r\n\r\nMost ArrayFire functions are vectorized. A small subset of these include:\r\n\r\n<strong>Arithmetic operations:</strong> +, -, *, / , %, &gt;&gt;, &lt;&lt;\r\n<strong>Logical operations:</strong> &amp;&amp;, ||, &lt;, &gt;, ==, !=\r\n<strong>Numeric functions:</strong> abs(), floor(), round(), min(), max()…\r\n<strong>Complex operations:</strong> real(), imag(), conj()…\r\n<strong>Exponential and logarithmic functions:</strong> exp(), log(), expm1(), log1p()…\r\n<strong>Trigonometric functions:</strong> sin(), cos(), tan()…\r\n<strong>Hyperbolic functions:</strong> sinh(), cosh(), tanh()…\r\n\r\nIn addition to element-wise operations, many other functions are also vectorized in ArrayFire.\r\n\r\nNotice that even that perform some form of aggregation (e.g. <code>sum()</code> or <code>min()</code>), signal processing (like <code>convolve()</code>), and even image processing functions (i.e. <code>rotate()</code>) all support vectorization on different columns or images. For example, if we have <code>NUM</code> images of size <code>WIDTH</code> by <code>HEIGHT</code>, one could convolve each image in a vector fashion as follows:\r\n<pre class=\"lang:default decode:true \">float g_coef[] = { 1, 2, 1,\r\n                   2, 4, 2,\r\n                   1, 2, 1 };\r\naf::array filter = 1.f/16 * af::array(3, 3, f_coef);\r\naf::array signal = randu(WIDTH, HEIGHT, NUM);\r\naf::array conv = convolve2(signal, filter);</pre>\r\nSimilarly, one can rotate 100 images by 45 degrees in a single call using code like the following:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// Construct an array of 100 WIDTH x HEIGHT images of random numbers\r\naf::array imgs = randu(WIDTH, HEIGHT, 100);\r\n// Rotate all of the images in a single command\r\naf::array rot_imgs = rotate(imgs, 45);</pre>\r\n</div>\r\n</div>\r\nAlthough <em>most</em> functions in ArrayFire do support vectorization, some do not. Most notably, all linear algebra functions. Even though they are not vectorized linear algebra operations still execute in parallel on your hardware.\r\n\r\nUsing the built in vectorized operations should be the first and preferred method of vectorizing any code written with ArrayFire.\r\n<h4><a id=\"GFOR_Parallel_forloops_76\"></a>GFOR: Parallel for-loops</h4>\r\nAnother novel method of vectorization present in ArrayFire is the GFOR loop replacement construct. GFOR allows launching all iterations of a loop in parallel on the GPU or device, as long as the iterations are independent. While the standard for-loop performs each iteration sequentially, ArrayFire\'s gfor-loop performs each iteration at the same time (in parallel). ArrayFire does this by tiling out the values of all loop iterations and then performing computation on those tiles in one pass. You can think of gfor as performing auto-vectorization of your code, e.g. you write a gfor-loop that increments every element of a vector but behind the scenes ArrayFire rewrites it to operate on the entire vector in parallel.\r\n\r\nThe original for-loop example at the beginning of this document could be rewritten using GFOR as follows:\r\n<pre><code class=\"language-{.cpp}\">af::array a = af::range(10);\r\ngfor(seq i, n)\r\n    a(i) = a(i) + 1;</code></pre>\r\nIn this case, each instance of the gfor loop is independent, thus ArrayFire will automatically tile out the <code>a</code> array in device memory and execute the increment kernels in parallel.\r\n\r\nTo see another example, you could run an <a class=\"el\" title=\"C++ Interface exclusive sum (cumulative sum) of an array. \" href=\"group__scan__func__accum.htm#gae450135c4ae1bdaa4489804a215f3214\">accum()</a> on every slice of a matrix in a for-loop, or you could \"vectorize\" and simply do it all in one gfor-loop operation:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// runs each accum() in sequence\r\nfor (int i = 0; i &lt; N; ++i)\r\n    B(span,i) = accum(A(span,i));\r\n \r\n// runs N accums in parallel\r\ngfor (seq i, N)\r\n    B(span,i) = accum(A(span,i));</pre>\r\n</div>\r\n</div>\r\nHowever, returning to our previous vectorization technique, <a class=\"el\" title=\"C++ Interface exclusive sum (cumulative sum) of an array. \" href=\"group__scan__func__accum.htm#gae450135c4ae1bdaa4489804a215f3214\">accum()</a> is already vectorized and the operation could be completely replaced with merely:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">B = accum(A);</pre>\r\n</div>\r\n</div>\r\nIt is best to vectorize computation as much as possible to avoid the overhead in both for-loops and gfor-loops. However, the gfor-loop construct is most effective in the narrow case of broadcast-style operations. Consider the case when we have a vector of constants that we wish to apply to a collection of variables, such as expressing the values of a linear combination for multiple vectors. The broadcast of one set of constants to many vectors works well with gfor-loops:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">const static int p=4, n=1000;\r\naf::array consts = af::randu(p);\r\naf::array var_terms = randn(p, n);\r\n \r\ngfor(seq i, n)\r\n    combination(span, i) = consts * var_terms(span, i);</pre>\r\n</div>\r\n</div>\r\nUsing GFOR requires following several rules and multiple guidelines for optimal performance. The details of this vectorization method can be found in the <a class=\"el\" href=\"page_gfor.htm#gfor\">GFOR documentation</a>.\r\n<h4><a id=\"Batching_127\"></a>Batching</h4>\r\nThe <a class=\"el\" href=\"namespaceaf.htm#aa0eb9e160f5be4b95234543e5c47934b\">batchFunc()</a> function allows the broad application of existing ArrayFire functions to multiple sets of data. Effectively,<a class=\"el\" href=\"namespaceaf.htm#aa0eb9e160f5be4b95234543e5c47934b\">batchFunc()</a> allows ArrayFire functions to execute in \"batch processing\" mode. In this mode, functions will find a dimension which contains \"batches\" of data to be processed and will parallelize the procedure.\r\n\r\nConsider the following example. Here we create a filter which we would like to apply to each of the weight vectors. The naive solution would be using a for-loop as we have seen previously:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// Create the filter and the weight vectors\r\naf::array filter = randn(1, 5);\r\naf::array weights = randu(5, 5);\r\n \r\n// Apply the filter using a for-loop\r\naf::array filtered_weights = constant(0, 5, 5);\r\nfor(int i=0; i&lt;weights.dims(1); ++i){\r\n    filtered_weights.col(i) = filter * weights.col(i);\r\n}</pre>\r\n</div>\r\n</div>\r\nHowever, as we have discussed above, this solution will be very inefficient. One may be tempted to implement a vectorized solution as follows:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// Create the filter and the weight vectors\r\naf::array filter = randn(1, 5);\r\naf::array weights = randu(5, 5);\r\n \r\naf::array filtered_weights = filter * weights; // fails due to dimension mismatch</pre>\r\n</div>\r\n</div>\r\nHowever, the dimensions of <code>filter</code> and <code>weights</code> do not match, thus ArrayFire will generate a runtime error.\r\n\r\n<code>batchfunc()</code> was created to solve this specific problem. The signature of the function is as follows:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">array batchFunc(const array &amp;lhs, const array &amp;rhs, batchFunc_t func);</pre>\r\n</div>\r\n</div>\r\nwhere <code>__batchFunc_t__</code> is a function pointer of the form:\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">typedef array (*batchFunc_t) (const array &amp;lhs, const array &amp;rhs);</pre>\r\n</div>\r\n</div>\r\nSo, to use <a class=\"el\" href=\"namespaceaf.htm#aa0eb9e160f5be4b95234543e5c47934b\">batchFunc()</a>, we need to provide the function we wish to apply as a batch operation. For illustration\'s sake, let\'s \"implement\" a multiplication function following the format.\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">af::array my_mult (const af::array &amp;lhs, const af::array &amp;rhs){\r\nreturn lhs * rhs;\r\n}</pre>\r\n</div>\r\n</div>\r\nOur final batch call is not much more difficult than the ideal syntax we imagined.\r\n<div class=\"fragment\">\r\n<div class=\"line\">\r\n<pre class=\"lang:default decode:true \">// Create the filter and the weight vectors\r\naf::array filter = randn(1, 5);\r\naf::array weights = randu(5, 5);\r\n \r\n// Apply the batch function\r\naf::array filtered_weights = batchFunc( filter, weights, my_mult );</pre>\r\n</div>\r\n</div>\r\nThe batch function will work with many previously mentioned vectorized ArrayFire functions. It can even work with a combination of those functions if they are wrapped inside a helper function matching the <code>__batchFunc_t__</code> signature. One limitation of <code>batchfunc()</code> is that it cannot be used from within a <code><a class=\"el\" href=\"gfor_8h.htm#a6d6cd11d53daad217fd0b92f5a7ceec6\">gfor()</a></code> loop at the present time.\r\n<h4><a id=\"Advanced_Vectorization_181\"></a>Advanced Vectorization</h4>\r\nWe have seen the different methods ArrayFire provides to vectorize our code. Tying them all together is a slightly more involved process that needs to consider data dimensionality and layout, memory usage, nesting order, etc. An excellent example and discussion of these factors can be found in another blog post:\r\n\r\n<a href=\"http://sandbox.arrayfire.com/how-to-write-vectorized-code/\">http://sandbox.arrayfire.com/how-to-write-vectorized-code/</a>\r\n\r\nIt’s worth noting that the whole implementation discussed in the blog has since been transformed into a convenient <strong>af::nearestNeighbour()</strong> function. Before writing something from scratch, check that ArrayFire doesn’t already have an implementation. The default vectorized nature of ArrayFire and an extensive collection of functions will speed things up in addition to replacing dozens of lines of code!','Introduction to Vectorization in ArrayFire','','inherit','closed','closed','','8735-revision-v1','','','2016-05-25 13:36:20','2016-05-25 17:36:20','',8735,'http://sandbox.arrayfire.com/8735-revision-v1/',0,'revision','',0),