blob: 51b7441a5602eae4a3ce6a1da1298fdc308150a5 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.rs.blasbenchmark;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import android.view.View;
import android.graphics.Point;
import android.view.WindowManager;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.renderscript.ScriptC;
import android.renderscript.RenderScript;
import android.renderscript.Type;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.Script;
public class BlasBenchmark extends Activity {
private final String TAG = "BLAS";
public final String RESULT_FILE = "blas_benchmark_result.csv";
private int mTestList[];
private float mTestResults[];
private String mTestInfo[];
private TextView mTextView;
private boolean mToggleLong;
private boolean mTogglePause;
// In demo mode this is used to count updates in the pipeline. It's
// incremented when work is submitted to RS and decremented when invalidate is
// called to display a result.
private boolean mDemoMode;
// Initialize the parameters for Instrumentation tests.
protected void prepareInstrumentationTest() {
mTestList = new int[1];
mTestResults = new float[1];
mTestInfo = new String[1];
mDemoMode = false;
mProcessor = new Processor(RenderScript.create(this), !mDemoMode);
}
/////////////////////////////////////////////////////////////////////////
// Processor is a helper thread for running the work without
// blocking the UI thread.
class Processor extends Thread {
RenderScript mRS;
private float mLastResult;
private boolean mRun = true;
private boolean mDoingBenchmark;
private TestBase mTest;
private boolean mBenchmarkMode;
void runTest() {
mTest.runTest();
}
Processor(RenderScript rs, boolean benchmarkMode) {
mRS = rs;
mBenchmarkMode = benchmarkMode;
}
class Result {
float totalTime;
int iterations;
String testInfo;
}
// Method to retreive benchmark results for instrumentation tests.
float getInstrumentationResult(BlasTestList.TestName t) {
mTest = changeTest(t, false);
Result r = getBenchmark();
return r.totalTime / r.iterations * 1000.f;
}
// Run one loop of kernels for at least the specified minimum time.
// The function returns the average time in ms for the test run
private Result runBenchmarkLoop(float minTime) {
Result r = new Result();
long t = java.lang.System.currentTimeMillis();
r.testInfo = mTest.getTestInfo();
do {
// Run the kernel
mTest.runTest();
r.iterations ++;
long t2 = java.lang.System.currentTimeMillis();
r.totalTime += (t2 - t) / 1000.f;
t = t2;
} while (r.totalTime < minTime);
// Wait for any stray operations to complete and update the final time
mRS.finish();
long t2 = java.lang.System.currentTimeMillis();
r.totalTime += (t2 - t) / 1000.f;
t = t2;
return r;
}
// Get a benchmark result for a specific test
private Result getBenchmark() {
mDoingBenchmark = true;
long result = 0;
float runtime = 1.f;
if (mToggleLong) {
runtime = 10.f;
}
// We run a short bit of work before starting the actual test
// this is to let any power management do its job and respond
runBenchmarkLoop(0.3f);
// Run the actual benchmark
Result r = runBenchmarkLoop(runtime);
Log.v("rs", "Test: time=" + r.totalTime +"s, iterations=" + r.iterations +
", avg=" + r.totalTime / r.iterations * 1000.f + " " + r.testInfo);
mDoingBenchmark = false;
return r;
}
public void run() {
while (mRun) {
// Our loop for launching tests or benchmarks
synchronized(this) {
// We may have been asked to exit while waiting
if (!mRun) return;
}
if (mBenchmarkMode) {
// Loop over the tests we want to benchmark
for (int ct=0; (ct < mTestList.length) && mRun; ct++) {
// For reproducibility we wait a short time for any sporadic work
// created by the user touching the screen to launch the test to pass.
// Also allows for things to settle after the test changes.
mRS.finish();
try {
sleep(250);
} catch(InterruptedException e) {
}
// If we just ran a test, we destroy it here to relieve some memory pressure
if (mTest != null) {
mTest.destroy();
}
// Select the next test
mTest = changeTest(mTestList[ct], false);
// If the user selected the "long pause" option, wait
if (mTogglePause) {
for (int i=0; (i < 100) && mRun; i++) {
try {
sleep(100);
} catch(InterruptedException e) {
}
}
}
// Run the test
Result r = getBenchmark();
mTestResults[ct] = r.totalTime / r.iterations * 1000.f;
mTestInfo[ct] = r.testInfo;
}
onBenchmarkFinish(mRun);
} else {
// Run the kernel
runTest();
}
}
}
public void exit() {
mRun = false;
synchronized(this) {
notifyAll();
}
try {
this.join();
} catch(InterruptedException e) {
}
if (mTest != null) {
mTest.destroy();
mTest = null;
}
mRS.destroy();
mRS = null;
}
}
private boolean mDoingBenchmark;
public Processor mProcessor;
TestBase changeTest(BlasTestList.TestName t, boolean setupUI) {
TestBase tb = BlasTestList.newTest(t);
tb.createBaseTest(this);
return tb;
}
TestBase changeTest(int id, boolean setupUI) {
BlasTestList.TestName t = BlasTestList.TestName.values()[id];
return changeTest(t, setupUI);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView textView = new TextView(this);
textView.setTextSize(20);
textView.setText("BLAS BenchMark Running.");
setContentView(textView);
}
@Override
protected void onPause() {
super.onPause();
if (mProcessor != null) {
mProcessor.exit();
}
}
public void onBenchmarkFinish(boolean ok) {
if (ok) {
Intent intent = new Intent();
intent.putExtra("tests", mTestList);
intent.putExtra("results", mTestResults);
intent.putExtra("testinfo", mTestInfo);
setResult(RESULT_OK, intent);
} else {
setResult(RESULT_CANCELED);
}
finish();
}
@Override
protected void onResume() {
super.onResume();
Intent i = getIntent();
mTestList = i.getIntArrayExtra("tests");
mToggleLong = i.getBooleanExtra("enable long", false);
mTogglePause = i.getBooleanExtra("enable pause", false);
mDemoMode = i.getBooleanExtra("demo", false);
if (mTestList != null) {
mTestResults = new float[mTestList.length];
mTestInfo = new String[mTestList.length];
mProcessor = new Processor(RenderScript.create(this), !mDemoMode);
if (mDemoMode) {
mProcessor.mTest = changeTest(mTestList[0], true);
}
mProcessor.start();
}
}
protected void onDestroy() {
super.onDestroy();
}
}