In this post we will be looking at benchmarks of the following ArrayFire image processing functions on an ARM device.
<ul>
	<li><a href="http://www.sandbox.arrayfire.com/docs/group__morph__mat.htm">Erosion/Dilation</a></li>
	<li><a href="http://www.sandbox.arrayfire.com/docs/group__image__func__cpp__medfilt.htm">Median filter</a></li>
	<li><a href="http://www.sandbox.arrayfire.com/docs/group__image__func__cpp__resize.htm">Resize</a></li>
	<li><a href="http://www.sandbox.arrayfire.com/docs/group__image__func__cpp__histogram.htm">Histogram</a></li>
	<li><a href="http://www.sandbox.arrayfire.com/docs/group__image__func__cpp__bilateral.htm">Bilateral filter</a></li>
	<li><a href="http://www.sandbox.arrayfire.com/docs/group__signal__func__cpp__convolve.htm">Convolution</a></li>
</ul>
We pitted the brand new compute 3.2 GPU on NVIDIA Jetson TK1 against a mobile NVIDIA GPU. The closest match to the GPU (from here on referred as TK1) on the Jetson board we have in our mobile card deck is a NVIDIA GT 650M. The GPU device properties that have critical effect on the function performance are listed below.
<table>
<thead>
<tr class="header">
<th style="text-align: left;">Property Name / Device Name</th>
<th style="text-align: left;">Jetson TK1 GK20A</th>
<th style="text-align: left;">GT 650M</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Compute</td>
<td style="text-align: left;">3.2</td>
<td style="text-align: left;">3.0</td>
</tr>
<tr class="even">
<td style="text-align: left;">Number of multiprocessors</td>
<td style="text-align: left;">1</td>
<td style="text-align: left;">2</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Cores</td>
<td style="text-align: left;">192</td>
<td style="text-align: left;">384</td>
</tr>
<tr class="even">
<td style="text-align: left;">Base clock rate</td>
<td style="text-align: left;">852 MHz</td>
<td style="text-align: left;">950 MHz</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Total global memory</td>
<td style="text-align: left;">1746 MB</td>
<td style="text-align: left;">2048 MB</td>
</tr>
<tr class="even">
<td style="text-align: left;">Total shared memory per block</td>
<td style="text-align: left;">48 KB</td>
<td style="text-align: left;">48 KB</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Total constant memory</td>
<td style="text-align: left;">64 KB</td>
<td style="text-align: left;">64KB</td>
</tr>
<tr class="even">
<td style="text-align: left;">Memory clock rate</td>
<td style="text-align: left;">924 MHz</td>
<td style="text-align: left;">900 MHz</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Memory bus width</td>
<td style="text-align: left;">64-bit</td>
<td style="text-align: left;">128-bit</td>
</tr>
<tr class="even">
<td style="text-align: left;">Total registers per block</td>
<td style="text-align: left;">32768</td>
<td style="text-align: left;">65536</td>
</tr>
<tr class="odd">
<td style="text-align: left;">Warp size</td>
<td style="text-align: left;">32</td>
<td style="text-align: left;">32</td>
</tr>
</tbody>
</table>
<h3 id="benchmarks">Benchmarks</h3>
Images with the the following resolutions are used for benchmarks.
<ul>
	<li>480p (720x480)</li>
	<li>720p and 1080p HD</li>
	<li>4K and 8K UHD</li>
</ul>
Note that the vertical axis (Frames per second) in all of the plots is on log scale. The higher the value along the vertical axis, the better the run times are for that function on a given device.
<h4 id="erosiondilation">Erosion/Dilation</h4>
<iframe src="//docs.google.com/a/sandbox.arrayfire.com/spreadsheets/d/1HMKSexMq_G8o8OKtVYq6lpuoezDVNJ2JwNfOS_h-5u8/gviz/chartiframe?oid=1799759820" width="792" height="563" frameborder="0" scrolling="no" seamless=""></iframe>

A 3x3 mask was used to benchmark <a href="http://www.sandbox.arrayfire.com/docs/group__morph__mat.htm"><code>erode</code></a> function. Dilate results will be similar to erode because they use the same algorithm with a different local neighborhood operator.
<h4 id="median-filter">Median Filter</h4>
<iframe src="//docs.google.com/a/sandbox.arrayfire.com/spreadsheets/d/1HMKSexMq_G8o8OKtVYq6lpuoezDVNJ2JwNfOS_h-5u8/gviz/chartiframe?oid=629321992" width="794" height="561" frameborder="0" scrolling="no" seamless=""></iframe>

A 3x3 mask was used to benchmark <a href="http://www.sandbox.arrayfire.com/docs/group__image__func__cpp__medfilt.htm"><code>medfilt</code></a> function as well.
<h4 id="resize">Resize</h4>
<iframe src="//docs.google.com/a/sandbox.arrayfire.com/spreadsheets/d/1HMKSexMq_G8o8OKtVYq6lpuoezDVNJ2JwNfOS_h-5u8/gviz/chartiframe?oid=1318972511" width="793" height="561" frameborder="0" scrolling="no" seamless=""></iframe>

We benchmarked <a href="http://www.sandbox.arrayfire.com/docs/group__image__func__cpp__resize.htm"><code>resize</code></a> for halving the image size.
<h4 id="histogram">Histogram</h4>
<iframe src="//docs.google.com/a/sandbox.arrayfire.com/spreadsheets/d/1HMKSexMq_G8o8OKtVYq6lpuoezDVNJ2JwNfOS_h-5u8/gviz/chartiframe?oid=12968102" width="794" height="566" frameborder="0" scrolling="no" seamless=""></iframe>

Standard 256 bin <code><a href="http://www.sandbox.arrayfire.com/docs/group__image__func__cpp__histogram.htm">histogram</a>.</code>
<h4 id="bilateral-filter">Bilateral filter</h4>
<iframe src="//docs.google.com/a/sandbox.arrayfire.com/spreadsheets/d/1HMKSexMq_G8o8OKtVYq6lpuoezDVNJ2JwNfOS_h-5u8/gviz/chartiframe?oid=528280719" width="792" height="560" frameborder="0" scrolling="no" seamless=""></iframe>

We used 3.5 (7x7 window) spatial variance and 50 chromatic variance to benchmark <a href="http://www.sandbox.arrayfire.com/docs/group__image__func__cpp__bilateral.htm"><code>bilateral</code></a> function.
<h4 id="convolution">Convolution</h4>
<iframe src="//docs.google.com/a/sandbox.arrayfire.com/spreadsheets/d/1HMKSexMq_G8o8OKtVYq6lpuoezDVNJ2JwNfOS_h-5u8/gviz/chartiframe?oid=905426513" width="795" height="563" frameborder="0" scrolling="no" seamless=""></iframe>

A 5x5 blur kernel was used to benchmark <a href="http://www.sandbox.arrayfire.com/docs/group__signal__func__cpp__convolve.htm"><code>convolve</code></a> function.
<h3>Conclusion</h3>
<ul>
	<li><code>erode</code>, <code>resize</code> and <code>conv</code> run in real time for all resolutions except 8K UHD.</li>
	<li><code>medfilt</code> runs in real time until 1080p HD resolution and falls to interactive rates for 4K UHD.</li>
	<li><code>bilateral</code> runs in real time until 1080p HD resolution and falls to 8 fps for 4k UHD.</li>
	<li><code>histogram</code> run times are good enough for it to be used in any photo editing software without noticing any lag for generating image histograms.</li>
</ul>
There are a plethora of other image processing functions available in ArrayFire. You can find the complete list of the functions available in our documentation <a href="http://www.sandbox.arrayfire.com/docs/group__image__mat.htm">here</a>. The main take away point from this post is that we can easily do image processing in real time using Jetson TK1 for up to 4k UHD resolution.

If you want to try out ArrayFire on your Jetson TK1, please contact us at sales@arrayfire.com.

<h4> Update </h4>

We've released ArrayFire for Jetson TK1. You can <a href="http://sandbox.arrayfire.com/download">download