1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.benchmark.synthetic; 18 19 import android.view.View; 20 import android.widget.TextView; 21 22 import org.apache.commons.math.stat.StatUtils; 23 import org.apache.commons.math.stat.descriptive.SummaryStatistics; 24 25 import java.util.LinkedList; 26 import java.util.Queue; 27 28 29 public class TestInterface { nInit(long options)30 native long nInit(long options); nDestroy(long b)31 native long nDestroy(long b); nGetData(long b, float[] data)32 native float nGetData(long b, float[] data); nRunPowerManagementTest(long b, long options)33 native boolean nRunPowerManagementTest(long b, long options); nRunCPUHeatSoakTest(long b, long options)34 native boolean nRunCPUHeatSoakTest(long b, long options); 35 nMemTestStart(long b)36 native boolean nMemTestStart(long b); nMemTestBandwidth(long b, long size)37 native float nMemTestBandwidth(long b, long size); nMemTestLatency(long b, long size)38 native float nMemTestLatency(long b, long size); nMemTestEnd(long b)39 native void nMemTestEnd(long b); 40 nGFlopsTest(long b, long opt)41 native float nGFlopsTest(long b, long opt); 42 43 public static class TestResultCallback { onTestResult(int command, float result)44 void onTestResult(int command, float result) { } 45 } 46 47 static { 48 System.loadLibrary("nativebench"); 49 } 50 51 float[] mLinesLow; 52 float[] mLinesHigh; 53 float[] mLinesValue; 54 TextView mTextStatus; 55 TextView mTextMin; 56 TextView mTextMax; 57 TextView mTextTypical; 58 59 private View mViewToUpdate; 60 61 private LooperThread mLT; 62 TestInterface(View v, int runtimeSeconds, TestResultCallback callback)63 TestInterface(View v, int runtimeSeconds, TestResultCallback callback) { 64 int buckets = runtimeSeconds * 1000; 65 mLinesLow = new float[buckets * 4]; 66 mLinesHigh = new float[buckets * 4]; 67 mLinesValue = new float[buckets * 4]; 68 mViewToUpdate = v; 69 70 mLT = new LooperThread(this, callback); 71 mLT.start(); 72 } 73 74 static class LooperThread extends Thread { 75 public static final int CommandExit = 1; 76 public static final int TestPowerManagement = 2; 77 public static final int TestMemoryBandwidth = 3; 78 public static final int TestMemoryLatency = 4; 79 public static final int TestHeatSoak = 5; 80 public static final int TestGFlops = 6; 81 82 private volatile boolean mRun = true; 83 private TestInterface mTI; 84 private TestResultCallback mCallback; 85 86 Queue<Integer> mCommandQueue = new LinkedList<Integer>(); 87 LooperThread(TestInterface ti, TestResultCallback callback)88 LooperThread(TestInterface ti, TestResultCallback callback) { 89 super("BenchmarkTestThread"); 90 mTI = ti; 91 mCallback = callback; 92 } 93 runCommand(int command)94 void runCommand(int command) { 95 Integer i = Integer.valueOf(command); 96 97 synchronized (this) { 98 mCommandQueue.add(i); 99 notifyAll(); 100 } 101 } 102 run()103 public void run() { 104 long b = mTI.nInit(0); 105 if (b == 0) { 106 return; 107 } 108 109 while (mRun) { 110 int command = 0; 111 synchronized (this) { 112 if (mCommandQueue.isEmpty()) { 113 try { 114 wait(); 115 } catch (InterruptedException e) { 116 } 117 } 118 119 if (!mCommandQueue.isEmpty()) { 120 command = mCommandQueue.remove(); 121 } 122 } 123 124 switch (command) { 125 case CommandExit: 126 mRun = false; 127 break; 128 case TestPowerManagement: 129 float score = mTI.testPowerManagement(b); 130 mCallback.onTestResult(command, 0); 131 break; 132 case TestMemoryBandwidth: 133 mTI.testCPUMemoryBandwidth(b); 134 break; 135 case TestMemoryLatency: 136 mTI.testCPUMemoryLatency(b); 137 break; 138 case TestHeatSoak: 139 mTI.testCPUHeatSoak(b); 140 break; 141 case TestGFlops: 142 mTI.testCPUGFlops(b); 143 break; 144 145 } 146 147 //mViewToUpdate.post(new Runnable() { 148 // public void run() { 149 // mViewToUpdate.invalidate(); 150 //} 151 //}); 152 } 153 154 mTI.nDestroy(b); 155 } 156 exit()157 void exit() { 158 mRun = false; 159 } 160 } 161 postTextToView(TextView v, String s)162 void postTextToView(TextView v, String s) { 163 final TextView tv = v; 164 final String ts = s; 165 166 v.post(new Runnable() { 167 public void run() { 168 tv.setText(ts); 169 } 170 }); 171 172 } 173 calcAverage(float[] data)174 float calcAverage(float[] data) { 175 float total = 0.f; 176 for (int ct=0; ct < data.length; ct++) { 177 total += data[ct]; 178 } 179 return total / data.length; 180 } 181 makeGraph(float[] data, float[] lines)182 void makeGraph(float[] data, float[] lines) { 183 for (int ct = 0; ct < data.length; ct++) { 184 lines[ct * 4 + 0] = (float)ct; 185 lines[ct * 4 + 1] = 500.f - data[ct]; 186 lines[ct * 4 + 2] = (float)ct; 187 lines[ct * 4 + 3] = 500.f; 188 } 189 } 190 testPowerManagement(long b)191 float testPowerManagement(long b) { 192 float[] dat = new float[mLinesLow.length / 4]; 193 postTextToView(mTextStatus, "Running single-threaded"); 194 nRunPowerManagementTest(b, 1); 195 nGetData(b, dat); 196 makeGraph(dat, mLinesLow); 197 mViewToUpdate.postInvalidate(); 198 float avgMin = calcAverage(dat); 199 200 postTextToView(mTextMin, "Single threaded " + avgMin + " per second"); 201 202 postTextToView(mTextStatus, "Running multi-threaded"); 203 nRunPowerManagementTest(b, 4); 204 nGetData(b, dat); 205 makeGraph(dat, mLinesHigh); 206 mViewToUpdate.postInvalidate(); 207 float avgMax = calcAverage(dat); 208 postTextToView(mTextMax, "Multi threaded " + avgMax + " per second"); 209 210 postTextToView(mTextStatus, "Running typical"); 211 nRunPowerManagementTest(b, 0); 212 nGetData(b, dat); 213 makeGraph(dat, mLinesValue); 214 mViewToUpdate.postInvalidate(); 215 float avgTypical = calcAverage(dat); 216 217 float ofIdeal = avgTypical / (avgMax + avgMin) * 200.f; 218 postTextToView(mTextTypical, String.format("Typical mix (50/50) %%%2.0f of ideal", ofIdeal)); 219 return ofIdeal * (avgMax + avgMin); 220 } 221 testCPUHeatSoak(long b)222 float testCPUHeatSoak(long b) { 223 float[] dat = new float[1000]; 224 postTextToView(mTextStatus, "Running heat soak test"); 225 for (int t = 0; t < 1000; t++) { 226 mLinesLow[t * 4 + 0] = (float)t; 227 mLinesLow[t * 4 + 1] = 498.f; 228 mLinesLow[t * 4 + 2] = (float)t; 229 mLinesLow[t * 4 + 3] = 500.f; 230 } 231 232 float peak = 0.f; 233 float total = 0.f; 234 float dThroughput = 0; 235 float prev = 0; 236 SummaryStatistics stats = new SummaryStatistics(); 237 for (int t = 0; t < 1000; t++) { 238 nRunCPUHeatSoakTest(b, 1); 239 nGetData(b, dat); 240 241 float p = calcAverage(dat); 242 if (prev != 0) { 243 dThroughput += (prev - p); 244 } 245 246 prev = p; 247 248 mLinesLow[t * 4 + 1] = 499.f - p; 249 if (peak < p) { 250 peak = p; 251 } 252 for (float f : dat) { 253 stats.addValue(f); 254 } 255 256 total += p; 257 258 mViewToUpdate.postInvalidate(); 259 postTextToView(mTextMin, "Peak " + peak + " per second"); 260 postTextToView(mTextMax, "Current " + p + " per second"); 261 postTextToView(mTextTypical, "Average " + (total / (t + 1)) + " per second"); 262 } 263 264 265 float decreaseOverTime = dThroughput / 1000; 266 267 System.out.println("dthroughput/dt: " + decreaseOverTime); 268 269 float score = (float) (stats.getMean() / (stats.getStandardDeviation() * decreaseOverTime)); 270 271 postTextToView(mTextStatus, "Score: " + score); 272 return score; 273 } 274 testCPUMemoryBandwidth(long b)275 void testCPUMemoryBandwidth(long b) { 276 int[] sizeK = {1, 2, 3, 4, 5, 6, 7, 277 8, 10, 12, 14, 16, 20, 24, 28, 278 32, 40, 48, 56, 64, 80, 96, 112, 279 128, 160, 192, 224, 256, 320, 384, 448, 280 512, 640, 768, 896, 1024, 1280, 1536, 1792, 281 2048, 2560, 3584, 4096, 5120, 6144, 7168, 282 8192, 10240, 12288, 14336, 16384 283 }; 284 final int subSteps = 15; 285 float[] results = new float[sizeK.length * subSteps]; 286 287 nMemTestStart(b); 288 289 float[] dat = new float[1000]; 290 postTextToView(mTextStatus, "Running Memory Bandwidth test"); 291 for (int t = 0; t < 1000; t++) { 292 mLinesLow[t * 4 + 0] = (float)t; 293 mLinesLow[t * 4 + 1] = 498.f; 294 mLinesLow[t * 4 + 2] = (float)t; 295 mLinesLow[t * 4 + 3] = 500.f; 296 } 297 298 for (int i = 0; i < sizeK.length; i++) { 299 postTextToView(mTextStatus, "Running " + sizeK[i] + " K"); 300 301 float rtot = 0.f; 302 for (int j = 0; j < subSteps; j++) { 303 float ret = nMemTestBandwidth(b, sizeK[i] * 1024); 304 rtot += ret; 305 results[i * subSteps + j] = ret; 306 mLinesLow[(i * subSteps + j) * 4 + 1] = 499.f - (results[i*15+j] * 20.f); 307 mViewToUpdate.postInvalidate(); 308 } 309 rtot /= subSteps; 310 311 if (sizeK[i] == 2) { 312 postTextToView(mTextMin, "2K " + rtot + " GB/s"); 313 } 314 if (sizeK[i] == 128) { 315 postTextToView(mTextMax, "128K " + rtot + " GB/s"); 316 } 317 if (sizeK[i] == 8192) { 318 postTextToView(mTextTypical, "8M " + rtot + " GB/s"); 319 } 320 321 } 322 323 nMemTestEnd(b); 324 postTextToView(mTextStatus, "Done"); 325 } 326 testCPUMemoryLatency(long b)327 void testCPUMemoryLatency(long b) { 328 int[] sizeK = {1, 2, 3, 4, 5, 6, 7, 329 8, 10, 12, 14, 16, 20, 24, 28, 330 32, 40, 48, 56, 64, 80, 96, 112, 331 128, 160, 192, 224, 256, 320, 384, 448, 332 512, 640, 768, 896, 1024, 1280, 1536, 1792, 333 2048, 2560, 3584, 4096, 5120, 6144, 7168, 334 8192, 10240, 12288, 14336, 16384 335 }; 336 final int subSteps = 15; 337 float[] results = new float[sizeK.length * subSteps]; 338 339 nMemTestStart(b); 340 341 float[] dat = new float[1000]; 342 postTextToView(mTextStatus, "Running Memory Latency test"); 343 for (int t = 0; t < 1000; t++) { 344 mLinesLow[t * 4 + 0] = (float)t; 345 mLinesLow[t * 4 + 1] = 498.f; 346 mLinesLow[t * 4 + 2] = (float)t; 347 mLinesLow[t * 4 + 3] = 500.f; 348 } 349 350 for (int i = 0; i < sizeK.length; i++) { 351 postTextToView(mTextStatus, "Running " + sizeK[i] + " K"); 352 353 float rtot = 0.f; 354 for (int j = 0; j < subSteps; j++) { 355 float ret = nMemTestLatency(b, sizeK[i] * 1024); 356 rtot += ret; 357 results[i * subSteps + j] = ret; 358 359 if (ret > 400.f) ret = 400.f; 360 if (ret < 0.f) ret = 0.f; 361 mLinesLow[(i * subSteps + j) * 4 + 1] = 499.f - ret; 362 //android.util.Log.e("bench", "test bw " + sizeK[i] + " - " + ret); 363 mViewToUpdate.postInvalidate(); 364 } 365 rtot /= subSteps; 366 367 if (sizeK[i] == 2) { 368 postTextToView(mTextMin, "2K " + rtot + " ns"); 369 } 370 if (sizeK[i] == 128) { 371 postTextToView(mTextMax, "128K " + rtot + " ns"); 372 } 373 if (sizeK[i] == 8192) { 374 postTextToView(mTextTypical, "8M " + rtot + " ns"); 375 } 376 377 } 378 379 nMemTestEnd(b); 380 postTextToView(mTextStatus, "Done"); 381 } 382 testCPUGFlops(long b)383 void testCPUGFlops(long b) { 384 int[] sizeK = {1, 2, 3, 4, 5, 6, 7 385 }; 386 final int subSteps = 15; 387 float[] results = new float[sizeK.length * subSteps]; 388 389 nMemTestStart(b); 390 391 float[] dat = new float[1000]; 392 postTextToView(mTextStatus, "Running Memory Latency test"); 393 for (int t = 0; t < 1000; t++) { 394 mLinesLow[t * 4 + 0] = (float)t; 395 mLinesLow[t * 4 + 1] = 498.f; 396 mLinesLow[t * 4 + 2] = (float)t; 397 mLinesLow[t * 4 + 3] = 500.f; 398 } 399 400 for (int i = 0; i < sizeK.length; i++) { 401 postTextToView(mTextStatus, "Running " + sizeK[i] + " K"); 402 403 float rtot = 0.f; 404 for (int j = 0; j < subSteps; j++) { 405 float ret = nGFlopsTest(b, sizeK[i] * 1024); 406 rtot += ret; 407 results[i * subSteps + j] = ret; 408 409 if (ret > 400.f) ret = 400.f; 410 if (ret < 0.f) ret = 0.f; 411 mLinesLow[(i * subSteps + j) * 4 + 1] = 499.f - ret; 412 mViewToUpdate.postInvalidate(); 413 } 414 rtot /= subSteps; 415 416 if (sizeK[i] == 2) { 417 postTextToView(mTextMin, "2K " + rtot + " ns"); 418 } 419 if (sizeK[i] == 128) { 420 postTextToView(mTextMax, "128K " + rtot + " ns"); 421 } 422 if (sizeK[i] == 8192) { 423 postTextToView(mTextTypical, "8M " + rtot + " ns"); 424 } 425 426 } 427 428 nMemTestEnd(b); 429 postTextToView(mTextStatus, "Done"); 430 } 431 runPowerManagement()432 public void runPowerManagement() { 433 mLT.runCommand(mLT.TestPowerManagement); 434 } 435 runMemoryBandwidth()436 public void runMemoryBandwidth() { 437 mLT.runCommand(mLT.TestMemoryBandwidth); 438 } 439 runMemoryLatency()440 public void runMemoryLatency() { 441 mLT.runCommand(mLT.TestMemoryLatency); 442 } 443 runCPUHeatSoak()444 public void runCPUHeatSoak() { 445 mLT.runCommand(mLT.TestHeatSoak); 446 } 447 runCPUGFlops()448 public void runCPUGFlops() { 449 mLT.runCommand(mLT.TestGFlops); 450 } 451 } 452