Developing Android* Applications Using Parallel Programming

If you’ve been considering purchasing a new Android* smartphone, you may have noticed that many manufacturers boast about a large number of core processors in their Android* OS phones. How do you make sense of it all in order to make a good decision about which smart phone to buy? Since most Android applications are written in single-threaded mode, it’s important to tease apart the bottom line for the developer/purchaser. After considerable study on the parallel programming on Android, I decided to share the information for those of you who are concerned about the performance of your smartphone applications and how the programming for parallel programs impacts Android OS phone performance.

AsyncTask

Class AsyncTask provides an easy mechanism for moving labor-intensive operations to the background thread. Thanks to Class AsyncTask, you get the convenience of synchronization event handlers with a graphical flow that allows you to update the UI elements for the report on the implementation of tasks or to display the results when the task is completed.

However, you cannot work directly with the class AsyncTask; you will need to extend the functionality. Your implementation should include 3 classes of objects that will be passed as parameters; input parameters, notification of progress parameters, and variables that will store the result. Use the following format for AsyncTask:

  AsyncTask<[Input Parameter Type], [Progress Report Type], [Result Type]>

If you do not have to accept parameters to update information on the progress or final output, simply select the type Void in all three cases.

In AsyncTask, there are some basic methods that you need to master first. The primary one is the mandatory method doInBackground(). The rest are optional but used frequently.

  • doInBackground() – the main method that is executed in a new thread. It does not have access to the UI. Complex tasks must be coded in this method as the parameters defined in the implementation. This method is executed in a background thread, so there should be no interaction with the user interface elements.
  • publishProgress() method passes information to the onProgressUpdate()
  • onProgressUpdate() passes the changes to the user interface. When a background task is completed, this method returns the final result handler onPostExecute(), which will report it to the UI thread.
  • onPreExecute() – has access to the UI when run before doInBackground().
  • onPostExecute() – run after doInBackground(). This handler has access to the UI and uses it to update the UI as soon as your background task is completed. It is called when synchronized with the flow GUI so you can safely change the UI elements. It may not be called if the AsyncTask has been canceled.
  • onProgressUpdate – Has access to the UI. Override this handler to display the interim updates to the UI. When you call, it syncs with the flow GUI so you can safely change the UI elements.

Following is a simple example of using these methods implementing the matrix multiplication A (3x2) and matrix B (3x2).

Create a new project and a form to input the matrix items and the start button **:

<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android”
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <ScrollView
        android:id="@+id/scrollView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >
            
            <TextView
                android:id="@+id/titleA"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="16dp"
                android:text="@string/a"
                android:textAppearance="?android:attr/textAppearanceSmall" />

		    <LinearLayout
		        android:layout_width="match_parent"
		        android:layout_height="wrap_content" >

		        <EditText
		            android:id="@+id/a00"
		            android:layout_width="wrap_content"
		            android:layout_height="wrap_content"
		            android:layout_weight="1"
		            android:ems="3"
		            android:inputType="numberDecimal|numberSigned" />

		        <EditText
		            android:id="@+id/a01"
		            android:layout_width="wrap_content"
		            android:layout_height="wrap_content"
		            android:layout_weight="1"
		            android:ems="3"
		            android:inputType="numberDecimal|numberSigned" >

		            <requestFocus />
		        </EditText>

		    </LinearLayout>

		    <LinearLayout
		        android:layout_width="match_parent"
		        android:layout_height="wrap_content" >

		        <EditText
		            android:id="@+id/a10"
		            android:layout_width="wrap_content"
		            android:layout_height="wrap_content"
		            android:layout_weight="1"
		            android:ems="3"
		            android:inputType="numberDecimal|numberSigned" />

		        <EditText
		            android:id="@+id/a11"
		            android:layout_width="wrap_content"
		            android:layout_height="wrap_content"
		            android:layout_weight="1"
		            android:ems="3"
		            android:inputType="numberDecimal|numberSigned" />

		    </LinearLayout>

		    <LinearLayout
		        android:layout_width="match_parent"
		        android:layout_height="wrap_content" >

		        <EditText
		            android:id="@+id/a20"
		            android:layout_width="wrap_content"
		            android:layout_height="wrap_content"
		            android:layout_weight="1"
		            android:ems="3"
		            android:inputType="numberDecimal|numberSigned" />

		        <EditText
		            android:id="@+id/a21"
		            android:layout_width="wrap_content"
		            android:layout_height="wrap_content"
		            android:layout_weight="1"
		            android:ems="3"
		            android:inputType="numberDecimal|numberSigned" />

		    </LinearLayout>
		
		    <TextView
		        android:id="@+id/titleB"
		        android:layout_width="wrap_content"
		        android:layout_height="wrap_content"
		        android:layout_marginTop="15dp"
		        android:text="@string/b"
		        android:textAppearance="?android:attr/textAppearanceSmall" />

		    <LinearLayout
		        android:layout_width="match_parent"
		        android:layout_height="wrap_content" >

		        <EditText
		            android:id="@+id/b00"
		            android:layout_width="wrap_content"
		            android:layout_height="wrap_content"
		            android:layout_weight="1"
		            android:ems="3"
		            android:inputType="numberDecimal|numberSigned" />

		        <EditText
		            android:id="@+id/b01"
		            android:layout_width="wrap_content"
		            android:layout_height="wrap_content"
		            android:layout_weight="1"
		            android:ems="3"
		            android:inputType="numberDecimal|numberSigned" />

		        <EditText
		            android:id="@+id/b02"
		            android:layout_width="wrap_content"
		            android:layout_height="wrap_content"
		            android:layout_weight="1"
		            android:ems="3"
		            android:inputType="numberDecimal|numberSigned" />

		    </LinearLayout>

		    <LinearLayout
		        android:layout_width="match_parent"
		        android:layout_height="wrap_content" >

		        <EditText
		            android:id="@+id/b10"
		            android:layout_width="wrap_content"
		            android:layout_height="wrap_content"
		            android:layout_weight="1"
		            android:ems="3"
		            android:inputType="numberDecimal|numberSigned" />

		        <EditText
		            android:id="@+id/b11"
		            android:layout_width="wrap_content"
		            android:layout_height="wrap_content"
		            android:layout_weight="1"
		            android:ems="3"
		            android:inputType="numberDecimal|numberSigned" />

		        <EditText
		            android:id="@+id/b12"
		            android:layout_width="wrap_content"
		            android:layout_height="wrap_content"
		            android:layout_weight="1"
		            android:ems="3"
		            android:inputType="numberDecimal|numberSigned" />

		    </LinearLayout>

		    <Button
		        android:id="@+id/button"
		        style="?android:attr/buttonStyleSmall"
		        android:layout_width="wrap_content"
		        android:layout_height="wrap_content"
		        android:layout_marginTop="17dp"
		        android:text="@string/button" />

		    <TextView
		        android:id="@+id/titleC"
		        android:layout_width="wrap_content"
		        android:layout_height="wrap_content"
		        android:text="@string/c"
		        android:textAppearance="?android:attr/textAppearanceSmall" />

		    <LinearLayout
		        android:layout_width="match_parent"
		        android:layout_height="wrap_content" >

		        <TextView
		            android:id="@+id/c00"
		            android:layout_width="70dp"
		            android:layout_height="wrap_content"
		            android:textAppearance="?android:attr/textAppearanceSmall" />

		        <TextView
		            android:id="@+id/c01"
		            android:layout_width="70dp"
		            android:layout_height="wrap_content"
		            android:textAppearance="?android:attr/textAppearanceSmall" />

		        <TextView
		            android:id="@+id/c02"
		            android:layout_width="70dp"
		            android:layout_height="wrap_content"
		            android:textAppearance="?android:attr/textAppearanceSmall" />

		    </LinearLayout>

		    <LinearLayout
		        android:layout_width="match_parent"
		        android:layout_height="wrap_content" >

		        <TextView
		            android:id="@+id/c10"
		            android:layout_width="70dp"
		            android:layout_height="wrap_content"
		            android:textAppearance="?android:attr/textAppearanceSmall" />

		        <TextView
		            android:id="@+id/c11"
		            android:layout_width="70dp"
		            android:layout_height="wrap_content"
		            android:textAppearance="?android:attr/textAppearanceSmall" />

		        <TextView
		            android:id="@+id/c12"
		            android:layout_width="70dp"
		            android:layout_height="wrap_content"
		            android:textAppearance="?android:attr/textAppearanceSmall" />

		    </LinearLayout>

		    <LinearLayout
		        android:layout_width="match_parent"
		        android:layout_height="wrap_content" >

		        <TextView
		            android:id="@+id/c20"
		            android:layout_width="70dp"
		            android:layout_height="wrap_content"
		            android:layout_marginBottom="40dp"
		            android:textAppearance="?android:attr/textAppearanceSmall" />

		        <TextView
		            android:id="@+id/c21"
		            android:layout_width="70dp"
		            android:layout_height="wrap_content"
		            android:textAppearance="?android:attr/textAppearanceSmall" />

		        <TextView
		            android:id="@+id/c22"
		            android:layout_width="70dp"
		            android:layout_height="wrap_content"
		            android:textAppearance="?android:attr/textAppearanceSmall" />

		    </LinearLayout>
            
        </LinearLayout>
    </ScrollView>

</RelativeLayout>

And file strings.xml **:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">Matrix AsyncTask Multiplication</string>
    <string name="a">A:</string>
    <string name="b">B:</string>
    <string name="c">C:</string>
    <string name="button">A x B = C</string>

</resources>

Pressing the button will start the specified number of processes that will calculate the product of two matrices.

The following is a separate class, which will implement an asynchronous task **:

package com.example.matrixmultiplicationasynctask;

import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;

public class MultThread extends AsyncTask<void, void=""> {
	private int row;
	private int col;
	private double A[][];
	private double B[][];
	private double C[][];
	private Context context;
	
	public MultThread(int row, int col, double A[][], double B[][], double C[][], Context context)
	{
	    this.row = row;
	    this.col = col;
	    this.A = A;
	    this.B = B;
	    this.C = C;
	    this.context = context;
	}
	
	@Override
	protected void onPreExecute() {
		super.onPreExecute();
		Toast.makeText(context, "Start row = " + String.valueOf(row) + ", col = " + String.valueOf(col), Toast.LENGTH_SHORT).show();
	}

	@Override
	protected Void doInBackground(Void... params) {
		for(int i = 0; i < B.length; ++i)
	    {
			C[row][col] += A[row][i] * B[i][col];
	    }
		return null;
	}
	
	@Override
	protected void onPostExecute(Void result) {
		super.onPostExecute(result);
		Toast.makeText(context, "End row = " + String.valueOf(row) + ", col = " + String.valueOf(col), Toast.LENGTH_SHORT).show();
	}
}

We have passed coordinates, 3 matrices and a context parameter to display a message in the Main Task Activity program.

Here is the Java code for MainActivity **:

package com.example.matrixmultiplicationasynctask;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.*;

public class MainActivity extends Activity {

	private EditText matrixA [][] = new EditText[3][2];
	private EditText matrixB [][] = new EditText[2][3];
	private TextView matrixC [][] = new TextView[3][3];
	private TextView titleC;
	private Button mult;
	MultThread async [] = new MultThread[9];
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initA();
		initB();
		initC();
		mult = (Button) findViewById(R.id.button);
		mult.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				setVisibleC(true);
				double [][] a = getA();
				double [][] b = getB();
				if (a == null || b == null) {
					Toast.makeText(getBaseContext(), "Unknown error!", Toast.LENGTH_SHORT).show();
					return;
				}
				double [][] c = new double [3][3];
				int runTasks = 0;
				for (int i = 0; i < 3; ++i) {
					for (int j = 0; j < 3; ++j) {
						async[runTasks] = new MultThread(i, j, a, b, c, getBaseContext());
						async[runTasks].execute();
						runTasks++;
					}
				}
				setC(c);
				setVisibleC(true);
			}
		});
		setVisibleC(false);
	}
	private void initA() {
		matrixA[0][0] = (EditText) findViewById(R.id.a00);
		matrixA[0][1] = (EditText) findViewById(R.id.a01);
		matrixA[1][0] = (EditText) findViewById(R.id.a10);
		matrixA[1][1] = (EditText) findViewById(R.id.a11);
		matrixA[2][0] = (EditText) findViewById(R.id.a20);
		matrixA[2][1] = (EditText) findViewById(R.id.a21);
	}
	private void initB() {
		matrixB[0][0] = (EditText) findViewById(R.id.b00);
		matrixB[0][1] = (EditText) findViewById(R.id.b01);
		matrixB[0][2] = (EditText) findViewById(R.id.b02);
		matrixB[1][0] = (EditText) findViewById(R.id.b10);
		matrixB[1][1] = (EditText) findViewById(R.id.b11);
		matrixB[1][2] = (EditText) findViewById(R.id.b12);
	}
	private void initC() {
		titleC = (TextView) findViewById(R.id.titleC);
		matrixC[0][0] = (TextView) findViewById(R.id.c00);
		matrixC[0][1] = (TextView) findViewById(R.id.c01);
		matrixC[0][2] = (TextView) findViewById(R.id.c02);
		matrixC[1][0] = (TextView) findViewById(R.id.c10);
		matrixC[1][1] = (TextView) findViewById(R.id.c11);
		matrixC[1][2] = (TextView) findViewById(R.id.c12);
		matrixC[2][0] = (TextView) findViewById(R.id.c20);
		matrixC[2][1] = (TextView) findViewById(R.id.c21);
		matrixC[2][2] = (TextView) findViewById(R.id.c22);
	}
	private double[][] getA() {
		double [][] ret = new double [matrixA.length][];
		for (int i = 0; i < matrixA.length; ++i) {
			ret[i] = new double [matrixA[i].length];
			for (int j = 0; j < matrixA[i].length; ++j) {
				if (matrixA[i][j].getText().toString().length() == 0) {
					Toast.makeText(getBaseContext(), "Error! One field is empty!", Toast.LENGTH_SHORT).show();
					return null;
				}
				ret[i][j] = Double.parseDouble(matrixA[i][j].getText().toString());
			}
		}
		return ret;
	}
	private double[][] getB() {
		double [][] ret = new double [matrixB.length][];
		for (int i = 0; i < matrixB.length; ++i) {
			ret[i] = new double [matrixB[i].length];
			for (int j = 0; j < matrixB[i].length; ++j) {
				if (matrixB[i][j].getText().toString().length() == 0) {
					Toast.makeText(getBaseContext(), "Error! One field is empty!", Toast.LENGTH_SHORT).show();
					return null;
				}
				ret[i][j] = Double.parseDouble(matrixB[i][j].getText().toString());
			}
		}
		return ret;
	}
	private void setC(double [][] cVal) {
		if (matrixC.length != cVal.length) {
			Toast.makeText(getBaseContext(), "Unknown error!", Toast.LENGTH_SHORT).show();
			return;
		}
		for (int i = 0; i < matrixC.length; ++i) {
			if (matrixC[i].length != cVal[i].length) {
				Toast.makeText(getBaseContext(), "Unknown error!", Toast.LENGTH_SHORT).show();
				return;
			}
			for (int j = 0; j < matrixC[i].length; ++j) {
				matrixC[i][j].setText(String.valueOf(cVal[i][j]));
			}
		}
	}
	private void setVisibleC(boolean cond) {
		if (cond == true)
			titleC.setVisibility(View.VISIBLE);
		else 
			titleC.setVisibility(View.GONE);
		for (int i = 0; i < matrixC.length; ++i) {
			for (int j = 0; j < matrixC[i].length; ++j) {
				if (cond == true) {
					matrixC[i][j].setVisibility(View.VISIBLE);
				}
				else {
					matrixC[i][j].setVisibility(View.GONE);
				}
			}
		}
	}

}

Using the method execute(), to start execution of an asynchronous task. At the end of the matrix computing method setC(double[][]), set the value of the matrix by the method setVisibleC(true), which shows this matrix on the display.

Thread

Follow the same method for the implementation of a multi-threaded interaction. You can use a standard Java class: Thread. We will write our program using the class Thread. Files strings.xml and main_activity.xml while following the previous example, with Class and the implementation of actions to be performed as follows **:

package com.example.threadtest;

public class MultThread implements Runnable {
	private int row;
	private int col;
	private double A[][];
	private double B[][];
	private double C[][];
	
	public MultThread(int row, int col, double A[][], double B[][], double C[][] )
	{
	    this.row = row;
	    this.col = col;
	    this.A = A;
	    this.B = B;
	    this.C = C;
	}
	   
	@Override
	public void run()
	{
		for(int i = 0; i < B.length; ++i)
	    {
			C[row][col] += A[row][i] * B[i][col];
	    }
	}
}

The principle of operation is the same as in the first example where we pased the coordinates and three matrices. There is no context parameter because we will not be displaying anything in the GUI through streams. A Java implementation class for the main Activity will be as follows **:

package com.example.threadtest;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.*;

public class MainActivity extends Activity {

	private EditText matrixA [][] = new EditText[3][2];
	private EditText matrixB [][] = new EditText[2][3];
	private TextView matrixC [][] = new TextView[3][3];
	private TextView titleC;
	private Button mult;
	Thread threads [] = new Thread[9];
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initA();
		initB();
		initC();
		mult = (Button) findViewById(R.id.button);
		mult.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				setVisibleC(true);
				double [][] a = getA();
				double [][] b = getB();
				if (a == null || b == null) {
					Toast.makeText(getBaseContext(), "Unknown error!", Toast.LENGTH_SHORT).show();
					return;
				}
				double [][] c = new double [3][3];
				int runThreads = 0;
				for (int i = 0; i < 3; ++i) {
					for (int j = 0; j < 3; ++j) {
						threads[runThreads] = new Thread(new MultThread(i, j, a, b, c));
						threads[runThreads].start();
						runThreads++;
					}
				}
				
				for (int i = 0; i < runThreads; ++i) {
					try {
						threads[i].join();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
				setC(c);
				setVisibleC(true);
			}
		});
		setVisibleC(false);
	}
	private void initA() {
		matrixA[0][0] = (EditText) findViewById(R.id.a00);
		matrixA[0][1] = (EditText) findViewById(R.id.a01);
		matrixA[1][0] = (EditText) findViewById(R.id.a10);
		matrixA[1][1] = (EditText) findViewById(R.id.a11);
		matrixA[2][0] = (EditText) findViewById(R.id.a20);
		matrixA[2][1] = (EditText) findViewById(R.id.a21);
	}
	private void initB() {
		matrixB[0][0] = (EditText) findViewById(R.id.b00);
		matrixB[0][1] = (EditText) findViewById(R.id.b01);
		matrixB[0][2] = (EditText) findViewById(R.id.b02);
		matrixB[1][0] = (EditText) findViewById(R.id.b10);
		matrixB[1][1] = (EditText) findViewById(R.id.b11);
		matrixB[1][2] = (EditText) findViewById(R.id.b12);
	}
	private void initC() {
		titleC = (TextView) findViewById(R.id.titleC);
		matrixC[0][0] = (TextView) findViewById(R.id.c00);
		matrixC[0][1] = (TextView) findViewById(R.id.c01);
		matrixC[0][2] = (TextView) findViewById(R.id.c02);
		matrixC[1][0] = (TextView) findViewById(R.id.c10);
		matrixC[1][1] = (TextView) findViewById(R.id.c11);
		matrixC[1][2] = (TextView) findViewById(R.id.c12);
		matrixC[2][0] = (TextView) findViewById(R.id.c20);
		matrixC[2][1] = (TextView) findViewById(R.id.c21);
		matrixC[2][2] = (TextView) findViewById(R.id.c22);
	}
	private double[][] getA() {
		double [][] ret = new double [matrixA.length][];
		for (int i = 0; i < matrixA.length; ++i) {
			ret[i] = new double [matrixA[i].length];
			for (int j = 0; j < matrixA[i].length; ++j) {
				if (matrixA[i][j].getText().toString().length() == 0) {
					Toast.makeText(getBaseContext(), "Error! One field is empty!", Toast.LENGTH_SHORT).show();
					return null;
				}
				ret[i][j] = Double.parseDouble(matrixA[i][j].getText().toString());
			}
		}
		return ret;
	}
	private double[][] getB() {
		double [][] ret = new double [matrixB.length][];
		for (int i = 0; i < matrixB.length; ++i) {
			ret[i] = new double [matrixB[i].length];
			for (int j = 0; j < matrixB[i].length; ++j) {
				if (matrixB[i][j].getText().toString().length() == 0) {
					Toast.makeText(getBaseContext(), "Error! One field is empty!", Toast.LENGTH_SHORT).show();
					return null;
				}
				ret[i][j] = Double.parseDouble(matrixB[i][j].getText().toString());
			}
		}
		return ret;
	}
	private void setC(double [][] cVal) {
		if (matrixC.length != cVal.length) {
			Toast.makeText(getBaseContext(), "Unknown error!", Toast.LENGTH_SHORT).show();
			return;
		}
		for (int i = 0; i < matrixC.length; ++i) {
			if (matrixC[i].length != cVal[i].length) {
				Toast.makeText(getBaseContext(), "Unknown error!", Toast.LENGTH_SHORT).show();
				return;
			}
			for (int j = 0; j < matrixC[i].length; ++j) {
				matrixC[i][j].setText(String.valueOf(cVal[i][j]));
			}
		}
	}
	private void setVisibleC(boolean cond) {
		if (cond == true)
			titleC.setVisibility(View.VISIBLE);
		else 
			titleC.setVisibility(View.GONE);
		for (int i = 0; i < matrixC.length; ++i) {
			for (int j = 0; j < matrixC[i].length; ++j) {
				if (cond == true) {
					matrixC[i][j].setVisibility(View.VISIBLE);
				}
				else {
					matrixC[i][j].setVisibility(View.GONE);
				}
			}
		}
	}

}

The only thing that has changed is that we have created an array of threads and run them using the start () and then waited until they are completed, using join ().

In conclusion, we have considered two program parallelization methods: (1) the class Thread allows running tasks in a separate thread, but does not allow us to receive any information about the work flow, and (2) class AsyncTask gives us this opportunity.

These two programs can be downloaded [ThreadTest.zip] and [AsyncTask.zip].

About the Author

Egor Churaev is a software intern in the client CRT. He is from Nizhny Novgorod, Russia.

Notices

INFORMATION IN THIS DOCUMENT IS PROVIDED IN CONNECTION WITH INTEL PRODUCTS. NO LICENSE, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, TO ANY INTELLECTUAL PROPERTY RIGHTS IS GRANTED BY THIS DOCUMENT. EXCEPT AS PROVIDED IN INTEL'S TERMS AND CONDITIONS OF SALE FOR SUCH PRODUCTS, INTEL ASSUMES NO LIABILITY WHATSOEVER AND INTEL DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY, RELATING TO SALE AND/OR USE OF INTEL PRODUCTS INCLUDING LIABILITY OR WARRANTIES RELATING TO FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR INFRINGEMENT OF ANY PATENT, COPYRIGHT OR OTHER INTELLECTUAL PROPERTY RIGHT.

UNLESS OTHERWISE AGREED IN WRITING BY INTEL, THE INTEL PRODUCTS ARE NOT DESIGNED NOR INTENDED FOR ANY APPLICATION IN WHICH THE FAILURE OF THE INTEL PRODUCT COULD CREATE A SITUATION WHERE PERSONAL INJURY OR DEATH MAY OCCUR.

Intel may make changes to specifications and product descriptions at any time, without notice. Designers must not rely on the absence or characteristics of any features or instructions marked "reserved" or "undefined." Intel reserves these for future definition and shall have no responsibility whatsoever for conflicts or incompatibilities arising from future changes to them. The information here is subject to change without notice. Do not finalize a design with this information.

The products described in this document may contain design defects or errors known as errata which may cause the product to deviate from published specifications. Current characterized errata are available on request.

Contact your local Intel sales office or your distributor to obtain the latest specifications and before placing your product order.

Copies of documents that have an order number and are referenced in this document or other Intel literature may be obtained by calling 1-800-548-4725 or going to http://www.intel.com/design/literature.htm

Software and workloads used in performance tests may have been optimized for performance only on Intel microprocessors. Performance tests, such as SYSmark* and MobileMark*, are measured using specific computer systems, components, software, operations, and functions. Any change to any of those factors may cause the results to vary. You should consult other information and performance tests to assist you in fully evaluating your contemplated purchases, including the performance of that product when combined with other products.

Any software source code reprinted in this document is furnished under a software license and may only be used or copied in accordance with the terms of that license.

Intel, the Intel logo, and VTune are trademarks of Intel Corporation in the U.S. and/or other countries.
*Other names and brands may be claimed as the property of others.
** This sample source code is released under the Intel Sample Source Code License Agreement
Copyright ©2014 Intel Corporation. All rights reserved.