Home | History | Annotate | Download | only in synthetic
      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 {
     30     native long nInit(long options);
     31     native long nDestroy(long b);
     32     native float nGetData(long b, float[] data);
     33     native boolean nRunPowerManagementTest(long b, long options);
     34     native boolean nRunCPUHeatSoakTest(long b, long options);
     35 
     36     native boolean nMemTestStart(long b);
     37     native float nMemTestBandwidth(long b, long size);
     38     native float nMemTestLatency(long b, long size);
     39     native void nMemTestEnd(long b);
     40 
     41     native float nGFlopsTest(long b, long opt);
     42 
     43     public static class TestResultCallback {
     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 
     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 
     88         LooperThread(TestInterface ti, TestResultCallback callback) {
     89             super("BenchmarkTestThread");
     90             mTI = ti;
     91             mCallback = callback;
     92         }
     93 
     94         void runCommand(int command) {
     95             Integer i = Integer.valueOf(command);
     96 
     97             synchronized (this) {
     98                 mCommandQueue.add(i);
     99                 notifyAll();
    100             }
    101         }
    102 
    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 
    157         void exit() {
    158             mRun = false;
    159         }
    160     }
    161 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    432     public void runPowerManagement() {
    433         mLT.runCommand(mLT.TestPowerManagement);
    434     }
    435 
    436     public void runMemoryBandwidth() {
    437         mLT.runCommand(mLT.TestMemoryBandwidth);
    438     }
    439 
    440     public void runMemoryLatency() {
    441         mLT.runCommand(mLT.TestMemoryLatency);
    442     }
    443 
    444     public void runCPUHeatSoak() {
    445         mLT.runCommand(mLT.TestHeatSoak);
    446     }
    447 
    448     public void runCPUGFlops() {
    449         mLT.runCommand(mLT.TestGFlops);
    450     }
    451 }
    452