(9662,17729,'2017-06-22 05:50:01','2017-06-22 09:50:01','Today, we are pleased to announce the first stable release of Forge - a high performance OpenGL visualization library for C/C++ applications that use CUDA/OpenCL as computational backbone.\r\n\r\nForge\'s functionality is primarily exposed via C API. We recommend using the C++ wrapper written atop C API. The C API is mainly intended to enable easy write of bindings for other languages. First, we shall go through the details of how to create a window using Forge and later illustrate the rest of functionality from v1.0 using some sample code snippets and images.\r\n\r\n<h4>How to Create a Window</h4>\r\n<code>\r\n<pre>\r\n#include <forge.h>\r\n\r\n#define USE_FORGE_CPU_COPY_HELPERS\r\n/*\r\n * Below <ComputeCopy.h> header inclusion requires definition of atleast one\r\n * of the following so that appropriate copy helper functions are included\r\n * for helping the user copy data from their own respective GPU buffer\'s to\r\n * the OpenGL buffers\r\n *     - USE_FORGE_CPU_COPY_HELPERS\r\n *     - USE_FORGE_CUDA_COPY_HELPERS\r\n *     - USE_FORGE_OPENCL_COPY_HELPERS\r\n */\r\n#include <ComputeCopy.h>\r\n\r\n/*\r\n * The user may choose to implement their own data updation code and skip\r\n * using the one provided by <ComputeCopy.h>\r\n */\r\n\r\nconst unsigned W = 1000;\r\nconst unsigned H = 800;\r\n\r\nusing namespace std;\r\n\r\nint main(void)\r\n{\r\n    /*\r\n     * First Forge call should be a window creation call\r\n     * so that necessary OpenGL context is created for any\r\n     * other forge::* object to be created successfully\r\n     */\r\n    forge::Window wnd(W, H, \"Forge Demo\");\r\n    wnd.makeCurrent(); //Make the window\'s context current\r\n\r\n	/* All GPU buffers creation and population with data\r\n     *  happens here\r\n     */\r\n\r\n    // Render loop begins\r\n    do {\r\n        // All draw calls go here\r\n    } while(!wnd.close());\r\n\r\n    return 0;\r\n}\r\n</pre>\r\n</code>\r\n\r\n<ul> 	\r\n 	<li>Full documentation of the library can be found <a href=\"http://arrayfire.org/forge/index.htm\">here</a>.</li>\r\n 	<li>Forge exposes all it\'s objects and function via the namespace <code>forge</code>. It has the following main classes.\r\n<ul>\r\n 	<li><code>forge::Window</code> - objects of this class provide the rendering canvas over which other objects are rendered.</li>\r\n 	<li><code>forge::Image</code> and <code>forge::Chart</code> are the two main rendering objects that drawn on <code>forge::Window</code>\r\n<ul>\r\n 	<li><code>forge::Image</code> is a rendering of a simple image to Window.</li>\r\n 	<li><code>forge::Chart</code> is base object to which other plotting objects (listed below) are appended and rendered in the order of addition with alpha blending.\r\n<ul>\r\n 	<li><code>forge::Histogram</code> - bar graphs</li>\r\n 	<li><code>forge::Plot</code> - 2D and 3D plots</li>\r\n 	<li><code>forge::Surface</code> - 3D surface plots</li>\r\n 	<li><code>forge::VectorField</code> - 2D and 3D vector fields</li>\r\n</ul>\r\n</li>\r\n</ul>\r\n</li>\r\n 	<li><code>forge::Font</code> - provides the choice of selecting the font for your program\'s rendering. You may skip using this class and the library will defer to the default fonts.</li>\r\n 	<li><code>forge::Error</code> - This is the exception object that you should use to catch the errors thrown by Forge.</li>\r\n</ul>\r\n</li>\r\n<li> Forge provides basic mouse interactivity such as pan, zoom and trackball rotation. </li>\r\n<li> All chart objects can have legends specific to each type of plot added to charts. </li>\r\n<li> Default window toolkit used by Forge is <a href=\"http://www.glfw.org/\" target=\"_blank\">GLFW</a>. However, you can also build Forge with <a href=\"https://www.libsdl.org/\" target=\"_blank\">SDL2</a>. </li>\r\n 	<li>Forge being a rendering only library, provides only the logic for rendering. However, we do provide helper functions through <a href=\"https://github.com/arrayfire/forge/blob/devel/include/ComputeCopy.h\">ComputeCopy.h headers</a> for the user\'s convenience.</li>\r\n 	<li>You can find the list of examples <a href=\"http://arrayfire.org/forge/examples.htm\">here</a>. These examples use the above <code>ComputeCopy</code> header.</li>\r\n</ul>\r\n\r\n<h4>Sample Images</h4>\r\n\r\n<table border=\"0\">\r\n<tbody>\r\n<tr>\r\n<td>\r\n\r\n[caption id=\"attachment_9630\" align=\"alignnone\" width=\"283\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_image.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_image-283x300.png\" alt=\"Image\" width=\"283\" height=\"300\" class=\"size-medium wp-image-9630\" /></a> Image[/caption]\r\n\r\n</td>\r\n<td>\r\n\r\n[caption id=\"attachment_9629\" align=\"alignnone\" width=\"300\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_hist.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_hist-300x203.png\" alt=\"Histogram\" width=\"300\" height=\"203\" class=\"size-medium wp-image-9629\" /></a> Histogram[/caption]\r\n\r\n</td>\r\n</tr>\r\n<tr>\r\n<td>\r\n\r\n[caption id=\"attachment_9628\" align=\"alignnone\" width=\"300\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_bubble.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_bubble-300x254.png\" alt=\"2D Plot\" width=\"300\" height=\"254\" class=\"size-medium wp-image-9628\" /></a> 2D Plot[/caption]\r\n\r\n</td>\r\n<td>\r\n\r\n[caption id=\"attachment_9634\" align=\"alignnone\" width=\"300\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_surface.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_surface-300x238.png\" alt=\"Surface\" width=\"300\" height=\"238\" class=\"size-medium wp-image-9634\" /></a> Surface[/caption]\r\n\r\n</td>\r\n</tr>\r\n<tr>\r\n<td>\r\n\r\n[caption id=\"attachment_9632\" align=\"alignnone\" width=\"300\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_plot31.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_plot31-300x251.png\" alt=\"3D Plot\" width=\"300\" height=\"251\" class=\"size-medium wp-image-9632\" /></a> 3D Plot[/caption]\r\n\r\n</td>\r\n<td>\r\n\r\n[caption id=\"attachment_9633\" align=\"alignnone\" width=\"300\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_plot32.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_plot32-300x253.png\" alt=\"Rotated 3D Plot\" width=\"300\" height=\"253\" class=\"size-medium wp-image-9633\" /></a> Rotated 3D Plot[/caption]\r\n\r\n</td>\r\n</tr>\r\n</tbody>\r\n</table>\r\n\r\n<h4>Community</h4>\r\nForge is continually improving through addition of new features. We welcome your feedback:\r\n\r\nGeneral discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\" target=\"_blank\">ArrayFire Google Group</a>\r\nLive discussion chat on the <a href=\"https://gitter.im/arrayfire/forge?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\" target=\"_blank\">Forge Gitter</a>\r\nIssue reports on the <a href=\"https://github.com/arrayfire/forge/issues\" target=\"_blank\">Forge GitHub</a>\r\nFinally, as you find success with Forge, we invite you to contribute a post to this blog to share with the broader community. Email sales@arrayfire.com to contribute to this blog.','Forge v1.0 Official Release','','inherit','closed','closed','','9615-revision-v1','','','2017-06-22 05:50:01','2017-06-22 09:50:01','',9615,'https://sandbox.arrayfire.com/9615-revision-v1/',0,'revision','',0),(9663,17729,'2017-06-22 07:55:54','2017-06-22 11:55:54','Today, we are pleased to announce the first stable release of Forge - a high performance OpenGL visualization library for C/C++ applications that use CUDA/OpenCL as computational backbone.\r\n\r\nForge\'s functionality is primarily exposed via C API. We recommend using the C++ wrapper written atop C API. The C API is mainly intended to enable easy write of bindings for other languages. First, we shall go through the details of how to create a window using Forge and later illustrate the rest of functionality from v1.0 using some sample code snippets and images. Note that all the example code snippets given below use the C++ API.\r\n\r\nThere are two kinds of basic renderings in forge. One is an Image and the other is a Chart. Chart by itself doesn\'t render anything other than axes and some labels on it. Chart has to be embedded with one or more of the following graphs.\r\n<ul>\r\n<li> 2D Line Plots </li>\r\n<li> 3D Line Plots </li>\r\n<li> Surfaces </li>\r\n<li> Histograms </li>\r\n<li> Vector fields, both 2D and 3D</li>\r\n<li> Images </li>\r\n</ul>\r\n\r\n<h4>How to Create a Window</h4>\r\nThe code used to create a window is identical in all the examples that illustrate inter-operation of CPU/CUDA/OpenCL with OpenGL. Therefore, the following window creation code is not repeated in later code snippets where only the draw calls and data-update steps will be shown.\r\n<pre>\r\n<code>\r\n#include <forge.h>\r\n\r\n#define USE_FORGE_CPU_COPY_HELPERS\r\n/*\r\n * Below <ComputeCopy.h> header inclusion requires definition of atleast one\r\n * of the following so that appropriate copy helper functions are included\r\n * for helping the user copy data from their own respective GPU buffer\'s to\r\n * the OpenGL buffers\r\n *     - USE_FORGE_CPU_COPY_HELPERS     // Used for Interoperation of OpenGL with CPU memory\r\n *     - USE_FORGE_CUDA_COPY_HELPERS    // Used for Interoperation of OpenGL with CUDA device memory\r\n *     - USE_FORGE_OPENCL_COPY_HELPERS  // Used for Interoperation of OpenGL with OpenCL device memory\r\n */\r\n#include <ComputeCopy.h>\r\n\r\n/*\r\n * The user may choose to implement their own data updation code and skip\r\n * using the one provided by <ComputeCopy.h>\r\n */\r\n\r\nconst unsigned W = 512;\r\nconst unsigned H = 512;\r\n\r\nusing namespace std;\r\n\r\nint main(void)\r\n{\r\n    /*\r\n     * First Forge call should be a window creation call\r\n     * so that necessary OpenGL context is created for any\r\n     * other forge::* object to be created successfully\r\n     */\r\n    forge::Window wnd(W, H, \"Forge Demo\");\r\n    wnd.makeCurrent(); //Make the window\'s context current\r\n\r\n	/* All GPU buffers creation and population with data\r\n     *  happens here\r\n     */\r\n\r\n    // Render loop begins\r\n    do {\r\n        // All draw calls go here\r\n\r\n        // We can also update the data inside\r\n        // render loop to creation animations\r\n    } while(!wnd.close());\r\n\r\n    return 0;\r\n}\r\n</code>\r\n</pre>\r\n\r\n<h4>Rendering an Image to Window</h4>\r\nImage rendering example will be demonstrated using GL-CPU interop. Once the window creation is completed, we have to create an object of class <em>forge::Image</em>. \r\n<pre>\r\n<code>\r\n/* Create an image object which creates the necessary\r\n * textures and pixel buffer objects to hold the image\r\n * */\r\nforge::Image img(W, H, FG_RGBA, forge::u8);\r\n</code>\r\n</pre>\r\n\r\nNow, create a variable of type <em>GfxHandle</em> that points to the OpenGL buffer and transfer the\r\ndata from CPU memory to OpenGL memory. The functions <em>createGLBuffer</em>, <em>copyToGLBuffer</em> are defined in ComputeCopy.h header.\r\n<pre>\r\n<code>\r\nkernel(bmp);                    // create the fractal\r\n\r\nGfxHandle* handle = 0;          // GL-CPU interop buffer handle\r\n    \r\ncreateGLBuffer(&handle, img.pixels(), FORGE_IMAGE_BUFFER);\r\n\r\n// copy the data from compute buffer to graphics buffer\r\ncopyToGLBuffer(handle, (ComputeResourceHandle)bmp.ptr, img.size());\r\n</code>\r\n</pre>\r\nIt\'s time to render the image to window. If at all, the image needs to be updated during the render loop, you can do so by calling <em>copyToGLBuffer</em> with updated data pointer.\r\n<pre>\r\n<code>\r\ndo {\r\n    wnd.draw(img); // Draw call to render an image to window\r\n} while(!wnd.close());\r\n</code>\r\n</pre>\r\n\r\nClean up the resources.\r\n<pre>\r\n<code>\r\n// destroy GL-CPU Interop buffer\r\nreleaseGLBuffer(handle); // In ComputeCopy.h\r\ndestroyBitmap(bmp); // Clear CPU memory buffer\r\n</code>\r\n</pre>\r\n\r\nYou can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/cpu/fractal.cpp\">here</a>. The output of fractal render is shown below.\r\n[caption id=\"attachment_9630\" align=\"aligncenter\" width=\"728\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_image.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_image.png\" alt=\"Fractal Demo\" width=\"728\" height=\"772\" class=\"size-full wp-image-9630\" /></a> Fractal Demo[/caption]\r\n\r\n<h4>Rendering a Histogram</h4>\r\nWe will use CUDA-GL interop for this example. Let\'s create an object of class <em>forge::Histogram</em> and add it to a <em>forge::Chart</em> object.\r\n<pre>\r\n<code>\r\nforge::Image img(IMGW, IMGH, FG_RGBA, forge::u8); //Image placeholder\r\n\r\nforge::Chart chart(FG_CHART_2D); // Histogram is a 2D graph, hence a 2D chart\r\n\r\n//Axes Labels Format uses printf style formatting\r\nchart.setAxesLabelFormat(\"%3.1f\", \"%.2e\");\r\n\r\n/* set x axis limits to maximum and minimum values of data\r\n * and y axis limits to range [0, number of pixels ideally]\r\n * but practically total number of pixels as y range will skew\r\n * the histogram graph vertically. Therefore setting it to\r\n * 25% of total number of pixels */\r\nchart.setAxesLimits(0, 1, 0, IMGW*IMGH/(float)(NBINS/4.0));\r\n\r\n// Create histogram object specifying number of bins\r\n// this call automatically appends the histogram to list\r\n// of objects to be rendered by chart after it is created.\r\nforge::Histogram hist = chart.histogram(NBINS, forge::s32);\r\n\r\n// Set histogram colors\r\n// this color is used if no per-bar colors are not used\r\nhist.setColor(FG_YELLOW);\r\n</code>\r\n</pre>\r\nNow, create GL buffer handles for image, histogram bars and histogram bar colors.\r\n<pre>\r\n<code>\r\n#define USE_FORGE_CUDA_COPY_HELPERS\r\n//Including USE_FORGE_CUDA_COPY_HELPERS instead of USE_FORGE_CPU_COPY_HELPERS\r\n//makes all the difference when it comes to using the copy helper functions\r\n//provided in the below header. The user code will still remain very similar\r\n//to it\'s CPU or OPENCL counterparts.\r\n#include <ComputeCopy.h>\r\n\r\nGfxHandle* handles[3];\r\n\r\ncreateGLBuffer(&handles[0], img.pixels(), FORGE_IMAGE_BUFFER);\r\ncreateGLBuffer(&handles[1], hist.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[2], hist.colors(), FORGE_VERTEX_BUFFER);\r\n\r\n//Helper fn used to create histogram from image\r\nkernel(bmp, noiseGenerator);\r\n\r\n//Copy image to img resource handle\r\ncopyToGLBuffer(handles[0], (ComputeResourceHandle)bmp.ptr, img.size());\r\n\r\n// create the histogram from image and generate\r\n// histogram bar colors\r\npopulateBins(bmp, histOut, NBINS, histColors);\r\n\r\n//Copy histogram frequencies and bar colors to OpenGL buffers\r\ncopyToGLBuffer(handles[1], (ComputeResourceHandle)histOut, hist.verticesSize());\r\ncopyToGLBuffer(handles[2], (ComputeResourceHandle)histColors, hist.colorsSize());\r\n</code>\r\n</pre>\r\nIt\'s time to render the histogram and image to the window. Note that we added only histogram to chart, so the image has to be somehow rendered to the same window such that we can view both the image and histogram at the same time. Multiple view rendering comes to rescue here.\r\n<pre>\r\n<code>\r\ndo {\r\n     /*\r\n      * Split the window into grid regions\r\n      */\r\n     // Render the image to the sub-view with index 0 if the\r\n     // entire window is divided into 1 row and 2 columns\r\n     wnd.draw(1, 2, 0, img,  \"Dynamic Perlin Noise\" );\r\n\r\n     // Render the image to the sub-view with index 1 if the\r\n     // entire window is divided into 1 row and 2 columns\r\n     wnd.draw(1, 2, 1, chart, \"Histogram of Noisy Image\");\r\n\r\n     // Swap the render buffers to display new rendering\r\n     wnd.swapBuffers(); \r\n} while(!wnd.close());\r\n\r\n// cleanup resources\r\nFORGE_CUDA_CHECK(cudaFree(histOut));\r\nFORGE_CUDA_CHECK(cudaFree(histColors));\r\nreleaseGLBuffer(handles[0]);\r\nreleaseGLBuffer(handles[1]);\r\nreleaseGLBuffer(handles[2]);\r\n</code>\r\n</pre>\r\nYou can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/cuda/histogram.cu\">here</a>. The output of histogram render is shown below.\r\n[caption id=\"attachment_9629\" align=\"aligncenter\" width=\"1228\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_hist.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_hist.png\" alt=\"Histogram\" width=\"1228\" height=\"829\" class=\"size-full wp-image-9629\" /></a> Histogram[/caption]\r\n\r\n<h4>Rendering Multiple Plots on a Chart</h4>\r\nWe will use OpenCL-OpenGL interop for this example. When it comes to interop with OpenCL, please make sure OpenGL context is created first before setting up any of the OpenCL objects.\r\n<pre>\r\n<code>\r\n// Do \"#define USE_FORGE_OPENCL_COPY_HELPERS\" before including ComputeCopy header.\r\n\r\nforge::Chart chart(FG_CHART_2D);\r\nchart.setAxesLimits(FRANGE_START, FRANGE_END, -1.0f, 1.0f);\r\n\r\n/* Create several plot objects which creates the necessary\r\n * vertex buffer objects to hold the different plot types\r\n */\r\n// Line plot with triangle markers at data points\r\nforge::Plot plt1 = chart.plot(DATA_SIZE, forge::f32, FG_PLOT_LINE, FG_MARKER_TRIANGLE);\r\n\r\n// Line plot with circular markers at data points\r\nforge::Plot plt2 = chart.plot(DATA_SIZE, forge::f32, FG_PLOT_LINE, FG_MARKER_CIRCLE);\r\n\r\n/* Set plot colors */\r\n//use a forge predefined color FG_GREEN & FG_RED\r\nplt1.setColor(FG_RED);\r\nplt2.setColor(FG_GREEN);\r\n\r\n/* Set plot legends */\r\nplt1.setLegend(\"Cosine\");\r\nplt2.setLegend(\"Tangent\");\r\n\r\n/* set plot global marker size */\r\nplt1.setMarkerSize(20);\r\n//plt2 will use default marker size\r\n\r\n/*\r\n * Helper function to create a CLGL interop context.\r\n * This function checks for if the extension is available\r\n * and creates the context on the appropriate device.\r\n *\r\n * Note: context and queue are defined in cl_helpers.h\r\n *       and these are returned by getContext() and getCommandQueue()\r\n *       functions when they are called by createGLBuffer, copyToGLBuffer\r\n *       and releaseGLBuffer copy helper functions\r\n */\r\ncontext = createCLGLContext(wnd);\r\nDevice device = context.getInfo<CL_CONTEXT_DEVICES>()[0];\r\nqueue = CommandQueue(context, device);\r\n\r\nGfxHandle* handles[5];\r\n\r\n// create GL-OpenCL interop buffers\r\ncreateGLBuffer(&handles[0], plt1.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[1], plt2.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[2], plt2.colors(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[3], plt2.alphas(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[4], plt2.radii(), FORGE_VERTEX_BUFFER);\r\n\r\ncl::Buffer cosOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 2);\r\ncl::Buffer tanOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 2);\r\ncl::Buffer colorsOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 3);\r\ncl::Buffer alphasOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE);\r\ncl::Buffer radiiOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE);\r\ncl::Buffer dummy;\r\n\r\nkernel(cosOut, 0, 0, dummy, dummy, dummy, queue, device);\r\nkernel(tanOut, 1, 0x00000007, colorsOut, alphasOut, radiiOut, queue, device);\r\n\r\n/* copy your data into the opengl buffer object exposed by\r\n * forge::Plot class and then proceed to rendering.\r\n * To help the users with copying the data from compute\r\n * memory to display memory, Forge provides copy headers\r\n * along with the library to help with this task\r\n */\r\ncopyToGLBuffer(handles[0], (ComputeResourceHandle)cosOut(), plt1.verticesSize());\r\ncopyToGLBuffer(handles[1], (ComputeResourceHandle)tanOut(), plt2.verticesSize());\r\n\r\n/* update color value for tan graph */\r\ncopyToGLBuffer(handles[2], (ComputeResourceHandle)colorsOut(), plt2.colorsSize());\r\n\r\n/* update alpha values for tan graph */\r\ncopyToGLBuffer(handles[3], (ComputeResourceHandle)alphasOut(), plt2.alphasSize());\r\n\r\n/* update marker sizes for tan graph markers */\r\ncopyToGLBuffer(handles[4], (ComputeResourceHandle)radiiOut(), plt2.radiiSize());\r\n</code>\r\n</pre>\r\nThe draw call is similar to how image example since we don\'t have multiple view rendering here. You can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/opencl/bubblechart.cpp\">here</a>. The output of multiple plot rendering is shown below.\r\n[caption id=\"attachment_9628\" align=\"aligncenter\" width=\"998\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_bubble.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_bubble.png\" alt=\"Multiple Plots Per Chart\" width=\"998\" height=\"844\" class=\"size-full wp-image-9628\" /></a> Multiple Plots Per Chart[/caption]\r\n\r\n<h4>Community</h4>\r\nForge is continually improving through addition of new features. We welcome your feedback. Please feel free to leave your comments on any of the following channels.\r\n\r\nGeneral discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\" target=\"_blank\">ArrayFire Google Group</a>\r\nLive discussion chat on the <a href=\"https://gitter.im/arrayfire/forge?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\" target=\"_blank\">Forge Gitter</a>\r\nIssue reports on the <a href=\"https://github.com/arrayfire/forge/issues\" target=\"_blank\">Forge GitHub</a>\r\nFinally, as you find success with Forge, we invite you to contribute a post to this blog to share with the broader community. Email sales@arrayfire.com to contribute to this blog.','Forge v1.0 Official Release','','inherit','closed','closed','','9615-revision-v1','','','2017-06-22 07:55:54','2017-06-22 11:55:54','',9615,'https://sandbox.arrayfire.com/9615-revision-v1/',0,'revision','',0),(9664,17729,'2017-06-22 08:39:48','2017-06-22 12:39:48','','grids','','inherit','open','closed','','grids','','','2017-06-22 08:39:48','2017-06-22 12:39:48','',9615,'https://sandbox.arrayfire.com/wp-content/uploads/2017/06/grids.png',0,'attachment','image/png',0),(9665,17729,'2017-06-22 08:56:07','2017-06-22 12:56:07','','vfield','Vector Field','inherit','open','closed','','vfield-2','','','2017-06-22 08:56:18','2017-06-22 12:56:18','',9615,'https://sandbox.arrayfire.com/wp-content/uploads/2017/06/vfield.png',0,'attachment','image/png',0),(9669,1,'2017-06-23 12:33:19','2017-06-23 16:33:19','','Order &ndash; June 23, 2017 @ 12:33 PM','','wc-completed','open','closed','order_594d42ce30b7f','order-jun-23-2017-0433-pm','','','2017-06-23 12:33:26','2017-06-23 16:33:26','',0,'https://sandbox.arrayfire.com/?post_type=shop_order&#038;p=9669',0,'shop_order','',3),(9674,17729,'2017-07-04 04:11:37','2017-07-04 08:11:37','[content_band inner_container=\"true\" no_margin=\"true\" border=\"none\" padding_top=\"10px\" padding_bottom=\"40px\"]\n[custom_headline type=\"left\" level=\"h2\"]\nArrayFire Installers\n[/custom_headline]\n[custom_headline type=\"left\" level=\"h5\"]\nEach download contains both CUDA and OpenCL files.\n[/custom_headline]\n[gap size=\"4%\"]\n\n[column type=\"one-fifth\"][button  block=\"true\" onclick=\"&lt;!-- Google Code for ArrayFire Download (Windows) Conversion Page\nIn your html page, add the snippet and call\ngoog_report_conversion when someone clicks on the\nchosen link or button. --&gt;\n&lt;script type=\"text/javascript\"&gt;\n/* &lt;!&amp;#91;CDATA&amp;#91; */\ngoog_snippet_vars = function() {\nvar w = window;\nw.google_conversion_id = 1021026651;\nw.google_conversion_label = \"18VJCJjPql4Q28Lu5gM\";\nw.google_remarketing_only = false;\n}\n// DO NOT CHANGE THE CODE BELOW.\ngoog_report_conversion = function(url) {\ngoog_snippet_vars();\nwindow.google_conversion_format = \"3\";\nwindow.google_is_call = true;\nvar opt = new Object();\nopt.onload_callback = function() {\nif (typeof(url) != \'undefined\') {\nwindow.location = url;\n}\n}\nvar conv_handler = window&amp;#91;\'google_trackConversion\'&amp;#93;;\nif (typeof(conv_handler) == \'function\') {\nconv_handler(opt);\n}\n}\n/* &amp;#93;&amp;#93;&gt; */\n&lt;/script&gt;\n&lt;script type=\"text/javascript\"\nsrc=\"//www.googleadservices.com/pagead/conversion_async.js\"&gt;\n&lt;/script&gt;\" class=\"center-text\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/lvvyk\" size=\"regular\" ]Windows, v3.5.0\n(64-bit)[/button][/column][column type=\"one-fifth\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/lw515\" size=\"regular\" ]Linux, v3.5.0\n(64-bit)[/button][/column][column type=\"one-fifth\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/ltx4p\" size=\"regular\" ]Mac OSX, v3.5.0\n(64-bit)[/button][/column][column type=\"one-fifth\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"http://sandbox.arrayfire.com/installer_archive/3.5.0/ArrayFire-v3.5.0_Linux_aarch64.sh\" size=\"regular\" ]Tegra X1 v3.5.0\n(64-bit)[/button][/column][column type=\"one-fifth\" last=\"true\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/lw51f\" size=\"regular\"]Tegra K1 v3.5.0\n(32-bit)[/button][/column][gap size=\"9%\"]\n\nCheck out our GitHub repository to <a href=\"https://github.com/arrayfire/arrayfire\">build from the source</a>.\n\nLooking for an older installer? <a href=\"http://sandbox.arrayfire.com/installer_archive\">Try here</a>.[/content_band]\n<p style=\"text-align: left;\">[content_band inner_container=\"true\" no_margin=\"true\" border=\"none\" padding_top=\"10px\" padding_bottom=\"40px\" bg_color=\"#f1f1f1\"][column type=\"one-half\"][gap size=\"8%\"]<img class=\"aligncenter wp-image-5156\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/mobile_Exported1-e1395437261846.png\" alt=\"mobile_Exported\" width=\"233\" height=\"311\" />[/column][column type=\"one-half\" last=\"true\"]\n[custom_headline type=\"left\" level=\"h2\"]\nGreat. What now?\n[/custom_headline]</p>\n<p style=\"text-align: left;\">[gap size=\"5%\"]</p>\n<p style=\"text-align: left;\">Welcome to ArrayFire! You\'ve got an awesome library there—learn more about its features and functions on <a href=\"http://www.sandbox.arrayfire.com/docs/index.htm\">our documentation</a>.</p>\n<p style=\"text-align: left;\">In addition to our <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire user group</a> and <a href=\"http://sandbox.arrayfire.com/blog/\">our blog</a>, we offer a plethora of <a href=\"http://sandbox.arrayfire.com/support/\">support options</a> to fit your needs.</p>\n<p style=\"text-align: left;\">Got a job that needs closer attention? Hire us! Our engineers are acceleration wizards. Check out our <a href=\"http://sandbox.arrayfire.com/consulting/\">consulting offerings</a>, or set up a free <a href=\"http://meetme.so/arrayfire\">technical consultation</a> with us today![/column]</p>\n<p style=\"text-align: left;\">[/content_band]</p>\n<p style=\"text-align: center;\"></p>','Download','','inherit','closed','closed','','5931-autosave-v1','','','2017-07-04 04:11:37','2017-07-04 08:11:37','',5931,'https://sandbox.arrayfire.com/5931-autosave-v1/',0,'revision','',0),(9677,18672,'2017-07-04 05:18:02','2017-07-04 09:18:02','<del datetime=\"2017-07-04T09:17:16+00:00\">','Linux x86_64 installer','','inherit','closed','closed','','8520-revision-v1','','','2017-07-04 05:18:02','2017-07-04 09:18:02','',8520,'https://sandbox.arrayfire.com/8520-revision-v1/',0,'revision','',0),(9678,18672,'2017-07-04 05:22:00','2017-07-04 09:22:00','[content_band inner_container=\"true\" no_margin=\"true\" border=\"none\" padding_top=\"10px\" padding_bottom=\"40px\"]\r\n[custom_headline type=\"left\" level=\"h2\"]\r\nArrayFire Installers\r\n[/custom_headline]\r\n[custom_headline type=\"left\" level=\"h5\"]\r\nEach download contains both CUDA and OpenCL files.\r\n[/custom_headline]\r\n[gap size=\"4%\"]\r\n\r\n[column type=\"one-fifth\"][button  block=\"true\" onclick=\"&lt;!-- Google Code for ArrayFire Download (Windows) Conversion Page\r\nIn your html page, add the snippet and call\r\ngoog_report_conversion when someone clicks on the\r\nchosen link or button. --&gt;\r\n&lt;script type=\"text/javascript\"&gt;\r\n/* &lt;!&amp;#91;CDATA&amp;#91; */\r\ngoog_snippet_vars = function() {\r\nvar w = window;\r\nw.google_conversion_id = 1021026651;\r\nw.google_conversion_label = \"18VJCJjPql4Q28Lu5gM\";\r\nw.google_remarketing_only = false;\r\n}\r\n// DO NOT CHANGE THE CODE BELOW.\r\ngoog_report_conversion = function(url) {\r\ngoog_snippet_vars();\r\nwindow.google_conversion_format = \"3\";\r\nwindow.google_is_call = true;\r\nvar opt = new Object();\r\nopt.onload_callback = function() {\r\nif (typeof(url) != \'undefined\') {\r\nwindow.location = url;\r\n}\r\n}\r\nvar conv_handler = window&amp;#91;\'google_trackConversion\'&amp;#93;;\r\nif (typeof(conv_handler) == \'function\') {\r\nconv_handler(opt);\r\n}\r\n}\r\n/* &amp;#93;&amp;#93;&gt; */\r\n&lt;/script&gt;\r\n&lt;script type=\"text/javascript\"\r\nsrc=\"//www.googleadservices.com/pagead/conversion_async.js\"&gt;\r\n&lt;/script&gt;\" class=\"center-text\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/lvvyk\" size=\"regular\" ]Windows, v3.5.0\r\n(64-bit)[/button][/column][column type=\"one-fifth\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/lw515\" size=\"regular\" ]Linux, v3.5.0\r\n(64-bit)[/button][/column][column type=\"one-fifth\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/ltx4p\" size=\"regular\" ]Mac OSX, v3.5.0\r\n(64-bit)[/button][/column][column type=\"one-fifth\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"http://sandbox.arrayfire.com/installer_archive/3.4.2/ArrayFire-v3.4.2_Linux_aarch64.sh\" size=\"regular\" ]Tegra X1 v3.4.2\r\n(64-bit)[/button][/column][column type=\"one-fifth\" last=\"true\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/lw51f\" size=\"regular\"]Tegra K1 v3.4.2\r\n(32-bit)[/button][/column][gap size=\"9%\"]\r\n\r\nCheck out our GitHub repository to <a href=\"https://github.com/arrayfire/arrayfire\">build from the source</a>.\r\n\r\nLooking for an older installer? <a href=\"http://sandbox.arrayfire.com/installer_archive\">Try here</a>.[/content_band]\r\n<p style=\"text-align: left;\">[content_band inner_container=\"true\" no_margin=\"true\" border=\"none\" padding_top=\"10px\" padding_bottom=\"40px\" bg_color=\"#f1f1f1\"][column type=\"one-half\"][gap size=\"8%\"]<img class=\"aligncenter wp-image-5156\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/mobile_Exported1-e1395437261846.png\" alt=\"mobile_Exported\" width=\"233\" height=\"311\" />[/column][column type=\"one-half\" last=\"true\"]\r\n[custom_headline type=\"left\" level=\"h2\"]\r\nGreat. What now?\r\n[/custom_headline]</p>\r\n<p style=\"text-align: left;\">[gap size=\"5%\"]</p>\r\n<p style=\"text-align: left;\">Welcome to ArrayFire! You\'ve got an awesome library there—learn more about its features and functions on <a href=\"http://www.sandbox.arrayfire.com/docs/index.htm\">our documentation</a>.</p>\r\n<p style=\"text-align: left;\">In addition to our <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire user group</a> and <a href=\"http://sandbox.arrayfire.com/blog/\">our blog</a>, we offer a plethora of <a href=\"http://sandbox.arrayfire.com/support/\">support options</a> to fit your needs.</p>\r\n<p style=\"text-align: left;\">Got a job that needs closer attention? Hire us! Our engineers are acceleration wizards. Check out our <a href=\"http://sandbox.arrayfire.com/consulting/\">consulting offerings</a>, or set up a free <a href=\"http://meetme.so/arrayfire\">technical consultation</a> with us today![/column]</p>\r\n<p style=\"text-align: left;\">[/content_band]</p>\r\n<p style=\"text-align: center;\"></p>','Download','','inherit','closed','closed','','5931-revision-v1','','','2017-07-04 05:22:00','2017-07-04 09:22:00','',5931,'https://sandbox.arrayfire.com/5931-revision-v1/',0,'revision','',0),(9683,17794,'2017-07-10 14:18:31','2017-07-10 18:18:31','Today we are pleased to announce the release of ArrayFire v3.5, our open source\r\nlibrary of parallel computing functions supporting CUDA, OpenCL, and CPU\r\ndevices. This new version of ArrayFire improves features and performance for\r\napplications in machine learning, computer vision, signal processing,\r\nstatistics, finance, and more.\r\n\r\nThis release focuses on thread-safety, support for simple sparse-dense\r\narithmetic operations, canny edge detector function, and a genetic algorithm\r\nexample. A complete list of ArrayFire v3.5 updates and new features are found\r\nin the product <a href=\"http://arrayfire.org/docs/releasenotes.htm\">Release Notes</a>.\r\n<h3><strong>Thread Safety</strong></h3>\r\nArrayFire now supports threading programming models. This is not intended to\r\nimprove the performance since most of the parallelism is happening on the\r\ndevice, but it does allow you to use multiple devices in an easy way.\r\nWith ArrayFire you had to use a for loop to get this functionality. Normally\r\nthis isn\'t a problem but when you have to work with host side transfers, this\r\nbecomes troublesome.\r\n\r\nLet\'s suppose we wanted to perform a matrix multiply on multiple GPUs. Because\r\nmost ArrayFire functions are asynchronous this can be done in a for loop.\r\n<pre class=\"lang:c++ decode:true\" title=\"Simple multi-device\">for (int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n}</pre>\r\n&nbsp;\r\n\r\nThis works well most of the time but this becomes an issue when you want to interact\r\nwith host side code in your application.\r\n\r\nFor example, this code attempts to perform a matrix multiply and then transfer\r\nthat data back to the CPU to do additional work. The ArrayFire code executes the\r\ncomputation on different devices but they will not be queued at the same time\r\nbecause the data transfer to the c_data array is a blocking operation.\r\n<pre class=\"lang:c++ decode:true\">for(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nIn order for this to work correctly you would have had to split the loop so that\r\nthe matmul operation is queued first then in a separate loop the data is transfered\r\nto the CPU. If more work needs to be performed, you will need to create a third loop\r\nto iterate through the devices again.\r\n<pre class=\"lang:c++ decode:true\">vector&lt;array&gt; a(nDevices);\r\nvector&lt;array&gt; b(nDevices);\r\nvector&lt;array&gt; c(nDevices);\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    a[i] = randu(1000, 1000);\r\n    b[i] = constant(3, 1000, 1000);\r\n    c[i] = matmul(a, b);\r\n}\r\n\r\nvector&lt;vector&lt;float&gt;&gt; c_data(nDevices)\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    c_data[i] = vector&lt;float&gt;(c.elements());\r\n    c[i].host(c_data[i].data());\r\n}\r\n\r\n// Perform some host side side work\r\n\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nThis will perform the operations on each of the GPUs on the machines as expected\r\nbut it is troublesome to program like this. With the thread-safety updates in 3.5\r\nyou can now execute the operations for each of the GPUs in separate threads.\r\n<pre class=\"lang:c++ decode:true\">vector&lt;thread&gt; threads;\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n  threads.emplace_back([=]() {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n  });\r\n}\r\n</pre>\r\nThis is a much easier to implement using threads then the for loop approach.\r\n<h3><strong>Canny edge detector</strong></h3>\r\nWe have added the Canny edge detection algorithm to ArrayFire. The Canny\r\nalgorithm is a multi-stage algorithm which can handle a wide variety of edges\r\nThe canny algorithm can automatically calculate the thresholds\r\nusing Otsu\'s method.\r\n<h3><strong>Sparse-Dense arithmetic</strong></h3>\r\nArrayFire 3.4 introduced initial support for sparse arrays. With 3.5 we are\r\nexpanding the sparse arrays to allow for sparse-dense arithmetic.\r\n<h3><strong>Support for CLBlast</strong></h3>\r\nWith ArrayFire 3.5 we are introducing support for a new OpenCL BLAS\r\nimplementation. It is developed by Cedric Nugteren and it is called CLBlast. It\r\nhas improved performance on NVIDIA hardware and features an autotuner support\r\ndevices that have not been explicitly been optimized. You can read more about\r\nclBlast at the GitHub repository <a href=\"https://github.com/CNugteren/CLBlast\">here</a>.\r\n<h3><strong>Improved CUDA JIT engine</strong></h3>\r\nThe CUDA JIT engine has been refactored to use the NVRTC library. Previously the\r\nJIT functionality was implemented using the NVVM library which made it difficult\r\nto employ more advanced control flows. With NVRTC we can create more advanced\r\nJIT functions to improve the performance.\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Download[/custom_headline]\r\n\r\nArrayFire v3.5 can be downloaded from these locations:\r\n<ul>\r\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Community[/custom_headline]\r\n\r\nArrayFire is continually improving through the addition of new functions and features. We welcome your feedback:\r\n<ul>\r\n 	<li>General discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a></li>\r\n 	<li>Live discussion chat on the <a href=\"https://gitter.im/arrayfire/arrayfire?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\">ArrayFire Gitter</a></li>\r\n 	<li>Issue reports on the <a href=\"https://github.com/arrayfire/arrayfire/issues\">ArrayFire GitHub</a></li>\r\n</ul>\r\nAs you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> to contribute to this blog.\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Dedicated Support and Coding Services[/custom_headline]\r\n\r\nArrayFire offers dedicated <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a> for ArrayFire users.\r\n\r\nArrayFire serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers. Contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> or <a href=\"http://meetme.so/arrayfire\">schedule</a> a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5 Official Release','','publish','open','closed','','arrayfire-v3-5-official-release','','','2017-07-10 14:18:31','2017-07-10 18:18:31','',0,'https://sandbox.arrayfire.com/?p=9683',0,'post','',1),(9684,17794,'2017-07-09 00:22:14','2017-07-09 04:22:14','Today we are pleased to announce the release of ArrayFire v3.5, our open source\r\nlibrary of parallel computing functions supporting CUDA, OpenCL, and CPU\r\ndevices. This new version of ArrayFire improves features and performance for\r\napplications in machine learning, computer vision, signal processing,\r\nstatistics, finance, and more.\r\n\r\nThis release focuses on thread-safety, support for simple sparse-dense\r\narithmetic operations, canny edge detector function, and a genetic algorithm\r\nexample. A complete list of ArrayFire v3.5 updates and new features can be found\r\nin the product [[http://arrayfire.org/docs/releasenotes.htm][Release Notes]].\r\n* Thread Safety\r\n\r\nArrayFire now supports threading programming models. This is not intended to\r\nimprove the performance since most of the parallelism is happening on the\r\ndevice, but it does allow you to easily use multiple devices in an easy way.\r\nWith ArrayFire you had to use a for loop to get this functionallity. Normally\r\nthis isn\'t a problem but when you have to work with host side transfers, this\r\nbecomes troublesome.\r\n\r\nLets suppose we wanted to perform a matrix multipley on muiltiple GPUs. Because\r\nmost ArrayFire functions are asynchronous this can be done in a for loop.\r\n\r\n#+BEGIN_SRC cpp\r\nfor (int i = 0; i &lt; nDevices; i++) {\r\nsetDevice(i);\r\narray a = randu(1000, 1000);\r\narray b = constant(3, 1000, 1000);\r\narray c = matmul(a, b);\r\n}\r\n#+END_SRC\r\n\r\nThis works well most of the time but this becomes an issue when you want to interact\r\nwith host side code in your application.\r\n\r\nFor example this code attempts to perform a matrix multiply and then transfer\r\nthat data back to the CPU to do additional work. The ArrayFire code execute the\r\ncomputation on different devices but they will not be queued at the same time\r\nbecause the data transfer to the c_data array is a blocking operation.\r\n\r\n#+BEGIN_SRC cpp\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\nsetDevice(i)\r\narray a = randu(1000, 1000);\r\narray b = constant(3, 1000, 1000);\r\narray c = matmul(a, b);\r\n\r\n// Blocks until the previous operation has completed\r\nvector&lt;float&gt; c_data(c.elements());\r\nc.host(c_data.data());\r\n\r\n// Perform some host side side work\r\n\r\narray data(1000, 1000, c_data.data());\r\n// more work\r\n}\r\n#+END_SRC\r\n\r\nIn order for this to work correctly you would have had to split the loop so that\r\nthe matmul operation is queued first then in a separate loop the data is transfered\r\nto the CPU. If more work needs to be performed, you will need to create a third loop\r\nto iterate through the devices again.\r\n\r\n#+BEGIN_SRC cpp\r\nvector&lt;array&gt; a(nDevices);\r\nvector&lt;array&gt; b(nDevices);\r\nvector&lt;array&gt; c(nDevices);\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\nsetDevice(i);\r\na[i] = randu(1000, 1000);\r\nb[i] = constant(3, 1000, 1000);\r\nc[i] = matmul(a, b);\r\n}\r\n\r\nvector&lt;vector&lt;float&gt;&gt; c_data(nDevices)\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\nsetDevice(i)\r\nc_data[i] = vector&lt;float&gt;(c.elements());\r\nc[i].host(c_data[i].data());\r\n}\r\n\r\n// Perform some host side side work\r\n\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\nsetDevice(i);\r\narray data(1000, 1000, c_data.data());\r\n// more work\r\n}\r\n#+END_SRC\r\n\r\nThis will perform the operations on each of the GPUs on the machines as expedted\r\nbut it is troublesome to program like this. With the thread-safety updates in 3.5\r\nyou can now execute the operations for each of the GPUs in separate threads.\r\n\r\n#+BEGIN_SRC cpp\r\n\r\nvector&lt;thread&gt; threads;\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\nthreads.emplace_back([=]() {\r\nsetDevice(i);\r\narray a = randu(1000, 1000);\r\narray b = constant(3, 1000, 1000);\r\narray c = matmul(a, b);\r\n\r\n// Blocks until the previous operation has completed\r\nvector&lt;float&gt; c_data(c.elements());\r\nc.host(c_data.data());\r\n\r\n// Perform some host side side work\r\n\r\narray data(1000, 1000, c_data.data());\r\n// more work\r\n});\r\n}\r\n#+END_SRC\r\n\r\nThis is a much easier to implement using threads then the for loop approach.\r\n\r\n* Canny edge detector\r\n\r\nWe have added the canny edge detection algoirthms to ArrayFire. The Canny\r\nalgoirthms is a multi-stage algorithm which is customizable to handle many types\r\nof situations. The canny algorithm can automatically calculate the thresholds\r\nusing Otsu\'s method.\r\n\r\n* Sparse Dense arithmetic\r\n\r\nArrayFire 3.4 introduced initial support for sparse arrays. With 3.5 we are\r\nexpanding the sparse arrays to allow for sparse dense arithmetic.\r\n\r\n* Support for CLBlast\r\n\r\nWith ArrayFire 3.5 we are introducing support for a new OpenCL BLAS\r\nimplementation. It is developed by Cedric Nugteren and it is called CLBlast. It\r\nhas improved performance on NVIDIA hardware and features an autotuner support\r\ndevices that have not been explicitly been optimized. You can read more about\r\nclBlast at the GitHub repository [[https://github.com/CNugteren/CLBlast][here]].\r\n\r\n* Improved CUDA JIT engine\r\n\r\nThe CUDA JIT engine has been refactored to use the NVRTC library. Previously the\r\nJIT functionallity was implemented using the NVVM library which made it difficult\r\nto implement more advanced control flows. With NVRTC we can create more advanced\r\nJIT functions to improve the performance.\r\n\r\nAs always we are working on improving the performance of all of our functions. This\r\nhas been another exciting release of ArrayFire and we have great plans for the next\r\nrelease. Stay tuned!','ArrayFire v3.5','','inherit','closed','closed','','9683-revision-v1','','','2017-07-09 00:22:14','2017-07-09 04:22:14','',9683,'https://sandbox.arrayfire.com/9683-revision-v1/',0,'revision','',0),(9685,17794,'2017-07-09 00:23:47','2017-07-09 04:23:47','Today we are pleased to announce the release of ArrayFire v3.5, our open source\r\nlibrary of parallel computing functions supporting CUDA, OpenCL, and CPU\r\ndevices. This new version of ArrayFire improves features and performance for\r\napplications in machine learning, computer vision, signal processing,\r\nstatistics, finance, and more.\r\n\r\nThis release focuses on thread-safety, support for simple sparse-dense\r\narithmetic operations, canny edge detector function, and a genetic algorithm\r\nexample. A complete list of ArrayFire v3.5 updates and new features can be found\r\nin the product <a href=\"http://arrayfire.org/docs/releasenotes.htm\">Release Notes</a>.\r\n# Thread Safety\r\n\r\nArrayFire now supports threading programming models. This is not intended to\r\nimprove the performance since most of the parallelism is happening on the\r\ndevice, but it does allow you to easily use multiple devices in an easy way.\r\nWith ArrayFire you had to use a for loop to get this functionallity. Normally\r\nthis isn\'t a problem but when you have to work with host side transfers, this\r\nbecomes troublesome.\r\n\r\nLets suppose we wanted to perform a matrix multipley on muiltiple GPUs. Because\r\nmost ArrayFire functions are asynchronous this can be done in a for loop.\r\n\r\n#+BEGIN_SRC cpp\r\nfor (int i = 0; i &lt; nDevices; i++) {\r\nsetDevice(i);\r\narray a = randu(1000, 1000);\r\narray b = constant(3, 1000, 1000);\r\narray c = matmul(a, b);\r\n}\r\n#+END_SRC\r\n\r\nThis works well most of the time but this becomes an issue when you want to interact\r\nwith host side code in your application.\r\n\r\nFor example this code attempts to perform a matrix multiply and then transfer\r\nthat data back to the CPU to do additional work. The ArrayFire code execute the\r\ncomputation on different devices but they will not be queued at the same time\r\nbecause the data transfer to the c_data array is a blocking operation.\r\n\r\n#+BEGIN_SRC cpp\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\nsetDevice(i)\r\narray a = randu(1000, 1000);\r\narray b = constant(3, 1000, 1000);\r\narray c = matmul(a, b);\r\n\r\n// Blocks until the previous operation has completed\r\nvector&lt;float&gt; c_data(c.elements());\r\nc.host(c_data.data());\r\n\r\n// Perform some host side side work\r\n\r\narray data(1000, 1000, c_data.data());\r\n// more work\r\n}\r\n#+END_SRC\r\n\r\nIn order for this to work correctly you would have had to split the loop so that\r\nthe matmul operation is queued first then in a separate loop the data is transfered\r\nto the CPU. If more work needs to be performed, you will need to create a third loop\r\nto iterate through the devices again.\r\n\r\n#+BEGIN_SRC cpp\r\nvector&lt;array&gt; a(nDevices);\r\nvector&lt;array&gt; b(nDevices);\r\nvector&lt;array&gt; c(nDevices);\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\nsetDevice(i);\r\na[i] = randu(1000, 1000);\r\nb[i] = constant(3, 1000, 1000);\r\nc[i] = matmul(a, b);\r\n}\r\n\r\nvector&lt;vector&lt;float&gt;&gt; c_data(nDevices)\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\nsetDevice(i)\r\nc_data[i] = vector&lt;float&gt;(c.elements());\r\nc[i].host(c_data[i].data());\r\n}\r\n\r\n// Perform some host side side work\r\n\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\nsetDevice(i);\r\narray data(1000, 1000, c_data.data());\r\n// more work\r\n}\r\n#+END_SRC\r\n\r\nThis will perform the operations on each of the GPUs on the machines as expedted\r\nbut it is troublesome to program like this. With the thread-safety updates in 3.5\r\nyou can now execute the operations for each of the GPUs in separate threads.\r\n\r\n#+BEGIN_SRC cpp\r\n\r\nvector&lt;thread&gt; threads;\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\nthreads.emplace_back([=]() {\r\nsetDevice(i);\r\narray a = randu(1000, 1000);\r\narray b = constant(3, 1000, 1000);\r\narray c = matmul(a, b);\r\n\r\n// Blocks until the previous operation has completed\r\nvector&lt;float&gt; c_data(c.elements());\r\nc.host(c_data.data());\r\n\r\n// Perform some host side side work\r\n\r\narray data(1000, 1000, c_data.data());\r\n// more work\r\n});\r\n}\r\n#+END_SRC\r\n\r\nThis is a much easier to implement using threads then the for loop approach.\r\n\r\n* Canny edge detector\r\n\r\nWe have added the canny edge detection algoirthms to ArrayFire. The Canny\r\nalgoirthms is a multi-stage algorithm which is customizable to handle many types\r\nof situations. The canny algorithm can automatically calculate the thresholds\r\nusing Otsu\'s method.\r\n\r\n* Sparse Dense arithmetic\r\n\r\nArrayFire 3.4 introduced initial support for sparse arrays. With 3.5 we are\r\nexpanding the sparse arrays to allow for sparse dense arithmetic.\r\n\r\n* Support for CLBlast\r\n\r\nWith ArrayFire 3.5 we are introducing support for a new OpenCL BLAS\r\nimplementation. It is developed by Cedric Nugteren and it is called CLBlast. It\r\nhas improved performance on NVIDIA hardware and features an autotuner support\r\ndevices that have not been explicitly been optimized. You can read more about\r\nclBlast at the GitHub repository [[https://github.com/CNugteren/CLBlast][here]].\r\n\r\n* Improved CUDA JIT engine\r\n\r\nThe CUDA JIT engine has been refactored to use the NVRTC library. Previously the\r\nJIT functionallity was implemented using the NVVM library which made it difficult\r\nto implement more advanced control flows. With NVRTC we can create more advanced\r\nJIT functions to improve the performance.\r\n\r\nAs always we are working on improving the performance of all of our functions. This\r\nhas been another exciting release of ArrayFire and we have great plans for the next\r\nrelease. Stay tuned!','ArrayFire v3.5','','inherit','closed','closed','','9683-revision-v1','','','2017-07-09 00:23:47','2017-07-09 04:23:47','',9683,'https://sandbox.arrayfire.com/9683-revision-v1/',0,'revision','',0),(9686,17794,'2017-07-09 00:32:55','2017-07-09 04:32:55','Today we are pleased to announce the release of ArrayFire v3.5, our open source\r\nlibrary of parallel computing functions supporting CUDA, OpenCL, and CPU\r\ndevices. This new version of ArrayFire improves features and performance for\r\napplications in machine learning, computer vision, signal processing,\r\nstatistics, finance, and more.\r\n\r\nThis release focuses on thread-safety, support for simple sparse-dense\r\narithmetic operations, canny edge detector function, and a genetic algorithm\r\nexample. A complete list of ArrayFire v3.5 updates and new features can be found\r\nin the product <a href=\"http://arrayfire.org/docs/releasenotes.htm\">Release Notes</a>.\r\n<ul>\r\n 	<li>Thread Safety</li>\r\n</ul>\r\nArrayFire now supports threading programming models. This is not intended to\r\nimprove the performance since most of the parallelism is happening on the\r\ndevice, but it does allow you to easily use multiple devices in an easy way.\r\nWith ArrayFire you had to use a for loop to get this functionality. Normally\r\nthis isn\'t a problem but when you have to work with host side transfers, this\r\nbecomes troublesome.\r\n\r\nLets suppose we wanted to perform a matrix multiply on multiple GPUs. Because\r\nmost ArrayFire functions are asynchronous this can be done in a for loop.\r\n<pre class=\"lang:c++ decode:true\" title=\"Simple multi-device\">for (int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n}</pre>\r\n&nbsp;\r\n\r\nThis works well most of the time but this becomes an issue when you want to interact\r\nwith host side code in your application.\r\n\r\nFor example this code attempts to perform a matrix multiply and then transfer\r\nthat data back to the CPU to do additional work. The ArrayFire code execute the\r\ncomputation on different devices but they will not be queued at the same time\r\nbecause the data transfer to the c_data array is a blocking operation.\r\n<pre class=\"lang:c++ decode:true \">for(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nIn order for this to work correctly you would have had to split the loop so that\r\nthe matmul operation is queued first then in a separate loop the data is transfered\r\nto the CPU. If more work needs to be performed, you will need to create a third loop\r\nto iterate through the devices again.\r\n\r\n#+BEGIN_SRC cpp\r\nvector&lt;array&gt; a(nDevices);\r\nvector&lt;array&gt; b(nDevices);\r\nvector&lt;array&gt; c(nDevices);\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\nsetDevice(i);\r\na[i] = randu(1000, 1000);\r\nb[i] = constant(3, 1000, 1000);\r\nc[i] = matmul(a, b);\r\n}\r\n\r\nvector&lt;vector&lt;float&gt;&gt; c_data(nDevices)\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\nsetDevice(i)\r\nc_data[i] = vector&lt;float&gt;(c.elements());\r\nc[i].host(c_data[i].data());\r\n}\r\n\r\n// Perform some host side side work\r\n\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\nsetDevice(i);\r\narray data(1000, 1000, c_data.data());\r\n// more work\r\n}\r\n#+END_SRC\r\n\r\nThis will perform the operations on each of the GPUs on the machines as expedted\r\nbut it is troublesome to program like this. With the thread-safety updates in 3.5\r\nyou can now execute the operations for each of the GPUs in separate threads.\r\n\r\n#+BEGIN_SRC cpp\r\n\r\nvector&lt;thread&gt; threads;\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\nthreads.emplace_back([=]() {\r\nsetDevice(i);\r\narray a = randu(1000, 1000);\r\narray b = constant(3, 1000, 1000);\r\narray c = matmul(a, b);\r\n\r\n// Blocks until the previous operation has completed\r\nvector&lt;float&gt; c_data(c.elements());\r\nc.host(c_data.data());\r\n\r\n// Perform some host side side work\r\n\r\narray data(1000, 1000, c_data.data());\r\n// more work\r\n});\r\n}\r\n#+END_SRC\r\n\r\nThis is a much easier to implement using threads then the for loop approach.\r\n<ul>\r\n 	<li>Canny edge detector</li>\r\n</ul>\r\nWe have added the canny edge detection algorithms to ArrayFire. The Canny\r\nalgorithm is a multi-stage algorithm which is customizable to handle many types\r\nof situations. The canny algorithm can automatically calculate the thresholds\r\nusing Otsu\'s method.\r\n<ul>\r\n 	<li>Sparse Dense arithmetic</li>\r\n</ul>\r\nArrayFire 3.4 introduced initial support for sparse arrays. With 3.5 we are\r\nexpanding the sparse arrays to allow for sparse-dense arithmetic.\r\n<ul>\r\n 	<li> Support for CLBlast</li>\r\n</ul>\r\nWith ArrayFire 3.5 we are introducing support for a new OpenCL BLAS\r\nimplementation. It is developed by Cedric Nugteren and it is called CLBlast. It\r\nhas improved performance on NVIDIA hardware and features an autotuner support\r\ndevices that have not been explicitly been optimized. You can read more about\r\nclBlast at the GitHub repository [[https://github.com/CNugteren/CLBlast][here]].\r\n<ul>\r\n 	<li>Improved CUDA JIT engine</li>\r\n</ul>\r\nThe CUDA JIT engine has been refactored to use the NVRTC library. Previously the\r\nJIT functionallity was implemented using the NVVM library which made it difficult\r\nto implement more advanced control flows. With NVRTC we can create more advanced\r\nJIT functions to improve the performance.\r\n\r\nAs always we are working on improving the performance of all of our functions. This\r\nhas been another exciting release of ArrayFire and we have great plans for the next\r\nrelease. Stay tuned!','ArrayFire v3.5','','inherit','closed','closed','','9683-revision-v1','','','2017-07-09 00:32:55','2017-07-09 04:32:55','',9683,'https://sandbox.arrayfire.com/9683-revision-v1/',0,'revision','',0),(9687,17794,'2017-07-09 00:36:48','2017-07-09 04:36:48','Today we are pleased to announce the release of ArrayFire v3.5, our open source\r\nlibrary of parallel computing functions supporting CUDA, OpenCL, and CPU\r\ndevices. This new version of ArrayFire improves features and performance for\r\napplications in machine learning, computer vision, signal processing,\r\nstatistics, finance, and more.\r\n\r\nThis release focuses on thread-safety, support for simple sparse-dense\r\narithmetic operations, canny edge detector function, and a genetic algorithm\r\nexample. A complete list of ArrayFire v3.5 updates and new features can be found\r\nin the product <a href=\"http://arrayfire.org/docs/releasenotes.htm\">Release Notes</a>.\r\n<ul>\r\n 	<li>Thread Safety</li>\r\n</ul>\r\nArrayFire now supports threading programming models. This is not intended to\r\nimprove the performance since most of the parallelism is happening on the\r\ndevice, but it does allow you to easily use multiple devices in an easy way.\r\nWith ArrayFire you had to use a for loop to get this functionality. Normally\r\nthis isn\'t a problem but when you have to work with host side transfers, this\r\nbecomes troublesome.\r\n\r\nLets suppose we wanted to perform a matrix multiply on multiple GPUs. Because\r\nmost ArrayFire functions are asynchronous this can be done in a for loop.\r\n<pre class=\"lang:c++ decode:true\" title=\"Simple multi-device\">for (int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n}</pre>\r\n&nbsp;\r\n\r\nThis works well most of the time but this becomes an issue when you want to interact\r\nwith host side code in your application.\r\n\r\nFor example, this code attempts to perform a matrix multiply and then transfer\r\nthat data back to the CPU to do additional work. The ArrayFire code executes the\r\ncomputation on different devices but they will not be queued at the same time\r\nbecause the data transfer to the c_data array is a blocking operation.\r\n<pre class=\"lang:c++ decode:true \">for(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nIn order for this to work correctly you would have had to split the loop so that\r\nthe matmul operation is queued first then in a separate loop the data is transfered\r\nto the CPU. If more work needs to be performed, you will need to create a third loop\r\nto iterate through the devices again.\r\n<pre class=\"lang:c++ decode:true \">vector&lt;array&gt; a(nDevices);\r\nvector&lt;array&gt; b(nDevices);\r\nvector&lt;array&gt; c(nDevices);\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    a[i] = randu(1000, 1000);\r\n    b[i] = constant(3, 1000, 1000);\r\n    c[i] = matmul(a, b);\r\n}\r\n\r\nvector&lt;vector&lt;float&gt;&gt; c_data(nDevices)\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    c_data[i] = vector&lt;float&gt;(c.elements());\r\n    c[i].host(c_data[i].data());\r\n}\r\n\r\n// Perform some host side side work\r\n\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nThis will perform the operations on each of the GPUs on the machines as expedted\r\nbut it is troublesome to program like this. With the thread-safety updates in 3.5\r\nyou can now execute the operations for each of the GPUs in separate threads.\r\n<pre class=\"lang:c++ decode:true \">vector&lt;thread&gt; threads;\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n  threads.emplace_back([=]() {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n  });\r\n}\r\n</pre>\r\nThis is a much easier to implement using threads then the for loop approach.\r\n<ul>\r\n 	<li>Canny edge detector</li>\r\n</ul>\r\nWe have added the canny edge detection algorithms to ArrayFire. The Canny\r\nalgorithm is a multi-stage algorithm which is customizable to handle many types\r\nof situations. The canny algorithm can automatically calculate the thresholds\r\nusing Otsu\'s method.\r\n<ul>\r\n 	<li>Sparse-Dense arithmetic</li>\r\n</ul>\r\nArrayFire 3.4 introduced initial support for sparse arrays. With 3.5 we are\r\nexpanding the sparse arrays to allow for sparse-dense arithmetic.\r\n<ul>\r\n 	<li> Support for CLBlast</li>\r\n</ul>\r\nWith ArrayFire 3.5 we are introducing support for a new OpenCL BLAS\r\nimplementation. It is developed by Cedric Nugteren and it is called CLBlast. It\r\nhas improved performance on NVIDIA hardware and features an autotuner support\r\ndevices that have not been explicitly been optimized. You can read more about\r\nclBlast at the GitHub repository [[https://github.com/CNugteren/CLBlast][here]].\r\n<ul>\r\n 	<li>Improved CUDA JIT engine</li>\r\n</ul>\r\nThe CUDA JIT engine has been refactored to use the NVRTC library. Previously the\r\nJIT functionality was implemented using the NVVM library which made it difficult\r\nto implement more advanced control flows. With NVRTC we can create more advanced\r\nJIT functions to improve the performance.\r\n\r\nAs always we are working on improving the performance of all of our functions. This\r\nhas been another exciting release of ArrayFire and we have great plans for the next\r\nrelease. Stay tuned!','ArrayFire v3.5 Official Release','','inherit','closed','closed','','9683-revision-v1','','','2017-07-09 00:36:48','2017-07-09 04:36:48','',9683,'https://sandbox.arrayfire.com/9683-revision-v1/',0,'revision','',0),(9688,17794,'2017-07-09 00:37:49','2017-07-09 04:37:49','Today we are pleased to announce the release of ArrayFire v3.5, our open source\r\nlibrary of parallel computing functions supporting CUDA, OpenCL, and CPU\r\ndevices. This new version of ArrayFire improves features and performance for\r\napplications in machine learning, computer vision, signal processing,\r\nstatistics, finance, and more.\r\n\r\nThis release focuses on thread-safety, support for simple sparse-dense\r\narithmetic operations, canny edge detector function, and a genetic algorithm\r\nexample. A complete list of ArrayFire v3.5 updates and new features can be found\r\nin the product <a href=\"http://arrayfire.org/docs/releasenotes.htm\">Release Notes</a>.\r\n<ul>\r\n 	<li><strong>Thread Safety</strong></li>\r\n</ul>\r\nArrayFire now supports threading programming models. This is not intended to\r\nimprove the performance since most of the parallelism is happening on the\r\ndevice, but it does allow you to easily use multiple devices in an easy way.\r\nWith ArrayFire you had to use a for loop to get this functionality. Normally\r\nthis isn\'t a problem but when you have to work with host side transfers, this\r\nbecomes troublesome.\r\n\r\nLets suppose we wanted to perform a matrix multiply on multiple GPUs. Because\r\nmost ArrayFire functions are asynchronous this can be done in a for loop.\r\n<pre class=\"lang:c++ decode:true\" title=\"Simple multi-device\">for (int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n}</pre>\r\n&nbsp;\r\n\r\nThis works well most of the time but this becomes an issue when you want to interact\r\nwith host side code in your application.\r\n\r\nFor example, this code attempts to perform a matrix multiply and then transfer\r\nthat data back to the CPU to do additional work. The ArrayFire code executes the\r\ncomputation on different devices but they will not be queued at the same time\r\nbecause the data transfer to the c_data array is a blocking operation.\r\n<pre class=\"lang:c++ decode:true \">for(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nIn order for this to work correctly you would have had to split the loop so that\r\nthe matmul operation is queued first then in a separate loop the data is transfered\r\nto the CPU. If more work needs to be performed, you will need to create a third loop\r\nto iterate through the devices again.\r\n<pre class=\"lang:c++ decode:true \">vector&lt;array&gt; a(nDevices);\r\nvector&lt;array&gt; b(nDevices);\r\nvector&lt;array&gt; c(nDevices);\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    a[i] = randu(1000, 1000);\r\n    b[i] = constant(3, 1000, 1000);\r\n    c[i] = matmul(a, b);\r\n}\r\n\r\nvector&lt;vector&lt;float&gt;&gt; c_data(nDevices)\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    c_data[i] = vector&lt;float&gt;(c.elements());\r\n    c[i].host(c_data[i].data());\r\n}\r\n\r\n// Perform some host side side work\r\n\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nThis will perform the operations on each of the GPUs on the machines as expedted\r\nbut it is troublesome to program like this. With the thread-safety updates in 3.5\r\nyou can now execute the operations for each of the GPUs in separate threads.\r\n<pre class=\"lang:c++ decode:true \">vector&lt;thread&gt; threads;\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n  threads.emplace_back([=]() {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n  });\r\n}\r\n</pre>\r\nThis is a much easier to implement using threads then the for loop approach.\r\n<ul>\r\n 	<li><strong>Canny edge detector</strong></li>\r\n</ul>\r\nWe have added the canny edge detection algorithms to ArrayFire. The Canny\r\nalgorithm is a multi-stage algorithm which is customizable to handle many types\r\nof situations. The canny algorithm can automatically calculate the thresholds\r\nusing Otsu\'s method.\r\n<ul>\r\n 	<li><strong>Sparse-Dense arithmetic</strong></li>\r\n</ul>\r\nArrayFire 3.4 introduced initial support for sparse arrays. With 3.5 we are\r\nexpanding the sparse arrays to allow for sparse-dense arithmetic.\r\n<ul>\r\n 	<li> <strong>Support for CLBlast</strong></li>\r\n</ul>\r\nWith ArrayFire 3.5 we are introducing support for a new OpenCL BLAS\r\nimplementation. It is developed by Cedric Nugteren and it is called CLBlast. It\r\nhas improved performance on NVIDIA hardware and features an autotuner support\r\ndevices that have not been explicitly been optimized. You can read more about\r\nclBlast at the GitHub repository [[https://github.com/CNugteren/CLBlast][here]].\r\n<ul>\r\n 	<li><strong>Improved CUDA JIT engine</strong></li>\r\n</ul>\r\nThe CUDA JIT engine has been refactored to use the NVRTC library. Previously the\r\nJIT functionality was implemented using the NVVM library which made it difficult\r\nto implement more advanced control flows. With NVRTC we can create more advanced\r\nJIT functions to improve the performance.\r\n\r\nAs always we are working on improving the performance of all of our functions. This\r\nhas been another exciting release of ArrayFire and we have great plans for the next\r\nrelease. Stay tuned!','ArrayFire v3.5 Official Release','','inherit','closed','closed','','9683-revision-v1','','','2017-07-09 00:37:49','2017-07-09 04:37:49','',9683,'https://sandbox.arrayfire.com/9683-revision-v1/',0,'revision','',0),(9692,17794,'2017-07-10 10:35:43','2017-07-10 14:35:43','Today we are pleased to announce the release of ArrayFire v3.5, our open source\r\nlibrary of parallel computing functions supporting CUDA, OpenCL, and CPU\r\ndevices. This new version of ArrayFire improves features and performance for\r\napplications in machine learning, computer vision, signal processing,\r\nstatistics, finance, and more.\r\n\r\nThis release focuses on thread-safety, support for simple sparse-dense\r\narithmetic operations, canny edge detector function, and a genetic algorithm\r\nexample. A complete list of ArrayFire v3.5 updates and new features are found\r\nin the product <a href=\"http://arrayfire.org/docs/releasenotes.htm\">Release Notes</a>.\r\n<h1><strong>Thread Safety</strong></h1>\r\nArrayFire now supports threading programming models. This is not intended to\r\nimprove the performance since most of the parallelism is happening on the\r\ndevice, but it does allow you to use multiple devices in an easy way.\r\nWith ArrayFire you had to use a for loop to get this functionality. Normally\r\nthis isn\'t a problem but when you have to work with host side transfers, this\r\nbecomes troublesome.\r\n\r\nLet\'s suppose we wanted to perform a matrix multiply on multiple GPUs. Because\r\nmost ArrayFire functions are asynchronous this can be done in a for loop.\r\n<pre class=\"lang:c++ decode:true\" title=\"Simple multi-device\">for (int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n}</pre>\r\n&nbsp;\r\n\r\nThis works well most of the time but this becomes an issue when you want to interact\r\nwith host side code in your application.\r\n\r\nFor example, this code attempts to perform a matrix multiply and then transfer\r\nthat data back to the CPU to do additional work. The ArrayFire code executes the\r\ncomputation on different devices but they will not be queued at the same time\r\nbecause the data transfer to the c_data array is a blocking operation.\r\n<pre class=\"lang:c++ decode:true\">for(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nIn order for this to work correctly you would have had to split the loop so that\r\nthe matmul operation is queued first then in a separate loop the data is transfered\r\nto the CPU. If more work needs to be performed, you will need to create a third loop\r\nto iterate through the devices again.\r\n<pre class=\"lang:c++ decode:true\">vector&lt;array&gt; a(nDevices);\r\nvector&lt;array&gt; b(nDevices);\r\nvector&lt;array&gt; c(nDevices);\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    a[i] = randu(1000, 1000);\r\n    b[i] = constant(3, 1000, 1000);\r\n    c[i] = matmul(a, b);\r\n}\r\n\r\nvector&lt;vector&lt;float&gt;&gt; c_data(nDevices)\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    c_data[i] = vector&lt;float&gt;(c.elements());\r\n    c[i].host(c_data[i].data());\r\n}\r\n\r\n// Perform some host side side work\r\n\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nThis will perform the operations on each of the GPUs on the machines as expected\r\nbut it is troublesome to program like this. With the thread-safety updates in 3.5\r\nyou can now execute the operations for each of the GPUs in separate threads.\r\n<pre class=\"lang:c++ decode:true\">vector&lt;thread&gt; threads;\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n  threads.emplace_back([=]() {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n  });\r\n}\r\n</pre>\r\nThis is a much easier to implement using threads then the for loop approach.\r\n<h1><strong>Canny edge detector</strong></h1>\r\nWe have added the Canny edge detection algorithm to ArrayFire. The Canny\r\nalgorithm is a multi-stage algorithm which can handle a wide variety of edges\r\nThe canny algorithm can automatically calculate the thresholds\r\nusing Otsu\'s method.\r\n<h1><strong>Sparse-Dense arithmetic</strong></h1>\r\nArrayFire 3.4 introduced initial support for sparse arrays. With 3.5 we are\r\nexpanding the sparse arrays to allow for sparse-dense arithmetic.\r\n<h1><strong>Support for CLBlast</strong></h1>\r\nWith ArrayFire 3.5 we are introducing support for a new OpenCL BLAS\r\nimplementation. It is developed by Cedric Nugteren and it is called CLBlast. It\r\nhas improved performance on NVIDIA hardware and features an autotuner support\r\ndevices that have not been explicitly been optimized. You can read more about\r\nclBlast at the GitHub repository <a href=\"https://github.com/CNugteren/CLBlast\">here</a>.\r\n<h1><strong>Improved CUDA JIT engine</strong></h1>\r\nThe CUDA JIT engine has been refactored to use the NVRTC library. Previously the\r\nJIT functionality was implemented using the NVVM library which made it difficult\r\nto employ more advanced control flows. With NVRTC we can create more advanced\r\nJIT functions to improve the performance.\r\n\r\nAs always we are working on improving the performance of all of our functions. This\r\nhas been another exciting update to ArrayFire and we have great plans for the next\r\nrelease. Stay tuned!','ArrayFire v3.5 Official Release','','inherit','closed','closed','','9683-revision-v1','','','2017-07-10 10:35:43','2017-07-10 14:35:43','',9683,'https://sandbox.arrayfire.com/9683-revision-v1/',0,'revision','',0),(9693,17794,'2017-07-10 10:36:40','2017-07-10 14:36:40','Today we are pleased to announce the release of ArrayFire v3.5, our open source\r\nlibrary of parallel computing functions supporting CUDA, OpenCL, and CPU\r\ndevices. This new version of ArrayFire improves features and performance for\r\napplications in machine learning, computer vision, signal processing,\r\nstatistics, finance, and more.\r\n\r\nThis release focuses on thread-safety, support for simple sparse-dense\r\narithmetic operations, canny edge detector function, and a genetic algorithm\r\nexample. A complete list of ArrayFire v3.5 updates and new features are found\r\nin the product <a href=\"http://arrayfire.org/docs/releasenotes.htm\">Release Notes</a>.\r\n<h3><strong>Thread Safety</strong></h3>\r\nArrayFire now supports threading programming models. This is not intended to\r\nimprove the performance since most of the parallelism is happening on the\r\ndevice, but it does allow you to use multiple devices in an easy way.\r\nWith ArrayFire you had to use a for loop to get this functionality. Normally\r\nthis isn\'t a problem but when you have to work with host side transfers, this\r\nbecomes troublesome.\r\n\r\nLet\'s suppose we wanted to perform a matrix multiply on multiple GPUs. Because\r\nmost ArrayFire functions are asynchronous this can be done in a for loop.\r\n<pre class=\"lang:c++ decode:true\" title=\"Simple multi-device\">for (int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n}</pre>\r\n&nbsp;\r\n\r\nThis works well most of the time but this becomes an issue when you want to interact\r\nwith host side code in your application.\r\n\r\nFor example, this code attempts to perform a matrix multiply and then transfer\r\nthat data back to the CPU to do additional work. The ArrayFire code executes the\r\ncomputation on different devices but they will not be queued at the same time\r\nbecause the data transfer to the c_data array is a blocking operation.\r\n<pre class=\"lang:c++ decode:true\">for(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nIn order for this to work correctly you would have had to split the loop so that\r\nthe matmul operation is queued first then in a separate loop the data is transfered\r\nto the CPU. If more work needs to be performed, you will need to create a third loop\r\nto iterate through the devices again.\r\n<pre class=\"lang:c++ decode:true\">vector&lt;array&gt; a(nDevices);\r\nvector&lt;array&gt; b(nDevices);\r\nvector&lt;array&gt; c(nDevices);\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    a[i] = randu(1000, 1000);\r\n    b[i] = constant(3, 1000, 1000);\r\n    c[i] = matmul(a, b);\r\n}\r\n\r\nvector&lt;vector&lt;float&gt;&gt; c_data(nDevices)\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    c_data[i] = vector&lt;float&gt;(c.elements());\r\n    c[i].host(c_data[i].data());\r\n}\r\n\r\n// Perform some host side side work\r\n\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nThis will perform the operations on each of the GPUs on the machines as expected\r\nbut it is troublesome to program like this. With the thread-safety updates in 3.5\r\nyou can now execute the operations for each of the GPUs in separate threads.\r\n<pre class=\"lang:c++ decode:true\">vector&lt;thread&gt; threads;\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n  threads.emplace_back([=]() {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n  });\r\n}\r\n</pre>\r\nThis is a much easier to implement using threads then the for loop approach.\r\n<h3><strong>Canny edge detector</strong></h3>\r\nWe have added the Canny edge detection algorithm to ArrayFire. The Canny\r\nalgorithm is a multi-stage algorithm which can handle a wide variety of edges\r\nThe canny algorithm can automatically calculate the thresholds\r\nusing Otsu\'s method.\r\n<h3><strong>Sparse-Dense arithmetic</strong></h3>\r\nArrayFire 3.4 introduced initial support for sparse arrays. With 3.5 we are\r\nexpanding the sparse arrays to allow for sparse-dense arithmetic.\r\n<h3><strong>Support for CLBlast</strong></h3>\r\nWith ArrayFire 3.5 we are introducing support for a new OpenCL BLAS\r\nimplementation. It is developed by Cedric Nugteren and it is called CLBlast. It\r\nhas improved performance on NVIDIA hardware and features an autotuner support\r\ndevices that have not been explicitly been optimized. You can read more about\r\nclBlast at the GitHub repository <a href=\"https://github.com/CNugteren/CLBlast\">here</a>.\r\n<h3><strong>Improved CUDA JIT engine</strong></h3>\r\nThe CUDA JIT engine has been refactored to use the NVRTC library. Previously the\r\nJIT functionality was implemented using the NVVM library which made it difficult\r\nto employ more advanced control flows. With NVRTC we can create more advanced\r\nJIT functions to improve the performance.\r\n\r\nAs always we are working on improving the performance of all of our functions. This\r\nhas been another exciting update to ArrayFire and we have great plans for the next\r\nrelease. Stay tuned!','ArrayFire v3.5 Official Release','','inherit','closed','closed','','9683-revision-v1','','','2017-07-10 10:36:40','2017-07-10 14:36:40','',9683,'https://sandbox.arrayfire.com/9683-revision-v1/',0,'revision','',0),(9697,6,'2017-07-10 13:45:44','2017-07-10 17:45:44','Today we are pleased to announce the release of ArrayFire v3.5, our open source\r\nlibrary of parallel computing functions supporting CUDA, OpenCL, and CPU\r\ndevices. This new version of ArrayFire improves features and performance for\r\napplications in machine learning, computer vision, signal processing,\r\nstatistics, finance, and more.\r\n\r\nThis release focuses on thread-safety, support for simple sparse-dense\r\narithmetic operations, canny edge detector function, and a genetic algorithm\r\nexample. A complete list of ArrayFire v3.5 updates and new features are found\r\nin the product <a href=\"http://arrayfire.org/docs/releasenotes.htm\">Release Notes</a>.\r\n<h3><strong>Thread Safety</strong></h3>\r\nArrayFire now supports threading programming models. This is not intended to\r\nimprove the performance since most of the parallelism is happening on the\r\ndevice, but it does allow you to use multiple devices in an easy way.\r\nWith ArrayFire you had to use a for loop to get this functionality. Normally\r\nthis isn\'t a problem but when you have to work with host side transfers, this\r\nbecomes troublesome.\r\n\r\nLet\'s suppose we wanted to perform a matrix multiply on multiple GPUs. Because\r\nmost ArrayFire functions are asynchronous this can be done in a for loop.\r\n<pre class=\"lang:c++ decode:true\" title=\"Simple multi-device\">for (int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n}</pre>\r\n&nbsp;\r\n\r\nThis works well most of the time but this becomes an issue when you want to interact\r\nwith host side code in your application.\r\n\r\nFor example, this code attempts to perform a matrix multiply and then transfer\r\nthat data back to the CPU to do additional work. The ArrayFire code executes the\r\ncomputation on different devices but they will not be queued at the same time\r\nbecause the data transfer to the c_data array is a blocking operation.\r\n<pre class=\"lang:c++ decode:true\">for(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nIn order for this to work correctly you would have had to split the loop so that\r\nthe matmul operation is queued first then in a separate loop the data is transfered\r\nto the CPU. If more work needs to be performed, you will need to create a third loop\r\nto iterate through the devices again.\r\n<pre class=\"lang:c++ decode:true\">vector&lt;array&gt; a(nDevices);\r\nvector&lt;array&gt; b(nDevices);\r\nvector&lt;array&gt; c(nDevices);\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    a[i] = randu(1000, 1000);\r\n    b[i] = constant(3, 1000, 1000);\r\n    c[i] = matmul(a, b);\r\n}\r\n\r\nvector&lt;vector&lt;float&gt;&gt; c_data(nDevices)\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    c_data[i] = vector&lt;float&gt;(c.elements());\r\n    c[i].host(c_data[i].data());\r\n}\r\n\r\n// Perform some host side side work\r\n\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nThis will perform the operations on each of the GPUs on the machines as expected\r\nbut it is troublesome to program like this. With the thread-safety updates in 3.5\r\nyou can now execute the operations for each of the GPUs in separate threads.\r\n<pre class=\"lang:c++ decode:true\">vector&lt;thread&gt; threads;\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n  threads.emplace_back([=]() {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n  });\r\n}\r\n</pre>\r\nThis is a much easier to implement using threads then the for loop approach.\r\n<h3><strong>Canny edge detector</strong></h3>\r\nWe have added the Canny edge detection algorithm to ArrayFire. The Canny\r\nalgorithm is a multi-stage algorithm which can handle a wide variety of edges\r\nThe canny algorithm can automatically calculate the thresholds\r\nusing Otsu\'s method.\r\n<h3><strong>Sparse-Dense arithmetic</strong></h3>\r\nArrayFire 3.4 introduced initial support for sparse arrays. With 3.5 we are\r\nexpanding the sparse arrays to allow for sparse-dense arithmetic.\r\n<h3><strong>Support for CLBlast</strong></h3>\r\nWith ArrayFire 3.5 we are introducing support for a new OpenCL BLAS\r\nimplementation. It is developed by Cedric Nugteren and it is called CLBlast. It\r\nhas improved performance on NVIDIA hardware and features an autotuner support\r\ndevices that have not been explicitly been optimized. You can read more about\r\nclBlast at the GitHub repository <a href=\"https://github.com/CNugteren/CLBlast\">here</a>.\r\n<h3><strong>Improved CUDA JIT engine</strong></h3>\r\nThe CUDA JIT engine has been refactored to use the NVRTC library. Previously the\r\nJIT functionality was implemented using the NVVM library which made it difficult\r\nto employ more advanced control flows. With NVRTC we can create more advanced\r\nJIT functions to improve the performance.\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Download[/custom_headline]\r\n\r\nArrayFire v3.5 can be downloaded from these locations:\r\n<ul>\r\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Community[/custom_headline]\r\n\r\nArrayFire is continually improving through the addition of new functions and features. We welcome your feedback:\r\n<ul>\r\n 	<li>General discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a></li>\r\n 	<li>Live discussion chat on the <a href=\"https://gitter.im/arrayfire/arrayfire?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\">ArrayFire Gitter</a></li>\r\n 	<li>Issue reports on the <a href=\"https://github.com/arrayfire/arrayfire/issues\">ArrayFire GitHub</a></li>\r\n</ul>\r\nAs you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email sales@arrayfire.com to contribute to this blog.\r\n\r\n<b>Dedicated support and coding services</b>\r\n\r\nArrayFire offers dedicated <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a> for ArrayFire users.\r\n\r\nArrayFire serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers.\r\n\r\n&nbsp;','ArrayFire v3.5 Official Release','','inherit','closed','closed','','9683-revision-v1','','','2017-07-10 13:45:44','2017-07-10 17:45:44','',9683,'https://sandbox.arrayfire.com/9683-revision-v1/',0,'revision','',0),(9698,6,'2017-07-10 13:47:51','2017-07-10 17:47:51','Today we are pleased to announce the release of ArrayFire v3.5, our open source\r\nlibrary of parallel computing functions supporting CUDA, OpenCL, and CPU\r\ndevices. This new version of ArrayFire improves features and performance for\r\napplications in machine learning, computer vision, signal processing,\r\nstatistics, finance, and more.\r\n\r\nThis release focuses on thread-safety, support for simple sparse-dense\r\narithmetic operations, canny edge detector function, and a genetic algorithm\r\nexample. A complete list of ArrayFire v3.5 updates and new features are found\r\nin the product <a href=\"http://arrayfire.org/docs/releasenotes.htm\">Release Notes</a>.\r\n<h3><strong>Thread Safety</strong></h3>\r\nArrayFire now supports threading programming models. This is not intended to\r\nimprove the performance since most of the parallelism is happening on the\r\ndevice, but it does allow you to use multiple devices in an easy way.\r\nWith ArrayFire you had to use a for loop to get this functionality. Normally\r\nthis isn\'t a problem but when you have to work with host side transfers, this\r\nbecomes troublesome.\r\n\r\nLet\'s suppose we wanted to perform a matrix multiply on multiple GPUs. Because\r\nmost ArrayFire functions are asynchronous this can be done in a for loop.\r\n<pre class=\"lang:c++ decode:true\" title=\"Simple multi-device\">for (int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n}</pre>\r\n&nbsp;\r\n\r\nThis works well most of the time but this becomes an issue when you want to interact\r\nwith host side code in your application.\r\n\r\nFor example, this code attempts to perform a matrix multiply and then transfer\r\nthat data back to the CPU to do additional work. The ArrayFire code executes the\r\ncomputation on different devices but they will not be queued at the same time\r\nbecause the data transfer to the c_data array is a blocking operation.\r\n<pre class=\"lang:c++ decode:true\">for(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nIn order for this to work correctly you would have had to split the loop so that\r\nthe matmul operation is queued first then in a separate loop the data is transfered\r\nto the CPU. If more work needs to be performed, you will need to create a third loop\r\nto iterate through the devices again.\r\n<pre class=\"lang:c++ decode:true\">vector&lt;array&gt; a(nDevices);\r\nvector&lt;array&gt; b(nDevices);\r\nvector&lt;array&gt; c(nDevices);\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    a[i] = randu(1000, 1000);\r\n    b[i] = constant(3, 1000, 1000);\r\n    c[i] = matmul(a, b);\r\n}\r\n\r\nvector&lt;vector&lt;float&gt;&gt; c_data(nDevices)\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    c_data[i] = vector&lt;float&gt;(c.elements());\r\n    c[i].host(c_data[i].data());\r\n}\r\n\r\n// Perform some host side side work\r\n\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nThis will perform the operations on each of the GPUs on the machines as expected\r\nbut it is troublesome to program like this. With the thread-safety updates in 3.5\r\nyou can now execute the operations for each of the GPUs in separate threads.\r\n<pre class=\"lang:c++ decode:true\">vector&lt;thread&gt; threads;\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n  threads.emplace_back([=]() {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n  });\r\n}\r\n</pre>\r\nThis is a much easier to implement using threads then the for loop approach.\r\n<h3><strong>Canny edge detector</strong></h3>\r\nWe have added the Canny edge detection algorithm to ArrayFire. The Canny\r\nalgorithm is a multi-stage algorithm which can handle a wide variety of edges\r\nThe canny algorithm can automatically calculate the thresholds\r\nusing Otsu\'s method.\r\n<h3><strong>Sparse-Dense arithmetic</strong></h3>\r\nArrayFire 3.4 introduced initial support for sparse arrays. With 3.5 we are\r\nexpanding the sparse arrays to allow for sparse-dense arithmetic.\r\n<h3><strong>Support for CLBlast</strong></h3>\r\nWith ArrayFire 3.5 we are introducing support for a new OpenCL BLAS\r\nimplementation. It is developed by Cedric Nugteren and it is called CLBlast. It\r\nhas improved performance on NVIDIA hardware and features an autotuner support\r\ndevices that have not been explicitly been optimized. You can read more about\r\nclBlast at the GitHub repository <a href=\"https://github.com/CNugteren/CLBlast\">here</a>.\r\n<h3><strong>Improved CUDA JIT engine</strong></h3>\r\nThe CUDA JIT engine has been refactored to use the NVRTC library. Previously the\r\nJIT functionality was implemented using the NVVM library which made it difficult\r\nto employ more advanced control flows. With NVRTC we can create more advanced\r\nJIT functions to improve the performance.\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Download[/custom_headline]\r\n\r\nArrayFire v3.5 can be downloaded from these locations:\r\n<ul>\r\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Community[/custom_headline]\r\n\r\nArrayFire is continually improving through the addition of new functions and features. We welcome your feedback:\r\n<ul>\r\n 	<li>General discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a></li>\r\n 	<li>Live discussion chat on the <a href=\"https://gitter.im/arrayfire/arrayfire?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\">ArrayFire Gitter</a></li>\r\n 	<li>Issue reports on the <a href=\"https://github.com/arrayfire/arrayfire/issues\">ArrayFire GitHub</a></li>\r\n</ul>\r\nAs you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email sales@arrayfire.com to contribute to this blog.\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Dedicated Support and Coding Services[/custom_headline]\r\n\r\nArrayFire offers dedicated <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a> for ArrayFire users.\r\n\r\nArrayFire serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers.\r\n\r\n&nbsp;','ArrayFire v3.5 Official Release','','inherit','closed','closed','','9683-revision-v1','','','2017-07-10 13:47:51','2017-07-10 17:47:51','',9683,'https://sandbox.arrayfire.com/9683-revision-v1/',0,'revision','',0),(9699,6,'2017-07-10 13:54:17','2017-07-10 17:54:17','Today we are pleased to announce the release of ArrayFire v3.5, our open source\r\nlibrary of parallel computing functions supporting CUDA, OpenCL, and CPU\r\ndevices. This new version of ArrayFire improves features and performance for\r\napplications in machine learning, computer vision, signal processing,\r\nstatistics, finance, and more.\r\n\r\nThis release focuses on thread-safety, support for simple sparse-dense\r\narithmetic operations, canny edge detector function, and a genetic algorithm\r\nexample. A complete list of ArrayFire v3.5 updates and new features are found\r\nin the product <a href=\"http://arrayfire.org/docs/releasenotes.htm\">Release Notes</a>.\r\n<h3><strong>Thread Safety</strong></h3>\r\nArrayFire now supports threading programming models. This is not intended to\r\nimprove the performance since most of the parallelism is happening on the\r\ndevice, but it does allow you to use multiple devices in an easy way.\r\nWith ArrayFire you had to use a for loop to get this functionality. Normally\r\nthis isn\'t a problem but when you have to work with host side transfers, this\r\nbecomes troublesome.\r\n\r\nLet\'s suppose we wanted to perform a matrix multiply on multiple GPUs. Because\r\nmost ArrayFire functions are asynchronous this can be done in a for loop.\r\n<pre class=\"lang:c++ decode:true\" title=\"Simple multi-device\">for (int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n}</pre>\r\n&nbsp;\r\n\r\nThis works well most of the time but this becomes an issue when you want to interact\r\nwith host side code in your application.\r\n\r\nFor example, this code attempts to perform a matrix multiply and then transfer\r\nthat data back to the CPU to do additional work. The ArrayFire code executes the\r\ncomputation on different devices but they will not be queued at the same time\r\nbecause the data transfer to the c_data array is a blocking operation.\r\n<pre class=\"lang:c++ decode:true\">for(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nIn order for this to work correctly you would have had to split the loop so that\r\nthe matmul operation is queued first then in a separate loop the data is transfered\r\nto the CPU. If more work needs to be performed, you will need to create a third loop\r\nto iterate through the devices again.\r\n<pre class=\"lang:c++ decode:true\">vector&lt;array&gt; a(nDevices);\r\nvector&lt;array&gt; b(nDevices);\r\nvector&lt;array&gt; c(nDevices);\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    a[i] = randu(1000, 1000);\r\n    b[i] = constant(3, 1000, 1000);\r\n    c[i] = matmul(a, b);\r\n}\r\n\r\nvector&lt;vector&lt;float&gt;&gt; c_data(nDevices)\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    c_data[i] = vector&lt;float&gt;(c.elements());\r\n    c[i].host(c_data[i].data());\r\n}\r\n\r\n// Perform some host side side work\r\n\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nThis will perform the operations on each of the GPUs on the machines as expected\r\nbut it is troublesome to program like this. With the thread-safety updates in 3.5\r\nyou can now execute the operations for each of the GPUs in separate threads.\r\n<pre class=\"lang:c++ decode:true\">vector&lt;thread&gt; threads;\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n  threads.emplace_back([=]() {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n  });\r\n}\r\n</pre>\r\nThis is a much easier to implement using threads then the for loop approach.\r\n<h3><strong>Canny edge detector</strong></h3>\r\nWe have added the Canny edge detection algorithm to ArrayFire. The Canny\r\nalgorithm is a multi-stage algorithm which can handle a wide variety of edges\r\nThe canny algorithm can automatically calculate the thresholds\r\nusing Otsu\'s method.\r\n<h3><strong>Sparse-Dense arithmetic</strong></h3>\r\nArrayFire 3.4 introduced initial support for sparse arrays. With 3.5 we are\r\nexpanding the sparse arrays to allow for sparse-dense arithmetic.\r\n<h3><strong>Support for CLBlast</strong></h3>\r\nWith ArrayFire 3.5 we are introducing support for a new OpenCL BLAS\r\nimplementation. It is developed by Cedric Nugteren and it is called CLBlast. It\r\nhas improved performance on NVIDIA hardware and features an autotuner support\r\ndevices that have not been explicitly been optimized. You can read more about\r\nclBlast at the GitHub repository <a href=\"https://github.com/CNugteren/CLBlast\">here</a>.\r\n<h3><strong>Improved CUDA JIT engine</strong></h3>\r\nThe CUDA JIT engine has been refactored to use the NVRTC library. Previously the\r\nJIT functionality was implemented using the NVVM library which made it difficult\r\nto employ more advanced control flows. With NVRTC we can create more advanced\r\nJIT functions to improve the performance.\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Download[/custom_headline]\r\n\r\nArrayFire v3.5 can be downloaded from these locations:\r\n<ul>\r\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Community[/custom_headline]\r\n\r\nArrayFire is continually improving through the addition of new functions and features. We welcome your feedback:\r\n<ul>\r\n 	<li>General discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a></li>\r\n 	<li>Live discussion chat on the <a href=\"https://gitter.im/arrayfire/arrayfire?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\">ArrayFire Gitter</a></li>\r\n 	<li>Issue reports on the <a href=\"https://github.com/arrayfire/arrayfire/issues\">ArrayFire GitHub</a></li>\r\n</ul>\r\nAs you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email sales@arrayfire.com to contribute to this blog.\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Dedicated Support and Coding Services[/custom_headline]\r\n\r\nArrayFire offers dedicated <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a> for ArrayFire users.\r\n\r\nArrayFire serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers. Email sales@arrayfire.com or <a href=\"http://meetme.so/arrayfire\">schedule a free technical consultation</a> to learn more about our consulting and coding services.','ArrayFire v3.5 Official Release','','inherit','closed','closed','','9683-revision-v1','','','2017-07-10 13:54:17','2017-07-10 17:54:17','',9683,'https://sandbox.arrayfire.com/9683-revision-v1/',0,'revision','',0),(9700,6,'2017-07-10 13:56:45','2017-07-10 17:56:45','Today we are pleased to announce the release of ArrayFire v3.5, our open source\r\nlibrary of parallel computing functions supporting CUDA, OpenCL, and CPU\r\ndevices. This new version of ArrayFire improves features and performance for\r\napplications in machine learning, computer vision, signal processing,\r\nstatistics, finance, and more.\r\n\r\nThis release focuses on thread-safety, support for simple sparse-dense\r\narithmetic operations, canny edge detector function, and a genetic algorithm\r\nexample. A complete list of ArrayFire v3.5 updates and new features are found\r\nin the product <a href=\"http://arrayfire.org/docs/releasenotes.htm\">Release Notes</a>.\r\n<h3><strong>Thread Safety</strong></h3>\r\nArrayFire now supports threading programming models. This is not intended to\r\nimprove the performance since most of the parallelism is happening on the\r\ndevice, but it does allow you to use multiple devices in an easy way.\r\nWith ArrayFire you had to use a for loop to get this functionality. Normally\r\nthis isn\'t a problem but when you have to work with host side transfers, this\r\nbecomes troublesome.\r\n\r\nLet\'s suppose we wanted to perform a matrix multiply on multiple GPUs. Because\r\nmost ArrayFire functions are asynchronous this can be done in a for loop.\r\n<pre class=\"lang:c++ decode:true\" title=\"Simple multi-device\">for (int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n}</pre>\r\n&nbsp;\r\n\r\nThis works well most of the time but this becomes an issue when you want to interact\r\nwith host side code in your application.\r\n\r\nFor example, this code attempts to perform a matrix multiply and then transfer\r\nthat data back to the CPU to do additional work. The ArrayFire code executes the\r\ncomputation on different devices but they will not be queued at the same time\r\nbecause the data transfer to the c_data array is a blocking operation.\r\n<pre class=\"lang:c++ decode:true\">for(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nIn order for this to work correctly you would have had to split the loop so that\r\nthe matmul operation is queued first then in a separate loop the data is transfered\r\nto the CPU. If more work needs to be performed, you will need to create a third loop\r\nto iterate through the devices again.\r\n<pre class=\"lang:c++ decode:true\">vector&lt;array&gt; a(nDevices);\r\nvector&lt;array&gt; b(nDevices);\r\nvector&lt;array&gt; c(nDevices);\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    a[i] = randu(1000, 1000);\r\n    b[i] = constant(3, 1000, 1000);\r\n    c[i] = matmul(a, b);\r\n}\r\n\r\nvector&lt;vector&lt;float&gt;&gt; c_data(nDevices)\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    c_data[i] = vector&lt;float&gt;(c.elements());\r\n    c[i].host(c_data[i].data());\r\n}\r\n\r\n// Perform some host side side work\r\n\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nThis will perform the operations on each of the GPUs on the machines as expected\r\nbut it is troublesome to program like this. With the thread-safety updates in 3.5\r\nyou can now execute the operations for each of the GPUs in separate threads.\r\n<pre class=\"lang:c++ decode:true\">vector&lt;thread&gt; threads;\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n  threads.emplace_back([=]() {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n  });\r\n}\r\n</pre>\r\nThis is a much easier to implement using threads then the for loop approach.\r\n<h3><strong>Canny edge detector</strong></h3>\r\nWe have added the Canny edge detection algorithm to ArrayFire. The Canny\r\nalgorithm is a multi-stage algorithm which can handle a wide variety of edges\r\nThe canny algorithm can automatically calculate the thresholds\r\nusing Otsu\'s method.\r\n<h3><strong>Sparse-Dense arithmetic</strong></h3>\r\nArrayFire 3.4 introduced initial support for sparse arrays. With 3.5 we are\r\nexpanding the sparse arrays to allow for sparse-dense arithmetic.\r\n<h3><strong>Support for CLBlast</strong></h3>\r\nWith ArrayFire 3.5 we are introducing support for a new OpenCL BLAS\r\nimplementation. It is developed by Cedric Nugteren and it is called CLBlast. It\r\nhas improved performance on NVIDIA hardware and features an autotuner support\r\ndevices that have not been explicitly been optimized. You can read more about\r\nclBlast at the GitHub repository <a href=\"https://github.com/CNugteren/CLBlast\">here</a>.\r\n<h3><strong>Improved CUDA JIT engine</strong></h3>\r\nThe CUDA JIT engine has been refactored to use the NVRTC library. Previously the\r\nJIT functionality was implemented using the NVVM library which made it difficult\r\nto employ more advanced control flows. With NVRTC we can create more advanced\r\nJIT functions to improve the performance.\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Download[/custom_headline]\r\n\r\nArrayFire v3.5 can be downloaded from these locations:\r\n<ul>\r\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Community[/custom_headline]\r\n\r\nArrayFire is continually improving through the addition of new functions and features. We welcome your feedback:\r\n<ul>\r\n 	<li>General discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a></li>\r\n 	<li>Live discussion chat on the <a href=\"https://gitter.im/arrayfire/arrayfire?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\">ArrayFire Gitter</a></li>\r\n 	<li>Issue reports on the <a href=\"https://github.com/arrayfire/arrayfire/issues\">ArrayFire GitHub</a></li>\r\n</ul>\r\nAs you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> to contribute to this blog.\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Dedicated Support and Coding Services[/custom_headline]\r\n\r\nArrayFire offers dedicated <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a> for ArrayFire users.\r\n\r\nArrayFire serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers. Contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> or <a href=\"http://meetme.so/arrayfire\">schedule a free technical consultation</a> to learn more about our consulting and coding services.','ArrayFire v3.5 Official Release','','inherit','closed','closed','','9683-revision-v1','','','2017-07-10 13:56:45','2017-07-10 17:56:45','',9683,'https://sandbox.arrayfire.com/9683-revision-v1/',0,'revision','',0),(9701,6,'2017-07-10 13:59:05','2017-07-10 17:59:05','Today we are pleased to announce the release of ArrayFire v3.5, our open source\r\nlibrary of parallel computing functions supporting CUDA, OpenCL, and CPU\r\ndevices. This new version of ArrayFire improves features and performance for\r\napplications in machine learning, computer vision, signal processing,\r\nstatistics, finance, and more.\r\n\r\nThis release focuses on thread-safety, support for simple sparse-dense\r\narithmetic operations, canny edge detector function, and a genetic algorithm\r\nexample. A complete list of ArrayFire v3.5 updates and new features are found\r\nin the product <a href=\"http://arrayfire.org/docs/releasenotes.htm\">Release Notes</a>.\r\n<h3><strong>Thread Safety</strong></h3>\r\nArrayFire now supports threading programming models. This is not intended to\r\nimprove the performance since most of the parallelism is happening on the\r\ndevice, but it does allow you to use multiple devices in an easy way.\r\nWith ArrayFire you had to use a for loop to get this functionality. Normally\r\nthis isn\'t a problem but when you have to work with host side transfers, this\r\nbecomes troublesome.\r\n\r\nLet\'s suppose we wanted to perform a matrix multiply on multiple GPUs. Because\r\nmost ArrayFire functions are asynchronous this can be done in a for loop.\r\n<pre class=\"lang:c++ decode:true\" title=\"Simple multi-device\">for (int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n}</pre>\r\n&nbsp;\r\n\r\nThis works well most of the time but this becomes an issue when you want to interact\r\nwith host side code in your application.\r\n\r\nFor example, this code attempts to perform a matrix multiply and then transfer\r\nthat data back to the CPU to do additional work. The ArrayFire code executes the\r\ncomputation on different devices but they will not be queued at the same time\r\nbecause the data transfer to the c_data array is a blocking operation.\r\n<pre class=\"lang:c++ decode:true\">for(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nIn order for this to work correctly you would have had to split the loop so that\r\nthe matmul operation is queued first then in a separate loop the data is transfered\r\nto the CPU. If more work needs to be performed, you will need to create a third loop\r\nto iterate through the devices again.\r\n<pre class=\"lang:c++ decode:true\">vector&lt;array&gt; a(nDevices);\r\nvector&lt;array&gt; b(nDevices);\r\nvector&lt;array&gt; c(nDevices);\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    a[i] = randu(1000, 1000);\r\n    b[i] = constant(3, 1000, 1000);\r\n    c[i] = matmul(a, b);\r\n}\r\n\r\nvector&lt;vector&lt;float&gt;&gt; c_data(nDevices)\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i)\r\n    c_data[i] = vector&lt;float&gt;(c.elements());\r\n    c[i].host(c_data[i].data());\r\n}\r\n\r\n// Perform some host side side work\r\n\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n    setDevice(i);\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n}</pre>\r\nThis will perform the operations on each of the GPUs on the machines as expected\r\nbut it is troublesome to program like this. With the thread-safety updates in 3.5\r\nyou can now execute the operations for each of the GPUs in separate threads.\r\n<pre class=\"lang:c++ decode:true\">vector&lt;thread&gt; threads;\r\nfor(int i = 0; i &lt; nDevices; i++) {\r\n  threads.emplace_back([=]() {\r\n    setDevice(i);\r\n    array a = randu(1000, 1000);\r\n    array b = constant(3, 1000, 1000);\r\n    array c = matmul(a, b);\r\n\r\n    // Blocks until the previous operation has completed\r\n    vector&lt;float&gt; c_data(c.elements());\r\n    c.host(c_data.data());\r\n\r\n    // Perform some host side side work\r\n\r\n    array data(1000, 1000, c_data.data());\r\n    // more work\r\n  });\r\n}\r\n</pre>\r\nThis is a much easier to implement using threads then the for loop approach.\r\n<h3><strong>Canny edge detector</strong></h3>\r\nWe have added the Canny edge detection algorithm to ArrayFire. The Canny\r\nalgorithm is a multi-stage algorithm which can handle a wide variety of edges\r\nThe canny algorithm can automatically calculate the thresholds\r\nusing Otsu\'s method.\r\n<h3><strong>Sparse-Dense arithmetic</strong></h3>\r\nArrayFire 3.4 introduced initial support for sparse arrays. With 3.5 we are\r\nexpanding the sparse arrays to allow for sparse-dense arithmetic.\r\n<h3><strong>Support for CLBlast</strong></h3>\r\nWith ArrayFire 3.5 we are introducing support for a new OpenCL BLAS\r\nimplementation. It is developed by Cedric Nugteren and it is called CLBlast. It\r\nhas improved performance on NVIDIA hardware and features an autotuner support\r\ndevices that have not been explicitly been optimized. You can read more about\r\nclBlast at the GitHub repository <a href=\"https://github.com/CNugteren/CLBlast\">here</a>.\r\n<h3><strong>Improved CUDA JIT engine</strong></h3>\r\nThe CUDA JIT engine has been refactored to use the NVRTC library. Previously the\r\nJIT functionality was implemented using the NVVM library which made it difficult\r\nto employ more advanced control flows. With NVRTC we can create more advanced\r\nJIT functions to improve the performance.\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Download[/custom_headline]\r\n\r\nArrayFire v3.5 can be downloaded from these locations:\r\n<ul>\r\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Community[/custom_headline]\r\n\r\nArrayFire is continually improving through the addition of new functions and features. We welcome your feedback:\r\n<ul>\r\n 	<li>General discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a></li>\r\n 	<li>Live discussion chat on the <a href=\"https://gitter.im/arrayfire/arrayfire?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\">ArrayFire Gitter</a></li>\r\n 	<li>Issue reports on the <a href=\"https://github.com/arrayfire/arrayfire/issues\">ArrayFire GitHub</a></li>\r\n</ul>\r\nAs you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> to contribute to this blog.\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Dedicated Support and Coding Services[/custom_headline]\r\n\r\nArrayFire offers dedicated <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a> for ArrayFire users.\r\n\r\nArrayFire serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers. Contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> or <a href=\"http://meetme.so/arrayfire\">schedule</a> a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5 Official Release','','inherit','closed','closed','','9683-revision-v1','','','2017-07-10 13:59:05','2017-07-10 17:59:05','',9683,'https://sandbox.arrayfire.com/9683-revision-v1/',0,'revision','',0),(9706,17729,'2017-07-13 10:00:37','2017-07-13 14:00:37','Today, we are pleased to announce the first stable release of Forge - a high performance OpenGL visualization library for C/C++ applications that use CUDA/OpenCL as computational backbone.\r\n\r\nIn Forge v1.0, two kinds of renderings are possible. One is an Image and the other is a Chart. Chart by itself doesn\'t render anything other than axes and some labels on it. Chart has to be embedded with one or more of the following graphs to render the respective renderings.\r\n<ul>\r\n<li> 2D Line Plots </li>\r\n<li> 3D Line Plots </li>\r\n<li> Surfaces </li>\r\n<li> Histograms </li>\r\n<li> Vector fields, both 2D and 3D</li>\r\n<li> Images </li>\r\n</ul>\r\n\r\nFirst, we shall go through the details of how to create a window using Forge and later illustrate the rest of the functionality from v1.0 using some sample code snippets and images.\r\n\r\n<h4>How to Create a Window</h4>\r\nThe code used to create a window is identical in all the examples that illustrate inter-operation of CPU/CUDA/OpenCL with OpenGL. Therefore, the following window creation code is not repeated in later code snippets where only the draw calls and data-update steps will be shown.\r\n<pre>\r\n<code>\r\n#include <forge.h>\r\n\r\n#define USE_FORGE_CPU_COPY_HELPERS\r\n/*\r\n * Below <ComputeCopy.h> header inclusion requires definition of atleast one\r\n * of the following so that appropriate copy helper functions are included\r\n * for helping the user copy data from their own respective GPU buffer\'s to\r\n * the OpenGL buffers\r\n *     - USE_FORGE_CPU_COPY_HELPERS     // Used for Interoperation of OpenGL with CPU memory\r\n *     - USE_FORGE_CUDA_COPY_HELPERS    // Used for Interoperation of OpenGL with CUDA device memory\r\n *     - USE_FORGE_OPENCL_COPY_HELPERS  // Used for Interoperation of OpenGL with OpenCL device memory\r\n */\r\n#include <ComputeCopy.h>\r\n\r\n/*\r\n * The user may choose to implement their own data updation code and skip\r\n * using the one provided by <ComputeCopy.h>\r\n */\r\n\r\nconst unsigned W = 512;\r\nconst unsigned H = 512;\r\n\r\nusing namespace std;\r\n\r\nint main(void)\r\n{\r\n    /*\r\n     * First Forge call should be a window creation call\r\n     * so that necessary OpenGL context is created for any\r\n     * other forge::* object to be created successfully\r\n     */\r\n    forge::Window wnd(W, H, \"Forge Demo\");\r\n    wnd.makeCurrent(); //Make the window\'s context current\r\n\r\n	/* All GPU buffers creation and population with data\r\n     *  happens here\r\n     */\r\n\r\n    // Render loop begins\r\n    do {\r\n        // All draw calls go here\r\n\r\n        // We can also update the data inside\r\n        // render loop to creation animations\r\n    } while(!wnd.close());\r\n\r\n    return 0;\r\n}\r\n</code>\r\n</pre>\r\n\r\n<h4>Rendering an Image to Window</h4>\r\nImage rendering example will be demonstrated using GL-CPU interop. Once the window creation is completed, we have to create an object of class <em>forge::Image</em>. \r\n<pre>\r\n<code>\r\n/* Create an image object which creates the necessary\r\n * textures and pixel buffer objects to hold the image\r\n * */\r\nforge::Image img(W, H, FG_RGBA, forge::u8);\r\n</code>\r\n</pre>\r\n\r\nNow, create a variable of type <em>GfxHandle</em> that points to the OpenGL buffer and transfer the\r\ndata from CPU memory to OpenGL memory. The functions <em>createGLBuffer</em>, <em>copyToGLBuffer</em> are defined in ComputeCopy.h header.\r\n<pre>\r\n<code>\r\nkernel(bmp);                    // create the fractal\r\n\r\nGfxHandle* handle = 0;          // GL-CPU interop buffer handle\r\n    \r\ncreateGLBuffer(&handle, img.pixels(), FORGE_IMAGE_BUFFER);\r\n\r\n// copy the data from compute buffer to graphics buffer\r\ncopyToGLBuffer(handle, (ComputeResourceHandle)bmp.ptr, img.size());\r\n</code>\r\n</pre>\r\nIt\'s time to render the image to window. If at all, the image needs to be updated during the render loop, you can do so by calling <em>copyToGLBuffer</em> with updated data pointer inside the render loop.\r\n<pre>\r\n<code>\r\ndo {\r\n    wnd.draw(img); // Draw call to render an image to window\r\n} while(!wnd.close());\r\n</code>\r\n</pre>\r\n\r\nClean up the resources.\r\n<pre>\r\n<code>\r\n// destroy GL-CPU Interop buffer\r\nreleaseGLBuffer(handle); // In ComputeCopy.h\r\ndestroyBitmap(bmp); // Clear CPU memory buffer\r\n</code>\r\n</pre>\r\n\r\nYou can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/cpu/fractal.cpp\">here</a>. The output of fractal render is shown below.\r\n[caption id=\"attachment_9630\" align=\"aligncenter\" width=\"728\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_image.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_image.png\" alt=\"Fractal Demo\" width=\"728\" height=\"772\" class=\"size-full wp-image-9630\" /></a> Fractal Demo[/caption]\r\n\r\n<h4>Rendering a Histogram</h4>\r\nWe will use CUDA-GL interop for this example. Let\'s create an object of class <em>forge::Histogram</em> and add it to a <em>forge::Chart</em> object.\r\n<pre>\r\n<code>\r\nforge::Image img(IMGW, IMGH, FG_RGBA, forge::u8); //Image placeholder\r\n\r\nforge::Chart chart(FG_CHART_2D); // Histogram is a 2D graph, hence a 2D chart\r\n\r\n//Axes Labels Format uses printf style formatting\r\nchart.setAxesLabelFormat(\"%3.1f\", \"%.2e\");\r\n\r\n/* set x axis limits to maximum and minimum values of data\r\n * and y axis limits to range [0, number of pixels ideally]\r\n * but practically total number of pixels as y range will skew\r\n * the histogram graph vertically. Therefore setting it to\r\n * 25% of total number of pixels */\r\nchart.setAxesLimits(0, 1, 0, IMGW*IMGH/(float)(NBINS/4.0));\r\n\r\n// Create histogram object specifying number of bins\r\n// this call automatically appends the histogram to list\r\n// of objects to be rendered by chart after it is created.\r\nforge::Histogram hist = chart.histogram(NBINS, forge::s32);\r\n\r\n// Set histogram colors\r\n// this color is used if no per-bar colors are not used\r\nhist.setColor(FG_YELLOW);\r\n</code>\r\n</pre>\r\nNow, create GL buffer handles for image, histogram data points and colors of histogram bars.\r\n<pre>\r\n<code>\r\n#define USE_FORGE_CUDA_COPY_HELPERS\r\n//Including USE_FORGE_CUDA_COPY_HELPERS instead of USE_FORGE_CPU_COPY_HELPERS\r\n//makes all the difference when it comes to using the copy helper functions\r\n//provided in the below header. The user code will still remain very similar\r\n//to it\'s CPU or OPENCL counterparts.\r\n#include <ComputeCopy.h>\r\n\r\nGfxHandle* handles[3];\r\n\r\ncreateGLBuffer(&handles[0], img.pixels(), FORGE_IMAGE_BUFFER);\r\ncreateGLBuffer(&handles[1], hist.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[2], hist.colors(), FORGE_VERTEX_BUFFER);\r\n\r\n//Helper fn used to create histogram from image\r\nkernel(bmp, noiseGenerator);\r\n\r\n//Copy image to img resource handle\r\ncopyToGLBuffer(handles[0], (ComputeResourceHandle)bmp.ptr, img.size());\r\n\r\n// create the histogram from image and generate\r\n// histogram bar colors\r\npopulateBins(bmp, histOut, NBINS, histColors);\r\n\r\n//Copy histogram frequencies and bar colors to OpenGL buffers\r\ncopyToGLBuffer(handles[1], (ComputeResourceHandle)histOut, hist.verticesSize());\r\ncopyToGLBuffer(handles[2], (ComputeResourceHandle)histColors, hist.colorsSize());\r\n</code>\r\n</pre>\r\nIt\'s time to render the histogram and image to the window. Note that we added only histogram to the chart. So, the image has to be somehow rendered to the same window such that we can view both the image and histogram at the same time. Multiple view rendering comes to rescue here. Let\'s take a look at the code to see how it helps.\r\n<pre>\r\n<code>\r\ndo {\r\n     /*\r\n      * Split the window into grid regions\r\n      */\r\n     // Render the image to the sub-view with index 0 if the\r\n     // entire window is divided into 1 row and 2 columns\r\n     wnd.draw(1, 2, 0, img,  \"Dynamic Perlin Noise\" );\r\n\r\n     // Render the image to the sub-view with index 1 if the\r\n     // entire window is divided into 1 row and 2 columns\r\n     wnd.draw(1, 2, 1, chart, \"Histogram of Noisy Image\");\r\n\r\n     // Swap the render buffers to display new rendering\r\n     wnd.swapBuffers(); \r\n} while(!wnd.close());\r\n\r\n// cleanup resources\r\nFORGE_CUDA_CHECK(cudaFree(histOut));\r\nFORGE_CUDA_CHECK(cudaFree(histColors));\r\nreleaseGLBuffer(handles[0]);\r\nreleaseGLBuffer(handles[1]);\r\nreleaseGLBuffer(handles[2]);\r\n</code>\r\n</pre>\r\nYou can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/cuda/histogram.cu\">here</a>. The output of histogram render is shown below.\r\n[caption id=\"attachment_9629\" align=\"aligncenter\" width=\"1228\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_hist.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_hist.png\" alt=\"Histogram\" width=\"1228\" height=\"829\" class=\"size-full wp-image-9629\" /></a> Histogram[/caption]\r\n\r\n<h4>Multiple View Rendering</h4>\r\nGiven below are some examples of non-regular grid layouts that are possible using Forge\'s multiple view rendering.\r\n<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/grids.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/grids.png\" alt=\"grids\" width=\"942\" height=\"419\" class=\"aligncenter size-full wp-image-9664\" /></a>\r\n\r\n<h4>Rendering Multiple Plots on a Chart</h4>\r\nWe will use OpenCL-GL interop for this example. When it comes to interop with OpenCL, please make sure OpenGL context is created first before setting up any of the OpenCL objects.\r\n<pre>\r\n<code>\r\n// Do \"#define USE_FORGE_OPENCL_COPY_HELPERS\" before including ComputeCopy header.\r\n\r\nforge::Chart chart(FG_CHART_2D);\r\nchart.setAxesLimits(FRANGE_START, FRANGE_END, -1.0f, 1.0f);\r\n\r\n/* Create several plot objects which creates the necessary\r\n * vertex buffer objects to hold the different plot types\r\n */\r\n// Line plot with triangle markers at data points\r\nforge::Plot plt1 = chart.plot(DATA_SIZE, forge::f32, FG_PLOT_LINE, FG_MARKER_TRIANGLE);\r\n\r\n// Line plot with circular markers at data points\r\nforge::Plot plt2 = chart.plot(DATA_SIZE, forge::f32, FG_PLOT_LINE, FG_MARKER_CIRCLE);\r\n\r\n/* Set plot colors */\r\n//use a forge predefined color FG_GREEN & FG_RED\r\nplt1.setColor(FG_RED);\r\nplt2.setColor(FG_GREEN);\r\n\r\n/* Set plot legends */\r\nplt1.setLegend(\"Cosine\");\r\nplt2.setLegend(\"Tangent\");\r\n\r\n/* set plot global marker size */\r\nplt1.setMarkerSize(20);\r\n//plt2 will use default marker size\r\n\r\n/*\r\n * Helper function to create a CLGL interop context.\r\n * This function checks for if the extension is available\r\n * and creates the context on the appropriate device.\r\n *\r\n * Note: context and queue are defined in cl_helpers.h\r\n *       and these are returned by getContext() and getCommandQueue()\r\n *       functions when they are called by createGLBuffer, copyToGLBuffer\r\n *       and releaseGLBuffer copy helper functions\r\n */\r\ncontext = createCLGLContext(wnd);\r\nDevice device = context.getInfo<CL_CONTEXT_DEVICES>()[0];\r\nqueue = CommandQueue(context, device);\r\n\r\nGfxHandle* handles[5];\r\n\r\n// create GL-OpenCL interop buffers\r\ncreateGLBuffer(&handles[0], plt1.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[1], plt2.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[2], plt2.colors(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[3], plt2.alphas(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[4], plt2.radii(), FORGE_VERTEX_BUFFER);\r\n\r\ncl::Buffer cosOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 2);\r\ncl::Buffer tanOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 2);\r\ncl::Buffer colorsOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 3);\r\ncl::Buffer alphasOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE);\r\ncl::Buffer radiiOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE);\r\ncl::Buffer dummy;\r\n\r\nkernel(cosOut, 0, 0, dummy, dummy, dummy, queue, device);\r\nkernel(tanOut, 1, 0x00000007, colorsOut, alphasOut, radiiOut, queue, device);\r\n\r\n/* copy your data into the opengl buffer object exposed by\r\n * forge::Plot class and then proceed to rendering.\r\n * To help the users with copying the data from compute\r\n * memory to display memory, Forge provides copy headers\r\n * along with the library to help with this task\r\n */\r\ncopyToGLBuffer(handles[0], (ComputeResourceHandle)cosOut(), plt1.verticesSize());\r\ncopyToGLBuffer(handles[1], (ComputeResourceHandle)tanOut(), plt2.verticesSize());\r\n\r\n/* update color value for tan graph */\r\ncopyToGLBuffer(handles[2], (ComputeResourceHandle)colorsOut(), plt2.colorsSize());\r\n\r\n/* update alpha values for tan graph */\r\ncopyToGLBuffer(handles[3], (ComputeResourceHandle)alphasOut(), plt2.alphasSize());\r\n\r\n/* update marker sizes for tan graph markers */\r\ncopyToGLBuffer(handles[4], (ComputeResourceHandle)radiiOut(), plt2.radiiSize());\r\n</code>\r\n</pre>\r\nWe don\'t have multiple view rendering here and the draw call is simple and similar to how image example does it. You can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/opencl/bubblechart.cpp\">here</a>. The output of multiple plot rendering is shown below.\r\n[caption id=\"attachment_9628\" align=\"aligncenter\" width=\"998\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_bubble.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_bubble.png\" alt=\"Multiple Plots Per Chart\" width=\"998\" height=\"844\" class=\"size-full wp-image-9628\" /></a> Multiple Plots Per Chart[/caption]\r\n\r\n<h4>Sample Renders of Surface & Vector Field</h4>\r\n[caption id=\"attachment_9634\" align=\"aligncenter\" width=\"1022\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_surface.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_surface.png\" alt=\"Surface\" width=\"1022\" height=\"812\" class=\"size-full wp-image-9634\" /></a> Surface[/caption]\r\n\r\n[caption id=\"attachment_9665\" align=\"aligncenter\" width=\"1011\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/vfield.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/vfield.png\" alt=\"Vector Field\" width=\"1011\" height=\"780\" class=\"size-full wp-image-9665\" /></a> Vector Field[/caption]\r\nSource code for these examples can be found <a href=\"https://github.com/arrayfire/forge/tree/devel/examples\">here</a>.\r\n\r\n<h4>Other Features </h4>\r\n<h5>Font Management</h5>\r\nThe class <em>forge::Font</em> provides the choice of selecting the font for your program\'s rendering. You may skip using this class and the library will defer to the default fonts.\r\n<pre>\r\n<code>\r\n    /* create an font object and load necessary font\r\n     * and later pass it on to window object so that\r\n     * it can be used for rendering text\r\n     *\r\n     * NOTE: THIS IS OPTIONAL STEP, BY DEFAULT WINDOW WILL\r\n     * HAVE FONT ALREADY SETUP*/\r\n    forge::Font fnt;\r\n#ifdef OS_WIN\r\n    fnt.loadSystemFont(\"Calibri\");\r\n#else\r\n    fnt.loadSystemFont(\"Vera\");\r\n#endif\r\n    wnd.setFont(&fnt);\r\n</code>\r\n</pre>\r\n\r\n<h5>Window Interactivity</h5>\r\nForge provides basic mouse interactivity such as pan, zoom and trackball rotation.\r\n\r\n<h5>Error Handling</h5>\r\n<em>forge::Error</em> is the exception class that you should use to catch the errors thrown by Forge.\r\n\r\n<h5>Documentation</h5>\r\nFull documentation of the library can be found <a href=\"http://arrayfire.org/forge/index.htm\">here</a>.\r\n\r\n<h5>Building from Source</h5>\r\nYou can find all the build dependencies required to build Forge from source <a href=\"https://github.com/arrayfire/forge/blob/devel/README.md\">here</a>. Default window toolkit used by Forge is <a href=\"http://www.glfw.org/\" target=\"_blank\">GLFW</a>. However, you can also build Forge with <a href=\"https://www.libsdl.org/\" target=\"_blank\">SDL2</a>.\r\n\r\n<h4>Community</h4>\r\nForge is continually improving through addition of new features. We welcome your feedback. Please feel free to leave your comments on any of the following channels.\r\n\r\nGeneral discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\" target=\"_blank\">ArrayFire Google Group</a>\r\nLive discussion chat on the <a href=\"https://gitter.im/arrayfire/forge?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\" target=\"_blank\">Forge Gitter</a>\r\nIssue reports on the <a href=\"https://github.com/arrayfire/forge/issues\" target=\"_blank\">Forge GitHub</a>\r\nFinally, as you find success with Forge, we invite you to contribute a post to this blog to share with the broader community. Email sales@arrayfire.com to contribute to this blog.','Forge v1.0 Official Release','','inherit','closed','closed','','9615-revision-v1','','','2017-07-13 10:00:37','2017-07-13 14:00:37','',9615,'https://sandbox.arrayfire.com/9615-revision-v1/',0,'revision','',0),(9707,17729,'2017-07-13 11:59:26','2017-07-13 15:59:26','Today, we are pleased to announce the first stable release of Forge - a high performance OpenGL visualization library for C/C++ applications that use CUDA/OpenCL as computational backbone.\r\n\r\nIn Forge v1.0, two kinds of renderings are possible. One is an Image and the other is a Chart. Chart by itself doesn\'t render anything other than axes and some labels on it. Chart has to be embedded with one or more of the following graphs to render the respective renderings.\r\n<ul>\r\n<li> 2D Line Plots </li>\r\n<li> 3D Line Plots </li>\r\n<li> Surfaces </li>\r\n<li> Histograms </li>\r\n<li> Vector fields, both 2D and 3D</li>\r\n<li> Images </li>\r\n</ul>\r\n\r\nFirst, we shall go through the details of how to create a window using Forge and later illustrate the rest of the functionality from v1.0 using some sample code snippets and images.\r\n\r\n<h4>How to Create a Window</h4>\r\nThe code used to create a window is identical in all the examples that illustrate inter-operation of CPU/CUDA/OpenCL with OpenGL. Therefore, the following window creation code is not repeated in later code snippets where only the draw calls and data-update steps will be shown.\r\n<pre>\r\n<code>#include <forge.h>\r\n\r\nint main(void)\r\n{\r\n    /*\r\n     * First Forge call should be a window creation call\r\n     * so that necessary backend context is created\r\n     */\r\n    forge::Window wnd(512, 512, \"Forge Demo\");\r\n\r\n    /* GPU buffers creation and population may happen here */\r\n    \r\n    do {// Render loop\r\n        // draw calls go here\r\n        // May update the data inside loop to creation animations\r\n    } while(!wnd.close());\r\n\r\n    return 0;\r\n}\r\n</code>\r\n</pre>\r\n\r\n<h4>Rendering an Image to Window</h4>\r\nImage rendering example will be demonstrated using GL-CPU interop. Once the window creation is completed, we have to create an object of class <em>forge::Image</em>. \r\n<pre>\r\n<code>\r\nforge::Image img(width, height, FG_RGBA, forge::u8);\r\n</code>\r\n</pre>\r\n\r\nNow, create a variable of type <em>GfxHandle</em> that points to the OpenGL buffer and transfer the\r\ndata from CPU memory to OpenGL memory. The functions <em>createGLBuffer</em>, <em>copyToGLBuffer</em> are defined in ComputeCopy.h header.\r\n<pre>\r\n<code>\r\n#define USE_FORGE_CPU_COPY_HELPERS\r\n#include <ComputeCopy.h> //User may implement their own data update code\r\n\r\nkernel(bmp);                    // create the fractal\r\n\r\nGfxHandle* handle = 0;          // GL-CPU interop buffer handle\r\n    \r\ncreateGLBuffer(&handle, img.pixels(), FORGE_IMAGE_BUFFER);\r\n\r\n// copy the data from compute buffer to graphics buffer\r\ncopyToGLBuffer(handle, (ComputeResourceHandle)bmp.ptr, img.size());\r\n</code>\r\n</pre>\r\nIt\'s time to render the image to window. If at all, the image needs to be updated during the render loop, you can do so by calling <em>copyToGLBuffer</em> with updated data pointer inside the render loop.\r\n<pre>\r\n<code>\r\ndo {\r\n    wnd.draw(img); // Draw call to render an image to window\r\n} while(!wnd.close());\r\n</code>\r\n</pre>\r\n\r\nClean up the resources.\r\n<pre>\r\n<code>\r\nreleaseGLBuffer(handle); // In ComputeCopy.h\r\ndestroyBitmap(bmp); // Clear CPU memory buffer\r\n</code>\r\n</pre>\r\n\r\nYou can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/cpu/fractal.cpp\">here</a>. The output of fractal render is shown below.\r\n[caption id=\"attachment_9630\" align=\"aligncenter\" width=\"728\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_image.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_image.png\" alt=\"Fractal Demo\" width=\"728\" height=\"772\" class=\"size-full wp-image-9630\" /></a> Fractal Demo[/caption]\r\n\r\n<h4>Rendering a Histogram</h4>\r\nWe will use CUDA-GL interop for this example. Let\'s create an object of class <em>forge::Histogram</em> and add it to a <em>forge::Chart</em> object.\r\n<pre>\r\n<code>\r\nforge::Image img(IMGW, IMGH, FG_RGBA, forge::u8); //Image placeholder\r\n\r\nforge::Chart chart(FG_CHART_2D); // Histogram is a 2D graph, hence a 2D chart\r\n\r\n//Axes Labels Format uses printf style formatting\r\nchart.setAxesLabelFormat(\"%3.1f\", \"%.2e\");\r\n\r\n/* set x axis limits to maximum and minimum values of data\r\n * and y axis limits to range [0, number of pixels ideally]\r\n * but practically total number of pixels as y range will skew\r\n * the histogram graph vertically. Therefore setting it to\r\n * 25% of total number of pixels */\r\nchart.setAxesLimits(0, 1, 0, IMGW*IMGH/(float)(NBINS/4.0));\r\n\r\n// Create histogram object specifying number of bins\r\n// this call automatically appends the histogram to list\r\n// of objects to be rendered by chart after it is created.\r\nforge::Histogram hist = chart.histogram(NBINS, forge::s32);\r\n\r\n// Set global bar color which is used if no per-bar colors are used\r\nhist.setColor(FG_YELLOW);\r\n</code>\r\n</pre>\r\nNow, create GL buffer handles for image, histogram data points and colors of histogram bars.\r\n<pre>\r\n<code>\r\n#define USE_FORGE_CUDA_COPY_HELPERS\r\n#include <ComputeCopy.h>\r\n\r\nGfxHandle* handles[3];\r\n\r\ncreateGLBuffer(&handles[0], img.pixels(), FORGE_IMAGE_BUFFER);\r\ncreateGLBuffer(&handles[1], hist.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[2], hist.colors(), FORGE_VERTEX_BUFFER);\r\n\r\n//Helper fn used to create histogram from image\r\nkernel(bmp, noiseGenerator);\r\n\r\n//Copy image to img resource handle\r\ncopyToGLBuffer(handles[0], (ComputeResourceHandle)bmp.ptr, img.size());\r\n\r\n// create the histogram from image and generate\r\n// histogram bar colors\r\npopulateBins(bmp, histOut, NBINS, histColors);\r\n\r\n//Copy histogram frequencies and bar colors to OpenGL buffers\r\ncopyToGLBuffer(handles[1], (ComputeResourceHandle)histOut, hist.verticesSize());\r\ncopyToGLBuffer(handles[2], (ComputeResourceHandle)histColors, hist.colorsSize());\r\n</code>\r\n</pre>\r\nIt\'s time to render the histogram and image to the window. Note that we added only histogram to the chart. So, the image has to be somehow rendered to the same window such that we can view both the image and histogram at the same time. Multiple view rendering comes to rescue here. Let\'s take a look at the code to see how it helps.\r\n<pre>\r\n<code>\r\ndo {\r\n     /*\r\n      * Split the window into grid regions\r\n      */\r\n     // Render the image to the sub-view with index 0 if the\r\n     // entire window is divided into 1 row and 2 columns\r\n     wnd.draw(1, 2, 0, img,  \"Dynamic Perlin Noise\" );\r\n     // Render the image to the sub-view with index 1 if the\r\n     // entire window is divided into 1 row and 2 columns\r\n     wnd.draw(1, 2, 1, chart, \"Histogram of Noisy Image\");\r\n     // Swap the render buffers to display new rendering\r\n     wnd.swapBuffers(); \r\n} while(!wnd.close());\r\n\r\n// cleanup resources\r\nFORGE_CUDA_CHECK(cudaFree(histOut));\r\nFORGE_CUDA_CHECK(cudaFree(histColors));\r\nreleaseGLBuffer(handles[0]);\r\nreleaseGLBuffer(handles[1]);\r\nreleaseGLBuffer(handles[2]);\r\n</code>\r\n</pre>\r\nYou can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/cuda/histogram.cu\">here</a>. The output of histogram render is shown below.\r\n[caption id=\"attachment_9629\" align=\"aligncenter\" width=\"1228\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_hist.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_hist.png\" alt=\"Histogram\" width=\"1228\" height=\"829\" class=\"size-full wp-image-9629\" /></a> Histogram[/caption]\r\n\r\n<h4>Multiple View Rendering</h4>\r\nGiven below are some examples of non-regular grid layouts that are possible using Forge\'s multiple view rendering.\r\n<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/grids.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/grids.png\" alt=\"grids\" width=\"942\" height=\"419\" class=\"aligncenter size-full wp-image-9664\" /></a>\r\n\r\n<h4>Rendering Multiple Plots on a Chart</h4>\r\nWe will use OpenCL-GL interop for this example. When it comes to interop with OpenCL, please make sure OpenGL context is created first before setting up any of the OpenCL objects.\r\n<pre>\r\n<code>\r\n// Do \"#define USE_FORGE_OPENCL_COPY_HELPERS\" before including ComputeCopy header.\r\n\r\nforge::Chart chart(FG_CHART_2D);\r\nchart.setAxesLimits(FRANGE_START, FRANGE_END, -1.0f, 1.0f);\r\n\r\n/* Create several plot objects which creates the necessary\r\n * vertex buffer objects to hold the different plot types\r\n */\r\n// Line plot with triangle markers at data points\r\nforge::Plot plt1 = chart.plot(DATA_SIZE, forge::f32, FG_PLOT_LINE, FG_MARKER_TRIANGLE);\r\n\r\n// Line plot with circular markers at data points\r\nforge::Plot plt2 = chart.plot(DATA_SIZE, forge::f32, FG_PLOT_LINE, FG_MARKER_CIRCLE);\r\n\r\n/* Set plot colors */\r\n//use a forge predefined color FG_GREEN & FG_RED\r\nplt1.setColor(FG_RED);\r\nplt2.setColor(FG_GREEN);\r\n\r\n/* Set plot legends */\r\nplt1.setLegend(\"Cosine\");\r\nplt2.setLegend(\"Tangent\");\r\n\r\n/* set plot global marker size */\r\nplt1.setMarkerSize(20);\r\n//plt2 will use default marker size\r\n\r\n/*\r\n * Helper function to create a CLGL interop context.\r\n * This function checks for if the extension is available\r\n * and creates the context on the appropriate device.\r\n *\r\n * Note: context and queue are defined in cl_helpers.h\r\n *       and these are returned by getContext() and getCommandQueue()\r\n *       functions when they are called by createGLBuffer, copyToGLBuffer\r\n *       and releaseGLBuffer copy helper functions\r\n */\r\ncontext = createCLGLContext(wnd);\r\nDevice device = context.getInfo<CL_CONTEXT_DEVICES>()[0];\r\nqueue = CommandQueue(context, device);\r\n\r\nGfxHandle* handles[5];\r\n\r\n// create GL-OpenCL interop buffers\r\ncreateGLBuffer(&handles[0], plt1.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[1], plt2.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[2], plt2.colors(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[3], plt2.alphas(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[4], plt2.radii(), FORGE_VERTEX_BUFFER);\r\n\r\ncl::Buffer cosOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 2);\r\ncl::Buffer tanOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 2);\r\ncl::Buffer colorsOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 3);\r\ncl::Buffer alphasOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE);\r\ncl::Buffer radiiOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE);\r\ncl::Buffer dummy;\r\n\r\nkernel(cosOut, 0, 0, dummy, dummy, dummy, queue, device);\r\nkernel(tanOut, 1, 0x00000007, colorsOut, alphasOut, radiiOut, queue, device);\r\n\r\n/* copy your data into the opengl buffer object exposed by\r\n * forge::Plot class and then proceed to rendering.\r\n * To help the users with copying the data from compute\r\n * memory to display memory, Forge provides copy headers\r\n * along with the library to help with this task\r\n */\r\ncopyToGLBuffer(handles[0], (ComputeResourceHandle)cosOut(), plt1.verticesSize());\r\ncopyToGLBuffer(handles[1], (ComputeResourceHandle)tanOut(), plt2.verticesSize());\r\n\r\n/* update color value for tan graph */\r\ncopyToGLBuffer(handles[2], (ComputeResourceHandle)colorsOut(), plt2.colorsSize());\r\n\r\n/* update alpha values for tan graph */\r\ncopyToGLBuffer(handles[3], (ComputeResourceHandle)alphasOut(), plt2.alphasSize());\r\n\r\n/* update marker sizes for tan graph markers */\r\ncopyToGLBuffer(handles[4], (ComputeResourceHandle)radiiOut(), plt2.radiiSize());\r\n</code>\r\n</pre>\r\nWe don\'t have multiple view rendering here and the draw call is simple and similar to how image example does it. You can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/opencl/bubblechart.cpp\">here</a>. The output of multiple plot rendering is shown below.\r\n[caption id=\"attachment_9628\" align=\"aligncenter\" width=\"998\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_bubble.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_bubble.png\" alt=\"Multiple Plots Per Chart\" width=\"998\" height=\"844\" class=\"size-full wp-image-9628\" /></a> Multiple Plots Per Chart[/caption]\r\n\r\n<h4>Sample Renders of Surface & Vector Field</h4>\r\n[caption id=\"attachment_9634\" align=\"aligncenter\" width=\"1022\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_surface.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_surface.png\" alt=\"Surface\" width=\"1022\" height=\"812\" class=\"size-full wp-image-9634\" /></a> Surface[/caption]\r\n\r\n[caption id=\"attachment_9665\" align=\"aligncenter\" width=\"1011\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/vfield.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/vfield.png\" alt=\"Vector Field\" width=\"1011\" height=\"780\" class=\"size-full wp-image-9665\" /></a> Vector Field[/caption]\r\nSource code for these examples can be found <a href=\"https://github.com/arrayfire/forge/tree/devel/examples\">here</a>.\r\n\r\n<h4>Other Features </h4>\r\n<h5>Font Management</h5>\r\nThe class <em>forge::Font</em> provides the choice of selecting the font for your program\'s rendering. You may skip using this class and the library will defer to the default fonts.\r\n<pre>\r\n<code>\r\n    /* create an font object and load necessary font\r\n     * and later pass it on to window object so that\r\n     * it can be used for rendering text\r\n     *\r\n     * NOTE: THIS IS OPTIONAL STEP, BY DEFAULT WINDOW WILL\r\n     * HAVE FONT ALREADY SETUP*/\r\n    forge::Font fnt;\r\n#ifdef OS_WIN\r\n    fnt.loadSystemFont(\"Calibri\");\r\n#else\r\n    fnt.loadSystemFont(\"Vera\");\r\n#endif\r\n    wnd.setFont(&fnt);\r\n</code>\r\n</pre>\r\n\r\n<h5>Window Interactivity</h5>\r\nForge provides basic mouse interactivity such as pan, zoom and trackball rotation.\r\n\r\n<h5>Error Handling</h5>\r\n<em>forge::Error</em> is the exception class that you should use to catch the errors thrown by Forge.\r\n\r\n<h5>Documentation</h5>\r\nFull documentation of the library can be found <a href=\"http://arrayfire.org/forge/index.htm\">here</a>.\r\n\r\n<h5>Building from Source</h5>\r\nYou can find all the build dependencies required to build Forge from source <a href=\"https://github.com/arrayfire/forge/blob/devel/README.md\">here</a>. Default window toolkit used by Forge is <a href=\"http://www.glfw.org/\" target=\"_blank\">GLFW</a>. However, you can also build Forge with <a href=\"https://www.libsdl.org/\" target=\"_blank\">SDL2</a>.\r\n\r\n<h4>Community</h4>\r\nForge is continually improving through addition of new features. We welcome your feedback. Please feel free to leave your comments on any of the following channels.\r\n\r\nGeneral discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\" target=\"_blank\">ArrayFire Google Group</a>\r\nLive discussion chat on the <a href=\"https://gitter.im/arrayfire/forge?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\" target=\"_blank\">Forge Gitter</a>\r\nIssue reports on the <a href=\"https://github.com/arrayfire/forge/issues\" target=\"_blank\">Forge GitHub</a>\r\nFinally, as you find success with Forge, we invite you to contribute a post to this blog to share with the broader community. Email sales@arrayfire.com to contribute to this blog.','Forge v1.0 Official Release','','inherit','closed','closed','','9615-revision-v1','','','2017-07-13 11:59:26','2017-07-13 15:59:26','',9615,'https://sandbox.arrayfire.com/9615-revision-v1/',0,'revision','',0),(9708,17729,'2017-07-13 12:25:20','2017-07-13 16:25:20','Today, we are pleased to announce the first stable release of Forge - a high performance OpenGL visualization library for C/C++ applications that use CUDA/OpenCL as computational backbone.\r\n\r\nIn Forge v1.0, two kinds of renderings are possible. One is an Image and the other is a Chart. Chart by itself doesn\'t render anything other than axes and some labels on it. Chart has to be embedded with one or more of the following graphs to render the respective renderings.\r\n<ul>\r\n<li> 2D Line Plots </li>\r\n<li> 3D Line Plots </li>\r\n<li> Surfaces </li>\r\n<li> Histograms </li>\r\n<li> Vector fields, both 2D and 3D</li>\r\n<li> Images </li>\r\n</ul>\r\n\r\nFirst, we shall go through the details of how to create a window using Forge and later illustrate the rest of the functionality from v1.0 using some sample code snippets and images.\r\n<h4>How to Create a Window</h4>\r\nThe code used to create a window is identical in all the examples that illustrate inter-operation of CPU/CUDA/OpenCL with OpenGL. Therefore, the following window creation code is not repeated in later code snippets where only the draw calls and data-update steps will be shown.\r\n\r\n<pre><code>#include <forge.h>\r\n\r\nint main(void)\r\n{\r\n    /*\r\n     * First Forge call should be a window creation call\r\n     * so that necessary backend context is created\r\n     */\r\n    forge::Window wnd(512, 512, \"Forge Demo\");\r\n\r\n    /* GPU buffers creation and population may happen here */\r\n    \r\n    do {// Render loop\r\n        // draw calls go here\r\n        // May update the data inside loop to creation animations\r\n    } while(!wnd.close());\r\n\r\n    return 0;\r\n}</code></pre>\r\n\r\n<h4>Rendering an Image to Window</h4>\r\nImage rendering example will be demonstrated using GL-CPU interop. Once the window creation is completed, we have to create an object of class <em>forge::Image</em>. \r\n<pre><code>forge::Image img(width, height, FG_RGBA, forge::u8);</code></pre>\r\n\r\nNow, create a variable of type <em>GfxHandle</em> that points to the OpenGL buffer and transfer the\r\ndata from CPU memory to OpenGL memory. The functions <em>createGLBuffer</em>, <em>copyToGLBuffer</em> are defined in ComputeCopy.h header.\r\n<pre><code>#define USE_FORGE_CPU_COPY_HELPERS\r\n#include <ComputeCopy.h> //User may implement their own data update code\r\n\r\nkernel(bmp);                    // create the fractal\r\n\r\nGfxHandle* handle = 0;          // GL-CPU interop buffer handle\r\n    \r\ncreateGLBuffer(&handle, img.pixels(), FORGE_IMAGE_BUFFER);\r\n\r\n// copy the data from compute buffer to graphics buffer\r\ncopyToGLBuffer(handle, (ComputeResourceHandle)bmp.ptr, img.size());</code></pre>\r\n\r\nIt\'s time to render the image to window. If at all, the image needs to be updated during the render loop, you can do so by calling <em>copyToGLBuffer</em> with updated data pointer inside the render loop.\r\n<pre><code>do {\r\n    wnd.draw(img); // Draw call to render an image to window\r\n} while(!wnd.close());</code></pre>\r\n\r\nClean up the resources.\r\n<pre><code>releaseGLBuffer(handle); // In ComputeCopy.h\r\ndestroyBitmap(bmp); // Clear CPU memory buffer</code></pre>\r\n\r\nYou can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/cpu/fractal.cpp\">here</a>. The output of fractal render is shown below.\r\n[caption id=\"attachment_9630\" align=\"aligncenter\" width=\"728\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_image.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_image.png\" alt=\"Fractal Demo\" width=\"728\" height=\"772\" class=\"size-full wp-image-9630\" /></a> Fractal Demo[/caption]\r\n\r\n<h4>Rendering a Histogram</h4>\r\nWe will use CUDA-GL interop for this example. Let\'s create an object of class <em>forge::Histogram</em> and add it to a <em>forge::Chart</em> object.\r\n<pre><code>forge::Image img(IMGW, IMGH, FG_RGBA, forge::u8); //Image placeholder\r\n\r\nforge::Chart chart(FG_CHART_2D); // Histogram is a 2D graph, hence a 2D chart\r\n\r\n//Axes Labels Format uses printf style formatting\r\nchart.setAxesLabelFormat(\"%3.1f\", \"%.2e\");\r\n\r\n/* set x axis limits to maximum and minimum values of data\r\n * and y axis limits to range [0, number of pixels ideally]\r\n * but practically total number of pixels as y range will skew\r\n * the histogram graph vertically. Therefore setting it to\r\n * 25% of total number of pixels */\r\nchart.setAxesLimits(0, 1, 0, IMGW*IMGH/(float)(NBINS/4.0));\r\n\r\n// Create histogram object specifying number of bins\r\n// this call automatically appends the histogram to list\r\n// of objects to be rendered by chart after it is created.\r\nforge::Histogram hist = chart.histogram(NBINS, forge::s32);\r\n\r\n// Set global bar color which is used if no per-bar colors are used\r\nhist.setColor(FG_YELLOW);</code></pre>\r\n\r\nNow, create GL buffer handles for image, histogram data points and colors of histogram bars.\r\n<pre><code>#define USE_FORGE_CUDA_COPY_HELPERS\r\n#include <ComputeCopy.h>\r\n\r\nGfxHandle* handles[3];\r\n\r\ncreateGLBuffer(&handles[0], img.pixels(), FORGE_IMAGE_BUFFER);\r\ncreateGLBuffer(&handles[1], hist.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[2], hist.colors(), FORGE_VERTEX_BUFFER);\r\n\r\n//Helper fn used to create histogram from image\r\nkernel(bmp, noiseGenerator);\r\n\r\n//Copy image to img resource handle\r\ncopyToGLBuffer(handles[0], (ComputeResourceHandle)bmp.ptr, img.size());\r\n\r\n// create the histogram from image and generate\r\n// histogram bar colors\r\npopulateBins(bmp, histOut, NBINS, histColors);\r\n\r\n//Copy histogram frequencies and bar colors to OpenGL buffers\r\ncopyToGLBuffer(handles[1], (ComputeResourceHandle)histOut, hist.verticesSize());\r\ncopyToGLBuffer(handles[2], (ComputeResourceHandle)histColors, hist.colorsSize());</code></pre>\r\n\r\nIt\'s time to render the histogram and image to the window. Note that we added only histogram to the chart. So, the image has to be somehow rendered to the same window such that we can view both the image and histogram at the same time. Multiple view rendering comes to rescue here. Let\'s take a look at the code to see how it helps.\r\n<pre><code>do {\r\n     /*\r\n      * Split the window into grid regions\r\n      */\r\n     // Render the image to the sub-view with index 0 if the\r\n     // entire window is divided into 1 row and 2 columns\r\n     wnd.draw(1, 2, 0, img,  \"Dynamic Perlin Noise\" );\r\n     // Render the image to the sub-view with index 1 if the\r\n     // entire window is divided into 1 row and 2 columns\r\n     wnd.draw(1, 2, 1, chart, \"Histogram of Noisy Image\");\r\n     // Swap the render buffers to display new rendering\r\n     wnd.swapBuffers(); \r\n} while(!wnd.close());\r\n\r\n// cleanup resources\r\nFORGE_CUDA_CHECK(cudaFree(histOut));\r\nFORGE_CUDA_CHECK(cudaFree(histColors));\r\nreleaseGLBuffer(handles[0]);\r\nreleaseGLBuffer(handles[1]);\r\nreleaseGLBuffer(handles[2]);</code></pre>\r\n\r\nYou can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/cuda/histogram.cu\">here</a>. The output of histogram render is shown below.\r\n[caption id=\"attachment_9629\" align=\"aligncenter\" width=\"1228\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_hist.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_hist.png\" alt=\"Histogram\" width=\"1228\" height=\"829\" class=\"size-full wp-image-9629\" /></a> Histogram[/caption]\r\n\r\n<h4>Multiple View Rendering</h4>\r\nGiven below are some examples of non-regular grid layouts that are possible using Forge\'s multiple view rendering.\r\n<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/grids.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/grids.png\" alt=\"grids\" width=\"942\" height=\"419\" class=\"aligncenter size-full wp-image-9664\" /></a>\r\n\r\n<h4>Rendering Multiple Plots on a Chart</h4>\r\nWe will use OpenCL-GL interop for this example. When it comes to interop with OpenCL, please make sure OpenGL context is created first before setting up any of the OpenCL objects.\r\n<pre><code>// Do \"#define USE_FORGE_OPENCL_COPY_HELPERS\" before including ComputeCopy header.\r\n\r\nforge::Chart chart(FG_CHART_2D);\r\nchart.setAxesLimits(FRANGE_START, FRANGE_END, -1.0f, 1.0f);\r\n\r\n/* Create several plot objects which creates the necessary\r\n * vertex buffer objects to hold the different plot types\r\n */\r\n// Line plot with triangle markers at data points\r\nforge::Plot plt1 = chart.plot(DATA_SIZE, forge::f32, FG_PLOT_LINE, FG_MARKER_TRIANGLE);\r\n\r\n// Line plot with circular markers at data points\r\nforge::Plot plt2 = chart.plot(DATA_SIZE, forge::f32, FG_PLOT_LINE, FG_MARKER_CIRCLE);\r\n\r\n/* Set plot colors */\r\n//use a forge predefined color FG_GREEN & FG_RED\r\nplt1.setColor(FG_RED);\r\nplt2.setColor(FG_GREEN);\r\n\r\n/* Set plot legends */\r\nplt1.setLegend(\"Cosine\");\r\nplt2.setLegend(\"Tangent\");\r\n\r\n/* set plot global marker size */\r\nplt1.setMarkerSize(20);\r\n//plt2 will use default marker size\r\n\r\n/*\r\n * Helper function to create a CLGL interop context.\r\n * This function checks for if the extension is available\r\n * and creates the context on the appropriate device.\r\n *\r\n * Note: context and queue are defined in cl_helpers.h\r\n *       and these are returned by getContext() and getCommandQueue()\r\n *       functions when they are called by createGLBuffer, copyToGLBuffer\r\n *       and releaseGLBuffer copy helper functions\r\n */\r\ncontext = createCLGLContext(wnd);\r\nDevice device = context.getInfo<CL_CONTEXT_DEVICES>()[0];\r\nqueue = CommandQueue(context, device);\r\n\r\nGfxHandle* handles[5];\r\n\r\n// create GL-OpenCL interop buffers\r\ncreateGLBuffer(&handles[0], plt1.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[1], plt2.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[2], plt2.colors(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[3], plt2.alphas(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[4], plt2.radii(), FORGE_VERTEX_BUFFER);\r\n\r\ncl::Buffer cosOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 2);\r\ncl::Buffer tanOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 2);\r\ncl::Buffer colorsOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 3);\r\ncl::Buffer alphasOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE);\r\ncl::Buffer radiiOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE);\r\ncl::Buffer dummy;\r\n\r\nkernel(cosOut, 0, 0, dummy, dummy, dummy, queue, device);\r\nkernel(tanOut, 1, 0x00000007, colorsOut, alphasOut, radiiOut, queue, device);\r\n\r\n/* copy your data into the opengl buffer object exposed by\r\n * forge::Plot class and then proceed to rendering.\r\n * To help the users with copying the data from compute\r\n * memory to display memory, Forge provides copy headers\r\n * along with the library to help with this task\r\n */\r\ncopyToGLBuffer(handles[0], (ComputeResourceHandle)cosOut(), plt1.verticesSize());\r\ncopyToGLBuffer(handles[1], (ComputeResourceHandle)tanOut(), plt2.verticesSize());\r\n\r\n/* update color value for tan graph */\r\ncopyToGLBuffer(handles[2], (ComputeResourceHandle)colorsOut(), plt2.colorsSize());\r\n\r\n/* update alpha values for tan graph */\r\ncopyToGLBuffer(handles[3], (ComputeResourceHandle)alphasOut(), plt2.alphasSize());\r\n\r\n/* update marker sizes for tan graph markers */\r\ncopyToGLBuffer(handles[4], (ComputeResourceHandle)radiiOut(), plt2.radiiSize());</code></pre>\r\n\r\nWe don\'t have multiple view rendering here and the draw call is simple and similar to how image example does it. You can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/opencl/bubblechart.cpp\">here</a>. The output of multiple plot rendering is shown below.\r\n[caption id=\"attachment_9628\" align=\"aligncenter\" width=\"998\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_bubble.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_bubble.png\" alt=\"Multiple Plots Per Chart\" width=\"998\" height=\"844\" class=\"size-full wp-image-9628\" /></a> Multiple Plots Per Chart[/caption]\r\n\r\n<h4>Sample Renders of Surface & Vector Field</h4>\r\n[caption id=\"attachment_9634\" align=\"aligncenter\" width=\"1022\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_surface.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_surface.png\" alt=\"Surface\" width=\"1022\" height=\"812\" class=\"size-full wp-image-9634\" /></a> Surface[/caption]\r\n\r\n[caption id=\"attachment_9665\" align=\"aligncenter\" width=\"1011\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/vfield.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/vfield.png\" alt=\"Vector Field\" width=\"1011\" height=\"780\" class=\"size-full wp-image-9665\" /></a> Vector Field[/caption]\r\nSource code for these examples can be found <a href=\"https://github.com/arrayfire/forge/tree/devel/examples\">here</a>.\r\n\r\n<h4>Other Features </h4>\r\n<h5>Font Management</h5>\r\nThe class <em>forge::Font</em> provides the choice of selecting the font for your program\'s rendering. You may skip using this class and the library will defer to the default fonts.\r\n<pre><code>/* create an font object and load necessary font\r\n     * and later pass it on to window object so that\r\n     * it can be used for rendering text\r\n     *\r\n     * NOTE: THIS IS OPTIONAL STEP, BY DEFAULT WINDOW WILL\r\n     * HAVE FONT ALREADY SETUP*/\r\n    forge::Font fnt;\r\n#ifdef OS_WIN\r\n    fnt.loadSystemFont(\"Calibri\");\r\n#else\r\n    fnt.loadSystemFont(\"Vera\");\r\n#endif\r\n    wnd.setFont(&fnt);</code></pre>\r\n\r\n<h5>Window Interactivity</h5>\r\nForge provides basic mouse interactivity such as pan, zoom and trackball rotation.\r\n\r\n<h5>Error Handling</h5>\r\n<em>forge::Error</em> is the exception class that you should use to catch the errors thrown by Forge.\r\n\r\n<h5>Documentation</h5>\r\nFull documentation of the library can be found <a href=\"http://arrayfire.org/forge/index.htm\">here</a>.\r\n\r\n<h5>Building from Source</h5>\r\nYou can find all the build dependencies required to build Forge from source <a href=\"https://github.com/arrayfire/forge/blob/devel/README.md\">here</a>. Default window toolkit used by Forge is <a href=\"http://www.glfw.org/\" target=\"_blank\">GLFW</a>. However, you can also build Forge with <a href=\"https://www.libsdl.org/\" target=\"_blank\">SDL2</a>.\r\n\r\n<h4>Community</h4>\r\nForge is continually improving through addition of new features. We welcome your feedback. Please feel free to leave your comments on any of the following channels.\r\n\r\nGeneral discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\" target=\"_blank\">ArrayFire Google Group</a>\r\nLive discussion chat on the <a href=\"https://gitter.im/arrayfire/forge?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\" target=\"_blank\">Forge Gitter</a>\r\nIssue reports on the <a href=\"https://github.com/arrayfire/forge/issues\" target=\"_blank\">Forge GitHub</a>\r\nFinally, as you find success with Forge, we invite you to contribute a post to this blog to share with the broader community. Email sales@arrayfire.com to contribute to this blog.','Forge v1.0 Official Release','','inherit','closed','closed','','9615-revision-v1','','','2017-07-13 12:25:20','2017-07-13 16:25:20','',9615,'https://sandbox.arrayfire.com/9615-revision-v1/',0,'revision','',0),(9709,17729,'2017-07-13 12:25:48','2017-07-13 16:25:48','Today, we are pleased to announce the first stable release of Forge - a high performance OpenGL visualization library for C/C++ applications that use CUDA/OpenCL as computational backbone.\r\n\r\nIn Forge v1.0, two kinds of renderings are possible. One is an Image and the other is a Chart. Chart by itself doesn\'t render anything other than axes and some labels on it. Chart has to be embedded with one or more of the following graphs to render the respective renderings.\r\n<ul>\r\n<li> 2D Line Plots </li>\r\n<li> 3D Line Plots </li>\r\n<li> Surfaces </li>\r\n<li> Histograms </li>\r\n<li> Vector fields, both 2D and 3D</li>\r\n<li> Images </li>\r\n</ul>\r\n\r\nFirst, we shall go through the details of how to create a window using Forge and later illustrate the rest of the functionality from v1.0 using some sample code snippets and images.<nobr/>\r\n<h4>How to Create a Window</h4>\r\nThe code used to create a window is identical in all the examples that illustrate inter-operation of CPU/CUDA/OpenCL with OpenGL. Therefore, the following window creation code is not repeated in later code snippets where only the draw calls and data-update steps will be shown.\r\n\r\n<pre><code>#include <forge.h>\r\n\r\nint main(void)\r\n{\r\n    /*\r\n     * First Forge call should be a window creation call\r\n     * so that necessary backend context is created\r\n     */\r\n    forge::Window wnd(512, 512, \"Forge Demo\");\r\n\r\n    /* GPU buffers creation and population may happen here */\r\n    \r\n    do {// Render loop\r\n        // draw calls go here\r\n        // May update the data inside loop to creation animations\r\n    } while(!wnd.close());\r\n\r\n    return 0;\r\n}</code></pre>\r\n\r\n<h4>Rendering an Image to Window</h4>\r\nImage rendering example will be demonstrated using GL-CPU interop. Once the window creation is completed, we have to create an object of class <em>forge::Image</em>. \r\n<pre><code>forge::Image img(width, height, FG_RGBA, forge::u8);</code></pre>\r\n\r\nNow, create a variable of type <em>GfxHandle</em> that points to the OpenGL buffer and transfer the\r\ndata from CPU memory to OpenGL memory. The functions <em>createGLBuffer</em>, <em>copyToGLBuffer</em> are defined in ComputeCopy.h header.\r\n<pre><code>#define USE_FORGE_CPU_COPY_HELPERS\r\n#include <ComputeCopy.h> //User may implement their own data update code\r\n\r\nkernel(bmp);                    // create the fractal\r\n\r\nGfxHandle* handle = 0;          // GL-CPU interop buffer handle\r\n    \r\ncreateGLBuffer(&handle, img.pixels(), FORGE_IMAGE_BUFFER);\r\n\r\n// copy the data from compute buffer to graphics buffer\r\ncopyToGLBuffer(handle, (ComputeResourceHandle)bmp.ptr, img.size());</code></pre>\r\n\r\nIt\'s time to render the image to window. If at all, the image needs to be updated during the render loop, you can do so by calling <em>copyToGLBuffer</em> with updated data pointer inside the render loop.\r\n<pre><code>do {\r\n    wnd.draw(img); // Draw call to render an image to window\r\n} while(!wnd.close());</code></pre>\r\n\r\nClean up the resources.\r\n<pre><code>releaseGLBuffer(handle); // In ComputeCopy.h\r\ndestroyBitmap(bmp); // Clear CPU memory buffer</code></pre>\r\n\r\nYou can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/cpu/fractal.cpp\">here</a>. The output of fractal render is shown below.\r\n[caption id=\"attachment_9630\" align=\"aligncenter\" width=\"728\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_image.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_image.png\" alt=\"Fractal Demo\" width=\"728\" height=\"772\" class=\"size-full wp-image-9630\" /></a> Fractal Demo[/caption]\r\n\r\n<h4>Rendering a Histogram</h4>\r\nWe will use CUDA-GL interop for this example. Let\'s create an object of class <em>forge::Histogram</em> and add it to a <em>forge::Chart</em> object.\r\n<pre><code>forge::Image img(IMGW, IMGH, FG_RGBA, forge::u8); //Image placeholder\r\n\r\nforge::Chart chart(FG_CHART_2D); // Histogram is a 2D graph, hence a 2D chart\r\n\r\n//Axes Labels Format uses printf style formatting\r\nchart.setAxesLabelFormat(\"%3.1f\", \"%.2e\");\r\n\r\n/* set x axis limits to maximum and minimum values of data\r\n * and y axis limits to range [0, number of pixels ideally]\r\n * but practically total number of pixels as y range will skew\r\n * the histogram graph vertically. Therefore setting it to\r\n * 25% of total number of pixels */\r\nchart.setAxesLimits(0, 1, 0, IMGW*IMGH/(float)(NBINS/4.0));\r\n\r\n// Create histogram object specifying number of bins\r\n// this call automatically appends the histogram to list\r\n// of objects to be rendered by chart after it is created.\r\nforge::Histogram hist = chart.histogram(NBINS, forge::s32);\r\n\r\n// Set global bar color which is used if no per-bar colors are used\r\nhist.setColor(FG_YELLOW);</code></pre>\r\n\r\nNow, create GL buffer handles for image, histogram data points and colors of histogram bars.\r\n<pre><code>#define USE_FORGE_CUDA_COPY_HELPERS\r\n#include <ComputeCopy.h>\r\n\r\nGfxHandle* handles[3];\r\n\r\ncreateGLBuffer(&handles[0], img.pixels(), FORGE_IMAGE_BUFFER);\r\ncreateGLBuffer(&handles[1], hist.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[2], hist.colors(), FORGE_VERTEX_BUFFER);\r\n\r\n//Helper fn used to create histogram from image\r\nkernel(bmp, noiseGenerator);\r\n\r\n//Copy image to img resource handle\r\ncopyToGLBuffer(handles[0], (ComputeResourceHandle)bmp.ptr, img.size());\r\n\r\n// create the histogram from image and generate\r\n// histogram bar colors\r\npopulateBins(bmp, histOut, NBINS, histColors);\r\n\r\n//Copy histogram frequencies and bar colors to OpenGL buffers\r\ncopyToGLBuffer(handles[1], (ComputeResourceHandle)histOut, hist.verticesSize());\r\ncopyToGLBuffer(handles[2], (ComputeResourceHandle)histColors, hist.colorsSize());</code></pre>\r\n\r\nIt\'s time to render the histogram and image to the window. Note that we added only histogram to the chart. So, the image has to be somehow rendered to the same window such that we can view both the image and histogram at the same time. Multiple view rendering comes to rescue here. Let\'s take a look at the code to see how it helps.\r\n<pre><code>do {\r\n     /*\r\n      * Split the window into grid regions\r\n      */\r\n     // Render the image to the sub-view with index 0 if the\r\n     // entire window is divided into 1 row and 2 columns\r\n     wnd.draw(1, 2, 0, img,  \"Dynamic Perlin Noise\" );\r\n     // Render the image to the sub-view with index 1 if the\r\n     // entire window is divided into 1 row and 2 columns\r\n     wnd.draw(1, 2, 1, chart, \"Histogram of Noisy Image\");\r\n     // Swap the render buffers to display new rendering\r\n     wnd.swapBuffers(); \r\n} while(!wnd.close());\r\n\r\n// cleanup resources\r\nFORGE_CUDA_CHECK(cudaFree(histOut));\r\nFORGE_CUDA_CHECK(cudaFree(histColors));\r\nreleaseGLBuffer(handles[0]);\r\nreleaseGLBuffer(handles[1]);\r\nreleaseGLBuffer(handles[2]);</code></pre>\r\n\r\nYou can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/cuda/histogram.cu\">here</a>. The output of histogram render is shown below.\r\n[caption id=\"attachment_9629\" align=\"aligncenter\" width=\"1228\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_hist.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_hist.png\" alt=\"Histogram\" width=\"1228\" height=\"829\" class=\"size-full wp-image-9629\" /></a> Histogram[/caption]\r\n\r\n<h4>Multiple View Rendering</h4>\r\nGiven below are some examples of non-regular grid layouts that are possible using Forge\'s multiple view rendering.\r\n<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/grids.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/grids.png\" alt=\"grids\" width=\"942\" height=\"419\" class=\"aligncenter size-full wp-image-9664\" /></a>\r\n\r\n<h4>Rendering Multiple Plots on a Chart</h4>\r\nWe will use OpenCL-GL interop for this example. When it comes to interop with OpenCL, please make sure OpenGL context is created first before setting up any of the OpenCL objects.\r\n<pre><code>// Do \"#define USE_FORGE_OPENCL_COPY_HELPERS\" before including ComputeCopy header.\r\n\r\nforge::Chart chart(FG_CHART_2D);\r\nchart.setAxesLimits(FRANGE_START, FRANGE_END, -1.0f, 1.0f);\r\n\r\n/* Create several plot objects which creates the necessary\r\n * vertex buffer objects to hold the different plot types\r\n */\r\n// Line plot with triangle markers at data points\r\nforge::Plot plt1 = chart.plot(DATA_SIZE, forge::f32, FG_PLOT_LINE, FG_MARKER_TRIANGLE);\r\n\r\n// Line plot with circular markers at data points\r\nforge::Plot plt2 = chart.plot(DATA_SIZE, forge::f32, FG_PLOT_LINE, FG_MARKER_CIRCLE);\r\n\r\n/* Set plot colors */\r\n//use a forge predefined color FG_GREEN & FG_RED\r\nplt1.setColor(FG_RED);\r\nplt2.setColor(FG_GREEN);\r\n\r\n/* Set plot legends */\r\nplt1.setLegend(\"Cosine\");\r\nplt2.setLegend(\"Tangent\");\r\n\r\n/* set plot global marker size */\r\nplt1.setMarkerSize(20);\r\n//plt2 will use default marker size\r\n\r\n/*\r\n * Helper function to create a CLGL interop context.\r\n * This function checks for if the extension is available\r\n * and creates the context on the appropriate device.\r\n *\r\n * Note: context and queue are defined in cl_helpers.h\r\n *       and these are returned by getContext() and getCommandQueue()\r\n *       functions when they are called by createGLBuffer, copyToGLBuffer\r\n *       and releaseGLBuffer copy helper functions\r\n */\r\ncontext = createCLGLContext(wnd);\r\nDevice device = context.getInfo<CL_CONTEXT_DEVICES>()[0];\r\nqueue = CommandQueue(context, device);\r\n\r\nGfxHandle* handles[5];\r\n\r\n// create GL-OpenCL interop buffers\r\ncreateGLBuffer(&handles[0], plt1.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[1], plt2.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[2], plt2.colors(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[3], plt2.alphas(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[4], plt2.radii(), FORGE_VERTEX_BUFFER);\r\n\r\ncl::Buffer cosOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 2);\r\ncl::Buffer tanOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 2);\r\ncl::Buffer colorsOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 3);\r\ncl::Buffer alphasOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE);\r\ncl::Buffer radiiOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE);\r\ncl::Buffer dummy;\r\n\r\nkernel(cosOut, 0, 0, dummy, dummy, dummy, queue, device);\r\nkernel(tanOut, 1, 0x00000007, colorsOut, alphasOut, radiiOut, queue, device);\r\n\r\n/* copy your data into the opengl buffer object exposed by\r\n * forge::Plot class and then proceed to rendering.\r\n * To help the users with copying the data from compute\r\n * memory to display memory, Forge provides copy headers\r\n * along with the library to help with this task\r\n */\r\ncopyToGLBuffer(handles[0], (ComputeResourceHandle)cosOut(), plt1.verticesSize());\r\ncopyToGLBuffer(handles[1], (ComputeResourceHandle)tanOut(), plt2.verticesSize());\r\n\r\n/* update color value for tan graph */\r\ncopyToGLBuffer(handles[2], (ComputeResourceHandle)colorsOut(), plt2.colorsSize());\r\n\r\n/* update alpha values for tan graph */\r\ncopyToGLBuffer(handles[3], (ComputeResourceHandle)alphasOut(), plt2.alphasSize());\r\n\r\n/* update marker sizes for tan graph markers */\r\ncopyToGLBuffer(handles[4], (ComputeResourceHandle)radiiOut(), plt2.radiiSize());</code></pre>\r\n\r\nWe don\'t have multiple view rendering here and the draw call is simple and similar to how image example does it. You can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/opencl/bubblechart.cpp\">here</a>. The output of multiple plot rendering is shown below.\r\n[caption id=\"attachment_9628\" align=\"aligncenter\" width=\"998\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_bubble.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_bubble.png\" alt=\"Multiple Plots Per Chart\" width=\"998\" height=\"844\" class=\"size-full wp-image-9628\" /></a> Multiple Plots Per Chart[/caption]\r\n\r\n<h4>Sample Renders of Surface & Vector Field</h4>\r\n[caption id=\"attachment_9634\" align=\"aligncenter\" width=\"1022\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_surface.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_surface.png\" alt=\"Surface\" width=\"1022\" height=\"812\" class=\"size-full wp-image-9634\" /></a> Surface[/caption]\r\n\r\n[caption id=\"attachment_9665\" align=\"aligncenter\" width=\"1011\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/vfield.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/vfield.png\" alt=\"Vector Field\" width=\"1011\" height=\"780\" class=\"size-full wp-image-9665\" /></a> Vector Field[/caption]\r\nSource code for these examples can be found <a href=\"https://github.com/arrayfire/forge/tree/devel/examples\">here</a>.\r\n\r\n<h4>Other Features </h4>\r\n<h5>Font Management</h5>\r\nThe class <em>forge::Font</em> provides the choice of selecting the font for your program\'s rendering. You may skip using this class and the library will defer to the default fonts.\r\n<pre><code>/* create an font object and load necessary font\r\n     * and later pass it on to window object so that\r\n     * it can be used for rendering text\r\n     *\r\n     * NOTE: THIS IS OPTIONAL STEP, BY DEFAULT WINDOW WILL\r\n     * HAVE FONT ALREADY SETUP*/\r\n    forge::Font fnt;\r\n#ifdef OS_WIN\r\n    fnt.loadSystemFont(\"Calibri\");\r\n#else\r\n    fnt.loadSystemFont(\"Vera\");\r\n#endif\r\n    wnd.setFont(&fnt);</code></pre>\r\n\r\n<h5>Window Interactivity</h5>\r\nForge provides basic mouse interactivity such as pan, zoom and trackball rotation.\r\n\r\n<h5>Error Handling</h5>\r\n<em>forge::Error</em> is the exception class that you should use to catch the errors thrown by Forge.\r\n\r\n<h5>Documentation</h5>\r\nFull documentation of the library can be found <a href=\"http://arrayfire.org/forge/index.htm\">here</a>.\r\n\r\n<h5>Building from Source</h5>\r\nYou can find all the build dependencies required to build Forge from source <a href=\"https://github.com/arrayfire/forge/blob/devel/README.md\">here</a>. Default window toolkit used by Forge is <a href=\"http://www.glfw.org/\" target=\"_blank\">GLFW</a>. However, you can also build Forge with <a href=\"https://www.libsdl.org/\" target=\"_blank\">SDL2</a>.\r\n\r\n<h4>Community</h4>\r\nForge is continually improving through addition of new features. We welcome your feedback. Please feel free to leave your comments on any of the following channels.\r\n\r\nGeneral discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\" target=\"_blank\">ArrayFire Google Group</a>\r\nLive discussion chat on the <a href=\"https://gitter.im/arrayfire/forge?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\" target=\"_blank\">Forge Gitter</a>\r\nIssue reports on the <a href=\"https://github.com/arrayfire/forge/issues\" target=\"_blank\">Forge GitHub</a>\r\nFinally, as you find success with Forge, we invite you to contribute a post to this blog to share with the broader community. Email sales@arrayfire.com to contribute to this blog.','Forge v1.0 Official Release','','inherit','closed','closed','','9615-revision-v1','','','2017-07-13 12:25:48','2017-07-13 16:25:48','',9615,'https://sandbox.arrayfire.com/9615-revision-v1/',0,'revision','',0),(9710,17729,'2017-07-13 12:26:08','2017-07-13 16:26:08','Today, we are pleased to announce the first stable release of Forge - a high performance OpenGL visualization library for C/C++ applications that use CUDA/OpenCL as computational backbone.\r\n\r\nIn Forge v1.0, two kinds of renderings are possible. One is an Image and the other is a Chart. Chart by itself doesn\'t render anything other than axes and some labels on it. Chart has to be embedded with one or more of the following graphs to render the respective renderings.\r\n<ul>\r\n<li> 2D Line Plots </li>\r\n<li> 3D Line Plots </li>\r\n<li> Surfaces </li>\r\n<li> Histograms </li>\r\n<li> Vector fields, both 2D and 3D</li>\r\n<li> Images </li>\r\n</ul>\r\n\r\nFirst, we shall go through the details of how to create a window using Forge and later illustrate the rest of the functionality from v1.0 using some sample code snippets and images.\r\n<h4>How to Create a Window</h4>\r\nThe code used to create a window is identical in all the examples that illustrate inter-operation of CPU/CUDA/OpenCL with OpenGL. Therefore, the following window creation code is not repeated in later code snippets where only the draw calls and data-update steps will be shown.\r\n\r\n<pre><code>#include <forge.h>\r\n\r\nint main(void)\r\n{\r\n    /*\r\n     * First Forge call should be a window creation call\r\n     * so that necessary backend context is created\r\n     */\r\n    forge::Window wnd(512, 512, \"Forge Demo\");\r\n\r\n    /* GPU buffers creation and population may happen here */\r\n    \r\n    do {// Render loop\r\n        // draw calls go here\r\n        // May update the data inside loop to creation animations\r\n    } while(!wnd.close());\r\n\r\n    return 0;\r\n}</code></pre>\r\n\r\n<h4>Rendering an Image to Window</h4>\r\nImage rendering example will be demonstrated using GL-CPU interop. Once the window creation is completed, we have to create an object of class <em>forge::Image</em>. \r\n<pre><code>forge::Image img(width, height, FG_RGBA, forge::u8);</code></pre>\r\n\r\nNow, create a variable of type <em>GfxHandle</em> that points to the OpenGL buffer and transfer the\r\ndata from CPU memory to OpenGL memory. The functions <em>createGLBuffer</em>, <em>copyToGLBuffer</em> are defined in ComputeCopy.h header.\r\n<pre><code>#define USE_FORGE_CPU_COPY_HELPERS\r\n#include <ComputeCopy.h> //User may implement their own data update code\r\n\r\nkernel(bmp);                    // create the fractal\r\n\r\nGfxHandle* handle = 0;          // GL-CPU interop buffer handle\r\n    \r\ncreateGLBuffer(&handle, img.pixels(), FORGE_IMAGE_BUFFER);\r\n\r\n// copy the data from compute buffer to graphics buffer\r\ncopyToGLBuffer(handle, (ComputeResourceHandle)bmp.ptr, img.size());</code></pre>\r\n\r\nIt\'s time to render the image to window. If at all, the image needs to be updated during the render loop, you can do so by calling <em>copyToGLBuffer</em> with updated data pointer inside the render loop.\r\n<pre><code>do {\r\n    wnd.draw(img); // Draw call to render an image to window\r\n} while(!wnd.close());</code></pre>\r\n\r\nClean up the resources.\r\n<pre><code>releaseGLBuffer(handle); // In ComputeCopy.h\r\ndestroyBitmap(bmp); // Clear CPU memory buffer</code></pre>\r\n\r\nYou can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/cpu/fractal.cpp\">here</a>. The output of fractal render is shown below.\r\n[caption id=\"attachment_9630\" align=\"aligncenter\" width=\"728\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_image.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_image.png\" alt=\"Fractal Demo\" width=\"728\" height=\"772\" class=\"size-full wp-image-9630\" /></a> Fractal Demo[/caption]\r\n\r\n<h4>Rendering a Histogram</h4>\r\nWe will use CUDA-GL interop for this example. Let\'s create an object of class <em>forge::Histogram</em> and add it to a <em>forge::Chart</em> object.\r\n<pre><code>forge::Image img(IMGW, IMGH, FG_RGBA, forge::u8); //Image placeholder\r\n\r\nforge::Chart chart(FG_CHART_2D); // Histogram is a 2D graph, hence a 2D chart\r\n\r\n//Axes Labels Format uses printf style formatting\r\nchart.setAxesLabelFormat(\"%3.1f\", \"%.2e\");\r\n\r\n/* set x axis limits to maximum and minimum values of data\r\n * and y axis limits to range [0, number of pixels ideally]\r\n * but practically total number of pixels as y range will skew\r\n * the histogram graph vertically. Therefore setting it to\r\n * 25% of total number of pixels */\r\nchart.setAxesLimits(0, 1, 0, IMGW*IMGH/(float)(NBINS/4.0));\r\n\r\n// Create histogram object specifying number of bins\r\n// this call automatically appends the histogram to list\r\n// of objects to be rendered by chart after it is created.\r\nforge::Histogram hist = chart.histogram(NBINS, forge::s32);\r\n\r\n// Set global bar color which is used if no per-bar colors are used\r\nhist.setColor(FG_YELLOW);</code></pre>\r\n\r\nNow, create GL buffer handles for image, histogram data points and colors of histogram bars.\r\n<pre><code>#define USE_FORGE_CUDA_COPY_HELPERS\r\n#include <ComputeCopy.h>\r\n\r\nGfxHandle* handles[3];\r\n\r\ncreateGLBuffer(&handles[0], img.pixels(), FORGE_IMAGE_BUFFER);\r\ncreateGLBuffer(&handles[1], hist.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[2], hist.colors(), FORGE_VERTEX_BUFFER);\r\n\r\n//Helper fn used to create histogram from image\r\nkernel(bmp, noiseGenerator);\r\n\r\n//Copy image to img resource handle\r\ncopyToGLBuffer(handles[0], (ComputeResourceHandle)bmp.ptr, img.size());\r\n\r\n// create the histogram from image and generate\r\n// histogram bar colors\r\npopulateBins(bmp, histOut, NBINS, histColors);\r\n\r\n//Copy histogram frequencies and bar colors to OpenGL buffers\r\ncopyToGLBuffer(handles[1], (ComputeResourceHandle)histOut, hist.verticesSize());\r\ncopyToGLBuffer(handles[2], (ComputeResourceHandle)histColors, hist.colorsSize());</code></pre>\r\n\r\nIt\'s time to render the histogram and image to the window. Note that we added only histogram to the chart. So, the image has to be somehow rendered to the same window such that we can view both the image and histogram at the same time. Multiple view rendering comes to rescue here. Let\'s take a look at the code to see how it helps.\r\n<pre><code>do {\r\n     /*\r\n      * Split the window into grid regions\r\n      */\r\n     // Render the image to the sub-view with index 0 if the\r\n     // entire window is divided into 1 row and 2 columns\r\n     wnd.draw(1, 2, 0, img,  \"Dynamic Perlin Noise\" );\r\n     // Render the image to the sub-view with index 1 if the\r\n     // entire window is divided into 1 row and 2 columns\r\n     wnd.draw(1, 2, 1, chart, \"Histogram of Noisy Image\");\r\n     // Swap the render buffers to display new rendering\r\n     wnd.swapBuffers(); \r\n} while(!wnd.close());\r\n\r\n// cleanup resources\r\nFORGE_CUDA_CHECK(cudaFree(histOut));\r\nFORGE_CUDA_CHECK(cudaFree(histColors));\r\nreleaseGLBuffer(handles[0]);\r\nreleaseGLBuffer(handles[1]);\r\nreleaseGLBuffer(handles[2]);</code></pre>\r\n\r\nYou can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/cuda/histogram.cu\">here</a>. The output of histogram render is shown below.\r\n[caption id=\"attachment_9629\" align=\"aligncenter\" width=\"1228\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_hist.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_hist.png\" alt=\"Histogram\" width=\"1228\" height=\"829\" class=\"size-full wp-image-9629\" /></a> Histogram[/caption]\r\n\r\n<h4>Multiple View Rendering</h4>\r\nGiven below are some examples of non-regular grid layouts that are possible using Forge\'s multiple view rendering.\r\n<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/grids.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/grids.png\" alt=\"grids\" width=\"942\" height=\"419\" class=\"aligncenter size-full wp-image-9664\" /></a>\r\n\r\n<h4>Rendering Multiple Plots on a Chart</h4>\r\nWe will use OpenCL-GL interop for this example. When it comes to interop with OpenCL, please make sure OpenGL context is created first before setting up any of the OpenCL objects.\r\n<pre><code>// Do \"#define USE_FORGE_OPENCL_COPY_HELPERS\" before including ComputeCopy header.\r\n\r\nforge::Chart chart(FG_CHART_2D);\r\nchart.setAxesLimits(FRANGE_START, FRANGE_END, -1.0f, 1.0f);\r\n\r\n/* Create several plot objects which creates the necessary\r\n * vertex buffer objects to hold the different plot types\r\n */\r\n// Line plot with triangle markers at data points\r\nforge::Plot plt1 = chart.plot(DATA_SIZE, forge::f32, FG_PLOT_LINE, FG_MARKER_TRIANGLE);\r\n\r\n// Line plot with circular markers at data points\r\nforge::Plot plt2 = chart.plot(DATA_SIZE, forge::f32, FG_PLOT_LINE, FG_MARKER_CIRCLE);\r\n\r\n/* Set plot colors */\r\n//use a forge predefined color FG_GREEN & FG_RED\r\nplt1.setColor(FG_RED);\r\nplt2.setColor(FG_GREEN);\r\n\r\n/* Set plot legends */\r\nplt1.setLegend(\"Cosine\");\r\nplt2.setLegend(\"Tangent\");\r\n\r\n/* set plot global marker size */\r\nplt1.setMarkerSize(20);\r\n//plt2 will use default marker size\r\n\r\n/*\r\n * Helper function to create a CLGL interop context.\r\n * This function checks for if the extension is available\r\n * and creates the context on the appropriate device.\r\n *\r\n * Note: context and queue are defined in cl_helpers.h\r\n *       and these are returned by getContext() and getCommandQueue()\r\n *       functions when they are called by createGLBuffer, copyToGLBuffer\r\n *       and releaseGLBuffer copy helper functions\r\n */\r\ncontext = createCLGLContext(wnd);\r\nDevice device = context.getInfo<CL_CONTEXT_DEVICES>()[0];\r\nqueue = CommandQueue(context, device);\r\n\r\nGfxHandle* handles[5];\r\n\r\n// create GL-OpenCL interop buffers\r\ncreateGLBuffer(&handles[0], plt1.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[1], plt2.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[2], plt2.colors(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[3], plt2.alphas(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[4], plt2.radii(), FORGE_VERTEX_BUFFER);\r\n\r\ncl::Buffer cosOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 2);\r\ncl::Buffer tanOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 2);\r\ncl::Buffer colorsOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 3);\r\ncl::Buffer alphasOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE);\r\ncl::Buffer radiiOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE);\r\ncl::Buffer dummy;\r\n\r\nkernel(cosOut, 0, 0, dummy, dummy, dummy, queue, device);\r\nkernel(tanOut, 1, 0x00000007, colorsOut, alphasOut, radiiOut, queue, device);\r\n\r\n/* copy your data into the opengl buffer object exposed by\r\n * forge::Plot class and then proceed to rendering.\r\n * To help the users with copying the data from compute\r\n * memory to display memory, Forge provides copy headers\r\n * along with the library to help with this task\r\n */\r\ncopyToGLBuffer(handles[0], (ComputeResourceHandle)cosOut(), plt1.verticesSize());\r\ncopyToGLBuffer(handles[1], (ComputeResourceHandle)tanOut(), plt2.verticesSize());\r\n\r\n/* update color value for tan graph */\r\ncopyToGLBuffer(handles[2], (ComputeResourceHandle)colorsOut(), plt2.colorsSize());\r\n\r\n/* update alpha values for tan graph */\r\ncopyToGLBuffer(handles[3], (ComputeResourceHandle)alphasOut(), plt2.alphasSize());\r\n\r\n/* update marker sizes for tan graph markers */\r\ncopyToGLBuffer(handles[4], (ComputeResourceHandle)radiiOut(), plt2.radiiSize());</code></pre>\r\n\r\nWe don\'t have multiple view rendering here and the draw call is simple and similar to how image example does it. You can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/opencl/bubblechart.cpp\">here</a>. The output of multiple plot rendering is shown below.\r\n[caption id=\"attachment_9628\" align=\"aligncenter\" width=\"998\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_bubble.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_bubble.png\" alt=\"Multiple Plots Per Chart\" width=\"998\" height=\"844\" class=\"size-full wp-image-9628\" /></a> Multiple Plots Per Chart[/caption]\r\n\r\n<h4>Sample Renders of Surface & Vector Field</h4>\r\n[caption id=\"attachment_9634\" align=\"aligncenter\" width=\"1022\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_surface.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_surface.png\" alt=\"Surface\" width=\"1022\" height=\"812\" class=\"size-full wp-image-9634\" /></a> Surface[/caption]\r\n\r\n[caption id=\"attachment_9665\" align=\"aligncenter\" width=\"1011\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/vfield.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/vfield.png\" alt=\"Vector Field\" width=\"1011\" height=\"780\" class=\"size-full wp-image-9665\" /></a> Vector Field[/caption]\r\nSource code for these examples can be found <a href=\"https://github.com/arrayfire/forge/tree/devel/examples\">here</a>.\r\n\r\n<h4>Other Features </h4>\r\n<h5>Font Management</h5>\r\nThe class <em>forge::Font</em> provides the choice of selecting the font for your program\'s rendering. You may skip using this class and the library will defer to the default fonts.\r\n<pre><code>/* create an font object and load necessary font\r\n     * and later pass it on to window object so that\r\n     * it can be used for rendering text\r\n     *\r\n     * NOTE: THIS IS OPTIONAL STEP, BY DEFAULT WINDOW WILL\r\n     * HAVE FONT ALREADY SETUP*/\r\n    forge::Font fnt;\r\n#ifdef OS_WIN\r\n    fnt.loadSystemFont(\"Calibri\");\r\n#else\r\n    fnt.loadSystemFont(\"Vera\");\r\n#endif\r\n    wnd.setFont(&fnt);</code></pre>\r\n\r\n<h5>Window Interactivity</h5>\r\nForge provides basic mouse interactivity such as pan, zoom and trackball rotation.\r\n\r\n<h5>Error Handling</h5>\r\n<em>forge::Error</em> is the exception class that you should use to catch the errors thrown by Forge.\r\n\r\n<h5>Documentation</h5>\r\nFull documentation of the library can be found <a href=\"http://arrayfire.org/forge/index.htm\">here</a>.\r\n\r\n<h5>Building from Source</h5>\r\nYou can find all the build dependencies required to build Forge from source <a href=\"https://github.com/arrayfire/forge/blob/devel/README.md\">here</a>. Default window toolkit used by Forge is <a href=\"http://www.glfw.org/\" target=\"_blank\">GLFW</a>. However, you can also build Forge with <a href=\"https://www.libsdl.org/\" target=\"_blank\">SDL2</a>.\r\n\r\n<h4>Community</h4>\r\nForge is continually improving through addition of new features. We welcome your feedback. Please feel free to leave your comments on any of the following channels.\r\n\r\nGeneral discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\" target=\"_blank\">ArrayFire Google Group</a>\r\nLive discussion chat on the <a href=\"https://gitter.im/arrayfire/forge?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\" target=\"_blank\">Forge Gitter</a>\r\nIssue reports on the <a href=\"https://github.com/arrayfire/forge/issues\" target=\"_blank\">Forge GitHub</a>\r\nFinally, as you find success with Forge, we invite you to contribute a post to this blog to share with the broader community. Email sales@arrayfire.com to contribute to this blog.','Forge v1.0 Official Release','','inherit','closed','closed','','9615-revision-v1','','','2017-07-13 12:26:08','2017-07-13 16:26:08','',9615,'https://sandbox.arrayfire.com/9615-revision-v1/',0,'revision','',0),(9711,17729,'2017-07-13 12:43:46','2017-07-13 16:43:46','Today, we are pleased to announce the first stable release of Forge - a high performance OpenGL visualization library for C/C++ applications that use CUDA/OpenCL as computational backbone.\r\n\r\nIn Forge v1.0, two kinds of renderings are possible. One is an Image and the other is a Chart. Chart by itself doesn\'t render anything other than axes and some labels on it. Chart has to be embedded with one or more of the following graphs to render the respective renderings.\r\n<ul>\r\n<li> 2D Line Plots </li>\r\n<li> 3D Line Plots </li>\r\n<li> Surfaces </li>\r\n<li> Histograms </li>\r\n<li> Vector fields, both 2D and 3D</li>\r\n<li> Images </li>\r\n</ul>\r\nFirst, we shall go through the details of how to create a window using Forge and later illustrate the rest of the functionality from v1.0 using some sample code snippets and images.\r\n<h5>How to Create a Window</h5>\r\nThe code used to create a window is identical in all the examples that illustrate inter-operation of CPU/CUDA/OpenCL with OpenGL. Therefore, the following window creation code is not repeated in later code snippets where only the draw calls and data-update steps will be shown.\r\n\r\n<pre><code>#include <forge.h>\r\n\r\nint main(void)\r\n{\r\n    /*\r\n     * First Forge call should be a window creation call\r\n     * so that necessary backend context is created\r\n     */\r\n    forge::Window wnd(512, 512, \"Forge Demo\");\r\n\r\n    /* GPU buffers creation and population may happen here */\r\n    \r\n    do {// Render loop\r\n        // draw calls go here\r\n        // May update the data inside loop to creation animations\r\n    } while(!wnd.close());\r\n\r\n    return 0;\r\n}</code></pre>\r\n\r\n<h5>Rendering an Image to Window</h5>\r\nImage rendering example will be demonstrated using GL-CPU interop. Once the window creation is completed, we have to create an object of class <em>forge::Image</em>. \r\n<pre><code>forge::Image img(width, height, FG_RGBA, forge::u8);</code></pre>\r\n\r\nNow, create a variable of type <em>GfxHandle</em> that points to the OpenGL buffer and transfer the\r\ndata from CPU memory to OpenGL memory. The functions <em>createGLBuffer</em>, <em>copyToGLBuffer</em> are defined in ComputeCopy.h header.\r\n<pre><code>#define USE_FORGE_CPU_COPY_HELPERS\r\n#include <ComputeCopy.h> //User may implement their own data update code\r\n\r\nkernel(bmp);                    // create the fractal\r\n\r\nGfxHandle* handle = 0;          // GL-CPU interop buffer handle\r\n    \r\ncreateGLBuffer(&handle, img.pixels(), FORGE_IMAGE_BUFFER);\r\n\r\n// copy the data from compute buffer to graphics buffer\r\ncopyToGLBuffer(handle, (ComputeResourceHandle)bmp.ptr, img.size());</code></pre>\r\n\r\nIt\'s time to render the image to window. If at all, the image needs to be updated during the render loop, you can do so by calling <em>copyToGLBuffer</em> with updated data pointer inside the render loop.\r\n<pre><code>do {\r\n    wnd.draw(img); // Draw call to render an image to window\r\n} while(!wnd.close());</code></pre>\r\n\r\nClean up the resources.\r\n<pre><code>releaseGLBuffer(handle); // In ComputeCopy.h\r\ndestroyBitmap(bmp); // Clear CPU memory buffer</code></pre>\r\n\r\nYou can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/cpu/fractal.cpp\">here</a>. The output of fractal render is shown below.\r\n[caption id=\"attachment_9630\" align=\"aligncenter\" width=\"728\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_image.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_image.png\" alt=\"Fractal Demo\" width=\"728\" height=\"772\" class=\"size-full wp-image-9630\" /></a> Fractal Demo[/caption]\r\n\r\n<h5>Rendering a Histogram</h5>\r\nWe will use CUDA-GL interop for this example. Let\'s create an object of class <em>forge::Histogram</em> and add it to a <em>forge::Chart</em> object.\r\n<pre><code>forge::Image img(IMGW, IMGH, FG_RGBA, forge::u8); //Image placeholder\r\n\r\nforge::Chart chart(FG_CHART_2D); // Histogram is a 2D graph, hence a 2D chart\r\n\r\n//Axes Labels Format uses printf style formatting\r\nchart.setAxesLabelFormat(\"%3.1f\", \"%.2e\");\r\n\r\n/* set x axis limits to maximum and minimum values of data\r\n * and y axis limits to range [0, number of pixels ideally]\r\n * but practically total number of pixels as y range will skew\r\n * the histogram graph vertically. Therefore setting it to\r\n * 25% of total number of pixels */\r\nchart.setAxesLimits(0, 1, 0, IMGW*IMGH/(float)(NBINS/4.0));\r\n\r\n// Create histogram object specifying number of bins\r\n// this call automatically appends the histogram to list\r\n// of objects to be rendered by chart after it is created.\r\nforge::Histogram hist = chart.histogram(NBINS, forge::s32);\r\n\r\n// Set global bar color which is used if no per-bar colors are used\r\nhist.setColor(FG_YELLOW);</code></pre>\r\n\r\nNow, create GL buffer handles for image, histogram data points and colors of histogram bars.\r\n<pre><code>#define USE_FORGE_CUDA_COPY_HELPERS\r\n#include <ComputeCopy.h>\r\n\r\nGfxHandle* handles[3];\r\n\r\ncreateGLBuffer(&handles[0], img.pixels(), FORGE_IMAGE_BUFFER);\r\ncreateGLBuffer(&handles[1], hist.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[2], hist.colors(), FORGE_VERTEX_BUFFER);\r\n\r\n//Helper fn used to create histogram from image\r\nkernel(bmp, noiseGenerator);\r\n\r\n//Copy image to img resource handle\r\ncopyToGLBuffer(handles[0], (ComputeResourceHandle)bmp.ptr, img.size());\r\n\r\n// create the histogram from image and generate\r\n// histogram bar colors\r\npopulateBins(bmp, histOut, NBINS, histColors);\r\n\r\n//Copy histogram frequencies and bar colors to OpenGL buffers\r\ncopyToGLBuffer(handles[1], (ComputeResourceHandle)histOut, hist.verticesSize());\r\ncopyToGLBuffer(handles[2], (ComputeResourceHandle)histColors, hist.colorsSize());</code></pre>\r\n\r\nIt\'s time to render the histogram and image to the window. Note that we added only histogram to the chart. So, the image has to be somehow rendered to the same window such that we can view both the image and histogram at the same time. Multiple view rendering comes to rescue here. Let\'s take a look at the code to see how it helps.\r\n<pre><code>do {\r\n     /*\r\n      * Split the window into grid regions\r\n      */\r\n     // Render the image to the sub-view with index 0 if the\r\n     // entire window is divided into 1 row and 2 columns\r\n     wnd.draw(1, 2, 0, img,  \"Dynamic Perlin Noise\" );\r\n     // Render the image to the sub-view with index 1 if the\r\n     // entire window is divided into 1 row and 2 columns\r\n     wnd.draw(1, 2, 1, chart, \"Histogram of Noisy Image\");\r\n     // Swap the render buffers to display new rendering\r\n     wnd.swapBuffers(); \r\n} while(!wnd.close());\r\n\r\n// cleanup resources\r\nFORGE_CUDA_CHECK(cudaFree(histOut));\r\nFORGE_CUDA_CHECK(cudaFree(histColors));\r\nreleaseGLBuffer(handles[0]);\r\nreleaseGLBuffer(handles[1]);\r\nreleaseGLBuffer(handles[2]);</code></pre>\r\n\r\nYou can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/cuda/histogram.cu\">here</a>. The output of histogram render is shown below.\r\n[caption id=\"attachment_9629\" align=\"aligncenter\" width=\"1228\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_hist.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_hist.png\" alt=\"Histogram\" width=\"1228\" height=\"829\" class=\"size-full wp-image-9629\" /></a> Histogram[/caption]\r\n\r\n<h5>Multiple View Rendering</h5>\r\nGiven below are some examples of non-regular grid layouts that are possible using Forge\'s multiple view rendering.\r\n<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/grids.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/06/grids.png\" alt=\"grids\" width=\"942\" height=\"419\" class=\"aligncenter size-full wp-image-9664\" /></a>\r\n\r\n<h5>Rendering Multiple Plots on a Chart</h5>\r\nWe will use OpenCL-GL interop for this example. When it comes to interop with OpenCL, please make sure OpenGL context is created first before setting up any of the OpenCL objects.\r\n<pre><code>// Do \"#define USE_FORGE_OPENCL_COPY_HELPERS\" before including ComputeCopy header.\r\n\r\nforge::Chart chart(FG_CHART_2D);\r\nchart.setAxesLimits(FRANGE_START, FRANGE_END, -1.0f, 1.0f);\r\n\r\n/* Create several plot objects which creates the necessary\r\n * vertex buffer objects to hold the different plot types\r\n */\r\n// Line plot with triangle markers at data points\r\nforge::Plot plt1 = chart.plot(DATA_SIZE, forge::f32, FG_PLOT_LINE, FG_MARKER_TRIANGLE);\r\n\r\n// Line plot with circular markers at data points\r\nforge::Plot plt2 = chart.plot(DATA_SIZE, forge::f32, FG_PLOT_LINE, FG_MARKER_CIRCLE);\r\n\r\n/* Set plot colors */\r\n//use a forge predefined color FG_GREEN & FG_RED\r\nplt1.setColor(FG_RED);\r\nplt2.setColor(FG_GREEN);\r\n\r\n/* Set plot legends */\r\nplt1.setLegend(\"Cosine\");\r\nplt2.setLegend(\"Tangent\");\r\n\r\n/* set plot global marker size */\r\nplt1.setMarkerSize(20);\r\n//plt2 will use default marker size\r\n\r\n/*\r\n * Helper function to create a CLGL interop context.\r\n * This function checks for if the extension is available\r\n * and creates the context on the appropriate device.\r\n *\r\n * Note: context and queue are defined in cl_helpers.h\r\n *       and these are returned by getContext() and getCommandQueue()\r\n *       functions when they are called by createGLBuffer, copyToGLBuffer\r\n *       and releaseGLBuffer copy helper functions\r\n */\r\ncontext = createCLGLContext(wnd);\r\nDevice device = context.getInfo<CL_CONTEXT_DEVICES>()[0];\r\nqueue = CommandQueue(context, device);\r\n\r\nGfxHandle* handles[5];\r\n\r\n// create GL-OpenCL interop buffers\r\ncreateGLBuffer(&handles[0], plt1.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[1], plt2.vertices(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[2], plt2.colors(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[3], plt2.alphas(), FORGE_VERTEX_BUFFER);\r\ncreateGLBuffer(&handles[4], plt2.radii(), FORGE_VERTEX_BUFFER);\r\n\r\ncl::Buffer cosOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 2);\r\ncl::Buffer tanOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 2);\r\ncl::Buffer colorsOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE * 3);\r\ncl::Buffer alphasOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE);\r\ncl::Buffer radiiOut(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE);\r\ncl::Buffer dummy;\r\n\r\nkernel(cosOut, 0, 0, dummy, dummy, dummy, queue, device);\r\nkernel(tanOut, 1, 0x00000007, colorsOut, alphasOut, radiiOut, queue, device);\r\n\r\n/* copy your data into the opengl buffer object exposed by\r\n * forge::Plot class and then proceed to rendering.\r\n * To help the users with copying the data from compute\r\n * memory to display memory, Forge provides copy headers\r\n * along with the library to help with this task\r\n */\r\ncopyToGLBuffer(handles[0], (ComputeResourceHandle)cosOut(), plt1.verticesSize());\r\ncopyToGLBuffer(handles[1], (ComputeResourceHandle)tanOut(), plt2.verticesSize());\r\n\r\n/* update color value for tan graph */\r\ncopyToGLBuffer(handles[2], (ComputeResourceHandle)colorsOut(), plt2.colorsSize());\r\n\r\n/* update alpha values for tan graph */\r\ncopyToGLBuffer(handles[3], (ComputeResourceHandle)alphasOut(), plt2.alphasSize());\r\n\r\n/* update marker sizes for tan graph markers */\r\ncopyToGLBuffer(handles[4], (ComputeResourceHandle)radiiOut(), plt2.radiiSize());</code></pre>\r\n\r\nWe don\'t have multiple view rendering here and the draw call is simple and similar to how image example does it. You can look up the entire example\'s source code <a href=\"https://github.com/arrayfire/forge/blob/devel/examples/opencl/bubblechart.cpp\">here</a>. The output of multiple plot rendering is shown below.\r\n[caption id=\"attachment_9628\" align=\"aligncenter\" width=\"998\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_bubble.png\"><img src=\"https://sandbox.arrayfire.com/wp-content/uploads/2017/05/fgv1_bubble.png\" alt=\"Multiple Plots Per Chart\" width=\"998\" height=\"844\" class=\"size-full wp-image-9628\" /></a> Multiple Plots Per Chart[/caption]\r\n\r\n<h5>Sample Renders of Surface & Vector Field</h5>\r\n[gallery columns=\"2\" size=\"medium\" ids=\"9634,9665\"]\r\nSource code for these examples can be found <a href=\"https://github.com/arrayfire/forge/tree/devel/examples\">here</a>.\r\n\r\n<h5>Font Management</h5>\r\nThe class <em>forge::Font</em> provides the choice of selecting the font for your program\'s rendering. You may skip using this class and the library will defer to the default fonts.\r\n<pre><code>/* create an font object and load necessary font\r\n     * and later pass it on to window object so that\r\n     * it can be used for rendering text\r\n     *\r\n     * NOTE: THIS IS OPTIONAL STEP, BY DEFAULT WINDOW WILL\r\n     * HAVE FONT ALREADY SETUP*/\r\n    forge::Font fnt;\r\n#ifdef OS_WIN\r\n    fnt.loadSystemFont(\"Calibri\");\r\n#else\r\n    fnt.loadSystemFont(\"Vera\");\r\n#endif\r\n    wnd.setFont(&fnt);</code></pre>\r\n\r\n<h5>Window Interactivity</h5>\r\nForge provides basic mouse interactivity such as pan, zoom and trackball rotation.\r\n\r\n<h5>Error Handling</h5>\r\n<em>forge::Error</em> is the exception class that you should use to catch the errors thrown by Forge.\r\n\r\n<h5>Documentation</h5>\r\nFull documentation of the library can be found <a href=\"http://arrayfire.org/forge/index.htm\">here</a>.\r\n\r\n<h5>Building from Source</h5>\r\nYou can find all the build dependencies required to build Forge from source <a href=\"https://github.com/arrayfire/forge/blob/devel/README.md\">here</a>. Default window toolkit used by Forge is <a href=\"http://www.glfw.org/\" target=\"_blank\">GLFW</a>. However, you can also build Forge with <a href=\"https://www.libsdl.org/\" target=\"_blank\">SDL2</a>.\r\n\r\n<h5>Community</h5>\r\nForge is continually improving through addition of new features. We welcome your feedback. Please feel free to leave your comments on any of the following channels.\r\n\r\nGeneral discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\" target=\"_blank\">ArrayFire Google Group</a>\r\nLive discussion chat on the <a href=\"https://gitter.im/arrayfire/forge?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\" target=\"_blank\">Forge Gitter</a>\r\nIssue reports on the <a href=\"https://github.com/arrayfire/forge/issues\" target=\"_blank\">Forge GitHub</a>\r\nFinally, as you find success with Forge, we invite you to contribute a post to this blog to share with the broader community. Email sales@arrayfire.com to contribute to this blog.','Forge v1.0 Official Release','','inherit','closed','closed','','9615-revision-v1','','','2017-07-13 12:43:46','2017-07-13 16:43:46','',9615,'https://sandbox.arrayfire.com/9615-revision-v1/',0,'revision','',0),(9713,1,'2017-07-28 11:56:13','2017-07-28 15:56:13','','Order &ndash; July 28, 2017 @ 11:56 AM','','wc-completed','open','closed','order_597b5e9b11b1b','order-jul-28-2017-0356-pm','','','2017-07-28 11:56:18','2017-07-28 15:56:18','',0,'https://sandbox.arrayfire.com/?post_type=shop_order&#038;p=9713',0,'shop_order','',3),(9715,17729,'2017-08-07 02:38:15','2017-08-07 06:38:15','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.\n\n<!--more-->\n\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.\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 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 performs 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=\"http://arrayfire.org/docs/group__scan__func__accum.htm\">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=\"http://arrayfire.org/docs/group__scan__func__accum.htm\">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=\"http://arrayfire.org/docs/page_gfor.htm\">GFOR documentation</a>.\n<h4><a id=\"Batching_127\"></a>Batching</h4>\nThe <a class=\"el\" href=\"http://arrayfire.org/docs/namespaceaf.htm#aa0eb9e160f5be4b95234543e5c47934b\">batchFunc()</a> function allows the broad application of existing ArrayFire functions to multiple sets of data. Effectively,<a class=\"el\" href=\"http://arrayfire.org/docs/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=\"http://arrayfire.org/docs/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=\"http://arrayfire.org/docs/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 in ArrayFire','','inherit','closed','closed','','8735-autosave-v1','','','2017-08-07 02:38:15','2017-08-07 06:38:15','',8735,'https://sandbox.arrayfire.com/8735-autosave-v1/',0,'revision','',0),(9716,17729,'2017-08-07 02:38:19','2017-08-07 06:38:19','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 performs 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=\"http://arrayfire.org/docs/group__scan__func__accum.htm\">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=\"http://arrayfire.org/docs/group__scan__func__accum.htm\">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=\"http://arrayfire.org/docs/page_gfor.htm\">GFOR documentation</a>.\r\n<h4><a id=\"Batching_127\"></a>Batching</h4>\r\nThe <a class=\"el\" href=\"http://arrayfire.org/docs/namespaceaf.htm#aa0eb9e160f5be4b95234543e5c47934b\">batchFunc()</a> function allows the broad application of existing ArrayFire functions to multiple sets of data. Effectively,<a class=\"el\" href=\"http://arrayfire.org/docs/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=\"http://arrayfire.org/docs/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=\"http://arrayfire.org/docs/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','','','2017-08-07 02:38:19','2017-08-07 06:38:19','',8735,'https://sandbox.arrayfire.com/8735-revision-v1/',0,'revision','',0),(9717,1,'2017-08-18 19:27:03','2017-08-18 23:27:03','','Order &ndash; August 18, 2017 @ 07:27 PM','TECH OPINION service for Corey at Glimmer Films','wc-completed','open','closed','order_599777c4a54c2','order-aug-18-2017-1127-pm','','','2017-08-18 19:27:07','2017-08-18 23:27:07','',0,'https://sandbox.arrayfire.com/?post_type=shop_order&#038;p=9717',0,'shop_order','',3),(9718,1,'2017-09-01 17:16:55','2017-09-01 21:16:55','','Order &ndash; September 1, 2017 @ 05:16 PM','','wc-completed','open','closed','order_59a9ce453e853','order-sep-01-2017-0916-pm','','','2017-09-01 17:17:00','2017-09-01 21:17:00','',0,'https://sandbox.arrayfire.com/?post_type=shop_order&#038;p=9718',0,'shop_order','',3),(9720,1,'2017-09-14 07:21:03','2017-09-14 11:21:03','','Order &ndash; September 14, 2017 @ 07:21 AM','PO : IBX_2017_177','wc-completed','open','closed','order_59ba661b58bce','order-sep-14-2017-1120-am','','','2017-09-14 07:21:06','2017-09-14 11:21:06','',0,'https://sandbox.arrayfire.com/?post_type=shop_order&#038;p=9720',0,'shop_order','',3),(9722,18672,'2017-09-19 00:41:52','2017-09-19 04:41:52','[content_band inner_container=\"true\" no_margin=\"true\" border=\"none\" padding_top=\"10px\" padding_bottom=\"40px\"]\r\n[custom_headline type=\"left\" level=\"h2\"]\r\nArrayFire Installers\r\n[/custom_headline]\r\n[custom_headline type=\"left\" level=\"h5\"]\r\nEach download contains both CUDA and OpenCL files.\r\n[/custom_headline]\r\n[gap size=\"4%\"]\r\n\r\n[column type=\"one-fifth\"][button  block=\"true\" onclick=\"&lt;!-- Google Code for ArrayFire Download (Windows) Conversion Page\r\nIn your html page, add the snippet and call\r\ngoog_report_conversion when someone clicks on the\r\nchosen link or button. --&gt;\r\n&lt;script type=\"text/javascript\"&gt;\r\n/* &lt;!&amp;#91;CDATA&amp;#91; */\r\ngoog_snippet_vars = function() {\r\nvar w = window;\r\nw.google_conversion_id = 1021026651;\r\nw.google_conversion_label = \"18VJCJjPql4Q28Lu5gM\";\r\nw.google_remarketing_only = false;\r\n}\r\n// DO NOT CHANGE THE CODE BELOW.\r\ngoog_report_conversion = function(url) {\r\ngoog_snippet_vars();\r\nwindow.google_conversion_format = \"3\";\r\nwindow.google_is_call = true;\r\nvar opt = new Object();\r\nopt.onload_callback = function() {\r\nif (typeof(url) != \'undefined\') {\r\nwindow.location = url;\r\n}\r\n}\r\nvar conv_handler = window&amp;#91;\'google_trackConversion\'&amp;#93;;\r\nif (typeof(conv_handler) == \'function\') {\r\nconv_handler(opt);\r\n}\r\n}\r\n/* &amp;#93;&amp;#93;&gt; */\r\n&lt;/script&gt;\r\n&lt;script type=\"text/javascript\"\r\nsrc=\"//www.googleadservices.com/pagead/conversion_async.js\"&gt;\r\n&lt;/script&gt;\" class=\"center-text\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/lvvyk\" size=\"regular\" ]Windows, v3.5.1\r\n(64-bit)[/button][/column][column type=\"one-fifth\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/lw515\" size=\"regular\" ]Linux, v3.5.1\r\n(64-bit)[/button][/column][column type=\"one-fifth\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/ltx4p\" size=\"regular\" ]Mac OSX, v3.5.1\r\n(64-bit)[/button][/column][column type=\"one-fifth\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"http://sandbox.arrayfire.com/installer_archive/3.4.2/ArrayFire-v3.4.2_Linux_aarch64.sh\" size=\"regular\" ]Tegra X1 v3.4.2\r\n(64-bit)[/button][/column][column type=\"one-fifth\" last=\"true\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/lw51f\" size=\"regular\"]Tegra K1 v3.4.2\r\n(32-bit)[/button][/column][gap size=\"9%\"]\r\n\r\nCheck out our GitHub repository to <a href=\"https://github.com/arrayfire/arrayfire\">build from the source</a>.\r\n\r\nLooking for an older installer? <a href=\"http://sandbox.arrayfire.com/installer_archive\">Try here</a>.[/content_band]\r\n<p style=\"text-align: left;\">[content_band inner_container=\"true\" no_margin=\"true\" border=\"none\" padding_top=\"10px\" padding_bottom=\"40px\" bg_color=\"#f1f1f1\"][column type=\"one-half\"][gap size=\"8%\"]<img class=\"aligncenter wp-image-5156\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/mobile_Exported1-e1395437261846.png\" alt=\"mobile_Exported\" width=\"233\" height=\"311\" />[/column][column type=\"one-half\" last=\"true\"]\r\n[custom_headline type=\"left\" level=\"h2\"]\r\nGreat. What now?\r\n[/custom_headline]</p>\r\n<p style=\"text-align: left;\">[gap size=\"5%\"]</p>\r\n<p style=\"text-align: left;\">Welcome to ArrayFire! You\'ve got an awesome library there—learn more about its features and functions on <a href=\"http://www.sandbox.arrayfire.com/docs/index.htm\">our documentation</a>.</p>\r\n<p style=\"text-align: left;\">In addition to our <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire user group</a> and <a href=\"http://sandbox.arrayfire.com/blog/\">our blog</a>, we offer a plethora of <a href=\"http://sandbox.arrayfire.com/support/\">support options</a> to fit your needs.</p>\r\n<p style=\"text-align: left;\">Got a job that needs closer attention? Hire us! Our engineers are acceleration wizards. Check out our <a href=\"http://sandbox.arrayfire.com/consulting/\">consulting offerings</a>, or set up a free <a href=\"http://meetme.so/arrayfire\">technical consultation</a> with us today![/column]</p>\r\n<p style=\"text-align: left;\">[/content_band]</p>\r\n<p style=\"text-align: center;\"></p>','Download','','inherit','closed','closed','','5931-revision-v1','','','2017-09-19 00:41:52','2017-09-19 04:41:52','',5931,'https://sandbox.arrayfire.com/5931-revision-v1/',0,'revision','',0),(9723,18672,'2017-09-19 11:37:31','2017-09-19 15:37:31','[content_band inner_container=\"true\" no_margin=\"true\" border=\"none\" padding_top=\"10px\" padding_bottom=\"40px\"]\r\n[custom_headline type=\"left\" level=\"h2\"]\r\nArrayFire Installers\r\n[/custom_headline]\r\n[custom_headline type=\"left\" level=\"h5\"]\r\nEach download contains both CUDA and OpenCL files.\r\n[/custom_headline]\r\n[gap size=\"4%\"]\r\n\r\n[column type=\"one-fifth\"][button  block=\"true\" onclick=\"&lt;!-- Google Code for ArrayFire Download (Windows) Conversion Page\r\nIn your html page, add the snippet and call\r\ngoog_report_conversion when someone clicks on the\r\nchosen link or button. --&gt;\r\n&lt;script type=\"text/javascript\"&gt;\r\n/* &lt;!&amp;#91;CDATA&amp;#91; */\r\ngoog_snippet_vars = function() {\r\nvar w = window;\r\nw.google_conversion_id = 1021026651;\r\nw.google_conversion_label = \"18VJCJjPql4Q28Lu5gM\";\r\nw.google_remarketing_only = false;\r\n}\r\n// DO NOT CHANGE THE CODE BELOW.\r\ngoog_report_conversion = function(url) {\r\ngoog_snippet_vars();\r\nwindow.google_conversion_format = \"3\";\r\nwindow.google_is_call = true;\r\nvar opt = new Object();\r\nopt.onload_callback = function() {\r\nif (typeof(url) != \'undefined\') {\r\nwindow.location = url;\r\n}\r\n}\r\nvar conv_handler = window&amp;#91;\'google_trackConversion\'&amp;#93;;\r\nif (typeof(conv_handler) == \'function\') {\r\nconv_handler(opt);\r\n}\r\n}\r\n/* &amp;#93;&amp;#93;&gt; */\r\n&lt;/script&gt;\r\n&lt;script type=\"text/javascript\"\r\nsrc=\"//www.googleadservices.com/pagead/conversion_async.js\"&gt;\r\n&lt;/script&gt;\" class=\"center-text\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/lvvyk\" size=\"regular\" ]Windows, v3.5.1\r\n(64-bit)[/button][/column][column type=\"one-fifth\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/lw515\" size=\"regular\" ]Linux, v3.5.1\r\n(64-bit)[/button][/column][column type=\"one-fifth\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/ltx4p\" size=\"regular\" ]Mac OSX, v3.5.1\r\n(64-bit)[/button][/column][column type=\"one-fifth\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2017-09-19/5dgdc4\" size=\"regular\" ]Tegra X1 v3.5.1\r\n(64-bit)[/button][/column][column type=\"one-fifth\" last=\"true\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/lw51f\" size=\"regular\"]Tegra K1 v3.4.2\r\n(32-bit)[/button][/column][gap size=\"9%\"]\r\n\r\nCheck out our GitHub repository to <a href=\"https://github.com/arrayfire/arrayfire\">build from the source</a>.\r\n\r\nLooking for an older installer? <a href=\"http://sandbox.arrayfire.com/installer_archive\">Try here</a>.[/content_band]\r\n<p style=\"text-align: left;\">[content_band inner_container=\"true\" no_margin=\"true\" border=\"none\" padding_top=\"10px\" padding_bottom=\"40px\" bg_color=\"#f1f1f1\"][column type=\"one-half\"][gap size=\"8%\"]<img class=\"aligncenter wp-image-5156\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/mobile_Exported1-e1395437261846.png\" alt=\"mobile_Exported\" width=\"233\" height=\"311\" />[/column][column type=\"one-half\" last=\"true\"]\r\n[custom_headline type=\"left\" level=\"h2\"]\r\nGreat. What now?\r\n[/custom_headline]</p>\r\n<p style=\"text-align: left;\">[gap size=\"5%\"]</p>\r\n<p style=\"text-align: left;\">Welcome to ArrayFire! You\'ve got an awesome library there—learn more about its features and functions on <a href=\"http://www.sandbox.arrayfire.com/docs/index.htm\">our documentation</a>.</p>\r\n<p style=\"text-align: left;\">In addition to our <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire user group</a> and <a href=\"http://sandbox.arrayfire.com/blog/\">our blog</a>, we offer a plethora of <a href=\"http://sandbox.arrayfire.com/support/\">support options</a> to fit your needs.</p>\r\n<p style=\"text-align: left;\">Got a job that needs closer attention? Hire us! Our engineers are acceleration wizards. Check out our <a href=\"http://sandbox.arrayfire.com/consulting/\">consulting offerings</a>, or set up a free <a href=\"http://meetme.so/arrayfire\">technical consultation</a> with us today![/column]</p>\r\n<p style=\"text-align: left;\">[/content_band]</p>\r\n<p style=\"text-align: center;\"></p>','Download','','inherit','closed','closed','','5931-revision-v1','','','2017-09-19 11:37:31','2017-09-19 15:37:31','',5931,'https://sandbox.arrayfire.com/5931-revision-v1/',0,'revision','',0),(9724,18672,'2017-09-19 11:43:14','2017-09-19 15:43:14','[content_band inner_container=\"true\" no_margin=\"true\" border=\"none\" padding_top=\"10px\" padding_bottom=\"40px\"]\r\n[custom_headline type=\"left\" level=\"h2\"]\r\nArrayFire Installers\r\n[/custom_headline]\r\n[custom_headline type=\"left\" level=\"h5\"]\r\nEach download contains both CUDA and OpenCL files.\r\n[/custom_headline]\r\n[gap size=\"4%\"]\r\n\r\n[column type=\"one-fourth\"][button  block=\"true\" onclick=\"&lt;!-- Google Code for ArrayFire Download (Windows) Conversion Page\r\nIn your html page, add the snippet and call\r\ngoog_report_conversion when someone clicks on the\r\nchosen link or button. --&gt;\r\n&lt;script type=\"text/javascript\"&gt;\r\n/* &lt;!&amp;#91;CDATA&amp;#91; */\r\ngoog_snippet_vars = function() {\r\nvar w = window;\r\nw.google_conversion_id = 1021026651;\r\nw.google_conversion_label = \"18VJCJjPql4Q28Lu5gM\";\r\nw.google_remarketing_only = false;\r\n}\r\n// DO NOT CHANGE THE CODE BELOW.\r\ngoog_report_conversion = function(url) {\r\ngoog_snippet_vars();\r\nwindow.google_conversion_format = \"3\";\r\nwindow.google_is_call = true;\r\nvar opt = new Object();\r\nopt.onload_callback = function() {\r\nif (typeof(url) != \'undefined\') {\r\nwindow.location = url;\r\n}\r\n}\r\nvar conv_handler = window&amp;#91;\'google_trackConversion\'&amp;#93;;\r\nif (typeof(conv_handler) == \'function\') {\r\nconv_handler(opt);\r\n}\r\n}\r\n/* &amp;#93;&amp;#93;&gt; */\r\n&lt;/script&gt;\r\n&lt;script type=\"text/javascript\"\r\nsrc=\"//www.googleadservices.com/pagead/conversion_async.js\"&gt;\r\n&lt;/script&gt;\" class=\"center-text\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/lvvyk\" size=\"regular\" ]Windows, v3.5.1\r\n(64-bit)[/button][/column][column type=\"one-fourth\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/lw515\" size=\"regular\" ]Linux, v3.5.1\r\n(64-bit)[/button][/column][column type=\"one-fourth\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/ltx4p\" size=\"regular\" ]Mac OSX, v3.5.1\r\n(64-bit)[/button][/column][column type=\"one-fourth\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2017-09-19/5dgdc4\" size=\"regular\" ]Tegra X1 v3.5.1\r\n(64-bit)[/button][/column][gap size=\"9%\"]\r\n\r\nCheck out our GitHub repository to <a href=\"https://github.com/arrayfire/arrayfire\">build from the source</a>.\r\n\r\nLooking for an older installer? <a href=\"http://sandbox.arrayfire.com/installer_archive\">Try here</a>.[/content_band]\r\n<p style=\"text-align: left;\">[content_band inner_container=\"true\" no_margin=\"true\" border=\"none\" padding_top=\"10px\" padding_bottom=\"40px\" bg_color=\"#f1f1f1\"][column type=\"one-half\"][gap size=\"8%\"]<img class=\"aligncenter wp-image-5156\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/mobile_Exported1-e1395437261846.png\" alt=\"mobile_Exported\" width=\"233\" height=\"311\" />[/column][column type=\"one-half\" last=\"true\"]\r\n[custom_headline type=\"left\" level=\"h2\"]\r\nGreat. What now?\r\n[/custom_headline]</p>\r\n<p style=\"text-align: left;\">[gap size=\"5%\"]</p>\r\n<p style=\"text-align: left;\">Welcome to ArrayFire! You\'ve got an awesome library there—learn more about its features and functions on <a href=\"http://www.sandbox.arrayfire.com/docs/index.htm\">our documentation</a>.</p>\r\n<p style=\"text-align: left;\">In addition to our <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire user group</a> and <a href=\"http://sandbox.arrayfire.com/blog/\">our blog</a>, we offer a plethora of <a href=\"http://sandbox.arrayfire.com/support/\">support options</a> to fit your needs.</p>\r\n<p style=\"text-align: left;\">Got a job that needs closer attention? Hire us! Our engineers are acceleration wizards. Check out our <a href=\"http://sandbox.arrayfire.com/consulting/\">consulting offerings</a>, or set up a free <a href=\"http://meetme.so/arrayfire\">technical consultation</a> with us today![/column]</p>\r\n<p style=\"text-align: left;\">[/content_band]</p>\r\n<p style=\"text-align: center;\"></p>','Download','','inherit','closed','closed','','5931-revision-v1','','','2017-09-19 11:43:14','2017-09-19 15:43:14','',5931,'https://sandbox.arrayfire.com/5931-revision-v1/',0,'revision','',0),(9725,18672,'2017-09-20 16:22:05','2017-09-20 20:22:05','We are excited to announce ArrayFire v3.5.1! This release focuses on fixing bugs and improving performance. Here are the improvements we think are most important:\r\n\r\n<strong>Performance improvements</strong>\r\n<ul>\r\n 	<li>We\'ve improved element-wise operation performance for the CPU backend.</li>\r\n 	<li>The <code>af::regions()</code> function has been modified to leverage texture memory, improving its performance.</li>\r\n 	<li>Our JIT engine has been further optimized to boost performance.</li>\r\n</ul>\r\n<strong>Bug fixes</strong>\r\n<ul>\r\n 	<li>We\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.</li>\r\n 	<li>The previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.</li>\r\n 	<li>The <code>af::canny()</code> function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.</li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Download[/custom_headline]\r\n\r\nArrayFire v3.5.1 can be downloaded from these locations:\r\n<ul>\r\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always, we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Dedicated Support and Coding Services[/custom_headline]\r\n\r\nArrayFire is open source and always will be. For those who want dedicated support or custom function development, we offer a variety of <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a>.\r\n\r\nArrayFire also serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers. Contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> or <a href=\"http://meetme.so/arrayfire\">schedule</a> a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 Release','','publish','open','closed','','arrayfire-v3-5-1-release','','','2017-09-20 16:22:05','2017-09-20 20:22:05','',0,'https://sandbox.arrayfire.com/?p=9725',0,'post','',1),(9726,18672,'2017-09-19 22:44:28','2017-09-20 02:44:28','* 3.5.1 blog post\r\n\r\nWe are excited to announce ArrayFire v3.5.1, our open-source library of\r\nparallel computing functions supporting CUDA, OpenCL, and CPU devices. This\r\nrelease focuses on fixing bugs and improving performance. Here are some of the\r\nimprovements available to you with this latest release:\r\n\r\n*** CUDA grid limitations\r\n\r\nWe\'ve squashed a long standing bug in the CUDA backend responsible for\r\nbreaking whenever the second, third, or fourth dimensions were large\r\nenough to exceed limits imposed by the CUDA runtime.\r\n\r\n*** Overflow-free ~mean()~\r\n\r\nOur previous implementation of ~af::mean()~ suffered from overflows when the\r\nsummation of the values lied outside the range of the backing data type. New\r\nkernels for each of our backends have been written to prevent this issue.\r\n\r\n*** Workaround for Apple OpenCL bug\r\n\r\nWe have also written a workaround for a bug present in Apple\'s OpenCL\r\ndriver. The bug occurs when passing ~static const~ C arrays in to\r\n~clEnqueueWriteBuffer()~. We have patched up ~af::canny()~ and are working on\r\nreleasing another patch which fixes several of our examples that are similarly\r\naffected.\r\n\r\nThese are just a few of the improvements in ArrayFire v3.5.1, so be sure to\r\nvisit the release notes for more information.\r\n\r\n** Future Releases\r\n\r\nAs always we are working on improving the performance of all of our\r\nfunctions. This has been another exciting update to ArrayFire and we have\r\ngreat plans for the next release. Stay tuned!\r\n\r\n** Download\r\n\r\nArrayFire v3.5.1 can be downloaded from these locations:\r\n\r\n- Binaries\r\n- Source code\r\n\r\n** Community\r\n\r\nArrayFire is continually improving through the addition of new functions and\r\nfeatures. We welcome your feedback:\r\n\r\n- General discussion forums on the ArrayFire Google Group\r\n- Live discussion chat on the ArrayFire Gitter\r\n- Issue reports on the ArrayFire GitHub\r\n\r\nAs you find success with ArrayFire, we invite you to contribute a post to this\r\nblog to share with the broader community. Email sales@arrayfire.com to\r\ncontribute to this blog.\r\n\r\n** Dedicated Support and Coding Services\r\n\r\nArrayFire offers dedicated support packages for ArrayFire users.\r\n\r\nArrayFire serves many clients through consulting and coding services,\r\nalgorithm development, porting code, and training courses for\r\ndevelopers. Contact us at sales@arrayfire.com or schedule a free technical\r\nconsultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 22:44:28','2017-09-20 02:44:28','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9727,18672,'2017-09-19 22:45:40','2017-09-20 02:45:40','* 3.5.1 blog post\r\n\r\nWe are excited to announce ArrayFire v3.5.1, our open-source library of parallel computing functions supporting CUDA, OpenCL, and CPU devices. This release focuses on fixing bugs and improving performance. Here are some of the improvements available to you with this latest release:\r\n\r\n*** CUDA grid limitations\r\n\r\nWe\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.\r\n\r\n*** Overflow-free ~mean()~\r\n\r\nOur previous implementation of ~af::mean()~ suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.\r\n\r\n*** Workaround for Apple OpenCL bug\r\n\r\nWe have also written a workaround for a bug present in Apple\'s OpenCL driver. The bug occurs when passing ~static const~ C arrays in to ~clEnqueueWriteBuffer()~. We have patched up ~af::canny()~ and are working on releasing another patch which fixes several of our examples that are similarly affected.\r\n\r\nThese are just a few of the improvements in ArrayFire v3.5.1, so be sure to visit the release notes for more information.\r\n\r\n** Future Releases\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n** Download\r\n\r\nArrayFire v3.5.1 can be downloaded from these locations:\r\n\r\n- Binaries\r\n- Source code\r\n\r\n** Community\r\n\r\nArrayFire is continually improving through the addition of new functions and features. We welcome your feedback:\r\n\r\n- General discussion forums on the ArrayFire Google Group\r\n- Live discussion chat on the ArrayFire Gitter\r\n- Issue reports on the ArrayFire GitHub\r\n\r\nAs you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email sales@arrayfire.com to contribute to this blog.\r\n\r\n** Dedicated Support and Coding Services\r\n\r\nArrayFire offers dedicated support packages for ArrayFire users.\r\n\r\nArrayFire serves many clients through consulting and coding services, algorithm development, porting code, and training courses for developers. Contact us at sales@arrayfire.com or schedule a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 22:45:40','2017-09-20 02:45:40','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9728,18672,'2017-09-19 22:46:51','2017-09-20 02:46:51','We are excited to announce ArrayFire v3.5.1, our open-source library of parallel computing functions supporting CUDA, OpenCL, and CPU devices. This release focuses on fixing bugs and improving performance. Here are some of the improvements available to you with this latest release:\r\n\r\n<strong>CUDA grid limitations</strong>\r\n\r\nWe\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.\r\n\r\n<strong>Overflow-free ~mean()~</strong>\r\n\r\nOur previous implementation of ~af::mean()~ suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.\r\n\r\n<strong>Workaround for Apple OpenCL bug</strong>\r\n\r\nWe have also written a workaround for a bug present in Apple\'s OpenCL driver. The bug occurs when passing ~static const~ C arrays in to ~clEnqueueWriteBuffer()~. We have patched up ~af::canny()~ and are working on releasing another patch which fixes several of our examples that are similarly affected.\r\n\r\nThese are just a few of the improvements in ArrayFire v3.5.1, so be sure to visit the release notes for more information.\r\n\r\n** Future Releases\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n** Download\r\n\r\nArrayFire v3.5.1 can be downloaded from these locations:\r\n\r\n- Binaries\r\n- Source code\r\n\r\n** Community\r\n\r\nArrayFire is continually improving through the addition of new functions and features. We welcome your feedback:\r\n\r\n- General discussion forums on the ArrayFire Google Group\r\n- Live discussion chat on the ArrayFire Gitter\r\n- Issue reports on the ArrayFire GitHub\r\n\r\nAs you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email sales@arrayfire.com to contribute to this blog.\r\n\r\n** Dedicated Support and Coding Services\r\n\r\nArrayFire offers dedicated support packages for ArrayFire users.\r\n\r\nArrayFire serves many clients through consulting and coding services, algorithm development, porting code, and training courses for developers. Contact us at sales@arrayfire.com or schedule a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 22:46:51','2017-09-20 02:46:51','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9729,18672,'2017-09-19 22:48:10','2017-09-20 02:48:10','We are excited to announce ArrayFire v3.5.1, our open-source library of parallel computing functions supporting CUDA, OpenCL, and CPU devices. This release focuses on fixing bugs and improving performance. Here are some of the improvements available to you with this latest release:\r\n\r\n<strong>CUDA grid limitations</strong>\r\n\r\nWe\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.\r\n\r\n<strong>Overflow-free <code>mean()</code></strong>\r\n\r\nOur previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.\r\n\r\n<strong>Workaround for Apple OpenCL bug</strong>\r\n\r\nWe have also written a workaround for a bug present in Apple\'s OpenCL driver. The bug occurs when passing ~static const~ C arrays in to <code>clEnqueueWriteBuffer()</code>. We have patched up <code>af::canny()</code> and are working on releasing another patch which fixes several of our examples that are similarly affected.\r\n\r\nThese are just a few of the improvements in ArrayFire v3.5.1, so be sure to visit the release notes for more information.\r\n\r\n** Future Releases\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n** Download\r\n\r\nArrayFire v3.5.1 can be downloaded from these locations:\r\n\r\n- Binaries\r\n- Source code\r\n\r\n** Community\r\n\r\nArrayFire is continually improving through the addition of new functions and features. We welcome your feedback:\r\n\r\n- General discussion forums on the ArrayFire Google Group\r\n- Live discussion chat on the ArrayFire Gitter\r\n- Issue reports on the ArrayFire GitHub\r\n\r\nAs you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email sales@arrayfire.com to contribute to this blog.\r\n\r\n** Dedicated Support and Coding Services\r\n\r\nArrayFire offers dedicated support packages for ArrayFire users.\r\n\r\nArrayFire serves many clients through consulting and coding services, algorithm development, porting code, and training courses for developers. Contact us at sales@arrayfire.com or schedule a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 22:48:10','2017-09-20 02:48:10','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9730,18672,'2017-09-19 22:51:10','2017-09-20 02:51:10','We are excited to announce ArrayFire v3.5.1, our open-source library of parallel computing functions supporting CUDA, OpenCL, and CPU devices. This release focuses on fixing bugs and improving performance. Here are some of the improvements available to you with this latest release:\r\n\r\n<strong>CUDA grid limitations</strong>\r\n\r\nWe\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.\r\n\r\n<strong>Overflow-free <code>mean()</code></strong>\r\n\r\nThe previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.\r\n\r\n<strong>Workaround for Apple OpenCL bug</strong>\r\n\r\nWe have also written a workaround for a bug present in Apple\'s OpenCL driver. The bug occurs when passing ~static const~ C arrays in to <code>clEnqueueWriteBuffer()</code>. We have patched up <code>af::canny()</code> and are working on releasing another patch which fixes several of our examples that are similarly affected.\r\n\r\nThese are just a few of the improvements in ArrayFire v3.5.1, so be sure to visit the release notes for more information.\r\n\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n** Download\r\n\r\nArrayFire v3.5.1 can be downloaded from these locations:\r\n\r\n- Binaries\r\n- Source code\r\n\r\n** Community\r\n\r\nArrayFire is continually improving through the addition of new functions and features. We welcome your feedback:\r\n\r\n- General discussion forums on the ArrayFire Google Group\r\n- Live discussion chat on the ArrayFire Gitter\r\n- Issue reports on the ArrayFire GitHub\r\n\r\nAs you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email sales@arrayfire.com to contribute to this blog.\r\n\r\n** Dedicated Support and Coding Services\r\n\r\nArrayFire offers dedicated support packages for ArrayFire users.\r\n\r\nArrayFire serves many clients through consulting and coding services, algorithm development, porting code, and training courses for developers. Contact us at sales@arrayfire.com or schedule a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 22:51:10','2017-09-20 02:51:10','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9731,18672,'2017-09-19 22:51:33','2017-09-20 02:51:33','We are excited to announce ArrayFire v3.5.1, our open-source library of parallel computing functions supporting CUDA, OpenCL, and CPU devices. This release focuses on fixing bugs and improving performance. Here are some of the improvements available to you with this latest release:\r\n\r\n<strong>CUDA grid limitations</strong>\r\n\r\nWe\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.\r\n\r\n<strong>Overflow-free <code>mean()</code></strong>\r\n\r\nThe previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.\r\n\r\n<strong>Workaround for Apple OpenCL bug</strong>\r\n\r\nWe have also written a workaround for a bug present in Apple\'s OpenCL driver. The bug occurs when passing ~static const~ C arrays in to <code>clEnqueueWriteBuffer()</code>. We have patched up <code>af::canny()</code> and are working on releasing another patch which fixes several of our examples that are similarly affected.\r\n\r\nThese are just a few of the improvements in ArrayFire v3.5.1, so be sure to visit the release notes for more information.\r\n\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n** Download\r\n\r\nArrayFire v3.5.1 can be downloaded from these locations:\r\n\r\n- Binaries\r\n- Source code\r\n\r\n** Community\r\n\r\nArrayFire is continually improving through the addition of new functions and features. We welcome your feedback:\r\n\r\n- General discussion forums on the ArrayFire Google Group\r\n- Live discussion chat on the ArrayFire Gitter\r\n- Issue reports on the ArrayFire GitHub\r\n\r\nAs you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email sales@arrayfire.com to contribute to this blog.\r\n\r\n** Dedicated Support and Coding Services\r\n\r\nArrayFire offers dedicated support packages for ArrayFire users.\r\n\r\nArrayFire serves many clients through consulting and coding services, algorithm development, porting code, and training courses for developers. Contact us at sales@arrayfire.com or schedule a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 22:51:33','2017-09-20 02:51:33','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9732,18672,'2017-09-19 22:52:28','2017-09-20 02:52:28','We are excited to announce ArrayFire v3.5.1, our open-source library of parallel computing functions supporting CUDA, OpenCL, and CPU devices. This release focuses on fixing bugs and improving performance. Here are some of the improvements available to you with this latest release:\r\n\r\n<strong>CUDA grid limitations</strong>\r\n\r\nWe\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.\r\n\r\n<strong>Overflow-free <code>mean()</code></strong>\r\n\r\nThe previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.\r\n\r\n<strong>Workaround for Apple OpenCL bug</strong>\r\n\r\nWe have also written a workaround for a bug present in Apple\'s OpenCL driver. The bug occurs when passing ~static const~ C arrays in to <code>clEnqueueWriteBuffer()</code>. We have patched up <code>af::canny()</code> and are working on releasing another patch which fixes several of our examples that are similarly affected.\r\n\r\nThese are just a few of the improvements in ArrayFire v3.5.1, so be sure to visit the release notes for more information.\r\n\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Download[/custom_headline]\r\n\r\nArrayFire v3.5.1 can be downloaded from these locations:\r\n\r\n- Binaries\r\n- Source code\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Community[/custom_headline]\r\n\r\nArrayFire is continually improving through the addition of new functions and features. We welcome your feedback:\r\n\r\n- General discussion forums on the ArrayFire Google Group\r\n- Live discussion chat on the ArrayFire Gitter\r\n- Issue reports on the ArrayFire GitHub\r\n\r\nAs you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email sales@arrayfire.com to contribute to this blog.\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Dedicated Support and Coding Services[/custom_headline]\r\n\r\nArrayFire offers dedicated support packages for ArrayFire users.\r\n\r\nArrayFire serves many clients through consulting and coding services, algorithm development, porting code, and training courses for developers. Contact us at sales@arrayfire.com or schedule a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 22:52:28','2017-09-20 02:52:28','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9733,18672,'2017-09-19 22:54:54','2017-09-20 02:54:54','We are excited to announce ArrayFire v3.5.1, our open-source library of parallel computing functions supporting CUDA, OpenCL, and CPU devices. This release focuses on fixing bugs and improving performance. Here are some of the improvements available to you with this latest release:\r\n\r\n<strong>CUDA grid limitations</strong>\r\n\r\nWe\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.\r\n\r\n<strong>Overflow-free <code>mean()</code></strong>\r\n\r\nThe previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.\r\n\r\n<strong>Workaround for Apple OpenCL bug</strong>\r\n\r\nWe have also written a workaround for a bug present in Apple\'s OpenCL driver. The bug occurs when passing ~static const~ C arrays in to <code>clEnqueueWriteBuffer()</code>. We have patched up <code>af::canny()</code> and are working on releasing another patch which fixes several of our examples that are similarly affected.\r\n\r\nThese are just a few of the improvements in ArrayFire v3.5.1, so be sure to visit the release notes for more information.\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Download[/custom_headline]\r\n\r\nArrayFire v3.5.1 can be downloaded from these locations:\r\n\r\n<ul>\r\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\r\n</ul>\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Community[/custom_headline]\r\n\r\nArrayFire is continually improving through the addition of new functions and features. We welcome your feedback:\r\n<ul>\r\n 	<li>General discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a></li>\r\n 	<li>Live discussion chat on the <a href=\"https://gitter.im/arrayfire/arrayfire?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\">ArrayFire Gitter</a></li>\r\n 	<li>Issue reports on the <a href=\"https://github.com/arrayfire/arrayfire/issues\">ArrayFire GitHub</a></li>\r\n</ul>\r\nAs you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> to contribute to this blog.\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Dedicated Support and Coding Services[/custom_headline]\r\n\r\nArrayFire offers dedicated <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a> for ArrayFire users.\r\n\r\nArrayFire serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers. Contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> or <a href=\"http://meetme.so/arrayfire\">schedule</a> a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 22:54:54','2017-09-20 02:54:54','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9734,18672,'2017-09-19 23:07:03','2017-09-20 03:07:03','We are excited to announce ArrayFire v3.5.1, our open-source library of parallel computing functions supporting CUDA, OpenCL, and CPU devices. This release focuses on fixing bugs and improving performance. Here are some of the improvements available to you with this latest release:\r\n\r\n<strong>CUDA grid limitations</strong>\r\n\r\nWe\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.\r\n\r\n<strong>Overflow-free <code>mean()</code></strong>\r\n\r\nThe previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.\r\n\r\n<strong>Workaround for Apple OpenCL bug</strong>\r\n\r\nThe ~af::canny()~ function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Download[/custom_headline]\r\n\r\nArrayFire v3.5.1 can be downloaded from these locations:\r\n\r\n<ul>\r\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\r\n</ul>\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Community[/custom_headline]\r\n\r\nArrayFire is continually improving through the addition of new functions and features. We welcome your feedback:\r\n<ul>\r\n 	<li>General discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a></li>\r\n 	<li>Live discussion chat on the <a href=\"https://gitter.im/arrayfire/arrayfire?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\">ArrayFire Gitter</a></li>\r\n 	<li>Issue reports on the <a href=\"https://github.com/arrayfire/arrayfire/issues\">ArrayFire GitHub</a></li>\r\n</ul>\r\nAs you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> to contribute to this blog.\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Dedicated Support and Coding Services[/custom_headline]\r\n\r\nArrayFire offers dedicated <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a> for ArrayFire users.\r\n\r\nArrayFire serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers. Contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> or <a href=\"http://meetme.so/arrayfire\">schedule</a> a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 23:07:03','2017-09-20 03:07:03','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9735,18672,'2017-09-19 23:09:04','2017-09-20 03:09:04','We are excited to announce ArrayFire v3.5.1, our open-source library of parallel computing functions supporting CUDA, OpenCL, and CPU devices. This release focuses on fixing bugs and improving performance. Here are the improvements we think are most important:\r\n\r\n<strong>CUDA grid limitations</strong>\r\n\r\nWe\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.\r\n\r\n<strong>Overflow-free <code>mean()</code></strong>\r\n\r\nThe previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.\r\n\r\n<strong>Workaround for Apple OpenCL bug</strong>\r\n\r\nThe ~af::canny()~ function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Download[/custom_headline]\r\n\r\nArrayFire v3.5.1 can be downloaded from these locations:\r\n\r\n<ul>\r\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\r\n</ul>\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Community[/custom_headline]\r\n\r\nArrayFire is continually improving through the addition of new functions and features. We welcome your feedback:\r\n<ul>\r\n 	<li>General discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a></li>\r\n 	<li>Live discussion chat on the <a href=\"https://gitter.im/arrayfire/arrayfire?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\">ArrayFire Gitter</a></li>\r\n 	<li>Issue reports on the <a href=\"https://github.com/arrayfire/arrayfire/issues\">ArrayFire GitHub</a></li>\r\n</ul>\r\nAs you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> to contribute to this blog.\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Dedicated Support and Coding Services[/custom_headline]\r\n\r\nArrayFire offers dedicated <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a> for ArrayFire users.\r\n\r\nArrayFire serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers. Contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> or <a href=\"http://meetme.so/arrayfire\">schedule</a> a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 23:09:04','2017-09-20 03:09:04','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9736,18672,'2017-09-19 23:10:33','2017-09-20 03:10:33','We are excited to announce ArrayFire v3.5.1, our open-source library of parallel computing functions supporting CUDA, OpenCL, and CPU devices. This release focuses on fixing bugs and improving performance. Here are the improvements we think are most important:\r\n\r\n<strong>CUDA grid limitations</strong>\r\n\r\nWe\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.\r\n\r\n<strong>Overflow-free <code>mean()</code></strong>\r\n\r\nThe previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.\r\n\r\n<strong>Workaround for Apple OpenCL bug</strong>\r\n\r\nThe <code>af::canny()</code> function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Download[/custom_headline]\r\n\r\nArrayFire v3.5.1 can be downloaded from these locations:\r\n\r\n<ul>\r\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\r\n</ul>\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Community[/custom_headline]\r\n\r\nArrayFire is continually improving through the addition of new functions and features. We welcome your feedback:\r\n<ul>\r\n 	<li>General discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a></li>\r\n 	<li>Live discussion chat on the <a href=\"https://gitter.im/arrayfire/arrayfire?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\">ArrayFire Gitter</a></li>\r\n 	<li>Issue reports on the <a href=\"https://github.com/arrayfire/arrayfire/issues\">ArrayFire GitHub</a></li>\r\n</ul>\r\nAs you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> to contribute to this blog.\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Dedicated Support and Coding Services[/custom_headline]\r\n\r\nArrayFire offers dedicated <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a> for ArrayFire users.\r\n\r\nArrayFire serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers. Contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> or <a href=\"http://meetme.so/arrayfire\">schedule</a> a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 23:10:33','2017-09-20 03:10:33','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9737,18672,'2017-09-19 23:12:29','2017-09-20 03:12:29','We are excited to announce ArrayFire v3.5.1, our open-source library of parallel computing functions supporting CUDA, OpenCL, and CPU devices. This release focuses on fixing bugs and improving performance - here are the improvements we think are most important:\r\n\r\n<strong>CUDA grid limitations</strong>\r\n\r\nWe\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.\r\n\r\n<strong>Overflow-free <code>mean()</code></strong>\r\n\r\nThe previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.\r\n\r\n<strong>Workaround for Apple OpenCL bug</strong>\r\n\r\nThe <code>af::canny()</code> function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Download[/custom_headline]\r\n\r\nArrayFire v3.5.1 can be downloaded from these locations:\r\n\r\n<ul>\r\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\r\n</ul>\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Community[/custom_headline]\r\n\r\nArrayFire is continually improving through the addition of new functions and features. We welcome your feedback:\r\n<ul>\r\n 	<li>General discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a></li>\r\n 	<li>Live discussion chat on the <a href=\"https://gitter.im/arrayfire/arrayfire?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\">ArrayFire Gitter</a></li>\r\n 	<li>Issue reports on the <a href=\"https://github.com/arrayfire/arrayfire/issues\">ArrayFire GitHub</a></li>\r\n</ul>\r\nAs you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> to contribute to this blog.\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Dedicated Support and Coding Services[/custom_headline]\r\n\r\nArrayFire offers dedicated <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a> for ArrayFire users.\r\n\r\nArrayFire serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers. Contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> or <a href=\"http://meetme.so/arrayfire\">schedule</a> a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 23:12:29','2017-09-20 03:12:29','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9738,18672,'2017-09-19 23:16:52','2017-09-20 03:16:52','Today we are pleased to announce the release of ArrayFire v3.5, our open source\nlibrary of parallel computing functions supporting CUDA, OpenCL, and CPU\ndevices. This new version of ArrayFire improves features and performance for\napplications in machine learning, computer vision, signal processing,\nstatistics, finance, and more.\n\nThis release focuses on thread-safety, support for simple sparse-dense\narithmetic operations, canny edge detector function, and a genetic algorithm\nexample. A complete list of ArrayFire v3.5 updates and new features are found\nin the product <a href=\"http://arrayfire.org/docs/releasenotes.htm\">Release Notes</a>.\n<h3><strong>Thread Safety</strong></h3>\nArrayFire now supports threading programming models. This is not intended to\nimprove the performance since most of the parallelism is happening on the\ndevice, but it does allow you to use multiple devices in an easy way.\nWith ArrayFire you had to use a for loop to get this functionality. Normally\nthis isn\'t a problem but when you have to work with host side transfers, this\nbecomes troublesome.\n\nLet\'s suppose we wanted to perform a matrix multiply on multiple GPUs. Because\nmost ArrayFire functions are asynchronous this can be done in a for loop.\n<pre class=\"lang:c++ decode:true\" title=\"Simple multi-device\">for (int i = 0; i &lt; nDevices; i++) {\n    setDevice(i);\n    array a = randu(1000, 1000);\n    array b = constant(3, 1000, 1000);\n    array c = matmul(a, b);\n}</pre>\n&nbsp;\n\nThis works well most of the time but this becomes an issue when you want to interact\nwith host side code in your application.\n\nFor example, this code attempts to perform a matrix multiply and then transfer\nthat data back to the CPU to do additional work. The ArrayFire code executes the\ncomputation on different devices but they will not be queued at the same time\nbecause the data transfer to the c_data array is a blocking operation.\n<pre class=\"lang:c++ decode:true\">for(int i = 0; i &lt; nDevices; i++) {\n    setDevice(i)\n    array a = randu(1000, 1000);\n    array b = constant(3, 1000, 1000);\n    array c = matmul(a, b);\n\n    // Blocks until the previous operation has completed\n    vector&lt;float&gt; c_data(c.elements());\n    c.host(c_data.data());\n\n    // Perform some host side side work\n\n    array data(1000, 1000, c_data.data());\n    // more work\n}</pre>\nIn order for this to work correctly you would have had to split the loop so that\nthe matmul operation is queued first then in a separate loop the data is transfered\nto the CPU. If more work needs to be performed, you will need to create a third loop\nto iterate through the devices again.\n<pre class=\"lang:c++ decode:true\">vector&lt;array&gt; a(nDevices);\nvector&lt;array&gt; b(nDevices);\nvector&lt;array&gt; c(nDevices);\nfor(int i = 0; i &lt; nDevices; i++) {\n    setDevice(i);\n    a[i] = randu(1000, 1000);\n    b[i] = constant(3, 1000, 1000);\n    c[i] = matmul(a, b);\n}\n\nvector&lt;vector&lt;float&gt;&gt; c_data(nDevices)\nfor(int i = 0; i &lt; nDevices; i++) {\n    setDevice(i)\n    c_data[i] = vector&lt;float&gt;(c.elements());\n    c[i].host(c_data[i].data());\n}\n\n// Perform some host side side work\n\nfor(int i = 0; i &lt; nDevices; i++) {\n    setDevice(i);\n    array data(1000, 1000, c_data.data());\n    // more work\n}</pre>\nThis will perform the operations on each of the GPUs on the machines as expected\nbut it is troublesome to program like this. With the thread-safety updates in 3.5\nyou can now execute the operations for each of the GPUs in separate threads.\n<pre class=\"lang:c++ decode:true\">vector&lt;thread&gt; threads;\nfor(int i = 0; i &lt; nDevices; i++) {\n  threads.emplace_back([=]() {\n    setDevice(i);\n    array a = randu(1000, 1000);\n    array b = constant(3, 1000, 1000);\n    array c = matmul(a, b);\n\n    // Blocks until the previous operation has completed\n    vector&lt;float&gt; c_data(c.elements());\n    c.host(c_data.data());\n\n    // Perform some host side side work\n\n    array data(1000, 1000, c_data.data());\n    // more work\n  });\n}\n</pre>\nThis is a much easier to implement using threads then the for loop approach.\n<h3><strong>Canny edge detector</strong></h3>\nWe have added the Canny edge detection algorithm to ArrayFire. The Canny\nalgorithm is a multi-stage algorithm which can handle a wide variety of edges\nThe canny algorithm can automatically calculate the thresholds\nusing Otsu\'s method.\n<h3><strong>Sparse-Dense arithmetic</strong></h3>\nArrayFire 3.4 introduced initial support for sparse arrays. With 3.5 we are\nexpanding the sparse arrays to allow for sparse-dense arithmetic.\n<h3><strong>Support for CLBlast</strong></h3>\nWith ArrayFire 3.5 we are introducing support for a new OpenCL BLAS\nimplementation. It is developed by Cedric Nugteren and it is called CLBlast. It\nhas improved performance on NVIDIA hardware and features an autotuner support\ndevices that have not been explicitly been optimized. You can read more about\nclBlast at the GitHub repository <a href=\"https://github.com/CNugteren/CLBlast\">here</a>.\n<h3><strong>Improved CUDA JIT engine</strong></h3>\nThe CUDA JIT engine has been refactored to use the NVRTC library. Previously the\nJIT functionality was implemented using the NVVM library which made it difficult\nto employ more advanced control flows. With NVRTC we can create more advanced\nJIT functions to improve the performance.\n\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Future Releases[/custom_headline]\n\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\n\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Download[/custom_headline]\n\nArrayFire v3.5 can be downloaded from these locations:\n<ul>\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\n</ul>\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Community[/custom_headline]\n\nArrayFire is continually improving through the addition of new functions and features. We welcome your feedback:\n<ul>\n 	<li>General discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a></li>\n 	<li>Live discussion chat on the <a href=\"https://gitter.im/arrayfire/arrayfire?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\">ArrayFire Slack c</a></li>\n 	<li>Issue reports on the <a href=\"https://github.com/arrayfire/arrayfire/issues\">ArrayFire GitHub</a></li>\n</ul>\nAs you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> to contribute to this blog.\n\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Dedicated Support and Coding Services[/custom_headline]\n\nArrayFire offers dedicated <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a> for ArrayFire users.\n\nArrayFire serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers. Contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> or <a href=\"http://meetme.so/arrayfire\">schedule</a> a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5 Official Release','','inherit','closed','closed','','9683-autosave-v1','','','2017-09-19 23:16:52','2017-09-20 03:16:52','',9683,'https://sandbox.arrayfire.com/9683-autosave-v1/',0,'revision','',0),(9739,18672,'2017-09-19 23:15:49','2017-09-20 03:15:49','We are excited to announce ArrayFire v3.5.1, our open-source library of parallel computing functions supporting CUDA, OpenCL, and CPU devices. This release focuses on fixing bugs and improving performance - here are the improvements we think are most important:\r\n\r\n<strong>CUDA grid limitations</strong>\r\n\r\nWe\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.\r\n\r\n<strong>Overflow-free <code>mean()</code></strong>\r\n\r\nThe previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.\r\n\r\n<strong>Workaround for Apple OpenCL bug</strong>\r\n\r\nThe <code>af::canny()</code> function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Download[/custom_headline]\r\n\r\nArrayFire v3.5.1 can be downloaded from these locations:\r\n\r\n<ul>\r\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\r\n</ul>\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Community[/custom_headline]\r\n\r\nArrayFire is continually improving through the addition of new functions and features. We welcome your feedback:\r\n<ul>\r\n 	<li>General discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a></li>\r\n 	<li>Live discussion chat on the <a href=\"https://join.slack.com/t/arrayfire-org/shared_invite/MjI4MjIzMDMzMTczLTE1MDI5ODg4NzYtN2QwNGE3ODA5OQ\">ArrayFire Slack channel</a></li>\r\n 	<li>Issue reports on the <a href=\"https://github.com/arrayfire/arrayfire/issues\">ArrayFire GitHub</a></li>\r\n</ul>\r\nAs you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> to contribute to this blog.\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Dedicated Support and Coding Services[/custom_headline]\r\n\r\nArrayFire offers dedicated <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a> for ArrayFire users.\r\n\r\nArrayFire serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers. Contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> or <a href=\"http://meetme.so/arrayfire\">schedule</a> a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 23:15:49','2017-09-20 03:15:49','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9741,18672,'2017-09-19 23:22:08','2017-09-20 03:22:08','We are excited to announce ArrayFire v3.5.1, our open-source library of parallel computing functions supporting CUDA, OpenCL, and CPU devices. This release focuses on fixing bugs and improving performance - here are the improvements we think are most important:\r\n\r\n<strong>CUDA grid limitations</strong>\r\n\r\nWe\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.\r\n\r\n<strong>Overflow-free <code>mean()</code></strong>\r\n\r\nThe previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.\r\n\r\n<strong>Workaround for Apple OpenCL bug</strong>\r\n\r\nThe <code>af::canny()</code> function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 23:22:08','2017-09-20 03:22:08','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9742,18672,'2017-09-19 23:23:04','2017-09-20 03:23:04','We are excited to announce ArrayFire v3.5.1! This release focuses on fixing bugs and improving performance - here are the improvements we think are most important:\r\n\r\n<strong>CUDA grid limitations</strong>\r\n\r\nWe\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.\r\n\r\n<strong>Overflow-free <code>mean()</code></strong>\r\n\r\nThe previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.\r\n\r\n<strong>Workaround for Apple OpenCL bug</strong>\r\n\r\nThe <code>af::canny()</code> function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 23:23:04','2017-09-20 03:23:04','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9743,18672,'2017-09-19 23:27:10','2017-09-20 03:27:10','We are excited to announce ArrayFire v3.5.1! This release focuses on fixing bugs and improving performance - here are the improvements we think are most important:\r\n\r\n<ul>\r\n    <li>We\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.</li>\r\n    <li>The previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.</li>\r\n    <li>The <code>af::canny()</code> function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.</li>\r\n</ul>\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 23:27:10','2017-09-20 03:27:10','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9744,18672,'2017-09-19 23:31:35','2017-09-20 03:31:35','We are excited to announce ArrayFire v3.5.1! This release focuses on fixing bugs and improving performance - here are the improvements we think are most important:\r\n\r\n<strong>Bug fixes</strong>\r\n<ul>\r\n    <li>We\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.</li>\r\n    <li>The previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.</li>\r\n    <li>The <code>af::canny()</code> function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.</li>\r\n</ul>\r\n\r\n<strong>Performance improvements</strong>\r\n\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 23:31:35','2017-09-20 03:31:35','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9745,18672,'2017-09-19 23:33:28','2017-09-20 03:33:28','We are excited to announce ArrayFire v3.5.1! This release focuses on fixing bugs and improving performance - here are the improvements we think are most important:\r\n\r\n<strong>Bug fixes</strong>\r\n<ul>\r\n    <li>We\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.</li>\r\n    <li>The previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.</li>\r\n    <li>The <code>af::canny()</code> function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.</li>\r\n</ul>\r\n\r\n<strong>Performance improvements</strong>\r\n<ul>\r\n    <li>Improved JIT performance.</li>\r\n    <li>Improved CPU element-wise operation performance.</li>\r\n    <li>Improved regions performance using texture objects.</li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 23:33:28','2017-09-20 03:33:28','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9746,18672,'2017-09-19 23:38:02','2017-09-20 03:38:02','We are excited to announce ArrayFire v3.5.1! This release focuses on fixing bugs and improving performance - here are the improvements we think are most important:\r\n\r\n<strong>Bug fixes</strong>\r\n<ul>\r\n    <li>We\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.</li>\r\n    <li>The previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.</li>\r\n    <li>The <code>af::canny()</code> function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.</li>\r\n</ul>\r\n\r\n<strong>Performance improvements</strong>\r\n<ul>\r\n    <li>We\'ve improved JIT performance.</li>\r\n    <li>Improved element-wise operation performance for the CPU backend.</li>\r\n    <li>The <code>af::regions()</code> function has been modified to leverage texture memory, improving its performance.</li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 23:38:02','2017-09-20 03:38:02','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9747,18672,'2017-09-19 23:40:39','2017-09-20 03:40:39','We are excited to announce ArrayFire v3.5.1! This release focuses on fixing bugs and improving performance - here are the improvements we think are most important:\r\n\r\n<strong>Bug fixes</strong>\r\n<ul>\r\n    <li>We\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.</li>\r\n    <li>The previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.</li>\r\n    <li>The <code>af::canny()</code> function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.</li>\r\n</ul>\r\n\r\n<strong>Performance improvements</strong>\r\n<ul>\r\n    <li>Improved element-wise operation performance for the CPU backend.</li>\r\n    <li>The <code>af::regions()</code> function has been modified to leverage texture memory, improving its performance.</li>\r\n    <li>Our JIT engine has been further optimized to improve performance.</li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 23:40:39','2017-09-20 03:40:39','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9748,18672,'2017-09-19 23:43:49','2017-09-20 03:43:49','We are excited to announce ArrayFire v3.5.1! This release focuses on fixing bugs and improving performance - here are the improvements we think are most important:\r\n\r\n<strong>Bug fixes</strong>\r\n<ul>\r\n    <li>We\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.</li>\r\n    <li>The previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.</li>\r\n    <li>The <code>af::canny()</code> function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.</li>\r\n</ul>\r\n\r\n<strong>Performance improvements</strong>\r\n<ul>\r\n    <li>We\'ve improved element-wise operation performance for the CPU backend.</li>\r\n    <li>The <code>af::regions()</code> function has been modified to leverage texture memory, improving its performance.</li>\r\n    <li>Our JIT engine has been further optimized to boost performance.</li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-19 23:43:49','2017-09-20 03:43:49','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9753,6,'2017-09-20 15:57:17','2017-09-20 19:57:17','We are excited to announce ArrayFire v3.5.1! This release focuses on fixing bugs and improving performance - here are the improvements we think are most important:\n\n<strong>Bug fixes</strong>\n<ul>\n 	<li>We\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.</li>\n 	<li>The previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.</li>\n 	<li>The <code>af::canny()</code> function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.</li>\n</ul>\n<strong>Performance improvements</strong>\n<ul>\n 	<li>We\'ve improved element-wise operation performance for the CPU backend.</li>\n 	<li>The <code>af::regions()</code> function has been modified to leverage texture memory, improving its performance.</li>\n 	<li>Our JIT engine has been further optimized to boost performance.</li>\n</ul>\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Download[/custom_headline]\n\nArrayFire v3.5.1 can be downloaded from these locations:\n<ul>\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\n</ul>\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\n\nAs always, we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\n\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Dedicated Support and Coding Services[/custom_headline]\n\nArrayFire is open source and always will be. For those who want dedicated support or custom fun development, we offer a variety of <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a>.\n\nArrayFire also serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers. Contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> or <a href=\"http://meetme.so/arrayfire\">schedule</a> a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-autosave-v1','','','2017-09-20 15:57:17','2017-09-20 19:57:17','',9725,'https://sandbox.arrayfire.com/9725-autosave-v1/',0,'revision','',0),(9754,6,'2017-09-20 15:54:15','2017-09-20 19:54:15','We are excited to announce ArrayFire v3.5.1! This release focuses on fixing bugs and improving performance - here are the improvements we think are most important:\r\n\r\n<strong>Bug fixes</strong>\r\n<ul>\r\n 	<li>We\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.</li>\r\n 	<li>The previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.</li>\r\n 	<li>The <code>af::canny()</code> function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.</li>\r\n</ul>\r\n<strong>Performance improvements</strong>\r\n<ul>\r\n 	<li>We\'ve improved element-wise operation performance for the CPU backend.</li>\r\n 	<li>The <code>af::regions()</code> function has been modified to leverage texture memory, improving its performance.</li>\r\n 	<li>Our JIT engine has been further optimized to boost performance.</li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Download[/custom_headline]\r\n\r\nArrayFire v3.5.1 can be downloaded from these locations:\r\n<ul>\r\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Dedicated Support and Coding Services[/custom_headline]\r\n\r\nArrayFire is open source and always will be. For those who want dedicated support, we have a variety of <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a> for ArrayFire users.\r\n\r\nArrayFire also serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers. Contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> or <a href=\"http://meetme.so/arrayfire\">schedule</a> a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-20 15:54:15','2017-09-20 19:54:15','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9755,6,'2017-09-20 15:56:14','2017-09-20 19:56:14','We are excited to announce ArrayFire v3.5.1! This release focuses on fixing bugs and improving performance - here are the improvements we think are most important:\r\n\r\n<strong>Bug fixes</strong>\r\n<ul>\r\n 	<li>We\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.</li>\r\n 	<li>The previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.</li>\r\n 	<li>The <code>af::canny()</code> function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.</li>\r\n</ul>\r\n<strong>Performance improvements</strong>\r\n<ul>\r\n 	<li>We\'ve improved element-wise operation performance for the CPU backend.</li>\r\n 	<li>The <code>af::regions()</code> function has been modified to leverage texture memory, improving its performance.</li>\r\n 	<li>Our JIT engine has been further optimized to boost performance.</li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Download[/custom_headline]\r\n\r\nArrayFire v3.5.1 can be downloaded from these locations:\r\n<ul>\r\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always, we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Dedicated Support and Coding Services[/custom_headline]\r\n\r\nArrayFire is open source and always will be. For those who want dedicated support, we have a variety of <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a>.\r\n\r\nArrayFire also serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers. Contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> or <a href=\"http://meetme.so/arrayfire\">schedule</a> a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-20 15:56:14','2017-09-20 19:56:14','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9756,6,'2017-09-20 15:57:48','2017-09-20 19:57:48','We are excited to announce ArrayFire v3.5.1! This release focuses on fixing bugs and improving performance - here are the improvements we think are most important:\r\n\r\n<strong>Bug fixes</strong>\r\n<ul>\r\n 	<li>We\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.</li>\r\n 	<li>The previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.</li>\r\n 	<li>The <code>af::canny()</code> function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.</li>\r\n</ul>\r\n<strong>Performance improvements</strong>\r\n<ul>\r\n 	<li>We\'ve improved element-wise operation performance for the CPU backend.</li>\r\n 	<li>The <code>af::regions()</code> function has been modified to leverage texture memory, improving its performance.</li>\r\n 	<li>Our JIT engine has been further optimized to boost performance.</li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Download[/custom_headline]\r\n\r\nArrayFire v3.5.1 can be downloaded from these locations:\r\n<ul>\r\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always, we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Dedicated Support and Coding Services[/custom_headline]\r\n\r\nArrayFire is open source and always will be. For those who want dedicated support or custom function development, we offer a variety of <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a>.\r\n\r\nArrayFire also serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers. Contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> or <a href=\"http://meetme.so/arrayfire\">schedule</a> a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-20 15:57:48','2017-09-20 19:57:48','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9757,6,'2017-09-20 15:58:29','2017-09-20 19:58:29','We are excited to announce ArrayFire v3.5.1! This release focuses on fixing bugs and improving performance. Here are the improvements we think are most important:\r\n\r\n<strong>Bug fixes</strong>\r\n<ul>\r\n 	<li>We\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.</li>\r\n 	<li>The previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.</li>\r\n 	<li>The <code>af::canny()</code> function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.</li>\r\n</ul>\r\n<strong>Performance improvements</strong>\r\n<ul>\r\n 	<li>We\'ve improved element-wise operation performance for the CPU backend.</li>\r\n 	<li>The <code>af::regions()</code> function has been modified to leverage texture memory, improving its performance.</li>\r\n 	<li>Our JIT engine has been further optimized to boost performance.</li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Download[/custom_headline]\r\n\r\nArrayFire v3.5.1 can be downloaded from these locations:\r\n<ul>\r\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always, we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Dedicated Support and Coding Services[/custom_headline]\r\n\r\nArrayFire is open source and always will be. For those who want dedicated support or custom function development, we offer a variety of <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a>.\r\n\r\nArrayFire also serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers. Contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> or <a href=\"http://meetme.so/arrayfire\">schedule</a> a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 Release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-20 15:58:29','2017-09-20 19:58:29','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9758,18672,'2017-09-20 16:09:17','2017-09-20 20:09:17','We are excited to announce ArrayFire v3.5.1! This release focuses on fixing bugs and improving performance. Here are the improvements we think are most important:\r\n\r\n<strong>Performance improvements</strong>\r\n<ul>\r\n 	<li>We\'ve improved element-wise operation performance for the CPU backend.</li>\r\n 	<li>The <code>af::regions()</code> function has been modified to leverage texture memory, improving its performance.</li>\r\n 	<li>Our JIT engine has been further optimized to boost performance.</li>\r\n</ul>\r\n\r\n<strong>Bug fixes</strong>\r\n<ul>\r\n 	<li>We\'ve squashed a long standing bug in the CUDA backend responsible for breaking whenever the second, third, or fourth dimensions were large enough to exceed limits imposed by the CUDA runtime.</li>\r\n 	<li>The previous implementation of <code>af::mean()</code> suffered from overflows when the summation of the values lied outside the range of the backing data type. New kernels for each of our backends have been written to prevent this issue.</li>\r\n 	<li>The <code>af::canny()</code> function has been patched with a workaround to avoid a bug in Apple\'s OpenCL driver. We are working on releasing an upcoming patch to fix all examples that are similarly affected.</li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Download[/custom_headline]\r\n\r\nArrayFire v3.5.1 can be downloaded from these locations:\r\n<ul>\r\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Future Releases[/custom_headline]\r\n\r\nAs always, we are working on improving the performance of all of our functions. This has been another exciting update to ArrayFire and we have great plans for the next release. Stay tuned!\r\n\r\n[custom_headline type=\"left\" level=\"h4\" looks_like=\"h4\"]Dedicated Support and Coding Services[/custom_headline]\r\n\r\nArrayFire is open source and always will be. For those who want dedicated support or custom function development, we offer a variety of <a href=\"http://sandbox.arrayfire.com/support/\">support packages</a>.\r\n\r\nArrayFire also serves many clients through consulting and <a href=\"http://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers. Contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> or <a href=\"http://meetme.so/arrayfire\">schedule</a> a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.5.1 Release','','inherit','closed','closed','','9725-revision-v1','','','2017-09-20 16:09:17','2017-09-20 20:09:17','',9725,'https://sandbox.arrayfire.com/9725-revision-v1/',0,'revision','',0),(9763,6,'2017-10-17 14:24:02','2017-10-17 18:24:02','[content_band inner_container=\"true\" no_margin=\"true\" border=\"bottom\" padding_top=\"40px\" padding_bottom=\"40px\"][column type=\"one-half\"] [custom_headline type=\"left\" level=\"h3\" ]About[/custom_headline]ArrayFire is the software shop for CUDA and OpenCL. Since 2007, ArrayFire has offered the most productive solutions for accelerating code using GPUs. Today, ArrayFire delivers products which are used to accelerate C, C++, and Fortran codes on CUDA GPUs and OpenCL devices. ArrayFire has thousands of customers. These customers come from a wide range of industries, including defense and intelligence, life science, oil and gas, finance, manufacturing, media, and others.\r\n\r\nArrayFire has had success accelerating numerous application types, including math and numerical algorithms, image processing, signal processing, statistics, optimization, and more. Many ArrayFire customers are realizing 100X speed-up with much less effort than is typically required to accelerate code.[/column][column type=\"one-half\" last=\"true\" fade=\"true\"][image src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/dj-Flame.png\"] [/column]\r\n<div id=\"contact\"></div>\r\n[line][column type=\"one-third\"][custom_headline type=\"center\" level=\"h5\" accent=\"false\"]Email[/custom_headline]\r\n<p style=\"text-align: center;\">Sales: sales@arrayfire.com\r\nSupport: support@arrayfire.com\r\nCareers: jobs@arrayfire.com[/column]</p>\r\n[column type=\"one-third\"][custom_headline type=\"center\" level=\"h5\" accent=\"false\"]Phone[/custom_headline]\r\n<p style=\"text-align: center;\">Sales: +1 (800) 570-1941 x 1\r\nTechnical Support: +1 (800) 570-1941 x 2 [/column]</p>\r\n[column type=\"one-third\" last=\"true\"][custom_headline type=\"center\" level=\"h5\" accent=\"false\"]Headquarters[/custom_headline]\r\n<p style=\"text-align: center;\">90 Peachtree Pl NE\r\nAtlanta, GA 30309[/column] [/content_band]</p>\r\n[content_band bg_color=\"#f2f2f2\" inner_container=\"true\" no_margin=\"true\" border=\"none\" padding_top=\"40px\" padding_bottom=\"40px\" ][column type=\"full\"][custom_headline type=\"left\" level=\"h3\" ]Careers[/custom_headline]As a global leader in GPU computing software, our business opportunities are always expanding. We are constantly searching for talented, qualified individuals to join the ArrayFire team. ArrayFire is committed to providing employees with the opportunity to grow and learn, the freedom to express ideas and contribute to new developments, and the motivation to succeed. To start the application process, simply email us your resume and let us know which position(s) you\'re interested in.[/column]\r\n\r\n[line][column type=\"one-third\"][promo image=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/little-boba-fett.png\" alt=\"Alt Text\"][custom_headline type=\"left\" level=\"h5\"  class=\"mtn\"]Software Engineer - Atlanta, GA[/custom_headline]\r\n\r\n<strong>Responsibilities:</strong> Develop in C/C++, Fortran, CUDA, and OpenCL. Respond to forum posts and customer support tickets.\r\n\r\n<strong>Qualifications</strong>: A background in any of high-performance computing, operating systems, or compilers. Several years of C/C++ and at least one year of CUDA or similar technology. Familiarity with Fortran is a plus. Undergraduate or graduate work in CS or related field. [/promo][/column]\r\n\r\n[column type=\"one-third\"][promo image=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/uncle-sam.png\" alt=\"Alt Text\"] [custom_headline type=\"left\" level=\"h5\"  class=\"mtn\"]Application Engineer - Atlanta, GA[/custom_headline]\r\n\r\n<strong>Responsibilities: </strong>Work closely with customers to develop software solutions using our products. Develop technical marketing materials including demos, webinars, tutorials, etc. Respond to forum posts and customer support tickets.\r\n\r\n<strong>Qualifications:</strong> Undergraduate or graduate work in CS or related field. Strong programming skills in C/C++. Excellent communication skills.[/promo][/column]\r\n\r\n[column type=\"one-third\" last=\"true\"][promo image=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/01/i-see-pride-i-see-power.png\" alt=\"Alt Text\"][custom_headline type=\"left\" level=\"h5\" class=\"mtn\"]Web/Dev Engineer - Atlanta, GA[/custom_headline]\r\n\r\n<strong>Responsibilities: </strong>Develop PHP/MySQL backend infrastructure with basic HTML/CSS/JavaScript frontend work. Developing lightweight webapps for system monitoring. Maintaining Wordpress and SalesForce integration. Maintaining server/cluster infrastructure.\r\n\r\n<strong>Qualifications:</strong> Strong PHP and MySQL experience. Very comfortable at a shell prompt. Proficient in HTML, CSS, and JavaScript. Familiarity with Wordpress or SalesForce is a plus.[/promo][/column]\r\n\r\n[/content_band]','Company','','inherit','closed','closed','','329-revision-v1','','','2017-10-17 14:24:02','2017-10-17 18:24:02','',329,'https://sandbox.arrayfire.com/329-revision-v1/',0,'revision','',0),(9765,18672,'2017-10-25 12:08:21','2017-10-25 16:08:21','This post outlines the new graphics features available in ArrayFire v3.4:  Vector Fields, Overlays\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Vector Fields[/custom_headline]\r\n\r\nWe have added visualization support to render ArrayFire <a href=\"http://arrayfire.org/docs/array_8h_source.htm\" target=\"_blank\">array</a> objects as vector fields. An <a href=\"https://github.com/arrayfire/arrayfire/blob/master/examples/graphics/field.cpp\">example</a> of how to visualize vector fields is included in ArrayFire v3.4. A screenshot of this example\'s output in multi-view mode is shown below, showcasing both static and dynamic vector field rendering.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/vfield.png\"><img class=\"alignnone size-large wp-image-9185\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/vfield-1024x550.png\" alt=\"vfield\" width=\"742\" height=\"399\" /></a>\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Overlays[/custom_headline]\r\n\r\nPreviously, each graph (such as plot, hist, scatter, etc) was rendered in its own window (or view). Overlaying graphs was not supported. ArrayFire v3.4 now support graph overlays.\r\n\r\nEach draw call in ArrayFire is either rendered to a whole window (single view) or to a view, which is a portion of the screen obtained in multiview mode.\r\n\r\nThe following image is an example of a graph overlay:\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/multipleplot.png\"><img class=\"alignnone size-full wp-image-9182\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/multipleplot.png\" alt=\"multipleplot\" width=\"1002\" height=\"828\" /></a>\r\n\r\nThe following graphs support overlay if they are of same type of object (2d/3d):\r\n<table width=\"100%\">\r\n<tbody>\r\n<tr>\r\n<td><a href=\"https://github.com/arrayfire/arrayfire/blob/master/examples/graphics/plot3.cpp\" target=\"_blank\">plot</a></td>\r\n<td><a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/plot3.png\"><img class=\"alignnone size-medium wp-image-9211\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/plot3-300x300.png\" alt=\"plot3\" width=\"300\" height=\"300\" /></a></td>\r\n</tr>\r\n<tr>\r\n<td><a href=\"https://github.com/arrayfire/arrayfire/blob/master/examples/graphics/histogram.cpp\" target=\"_blank\">histogram</a></td>\r\n<td><a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/histogram.png\"><img class=\"alignnone size-medium wp-image-9207\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/histogram-300x152.png\" alt=\"histogram\" width=\"300\" height=\"152\" /></a></td>\r\n</tr>\r\n<tr>\r\n<td><a href=\"https://github.com/arrayfire/arrayfire/blob/master/examples/graphics/surface.cpp\" target=\"_blank\">surface</a></td>\r\n<td><a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/surface.png\"><img class=\"alignnone size-medium wp-image-9212\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/surface-300x300.png\" alt=\"surface\" width=\"300\" height=\"300\" /></a></td>\r\n</tr>\r\n<tr>\r\n<td><a href=\"https://github.com/arrayfire/arrayfire/blob/master/examples/graphics/field.cpp\" target=\"_blank\">vector fields</a></td>\r\n<td><a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/vfield.png\"><img src=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/vfield-300x161.png\" alt=\"vfield\" width=\"300\" height=\"161\" class=\"alignnone size-medium wp-image-9185\" /></a></td>\r\n</tr>\r\n</tbody>\r\n</table>\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Animations[/custom_headline]\r\n\r\nArrayFire v3.4 includes the following examples of producing fun animations based on simple equations: <a href=\"https://github.com/arrayfire/arrayfire/blob/master/examples/graphics/conway.cpp\" target=\"_blank\">conway</a>, <a href=\"https://github.com/arrayfire/arrayfire/blob/master/examples/graphics/conway_pretty.cpp\" target=\"_blank\">conway_pretty</a>, <a href=\"https://github.com/arrayfire/arrayfire/blob/master/examples/graphics/gravity_sim.cpp\" target=\"_blank\">gravity</a>, and <a href=\"https://github.com/arrayfire/arrayfire/blob/master/examples/graphics/fractal.cpp\" target=\"_blank\">julia fractal</a>.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/conway.gif\"><img class=\"alignnone size-full wp-image-9227\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/conway.gif\" alt=\"conway\" width=\"256\" height=\"256\" /></a> <a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/conway_pretty.gif\"><img class=\"alignnone size-full wp-image-9228\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/conway_pretty.gif\" alt=\"conway_pretty\" width=\"256\" height=\"256\" /></a> <a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/gravity.gif\"><img class=\"alignnone size-full wp-image-9216\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/gravity.gif\" alt=\"gravity\" width=\"256\" height=\"256\" /></a> <a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/julia.gif\"><img class=\"alignnone size-full wp-image-9240\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/julia.gif\" alt=\"julia\" width=\"256\" height=\"256\" /></a>\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Behavioral Changes[/custom_headline]\r\n\r\nIn previous versions of ArrayFire, axes limits were computed automatically to fit the data. In ArrayFire v3.4, users are required to set axes limits, as shown below:\r\n<pre><code class=\"language-cpp\">\r\naf::Window myWindow(800, 800, \"2D Plot example: ArrayFire\");\r\n\r\narray Y;\r\nint sign = 1;\r\narray X = seq(-af::Pi, af::Pi, PRECISION);\r\narray noise = randn(X.dims(0))/5.f;\r\n\r\nmyWindow.grid(2, 1);\r\n// Set the axes limits to view (0,0), prior to v3.4 this was not needed\r\nmyWindow(0, 0).setAxesLimits(-2 * af::Pi, 2 * af::Pi, -1, 1, true);\r\n// Set the axes limits to view (0,0), prior to v3.4 this was not needed\r\nmyWindow(1, 0).setAxesLimits(-2 * af::Pi, 2 * af::Pi, -1.25, 1.25, true);\r\n\r\nfor (double val=0; !myWindow.close(); )\r\n{\r\n    Y = sin(X);\r\n\r\n    myWindow(0,0).plot(X, Y);\r\n    myWindow(1,0).scatter(X, Y + noise, AF_MARKER_POINT);\r\n\r\n    myWindow.show();\r\n\r\n    X = X + PRECISION * float(sign);\r\n    val += PRECISION * float(sign);\r\n\r\n    if (val >af::Pi) {\r\n        sign = -1;\r\n    } else if (val < -af::Pi) {\r\n        sign = 1;\r\n    }\r\n}\r\n</code></pre>\r\nThe code above produces the output below. You can find the complete example <a href=\"https://github.com/arrayfire/arrayfire/blob/master/examples/graphics/plot2d.cpp\" target=\"_blank\">here</a>.\r\n\r\n<a href=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/plot2d.png\"><img class=\"alignnone size-large wp-image-9183\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2016/09/plot2d-1024x927.png\" alt=\"plot2d\" width=\"742\" height=\"672\" /></a>\r\n\r\n<strong>Miscellaneous Change</strong>\r\n\r\nRemoved <a href=\"http://glew.sourceforge.net/\">GLEW</a> and replaced with <a href=\"https://github.com/cginternals/glbinding\">glbinding</a>.\r\n\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Download[/custom_headline]\r\n\r\nArrayFire v3.4 can be downloaded from these locations:\r\n<ul>\r\n 	<li><a href=\"http://sandbox.arrayfire.com/download/\">Binaries</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">Source code</a></li>\r\n</ul>\r\n[custom_headline type=\"left\" level=\"h3\" looks_like=\"h3\"]Community[/custom_headline]\r\n\r\nArrayFire is continually improving through the addition of new visualization functions. We welcome your feedback:\r\n<ul>\r\n 	<li>General discussion forums on the <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire Google Group</a></li>\r\n 	<li>Live discussion chat on the <a href=\"https://gitter.im/arrayfire/arrayfire?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge\">ArrayFire Gitter</a></li>\r\n 	<li>Issue reports on the <a href=\"https://github.com/arrayfire/arrayfire/issues\">ArrayFire GitHub</a></li>\r\n</ul>\r\nFinally, as you find success with ArrayFire, we invite you to contribute a post to this blog to share with the broader community. Email <a href=\"mailto:scott@arrayfire.com\">scott@arrayfire.com</a> to contribute to this blog.','Graphics Updates in ArrayFire v3.4','','inherit','closed','closed','','9172-revision-v1','','','2017-10-25 12:08:21','2017-10-25 16:08:21','',9172,'https://sandbox.arrayfire.com/9172-revision-v1/',0,'revision','',0),(9766,1,'2017-10-31 13:35:30','2017-10-31 17:35:30','','Order &ndash; October 31, 2017 @ 01:35 PM','topk/partialsort','wc-completed','open','closed','order_59f8b4613c03b','order-oct-31-2017-0535-pm','','','2017-10-31 13:35:38','2017-10-31 17:35:38','',0,'https://sandbox.arrayfire.com/?post_type=shop_order&#038;p=9766',0,'shop_order','',3),(9767,1,'2017-11-14 18:34:38','2017-11-14 23:34:38','','Order &ndash; November 14, 2017 @ 06:34 PM','batched matmul','wc-completed','open','closed','order_5a0b7d8ccb22c','order-nov-14-2017-1134-pm','','','2017-11-14 18:34:43','2017-11-14 23:34:43','',0,'https://sandbox.arrayfire.com/?post_type=shop_order&#038;p=9767',0,'shop_order','',3),(9768,1,'2017-12-19 17:25:58','2017-12-19 22:25:58','','Order &ndash; December 19, 2017 @ 05:25 PM','','wc-completed','open','closed','order_5a3991f41d90e','order-dec-19-2017-1025-pm','','','2017-12-19 17:26:03','2017-12-19 22:26:03','',0,'https://sandbox.arrayfire.com/?post_type=shop_order&#038;p=9768',0,'shop_order','',3),(9769,1,'2018-01-09 18:50:52','2018-01-09 23:50:52','','Order &ndash; January 9, 2018 @ 06:50 PM','','wc-completed','open','closed','order_5a555559f396a','order-jan-09-2018-1150-pm','','','2018-01-09 18:50:56','2018-01-09 23:50:56','',0,'https://sandbox.arrayfire.com/?post_type=shop_order&#038;p=9769',0,'shop_order','',3),(9770,1,'2018-01-19 13:18:14','2018-01-19 18:18:14','','Order &ndash; January 19, 2018 @ 01:18 PM','beta1 cuda 8 build','wc-completed','open','closed','order_5a623664bbf1e','order-jan-19-2018-0618-pm','','','2018-01-19 13:18:19','2018-01-19 18:18:19','',0,'https://sandbox.arrayfire.com/?post_type=shop_order&#038;p=9770',0,'shop_order','',3),(9771,6,'2018-01-22 17:39:29','2018-01-22 22:39:29','','awesome whitepaper','','inherit','open','closed','','matrix_wp_arrayfire_2017','','','2018-01-22 17:42:43','2018-01-22 22:42:43','',2628,'https://sandbox.arrayfire.com/wp-content/uploads/2012/05/Matrix_WP_ArrayFire_2017.pdf',0,'attachment','application/pdf',0),(9772,6,'2018-01-22 17:53:14','2018-01-22 22:53:14','What do you get when you offer the world\'s most comprehensive <a href=\"https://sandbox.arrayfire.com/download\">GPU library</a> available for free? Excited users who go the extra mile and give back to the community.\r\n\r\nAndrzej Chrzȩszczyk from Jan Kochanowski University recently wrote an <a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2012/05/Matrix_WP_ArrayFire_2017.pdf\" target=\"_blank\">awesome whitepaper</a>, entitled \"Matrix Computations on the GPU with ArrayFire for Python and C/C++.\" The whitepaper contains many GPU computing tutorial examples as well as performance timings for each example.\r\n\r\nAndrzej notes, \"The purpose of this document is to make the first steps in using modern graphics cards to general purpose computations simpler.\"  This document is especially beneficial for programmers looking to accelerate Python or C/C++ codes.\r\n\r\nWe thank Andrzej this fine contribution to the ArrayFire community.  His documentation on ArrayFire will be beneficial to all new users of the library.','ArrayFire Examples and Benchmarks Whitepaper','','inherit','closed','closed','','2628-autosave-v1','','','2018-01-22 17:53:14','2018-01-22 22:53:14','',2628,'https://sandbox.arrayfire.com/2628-autosave-v1/',0,'revision','',0),(9773,6,'2018-01-22 17:44:40','2018-01-22 22:44:40','<a href=\"http://accelereyes.com/whitepapers\"><img class=\"alignright size-full wp-image-2674\" style=\"border: 1px solid black;\" title=\"arrayfire_matrix_computations_chrzeszczyk\" src=\"http://blog.accelereyes.com/blog/wp-content/uploads/2012/05/arrayfire_matrix_computations_chrzeszczyk.png\" alt=\"\" width=\"150\" height=\"194\" /></a>What do you get when you offer the world\'s most comprehensive <a href=\"https://sandbox.arrayfire.com/download\">GPU library</a> available for free? Excited users who go the extra mile and give back to the community.\r\n\r\nAndrzej Chrzȩszczyk from Jan Kochanowski University recently wrote an <a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2012/05/Matrix_WP_ArrayFire_2017.pdf\" target=\"_blank\">awesome whitepaper</a>, entitled \"Matrix Computations on the GPU with ArrayFire for Python and C/C++.\" The whitepaper contains many GPU computing tutorial examples as well as performance timings for each example.\r\n\r\nAndrzej notes, \"The purpose of this document is to make the first steps in using modern graphics cards to general purpose computations simpler.\"  This document is especially beneficial for programmers looking to accelerate Python or C/C++ codes.\r\n\r\nWe thank Andrzej this fine contribution to the ArrayFire community.  His documentation on ArrayFire will be beneficial to all new users of the library.','ArrayFire Examples and Benchmarks Whitepaper','','inherit','closed','closed','','2628-revision-v1','','','2018-01-22 17:44:40','2018-01-22 22:44:40','',2628,'https://sandbox.arrayfire.com/2628-revision-v1/',0,'revision','',0),(9774,6,'2018-01-22 17:55:37','2018-01-22 22:55:37','What do you get when you offer the world\'s most comprehensive <a href=\"https://sandbox.arrayfire.com/download\">GPU library</a> available for free? Excited users who go the extra mile and give back to the community.\r\n\r\nAndrzej Chrzȩszczyk from Jan Kochanowski University recently wrote an <a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2012/05/Matrix_WP_ArrayFire_2017.pdf\" target=\"_blank\">awesome whitepaper</a>, entitled \"Matrix Computations on the GPU with ArrayFire for Python and C/C++.\" The whitepaper contains many GPU computing tutorial examples as well as performance timings for each example.\r\n\r\nAndrzej notes, \"The purpose of this document is to make the first steps in using modern graphics cards to general purpose computations simpler.\"  This document is especially beneficial for programmers looking to accelerate Python or C/C++ codes.\r\n\r\nWe thank Andrzej this fine contribution to the ArrayFire community.  His documentation on ArrayFire will be beneficial to all new users of the library.','ArrayFire Examples and Benchmarks Whitepaper','','inherit','closed','closed','','2628-revision-v1','','','2018-01-22 17:55:37','2018-01-22 22:55:37','',2628,'https://sandbox.arrayfire.com/2628-revision-v1/',0,'revision','',0),(9775,1,'2018-02-06 11:55:42','2018-02-06 16:55:42','','Order &ndash; February 6, 2018 @ 11:55 AM','af::topk for OpenCL CPU backend : \r\n- no memory copy of the data to topk on\r\n- approximately as fast as std partial_sort\r\n- at least f32 data type\r\n- to be included in AF 3.6.0\r\n- for CPU backend only (no need for gpu openCL)\r\n- Linux 64 installer no-gl compatible centos 6\r\nTo be delivered on Feb 9th in a installer from AF master + cuda topk','wc-completed','open','closed','order_5a79de0c30e67','order-feb-06-2018-0455-pm','','','2018-02-06 11:55:47','2018-02-06 16:55:47','',0,'https://sandbox.arrayfire.com/?post_type=shop_order&#038;p=9775',0,'shop_order','',3),(9776,1,'2018-02-28 11:58:08','2018-02-28 16:58:08','','Order &ndash; February 28, 2018 @ 11:58 AM','Deliver to SDL a 3.6.0 ArrayFire beta package Linux installer CentOS6 compatible embedding all the needed cuda 9 libraries in order to run on a machine without the need to install cuda.\r\nTo be delivered on 2018 February 29th.','wc-completed','open','closed','order_5a96cf766dbfe','order-feb-28-2018-0349-pm','','','2018-02-28 11:58:12','2018-02-28 16:58:12','',0,'https://sandbox.arrayfire.com/?post_type=shop_order&#038;p=9776',0,'shop_order','',4),(9777,1,'2018-03-20 17:42:35','2018-03-20 21:42:35','','Order &ndash; March 20, 2018 @ 05:42 PM','','wc-completed','open','closed','order_5ab18048cc87a','order-mar-20-2018-0942-pm','','','2018-03-20 17:42:38','2018-03-20 21:42:38','',0,'https://sandbox.arrayfire.com/?post_type=shop_order&#038;p=9777',0,'shop_order','',3),(9778,1,'2018-04-05 17:34:12','2018-04-05 21:34:12','','Order &ndash; April 5, 2018 @ 05:34 PM','This order is for AF support to fix af::mean : \r\nhttps://github.com/arrayfire/arrayfire/issues/2093\r\nThis PR seems to partially fix the bug :  \r\nhttps://github.com/arrayfire/arrayfire/pull/2106','wc-completed','open','closed','order_5ac6965291266','order-apr-05-2018-0934-pm','','','2018-04-05 17:34:16','2018-04-05 21:34:16','',0,'https://sandbox.arrayfire.com/?post_type=shop_order&#038;p=9778',0,'shop_order','',3),(9779,1,'2018-04-10 13:48:25','2018-04-10 17:48:25','','Order &ndash; April 10, 2018 @ 01:48 PM','AF opencl mean/var bug fix : \r\nhttps://github.com/arrayfire/arrayfire/issues/2117','wc-completed','open','closed','order_5accf8e7b7bd5','order-apr-10-2018-0548-pm','','','2018-04-10 13:48:31','2018-04-10 17:48:31','',0,'https://sandbox.arrayfire.com/?post_type=shop_order&#038;p=9779',0,'shop_order','',3),(9780,1,'2018-04-13 18:38:01','2018-04-13 22:38:01','','Order &ndash; April 13, 2018 @ 06:38 PM','ArrayFire 3.6.0 RC5 delivery : Cuda 9, Linux only, CentOS 6 compatible.','wc-completed','open','closed','order_5ad131476f619','order-apr-13-2018-1037-pm','','','2018-04-13 18:38:07','2018-04-13 22:38:07','',0,'https://sandbox.arrayfire.com/?post_type=shop_order&#038;p=9780',0,'shop_order','',3),(9783,17794,'2018-05-04 18:05:16','2018-05-04 22:05:16','Today we are pleased to announce the release of ArrayFire v3.6.  It can be downloaded from these locations:\r\n<ul>\r\n 	<li><a href=\"https://sandbox.arrayfire.com/download/\">Official installers</a></li>\r\n 	<li><a href=\"https://github.com/arrayfire\">GitHub repository</a></li>\r\n</ul>\r\nThis latest version of ArrayFire is better than ever! We added several new features that improve the performance and usability of the ArrayFire library. The main features are:\r\n<ul>\r\n 	<li>Support for batched matrix multiply</li>\r\n 	<li>Added the topk function</li>\r\n 	<li>Added the anisotropic diffusion filter</li>\r\n</ul>\r\nWe have also spent a significant amount of effort improving the internals of the library. The build system is significantly improved and organized.\r\n<h4>Batched Matrix Multiplication</h4>\r\nThe new batch matmul allows you to perform several matrix multiplication operations in one call of matmul. You might want to call this function if you are performing multiple smaller matrix multiplication operations. Here is an example:\r\n<pre class=\"lang:c++ decode:true\" title=\"Batched matrix multiply\">// Create a 3x3x2 matrix\r\narray a = randu(3, 3, 2);\r\narray b = randu(3, 3, 2);\r\n\r\narray c = matmul(a, b);\r\n</pre>\r\nThe example above is creating two 3 by 3 matrices as a 3x3x2 volume for a and b. The matmul function then multiplies the slice of a volume with the corresponding slice in b. With this approach you can reach higher efficiencies with smaller matrices. Here is a benchmark for batched matmul on the NVIDIA Tesla V100.\r\n\r\n[caption id=\"attachment_9793\" align=\"aligncenter\" width=\"646\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2018/05/chart-1.png\"><img class=\"size-full wp-image-9793\" src=\"https://sandbox.arrayfire.com/wp-content/uploads/2018/05/chart-1.png\" alt=\"Batched Matrix Multiplication Performance\" width=\"646\" height=\"430\" /></a> Batched Matrix Multiplication Performance[/caption]\r\n\r\nThe batched matrix multiplication allows you to reach the maximum performance of your GPU with smaller matrix sizes. Larger matrices do not necessarily need to be batched to fully utilize the GPU.\r\n<h4>TopK</h4>\r\nTopk is another exciting function that was added in this release. This function returns the top k maximum or minimum values in a vector or matrix along with their indices. Here is an example:\r\n<pre class=\"lang:c++ decode:true\" title=\"Topk Example\">array in = randu(10, 8); // Create a 10x8 matrix\r\n\r\narray idx, vals;\r\ntopk(vals, idx, in, 3); // Get the top 3 values of a</pre>\r\nIn this example we create a 10x8 matrix which will be passed into the topk function. This function will return two matrices of size 3x8. The first matrix is composed of the top 3 maximum values. The second matrix is made up of the index of those values in the original matrix along that particular column.\r\n<pre class=\"lang:default decode:true\">in\r\n[10 8 1 1]\r\n 0.6010 0.1583 0.6755 0.5143 0.7917 0.9092 0.5970 0.9048 \r\n 0.0278 0.3712 0.6105 0.3670 0.1654 0.8865 0.9594 0.0198 \r\n 0.9806 0.3543 0.5232 0.3336 0.8657 0.9676 0.2323 0.4436 \r\n 0.2126 0.6450 0.5567 0.0363 0.3766 0.1425 0.9623 0.6808 \r\n 0.0655 0.9675 0.7896 0.5349 0.7331 0.5137 0.8578 0.6636 \r\n 0.5497 0.3636 0.8966 0.0123 0.2522 0.6484 0.0192 0.8738 \r\n 0.2864 0.4165 0.0536 0.3988 0.9644 0.6353 0.7191 0.3954 \r\n 0.3410 0.5814 0.5775 0.9787 0.4711 0.7449 0.4035 0.5277 \r\n 0.7509 0.8962 0.2908 0.2308 0.3637 0.4391 0.4692 0.3592 \r\n 0.4105 0.3712 0.9941 0.6244 0.9643 0.6982 0.3353 0.8567 \r\n\r\nvals\r\n[3 8 1 1]\r\n 0.9806 0.9675 0.9941 0.9787 0.9644 0.9676 0.9623 0.9048 \r\n 0.7509 0.8962 0.8966 0.6244 0.9643 0.9092 0.9594 0.8738 \r\n 0.6010 0.6450 0.7896 0.5349 0.8657 0.8865 0.8578 0.8567 \r\nidx\r\n[3 8 1 1]\r\n 2 4 9 7 6 2 3 0 \r\n 8 8 5 9 9 0 1 5 \r\n 0 3 4 4 2 1 4 9 \r\n\r\n</pre>\r\nThe topk function is optimized for small sizes of k(&lt;32). You could have implemented something like this in older versions of ArrayFire using a combination of sort and indexing. Here are some benchmarks comparing the two approaches.\r\n\r\n<img src=\"data:image/png;base64,[encoded data, 41732 characters]\" />\r\n\r\nFor smaller sizes, topk is getting a 23x speedup over the sort and indexing approach. This test was performed on an NVIDIA Quadro GV100 GPU. Note that the run-times are on a log scale.\r\n<h4>Anisotropic Smoothing Filter</h4>\r\nAnisotropic smoothing filter is an edge-preserving smoothing filter. It smooths out minor intensity variations all the while enhancing edges and removing noise. A more detailed explanation of what this filter does internally is explained in the <a href=\"https://arrayfire.org/docs/group__image__func__anisotropic__diffusion.htm\" target=\"_blank\">documentation</a>. Given below is the sample output from this filter that illustrates how edges are better preserved in comparison to normal isotropic smoothing techniques, such as Gaussian blurring.\r\n\r\n[caption id=\"attachment_9803\" align=\"aligncenter\" width=\"742\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2018/05/anisotropic_diffusion_sample_v36_post.png\" target=\"_blank\"><img class=\"wp-image-9803 size-large\" src=\"https://sandbox.arrayfire.com/wp-content/uploads/2018/05/anisotropic_diffusion_sample_v36_post-1024x906.png\" alt=\"anisotropic_diffusion_sample_v36_post\" width=\"742\" height=\"656\" /></a> Image 1: Original Input(a), Prewitt edge filter(b), Anisotropically smoothed input(c), Gradient after gaussian blur(d), Gradient on original input (e), Gradient after diffusion(f)[/caption]\r\n\r\nNotice the edge details in images 1(b) &amp; 1(e). There are lot of extraneous details mostly that come out of noise. Even after we apply Gaussian blur (more than once) on the original input, some of the required details may also go away along with noise as illustrated in the image 1(d). anisotropic diffusion comes to the rescue in such cases. Notice the image 1(c) in comparison to 1(a). All minor/subtle variations in texture are smoothed out while preserving the edges as you can see in gradient of diffused image in 1(f). Feel free to play with the parameters and kindly notify us if there are unexpected behaviors.\r\n<h4>Other Improvements</h4>\r\nWe have also improved the performance of our JIT. We have moved the shift and select functions into JIT. We also reduced the number of mutex locks and improved the thread safety of ArrayFire.\r\n\r\nIn addition to the functions above, we have made several improvements which will increase the usability of the library. Our CMake config script now uses import targets instead of plain variables to add flags. If you are using CMake you can now compile and link your application with ArrayFire like this:\r\n<pre class=\"lang:default decode:true\" title=\"Linking with ArrayFire\">find_package(ArrayFire)\r\n\r\nadd_executable(FantasticApp main.cpp)\r\ntarget_link_library(FantasticApp PRIVATE ArrayFire::afopencl)</pre>\r\nThis will automatically add the correct compiler and linker flags when you compile your application.\r\n\r\nWe have also improved the building from source experience ArrayFire. Internally we have employed Modern CMake techniques and rewrote most of the build scripts to make it easy to maintain and read.\r\n\r\nThe period and quality of the random number generator has been improved, thanks to Ralf Stubner. He has also added several unit tests to keep track of the quality of the random number generator in the future. Adrien Vincent added a few color maps that were available in our Forge library but were missing from ArrayFire. Several other contributors helped us fix errors in our documentation and build system.\r\n\r\nWe are excited to finally release ArrayFire v3.6. We would like to thank our community for supporting us and helping us improve ArrayFire. We are looking forward to more community participation for the future releases!\r\n<h4>Dedicated Support and Coding Services</h4>\r\nArrayFire is open source and always will be. For those who want dedicated support or custom function development, we offer a variety of <a href=\"https://sandbox.arrayfire.com/support/\">support packages</a>.\r\n\r\nArrayFire also serves many clients through consulting and <a href=\"https://sandbox.arrayfire.com/consulting/\">coding services</a>, algorithm development, porting code, and <a href=\"https://sandbox.arrayfire.com/training/\">training courses</a> for developers. Contact us at <a href=\"mailto:sales@arrayfire.com\">sales@arrayfire.com</a> or <a href=\"https://meetme.so/arrayfire\">schedule</a> a free technical consultation to learn more about our consulting and coding services.','ArrayFire v3.6 Release','','publish','open','closed','','arrayfire-v3-6-release','','','2018-06-26 16:01:44','2018-06-26 20:01:44','',0,'https://sandbox.arrayfire.com/?p=9783',0,'post','',3),(9784,17794,'2018-05-03 11:11:50','2018-05-03 15:11:50','Today we are announcing the release of ArrayFire version 3.6. The official binary installers can be downloaded here:\r\n\r\nhttps://sandbox.arrayfire.com/downloads\r\n\r\nWe added several new features that improve the performance and usability of the ArrayFire library. The main features are:\r\n<ul>\r\n 	<li>Support for batched matrix multiply</li>\r\n 	<li>Added the topk function</li>\r\n 	<li>Added the anisotropic diffusion filter</li>\r\n</ul>\r\nThe new batch functionality allows you to perform several matrix multiplication operations in one call of matmul. The inte','ArrayFire v3.6 Released','','inherit','closed','closed','','9783-revision-v1','','','2018-05-03 11:11:50','2018-05-03 15:11:50','',9783,'https://sandbox.arrayfire.com/9783-revision-v1/',0,'revision','',0),(9785,1,'2018-05-03 11:46:10','2018-05-03 15:46:10','','Order &ndash; May 3, 2018 @ 11:46 AM','AFCPU high level multithreading project: makes the afcpu backend  friendly with high level multithreading : the perf of afcpu using only 1 core must scale linearly if used in a mutithreaded application.  This is half of the POC. The other half will be bought next week if early results are good enough.','wc-completed','open','closed','order_5aeb2ec015041','order-may-03-2018-0346-pm','','','2018-05-03 11:46:15','2018-05-03 15:46:15','',0,'https://sandbox.arrayfire.com/?post_type=shop_order&#038;p=9785',0,'shop_order','',3),(9786,18672,'2018-05-03 13:41:51','2018-05-03 17:41:51','[content_band inner_container=\"true\" no_margin=\"true\" border=\"none\" padding_top=\"10px\" padding_bottom=\"40px\"]\r\n[custom_headline type=\"left\" level=\"h2\"]\r\nArrayFire Installers\r\n[/custom_headline]\r\n[custom_headline type=\"left\" level=\"h5\"]\r\nEach download contains both CUDA and OpenCL files.\r\n[/custom_headline]\r\n[gap size=\"4%\"]\r\n\r\n[column type=\"one-fourth\"][button  block=\"true\" onclick=\"&lt;!-- Google Code for ArrayFire Download (Windows) Conversion Page\r\nIn your html page, add the snippet and call\r\ngoog_report_conversion when someone clicks on the\r\nchosen link or button. --&gt;\r\n&lt;script type=\"text/javascript\"&gt;\r\n/* &lt;!&amp;#91;CDATA&amp;#91; */\r\ngoog_snippet_vars = function() {\r\nvar w = window;\r\nw.google_conversion_id = 1021026651;\r\nw.google_conversion_label = \"18VJCJjPql4Q28Lu5gM\";\r\nw.google_remarketing_only = false;\r\n}\r\n// DO NOT CHANGE THE CODE BELOW.\r\ngoog_report_conversion = function(url) {\r\ngoog_snippet_vars();\r\nwindow.google_conversion_format = \"3\";\r\nwindow.google_is_call = true;\r\nvar opt = new Object();\r\nopt.onload_callback = function() {\r\nif (typeof(url) != \'undefined\') {\r\nwindow.location = url;\r\n}\r\n}\r\nvar conv_handler = window&amp;#91;\'google_trackConversion\'&amp;#93;;\r\nif (typeof(conv_handler) == \'function\') {\r\nconv_handler(opt);\r\n}\r\n}\r\n/* &amp;#93;&amp;#93;&gt; */\r\n&lt;/script&gt;\r\n&lt;script type=\"text/javascript\"\r\nsrc=\"//www.googleadservices.com/pagead/conversion_async.js\"&gt;\r\n&lt;/script&gt;\" class=\"center-text\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/lvvyk\" size=\"regular\" ]Windows, v3.6.0\r\n(64-bit)[/button][/column][column type=\"one-fourth\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/lw515\" size=\"regular\" ]Linux, v3.6.0\r\n(64-bit)[/button][/column][column type=\"one-fourth\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2015-03-19/ltx4p\" size=\"regular\" ]Mac OSX, v3.6.0\r\n(64-bit)[/button][/column][column type=\"one-fourth\"][button block=\"true\" type=\"flat\" shape=\"rounded\" href=\"https://go.pardot.com/l/37882/2017-09-19/5dgdc4\" size=\"regular\" ]Tegra X1 v3.5.1\r\n(64-bit)[/button][/column][gap size=\"9%\"]\r\n\r\nCheck out our GitHub repository to <a href=\"https://github.com/arrayfire/arrayfire\">build from the source</a>.\r\n\r\nLooking for an older installer? <a href=\"http://sandbox.arrayfire.com/installer_archive\">Try here</a>.[/content_band]\r\n<p style=\"text-align: left;\">[content_band inner_container=\"true\" no_margin=\"true\" border=\"none\" padding_top=\"10px\" padding_bottom=\"40px\" bg_color=\"#f1f1f1\"][column type=\"one-half\"][gap size=\"8%\"]<img class=\"aligncenter wp-image-5156\" src=\"http://sandbox.arrayfire.com/wp-content/uploads/2014/02/mobile_Exported1-e1395437261846.png\" alt=\"mobile_Exported\" width=\"233\" height=\"311\" />[/column][column type=\"one-half\" last=\"true\"]\r\n[custom_headline type=\"left\" level=\"h2\"]\r\nGreat. What now?\r\n[/custom_headline]</p>\r\n<p style=\"text-align: left;\">[gap size=\"5%\"]</p>\r\n<p style=\"text-align: left;\">Welcome to ArrayFire! You\'ve got an awesome library there—learn more about its features and functions on <a href=\"http://www.sandbox.arrayfire.com/docs/index.htm\">our documentation</a>.</p>\r\n<p style=\"text-align: left;\">In addition to our <a href=\"https://groups.google.com/forum/#!forum/arrayfire-users\">ArrayFire user group</a> and <a href=\"http://sandbox.arrayfire.com/blog/\">our blog</a>, we offer a plethora of <a href=\"http://sandbox.arrayfire.com/support/\">support options</a> to fit your needs.</p>\r\n<p style=\"text-align: left;\">Got a job that needs closer attention? Hire us! Our engineers are acceleration wizards. Check out our <a href=\"http://sandbox.arrayfire.com/consulting/\">consulting offerings</a>, or set up a free <a href=\"http://meetme.so/arrayfire\">technical consultation</a> with us today![/column]</p>\r\n<p style=\"text-align: left;\">[/content_band]</p>\r\n<p style=\"text-align: center;\"></p>','Download','','inherit','closed','closed','','5931-revision-v1','','','2018-05-03 13:41:51','2018-05-03 17:41:51','',5931,'https://sandbox.arrayfire.com/5931-revision-v1/',0,'revision','',0),(9787,17794,'2018-05-03 15:56:53','2018-05-03 19:56:53','Today we are announcing the release of ArrayFire version 3.6. The official binary installers can be downloaded here:\r\n\r\nhttps://sandbox.arrayfire.com/downloads\r\n\r\nWe added several new features that improve the performance and usability of the ArrayFire library. The main features are:\r\n<ul>\r\n 	<li>Support for batched matrix multiply</li>\r\n 	<li>Added the topk function</li>\r\n 	<li>Added the anisotropic diffusion filter</li>\r\n</ul>\r\nThe new batch functionality allows you to perform several matrix multiplication operations in one call of matmul. You might want to call this function if you are performing multiple smaller matrix multiplication operations. Here is an example:\r\n<pre class=\"lang:c++ decode:true\" title=\"Batched matrix multiply\">// Create a 3x3x2 matrix\r\narray a = randu(3, 3, 2);\r\narray b = randu(3, 3, 2);\r\n\r\narray c = matmul(a, b);\r\n</pre>\r\nThe example above is creating 2 3 by 3 matrices as a 3x3x2 volume for a and b. The matmul function then multiplies the slice of the a volume with the corresponding slice in b. Which this approach you can reach higher efficiencies with smaller matrices. Here are some benchmarks for the batched matmul for different sizes of a matrix.\r\n\r\n[column type=\"one-half\" fade_animation=\"in\" fade_animation_offset=\"45px\"]\r\n<pre class=\"\">ArrayFire v3.6.0 (CUDA, 64-bit Linux, build ee21c79)\r\nPlatform: CUDA Toolkit 9.1, Driver: 390.30\r\n[0] Tesla V100-PCIE-16GB, 16161 MB, CUDA Compute 7.0\r\nBenchmark N-by-N matrix multiply\r\n 128 x  128:   184 Gflops\r\n 256 x  256:  1478 Gflops\r\n 384 x  384:  4906 Gflops\r\n 512 x  512:  7609 Gflops\r\n 640 x  640:  9295 Gflops\r\n 768 x  768:  9620 Gflops\r\n 896 x  896:  10971 Gflops\r\n1024 x 1024:  11332 Gflops\r\n1152 x 1152:  11493 Gflops\r\n1280 x 1280:  11745 Gflops\r\n1408 x 1408:  12202 Gflops\r\n1536 x 1536:  11885 Gflops\r\n1664 x 1664:  12592 Gflops\r\n1792 x 1792:  13135 Gflops\r\n1920 x 1920:  12668 Gflops\r\n2048 x 2048:  13510 Gflops</pre>\r\n[/column]\r\n\r\n[column type=\"one-half\" fade_animation=\"in\" fade_animation_offset=\"45px\"]\r\n<pre class=\"\">ArrayFire v3.6.0 (CUDA, 64-bit Linux, build ee21c79)\r\nPlatform: CUDA Toolkit 9.1, Driver: 390.30\r\n[0] Tesla V100-PCIE-16GB, 16161 MB, CUDA Compute 7.0\r\nBenchmark N-by-N matrix multiply\r\n 128 x 128 x 32: 2090 Gflops\r\n 256 x 256 x 32: 8224 Gflops\r\n 384 x 384 x 32: 11191 Gflops\r\n 512 x 512 x 32: 10734 Gflops\r\n 640 x 640 x 32: 12974 Gflops\r\n 768 x 768 x 32: 13242 Gflops\r\n 896 x 896 x 32: 13583 Gflops\r\n1024 x 1024 x 32: 13544 Gflops\r\n1152 x 1152 x 32: 13706 Gflops\r\n1280 x 1280 x 32: 13804 Gflops\r\n1408 x 1408 x 32: 13829 Gflops\r\n1536 x 1536 x 32: 13849 Gflops\r\n1664 x 1664 x 32: 13914 Gflops\r\n1792 x 1792 x 32: 13932 Gflops\r\n1920 x 1920 x 32: 13966 Gflops\r\n2048 x 2048 x 32: 13791 Gflops\r\n ### peak 13966.2 GFLOPS</pre>\r\n[/column]\r\n\r\nThe batched calls allow you to reach higher computational efficiencies because we are able to better distribute the work across the GPU.\r\n\r\nThe topk function is another exciting function that is included in this release. This function returns the top k most maximum or minimum values in a vector or matrix across a given dimension. Here is an example.\r\n\r\n&nbsp;\r\n\r\n&nbsp;','ArrayFire v3.6 Released','','inherit','closed','closed','','9783-revision-v1','','','2018-05-03 15:56:53','2018-05-03 19:56:53','',9783,'https://sandbox.arrayfire.com/9783-revision-v1/',0,'revision','',0),(9788,17794,'2018-05-03 15:58:26','2018-05-03 19:58:26','Today we are announcing the release of ArrayFire version 3.6. The official binary installers can be downloaded here:\r\n\r\nhttps://sandbox.arrayfire.com/downloads\r\n\r\nWe added several new features that improve the performance and usability of the ArrayFire library. The main features are:\r\n<ul>\r\n 	<li>Support for batched matrix multiply</li>\r\n 	<li>Added the topk function</li>\r\n 	<li>Added the anisotropic diffusion filter</li>\r\n</ul>\r\nThe new batch functionality allows you to perform several matrix multiplication operations in one call of matmul. You might want to call this function if you are performing multiple smaller matrix multiplication operations. Here is an example:\r\n<pre class=\"lang:c++ decode:true\" title=\"Batched matrix multiply\">// Create a 3x3x2 matrix\r\narray a = randu(3, 3, 2);\r\narray b = randu(3, 3, 2);\r\n\r\narray c = matmul(a, b);\r\n</pre>\r\nThe example above is creating 2 3 by 3 matrices as a 3x3x2 volume for a and b. The matmul function then multiplies the slice of the a volume with the corresponding slice in b. Which this approach you can reach higher efficiencies with smaller matrices. Here are some benchmarks for the batched matmul for different sizes of a matrix.\r\n\r\n[column type=\"one-half\" fade_animation=\"in\" fade_animation_offset=\"45px\"]\r\n<pre class=\"\">ArrayFire v3.6.0 (CUDA, 64-bit Linux, build ee21c79)\r\nPlatform: CUDA Toolkit 9.1, Driver: 390.30\r\n[0] Tesla V100-PCIE-16GB, 16161 MB, CUDA Compute 7.0\r\nBenchmark N-by-N matrix multiply\r\n 128 x  128:   184 Gflops\r\n 256 x  256:  1478 Gflops\r\n 384 x  384:  4906 Gflops\r\n 512 x  512:  7609 Gflops\r\n 640 x  640:  9295 Gflops\r\n 768 x  768:  9620 Gflops\r\n 896 x  896:  10971 Gflops\r\n1024 x 1024:  11332 Gflops\r\n1152 x 1152:  11493 Gflops\r\n1280 x 1280:  11745 Gflops\r\n1408 x 1408:  12202 Gflops\r\n1536 x 1536:  11885 Gflops\r\n1664 x 1664:  12592 Gflops\r\n1792 x 1792:  13135 Gflops\r\n1920 x 1920:  12668 Gflops\r\n2048 x 2048:  13510 Gflops</pre>\r\n[/column][column type=\"one-half\" fade_animation=\"in\" fade_animation_offset=\"45px\"]\r\n<pre class=\"\">ArrayFire v3.6.0 (CUDA, 64-bit Linux, build ee21c79)\r\nPlatform: CUDA Toolkit 9.1, Driver: 390.30\r\n[0] Tesla V100-PCIE-16GB, 16161 MB, CUDA Compute 7.0\r\nBenchmark N-by-N matrix multiply\r\n 128 x 128 x 32: 2090 Gflops\r\n 256 x 256 x 32: 8224 Gflops\r\n 384 x 384 x 32: 11191 Gflops\r\n 512 x 512 x 32: 10734 Gflops\r\n 640 x 640 x 32: 12974 Gflops\r\n 768 x 768 x 32: 13242 Gflops\r\n 896 x 896 x 32: 13583 Gflops\r\n1024 x 1024 x 32: 13544 Gflops\r\n1152 x 1152 x 32: 13706 Gflops\r\n1280 x 1280 x 32: 13804 Gflops\r\n1408 x 1408 x 32: 13829 Gflops\r\n1536 x 1536 x 32: 13849 Gflops\r\n1664 x 1664 x 32: 13914 Gflops\r\n1792 x 1792 x 32: 13932 Gflops\r\n1920 x 1920 x 32: 13966 Gflops\r\n2048 x 2048 x 32: 13791 Gflops\r\n ### peak 13966.2 GFLOPS</pre>\r\n[/column]\r\n\r\nThe batched calls allow you to reach higher computational efficiencies because we are able to better distribute the work across the GPU.\r\n\r\nThe topk function is another exciting function that is included in this release. This function returns the top k most maximum or minimum values in a vector or matrix across a given dimension. Here is an example.\r\n\r\n&nbsp;\r\n\r\n&nbsp;','ArrayFire v3.6 Released','','inherit','closed','closed','','9783-revision-v1','','','2018-05-03 15:58:26','2018-05-03 19:58:26','',9783,'https://sandbox.arrayfire.com/9783-revision-v1/',0,'revision','',0),(9789,17794,'2018-05-03 16:00:13','2018-05-03 20:00:13','Today we are announcing the release of ArrayFire version 3.6. The official binary installers can be downloaded here:\r\n\r\nhttps://sandbox.arrayfire.com/downloads\r\n\r\nWe added several new features that improve the performance and usability of the ArrayFire library. The main features are:\r\n<ul>\r\n 	<li>Support for batched matrix multiply</li>\r\n 	<li>Added the topk function</li>\r\n 	<li>Added the anisotropic diffusion filter</li>\r\n</ul>\r\nThe new batch functionality allows you to perform several matrix multiplication operations in one call of matmul. You might want to call this function if you are performing multiple smaller matrix multiplication operations. Here is an example:\r\n<pre class=\"lang:c++ decode:true\" title=\"Batched matrix multiply\">// Create a 3x3x2 matrix\r\narray a = randu(3, 3, 2);\r\narray b = randu(3, 3, 2);\r\n\r\narray c = matmul(a, b);\r\n</pre>\r\nThe example above is creating 2 3 by 3 matrices as a 3x3x2 volume for a and b. The matmul function then multiplies the slice of the a volume with the corresponding slice in b. Which this approach you can reach higher efficiencies with smaller matrices. Here are some benchmarks for the batched matmul for different sizes of a matrix.\r\n\r\n[column type=\"one-half\" fade_animation=\"in\" fade_animation_offset=\"45px\"]\r\n<pre class=\"\">ArrayFire v3.6.0 (CUDA, 64-bit Linux, build ee21c79)\r\nPlatform: CUDA Toolkit 9.1, Driver: 390.30\r\n[0] Tesla V100-PCIE-16GB, 16161 MB, CUDA Compute 7.0\r\nBenchmark N-by-N matrix multiply\r\n 128 x  128:   184 Gflops\r\n 256 x  256:  1478 Gflops\r\n 384 x  384:  4906 Gflops\r\n 512 x  512:  7609 Gflops\r\n 640 x  640:  9295 Gflops\r\n 768 x  768:  9620 Gflops\r\n 896 x  896:  10971 Gflops\r\n1024 x 1024:  11332 Gflops\r\n1152 x 1152:  11493 Gflops\r\n1280 x 1280:  11745 Gflops\r\n1408 x 1408:  12202 Gflops\r\n1536 x 1536:  11885 Gflops\r\n1664 x 1664:  12592 Gflops\r\n1792 x 1792:  13135 Gflops\r\n1920 x 1920:  12668 Gflops\r\n2048 x 2048:  13510 Gflops</pre>\r\n[/column][column type=\"one-half\" fade_animation=\"in\" fade_animation_offset=\"45px\" last=\"true\"]\r\n<pre class=\"\">ArrayFire v3.6.0 (CUDA, 64-bit Linux, build ee21c79)\r\nPlatform: CUDA Toolkit 9.1, Driver: 390.30\r\n[0] Tesla V100-PCIE-16GB, 16161 MB, CUDA Compute 7.0\r\nBenchmark N-by-N matrix multiply\r\n 128 x 128 x 32: 2090 Gflops\r\n 256 x 256 x 32: 8224 Gflops\r\n 384 x 384 x 32: 11191 Gflops\r\n 512 x 512 x 32: 10734 Gflops\r\n 640 x 640 x 32: 12974 Gflops\r\n 768 x 768 x 32: 13242 Gflops\r\n 896 x 896 x 32: 13583 Gflops\r\n1024 x 1024 x 32: 13544 Gflops\r\n1152 x 1152 x 32: 13706 Gflops\r\n1280 x 1280 x 32: 13804 Gflops\r\n1408 x 1408 x 32: 13829 Gflops\r\n1536 x 1536 x 32: 13849 Gflops\r\n1664 x 1664 x 32: 13914 Gflops\r\n1792 x 1792 x 32: 13932 Gflops\r\n1920 x 1920 x 32: 13966 Gflops\r\n2048 x 2048 x 32: 13791 Gflops\r\n ### peak 13966.2 GFLOPS</pre>\r\n[/column]\r\n\r\nThe batched calls allow you to reach higher computational efficiencies because we are able to better distribute the work across the GPU.\r\n\r\nThe topk function is another exciting function that is included in this release. This function returns the top k most maximum or minimum values in a vector or matrix across a given dimension. Here is an example.\r\n\r\n&nbsp;\r\n\r\n&nbsp;','ArrayFire v3.6 Released','','inherit','closed','closed','','9783-revision-v1','','','2018-05-03 16:00:13','2018-05-03 20:00:13','',9783,'https://sandbox.arrayfire.com/9783-revision-v1/',0,'revision','',0),(9791,17794,'2018-05-03 16:37:54','2018-05-03 20:37:54','Today we are announcing the release of ArrayFire version 3.6. The official binary installers can be downloaded here:\r\n\r\nhttps://sandbox.arrayfire.com/downloads\r\n\r\nWe added several new features that improve the performance and usability of the ArrayFire library. The main features are:\r\n<ul>\r\n 	<li>Support for batched matrix multiply</li>\r\n 	<li>Added the topk function</li>\r\n 	<li>Added the anisotropic diffusion filter</li>\r\n</ul>\r\nThe new batch functionality allows you to perform several matrix multiplication operations in one call of matmul. You might want to call this function if you are performing multiple smaller matrix multiplication operations. Here is an example:\r\n<pre class=\"lang:c++ decode:true\" title=\"Batched matrix multiply\">// Create a 3x3x2 matrix\r\narray a = randu(3, 3, 2);\r\narray b = randu(3, 3, 2);\r\n\r\narray c = matmul(a, b);\r\n</pre>\r\nThe example above is creating 2 3 by 3 matrices as a 3x3x2 volume for a and b. The matmul function then multiplies the slice of the a volume with the corresponding slice in b. Which this approach you can reach higher efficiencies with smaller matrices. Here are some benchmarks for the batched matmul for different sizes of a matrix.\r\n\r\n<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2018/05/chart.png\"><img class=\" wp-image-9790\" src=\"https://sandbox.arrayfire.com/wp-content/uploads/2018/05/chart-300x186.png\" alt=\"A comparison between matmul and batched matmul\" width=\"431\" height=\"263\" /></a>\r\n\r\nThe batched calls allow you to reach higher computational efficiencies because we are able to better distribute the work across the GPU.\r\n\r\nThe topk function is another exciting function that is included in this release. This function returns the top k most maximum or minimum values in a vector or matrix across a given dimension. Here is an example.\r\n\r\n&nbsp;\r\n\r\n&nbsp;','ArrayFire v3.6 Released','','inherit','closed','closed','','9783-revision-v1','','','2018-05-03 16:37:54','2018-05-03 20:37:54','',9783,'https://sandbox.arrayfire.com/9783-revision-v1/',0,'revision','',0),(9792,17794,'2018-05-03 16:39:24','2018-05-03 20:39:24','Today we are announcing the release of ArrayFire version 3.6. The official binary installers can be downloaded here:\r\n\r\nhttps://sandbox.arrayfire.com/downloads\r\n\r\nWe added several new features that improve the performance and usability of the ArrayFire library. The main features are:\r\n<ul>\r\n 	<li>Support for batched matrix multiply</li>\r\n 	<li>Added the topk function</li>\r\n 	<li>Added the anisotropic diffusion filter</li>\r\n</ul>\r\nThe new batch functionality allows you to perform several matrix multiplication operations in one call of matmul. You might want to call this function if you are performing multiple smaller matrix multiplication operations. Here is an example:\r\n<pre class=\"lang:c++ decode:true\" title=\"Batched matrix multiply\">// Create a 3x3x2 matrix\r\narray a = randu(3, 3, 2);\r\narray b = randu(3, 3, 2);\r\n\r\narray c = matmul(a, b);\r\n</pre>\r\nThe example above is creating 2 3 by 3 matrices as a 3x3x2 volume for a and b. The matmul function then multiplies the slice of the a volume with the corresponding slice in b. Which this approach you can reach higher efficiencies with smaller matrices. Here are some benchmarks for the batched matmul for different sizes of a matrix.\r\n\r\n<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2018/05/chart.png\"><img class=\"aligncenter wp-image-9790 size-full\" src=\"https://sandbox.arrayfire.com/wp-content/uploads/2018/05/chart.png\" alt=\"A comparison between matmul and batched matmul\" width=\"600\" height=\"371\" /></a>\r\n\r\nThe batched calls allow you to reach higher computational efficiencies because we are able to better distribute the work across the GPU.\r\n\r\nThe topk function is another exciting function that is included in this release. This function returns the top k most maximum or minimum values in a vector or matrix across a given dimension. Here is an example.\r\n\r\n&nbsp;\r\n\r\n&nbsp;','ArrayFire v3.6 Released','','inherit','closed','closed','','9783-revision-v1','','','2018-05-03 16:39:24','2018-05-03 20:39:24','',9783,'https://sandbox.arrayfire.com/9783-revision-v1/',0,'revision','',0),(9793,17794,'2018-05-03 16:49:43','2018-05-03 20:49:43','','batched_matmul','Batched Matrix Multiplication Performance','inherit','open','closed','','chart-1','','','2018-05-03 16:50:22','2018-05-03 20:50:22','',9783,'https://sandbox.arrayfire.com/wp-content/uploads/2018/05/chart-1.png',0,'attachment','image/png',0),(9794,17794,'2018-05-03 17:30:41','2018-05-03 21:30:41','Today we are announcing the release of ArrayFire version 3.6. The official binary installers can be downloaded here:\r\n\r\nhttps://sandbox.arrayfire.com/downloads\r\n\r\nWe added several new features that improve the performance and usability of the ArrayFire library. The main features are:\r\n<ul>\r\n 	<li>Support for batched matrix multiply</li>\r\n 	<li>Added the topk function</li>\r\n 	<li>Added the anisotropic diffusion filter</li>\r\n</ul>\r\nThe new batch functionality allows you to perform several matrix multiplication operations in one call of matmul. You might want to call this function if you are performing multiple smaller matrix multiplication operations. Here is an example:\r\n<pre class=\"lang:c++ decode:true\" title=\"Batched matrix multiply\">// Create a 3x3x2 matrix\r\narray a = randu(3, 3, 2);\r\narray b = randu(3, 3, 2);\r\n\r\narray c = matmul(a, b);\r\n</pre>\r\nThe example above is creating 2 3 by 3 matrices as a 3x3x2 volume for a and b. The matmul function then multiplies the slice of the a volume with the corresponding slice in b. Which this approach you can reach higher efficiencies with smaller matrices. Here is a benchmark for batched matmul on the NVIDIA Tesla V100.\r\n\r\n[caption id=\"attachment_9793\" align=\"aligncenter\" width=\"646\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2018/05/chart-1.png\"><img class=\"size-full wp-image-9793\" src=\"https://sandbox.arrayfire.com/wp-content/uploads/2018/05/chart-1.png\" alt=\"Batched Matrix Multiplication Performance\" width=\"646\" height=\"430\" /></a> Batched Matrix Multiplication Performance[/caption]\r\n\r\nThe batched matrix multiplication allows you to reach the maximum performance of your GPU with smaller matrix sizes. Larger matrices do not necessarily need to be batched to fully utilize the GPU.\r\n\r\nTopk is another exciting function that was added in this release. This function returns the top k maximum or minimum values in a vector or matrix along with their indices. Here is an example:\r\n<pre class=\"lang:c++ decode:true\" title=\"Topk Example\">array a = randu(10, 10); // Create a 10x10 matrix\r\n\r\narray idx, vals;\r\ntopk(vals, idx, a, 3); // Get the top 3 values of a</pre>\r\nHere we create a 10x10 matrix then call the topk function on it. Topk will return the top 3 indices and values. The indices are based on the values position in the given column. Here is a sample output:\r\n<pre class=\"lang:default decode:true \">a\r\n[10 10 1 1]\r\n    0.6010     0.1583     0.6755     0.5143     0.7917     0.9092     0.5970     0.9048     0.3967     0.8891\r\n    0.0278     0.3712     0.6105     0.3670     0.1654     0.8865     0.9594     0.0198     0.8055     0.3434\r\n    0.9806     0.3543     0.5232     0.3336     0.8657     0.9676     0.2323     0.4436     0.5147     0.8040\r\n    0.2126     0.6450     0.5567     0.0363     0.3766     0.1425     0.9623     0.6808     0.3210     0.2986\r\n    0.0655     0.9675     0.7896     0.5349     0.7331     0.5137     0.8578     0.6636     0.7831     0.0438\r\n    0.5497     0.3636     0.8966     0.0123     0.2522     0.6484     0.0192     0.8738     0.4784     0.6108\r\n    0.2864     0.4165     0.0536     0.3988     0.9644     0.6353     0.7191     0.3954     0.5770     0.9033\r\n    0.3410     0.5814     0.5775     0.9787     0.4711     0.7449     0.4035     0.5277     0.8173     0.5131\r\n    0.7509     0.8962     0.2908     0.2308     0.3637     0.4391     0.4692     0.3592     0.5207     0.5784\r\n    0.4105     0.3712     0.9941     0.6244     0.9643     0.6982     0.3353     0.8567     0.4341     0.6910\r\n\r\nidx\r\n[3 10 1 1]\r\n         2          4          9          7          6          2          3          0          7          6\r\n         8          8          5          9          9          0          1          5          1          0\r\n         0          3          4          4          2          1          4          9          4          2\r\n\r\nvals\r\n[3 10 1 1]\r\n    0.9806     0.9675     0.9941     0.9787     0.9644     0.9676     0.9623     0.9048     0.8173     0.9033\r\n    0.7509     0.8962     0.8966     0.6244     0.9643     0.9092     0.9594     0.8738     0.8055     0.8891\r\n    0.6010     0.6450     0.7896     0.5349     0.8657     0.8865     0.8578     0.8567     0.7831     0.8040</pre>\r\n&nbsp;','ArrayFire v3.6 Released','','inherit','closed','closed','','9783-revision-v1','','','2018-05-03 17:30:41','2018-05-03 21:30:41','',9783,'https://sandbox.arrayfire.com/9783-revision-v1/',0,'revision','',0),(9795,17794,'2018-05-03 17:31:35','2018-05-03 21:31:35','Today we are announcing the release of ArrayFire version 3.6. The official binary installers can be downloaded here:\r\n\r\nhttps://sandbox.arrayfire.com/downloads\r\n\r\nWe added several new features that improve the performance and usability of the ArrayFire library. The main features are:\r\n<ul>\r\n 	<li>Support for batched matrix multiply</li>\r\n 	<li>Added the topk function</li>\r\n 	<li>Added the anisotropic diffusion filter</li>\r\n</ul>\r\nThe new batch functionality allows you to perform several matrix multiplication operations in one call of matmul. You might want to call this function if you are performing multiple smaller matrix multiplication operations. Here is an example:\r\n<pre class=\"lang:c++ decode:true\" title=\"Batched matrix multiply\">// Create a 3x3x2 matrix\r\narray a = randu(3, 3, 2);\r\narray b = randu(3, 3, 2);\r\n\r\narray c = matmul(a, b);\r\n</pre>\r\nThe example above is creating 2 3 by 3 matrices as a 3x3x2 volume for a and b. The matmul function then multiplies the slice of the a volume with the corresponding slice in b. Which this approach you can reach higher efficiencies with smaller matrices. Here is a benchmark for batched matmul on the NVIDIA Tesla V100.\r\n\r\n[caption id=\"attachment_9793\" align=\"aligncenter\" width=\"646\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2018/05/chart-1.png\"><img class=\"size-full wp-image-9793\" src=\"https://sandbox.arrayfire.com/wp-content/uploads/2018/05/chart-1.png\" alt=\"Batched Matrix Multiplication Performance\" width=\"646\" height=\"430\" /></a> Batched Matrix Multiplication Performance[/caption]\r\n\r\nThe batched matrix multiplication allows you to reach the maximum performance of your GPU with smaller matrix sizes. Larger matrices do not necessarily need to be batched to fully utilize the GPU.\r\n\r\nTopk is another exciting function that was added in this release. This function returns the top k maximum or minimum values in a vector or matrix along with their indices. Here is an example:\r\n<pre class=\"lang:c++ decode:true\" title=\"Topk Example\">array a = randu(10, 10); // Create a 10x10 matrix\r\n\r\narray idx, vals;\r\ntopk(vals, idx, a, 3); // Get the top 3 values of a</pre>\r\nHere we create a 10x10 matrix then call the topk function on it. Topk will return the top 3 indices and values. The indices are based on the values position in the given column. Here is a sample output:\r\n<pre class=\"lang:default decode:true\">a\r\n[10 10 1 1]\r\n    0.6010     0.1583     0.6755     0.5143     0.7917     0.9092     0.5970     0.9048 \r\n    0.0278     0.3712     0.6105     0.3670     0.1654     0.8865     0.9594     0.0198 \r\n    0.9806     0.3543     0.5232     0.3336     0.8657     0.9676     0.2323     0.4436 \r\n    0.2126     0.6450     0.5567     0.0363     0.3766     0.1425     0.9623     0.6808 \r\n    0.0655     0.9675     0.7896     0.5349     0.7331     0.5137     0.8578     0.6636 \r\n    0.5497     0.3636     0.8966     0.0123     0.2522     0.6484     0.0192     0.8738 \r\n    0.2864     0.4165     0.0536     0.3988     0.9644     0.6353     0.7191     0.3954 \r\n    0.3410     0.5814     0.5775     0.9787     0.4711     0.7449     0.4035     0.5277 \r\n    0.7509     0.8962     0.2908     0.2308     0.3637     0.4391     0.4692     0.3592 \r\n    0.4105     0.3712     0.9941     0.6244     0.9643     0.6982     0.3353     0.8567 \r\n\r\nidx\r\n[3 10 1 1]\r\n         2          4          9          7          6          2          3          0          7          6\r\n         8          8          5          9          9          0          1          5          1          0\r\n         0          3          4          4          2          1          4          9          4          2\r\n\r\nvals\r\n[3 10 1 1]\r\n    0.9806     0.9675     0.9941     0.9787     0.9644     0.9676     0.9623     0.9048     0.8173     0.9033\r\n    0.7509     0.8962     0.8966     0.6244     0.9643     0.9092     0.9594     0.8738     0.8055     0.8891\r\n    0.6010     0.6450     0.7896     0.5349     0.8657     0.8865     0.8578     0.8567     0.7831     0.8040</pre>\r\n&nbsp;','ArrayFire v3.6 Released','','inherit','closed','closed','','9783-revision-v1','','','2018-05-03 17:31:35','2018-05-03 21:31:35','',9783,'https://sandbox.arrayfire.com/9783-revision-v1/',0,'revision','',0),(9796,17794,'2018-05-03 17:32:45','2018-05-03 21:32:45','Today we are announcing the release of ArrayFire version 3.6. The official binary installers can be downloaded here:\r\n\r\nhttps://sandbox.arrayfire.com/downloads\r\n\r\nWe added several new features that improve the performance and usability of the ArrayFire library. The main features are:\r\n<ul>\r\n 	<li>Support for batched matrix multiply</li>\r\n 	<li>Added the topk function</li>\r\n 	<li>Added the anisotropic diffusion filter</li>\r\n</ul>\r\nThe new batch functionality allows you to perform several matrix multiplication operations in one call of matmul. You might want to call this function if you are performing multiple smaller matrix multiplication operations. Here is an example:\r\n<pre class=\"lang:c++ decode:true\" title=\"Batched matrix multiply\">// Create a 3x3x2 matrix\r\narray a = randu(3, 3, 2);\r\narray b = randu(3, 3, 2);\r\n\r\narray c = matmul(a, b);\r\n</pre>\r\nThe example above is creating 2 3 by 3 matrices as a 3x3x2 volume for a and b. The matmul function then multiplies the slice of the a volume with the corresponding slice in b. Which this approach you can reach higher efficiencies with smaller matrices. Here is a benchmark for batched matmul on the NVIDIA Tesla V100.\r\n\r\n[caption id=\"attachment_9793\" align=\"aligncenter\" width=\"646\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2018/05/chart-1.png\"><img class=\"size-full wp-image-9793\" src=\"https://sandbox.arrayfire.com/wp-content/uploads/2018/05/chart-1.png\" alt=\"Batched Matrix Multiplication Performance\" width=\"646\" height=\"430\" /></a> Batched Matrix Multiplication Performance[/caption]\r\n\r\nThe batched matrix multiplication allows you to reach the maximum performance of your GPU with smaller matrix sizes. Larger matrices do not necessarily need to be batched to fully utilize the GPU.\r\n\r\nTopk is another exciting function that was added in this release. This function returns the top k maximum or minimum values in a vector or matrix along with their indices. Here is an example:\r\n<pre class=\"lang:c++ decode:true\" title=\"Topk Example\">array a = randu(10, 10); // Create a 10x10 matrix\r\n\r\narray idx, vals;\r\ntopk(vals, idx, a, 3); // Get the top 3 values of a</pre>\r\nHere we create a 10x8 matrix then call the topk function on it. Topk will return the top 3 indices and values. The indices are based on the values position in the given column. Here is a sample output:\r\n<pre class=\"lang:default decode:true\">a\r\n[10 8 1 1]\r\n    0.6010     0.1583     0.6755     0.5143     0.7917     0.9092     0.5970     0.9048 \r\n    0.0278     0.3712     0.6105     0.3670     0.1654     0.8865     0.9594     0.0198 \r\n    0.9806     0.3543     0.5232     0.3336     0.8657     0.9676     0.2323     0.4436 \r\n    0.2126     0.6450     0.5567     0.0363     0.3766     0.1425     0.9623     0.6808 \r\n    0.0655     0.9675     0.7896     0.5349     0.7331     0.5137     0.8578     0.6636 \r\n    0.5497     0.3636     0.8966     0.0123     0.2522     0.6484     0.0192     0.8738 \r\n    0.2864     0.4165     0.0536     0.3988     0.9644     0.6353     0.7191     0.3954 \r\n    0.3410     0.5814     0.5775     0.9787     0.4711     0.7449     0.4035     0.5277 \r\n    0.7509     0.8962     0.2908     0.2308     0.3637     0.4391     0.4692     0.3592 \r\n    0.4105     0.3712     0.9941     0.6244     0.9643     0.6982     0.3353     0.8567 \r\n\r\nidx\r\n[3 8 1 1]\r\n         2          4          9          7          6          2          3          0 \r\n         8          8          5          9          9          0          1          5 \r\n         0          3          4          4          2          1          4          9 \r\n\r\nvals\r\n[3 8 1 1]\r\n    0.9806     0.9675     0.9941     0.9787     0.9644     0.9676     0.9623     0.9048 \r\n    0.7509     0.8962     0.8966     0.6244     0.9643     0.9092     0.9594     0.8738 \r\n    0.6010     0.6450     0.7896     0.5349     0.8657     0.8865     0.8578     0.8567</pre>\r\n&nbsp;','ArrayFire v3.6 Released','','inherit','closed','closed','','9783-revision-v1','','','2018-05-03 17:32:45','2018-05-03 21:32:45','',9783,'https://sandbox.arrayfire.com/9783-revision-v1/',0,'revision','',0),(9797,17794,'2018-05-03 21:14:33','2018-05-04 01:14:33','Today we are announcing the release of ArrayFire version 3.6. The official binary installers can be downloaded here:\r\n\r\nhttps://sandbox.arrayfire.com/downloads\r\n\r\nWe added several new features that improve the performance and usability of the ArrayFire library. The main features are:\r\n<ul>\r\n 	<li>Support for batched matrix multiply</li>\r\n 	<li>Added the topk function</li>\r\n 	<li>Added the anisotropic diffusion filter</li>\r\n</ul>\r\nWe have also spent a significant amount of effort improving the internals of the library. The build system is significantly improved and organized.\r\n<h2>Batched Matrix Multiplication</h2>\r\nThe new batch functionality allows you to perform several matrix multiplication operations in one call of matmul. You might want to call this function if you are performing multiple smaller matrix multiplication operations. Here is an example:\r\n<pre class=\"lang:c++ decode:true\" title=\"Batched matrix multiply\">// Create a 3x3x2 matrix\r\narray a = randu(3, 3, 2);\r\narray b = randu(3, 3, 2);\r\n\r\narray c = matmul(a, b);\r\n</pre>\r\nThe example above is creating 2 3 by 3 matrices as a 3x3x2 volume for a and b. The matmul function then multiplies the slice of a volume with the corresponding slice in b. Which this approach you can reach higher efficiencies with smaller matrices. Here is a benchmark for batched matmul on the NVIDIA Tesla V100.\r\n\r\n[caption id=\"attachment_9793\" align=\"aligncenter\" width=\"646\"]<a href=\"https://sandbox.arrayfire.com/wp-content/uploads/2018/05/chart-1.png\"><img class=\"size-full wp-image-9793\" src=\"https://sandbox.arrayfire.com/wp-content/uploads/2018/05/chart-1.png\" alt=\"Batched Matrix Multiplication Performance\" width=\"646\" height=\"430\" /></a> Batched Matrix Multiplication Performance[/caption]\r\n\r\nThe batched matrix multiplication allows you to reach the maximum performance of your GPU with smaller matrix sizes. Larger matrices do not necessarily need to be batched to fully utilize the GPU.\r\n<h2>TopK</h2>\r\nTopk is another exciting function that was added in this release. This function returns the top k maximum or minimum values in a vector or matrix along with their indices. Here is an example:\r\n<pre class=\"lang:c++ decode:true\" title=\"Topk Example\">array in = randu(10, 10); // Create a 10x10 matrix\r\n\r\narray idx, vals;\r\ntopk(vals, idx, in, 3); // Get the top 3 values of a</pre>\r\nIn this example we create a 10x8 matrix which will be passed into the topk function. This function will return 2 matrices of size 3x8. The first matrix is composed of the top 3 maximum values. The second matrix is made up of the index of those values in the original matrix along that particular column.\r\n<pre class=\"lang:default decode:true\">in\r\n[10 8 1 1]\r\n    0.6010     0.1583     0.6755     0.5143     0.7917     0.9092     0.5970     0.9048 \r\n    0.0278     0.3712     0.6105     0.3670     0.1654     0.8865     0.9594     0.0198 \r\n    0.9806     0.3543     0.5232     0.3336     0.8657     0.9676     0.2323     0.4436 \r\n    0.2126     0.6450     0.5567     0.0363     0.3766     0.1425     0.9623     0.6808 \r\n    0.0655     0.9675     0.7896     0.5349     0.7331     0.5137     0.8578     0.6636 \r\n    0.5497     0.3636     0.8966     0.0123     0.2522     0.6484     0.0192     0.8738 \r\n    0.2864     0.4165     0.0536     0.3988     0.9644     0.6353     0.7191     0.3954 \r\n    0.3410     0.5814     0.5775     0.9787     0.4711     0.7449     0.4035     0.5277 \r\n    0.7509     0.8962     0.2908     0.2308     0.3637     0.4391     0.4692     0.3592 \r\n    0.4105     0.3712     0.9941     0.6244     0.9643     0.6982     0.3353     0.8567 \r\n\r\nvals\r\n[3 8 1 1]\r\n    0.9806     0.9675     0.9941     0.9787     0.9644     0.9676     0.9623     0.9048 \r\n    0.7509     0.8962     0.8966     0.6244     0.9643     0.9092     0.9594     0.8738 \r\n    0.6010     0.6450     0.7896     0.5349     0.8657     0.8865     0.8578     0.8567 \r\nidx\r\n[3 8 1 1]\r\n         2          4          9          7          6          2          3          0 \r\n         8          8          5          9          9          0          1          5 \r\n         0          3          4          4          2          1          4          9 \r\n\r\n</pre>\r\nThe topk function is optimized for small sizes of k(&lt;32). You could have implemented something like this in older versions of ArrayFire using a combination of sort and indexing. Here are some benchmarks comparing the two approaches.\r\n\r\n<img src=\"data:image/png;base64,[encoded data, 41732 characters]\" />\r\n\r\nFor smaller sizes topk is getting a 23x speedup over the sort and indexing approach. Note that the runtimes are on a log scale.\r\n<h2>Anisotropic Filtering</h2>\r\n&nbsp;','ArrayFire v3.6 Released','','inherit','closed','closed','','9783-revision-v1','','','2018-05-03 21:14:33','2018-05-04 01:14:33','',9783,'https://sandbox.arrayfire.com/9783-revision-v1/',0,'revision','',0),