├── .gitignore
├── README.md
├── app
├── Android.mk
├── Application.mk
├── build.gradle
├── jniLibs
│ └── local
│ │ └── armeabi-v7a
│ │ └── libroofline.so
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── google
│ │ └── gables
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── assets
│ │ └── GPUkernel_template.comp
│ ├── ic_launcher-web.png
│ ├── java
│ │ └── com
│ │ │ └── google
│ │ │ └── gables
│ │ │ ├── CPURoofline.java
│ │ │ ├── DSPRoofline.java
│ │ │ ├── GPURoofline.java
│ │ │ ├── MainActivity.java
│ │ │ ├── Roofline.java
│ │ │ ├── SOCRoofline.java
│ │ │ ├── Utils.java
│ │ │ └── utils
│ │ │ └── NonSwipeViewPager.java
│ ├── jni
│ │ └── roofline
│ │ │ ├── CPUdriver.cpp
│ │ │ ├── CPUkernel.cpp
│ │ │ ├── GPUdriver.cpp
│ │ │ ├── Utils.cpp
│ │ │ └── inc
│ │ │ ├── CPUdriver.hpp
│ │ │ ├── CPUkernel.hpp
│ │ │ ├── GPUdriver.hpp
│ │ │ ├── Utils.hpp
│ │ │ └── rep.hpp
│ ├── python
│ │ └── gables
│ │ │ ├── __init__.py
│ │ │ └── gables_processor.py
│ └── res
│ │ ├── drawable-v24
│ │ ├── harvard_edge.png
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── fragment_cpu_roofline.xml
│ │ ├── fragment_dsp_roofline.xml
│ │ ├── fragment_gpu_roofline.xml
│ │ ├── fragment_main.xml
│ │ └── fragment_mixer_roofline.xml
│ │ ├── menu
│ │ └── menu_main.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── integers.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── google
│ └── gables
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── images
└── CPURooflineExamplePlot.png
├── settings.gradle
├── step_by_step.md
└── utils
├── expprep.sh
└── plotting
├── gnuplots
├── band-vs-wss.gnu.template
├── band-vs-wss_max.gnu.template
├── flops-vs-wss.gnu.template
├── roofline.gnu.template
└── secs-vs-trials.gnu.template
└── scripts
└── gables.py
/.gitignore:
--------------------------------------------------------------------------------
1 | #built application files
2 | *.apk
3 | *.ap_
4 |
5 | # files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # generated files
12 | bin/
13 | gen/
14 |
15 | # Local configuration file (sdk path, etc)
16 | local.properties
17 |
18 | # Windows thumbnail db
19 | Thumbs.db
20 |
21 | # Android Studio
22 | *.iml
23 | .idea
24 | .gradle
25 | build/
26 | .navigation
27 | captures/
28 | output.json
29 |
30 | #NDK
31 | obj/
32 | .externalNativeBuild
33 |
34 | # Crashlytics configuations
35 | com_crashlytics_export_strings.xml
36 |
37 | # Signing files
38 | .signing/
39 |
40 | # OS-specific files
41 | .DS_Store
42 | .DS_Store?
43 | ._*
44 | .Spotlight-V100
45 | .Trashes
46 | ehthumbs.db
47 | Thumbs.db
48 |
49 | # Gables specific
50 | gnuplots/
51 | output/
52 | *.gables
53 | *.o
54 | *.o.d
55 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Gables
2 |
3 | Welcome to the [_Gables: Roofline Model for Mobile SoCs._](http://research.cs.wisc.edu/multifacet/gables/) The code that is included in here is the code that is used to generate the roofline model for mobile SoCs CPUs/GPUs and DSP. The code has been tested primarily on the following two devices: (1) a Qualcomm 835 Development Kit and (2) Pixel 2/3 smartphones, but it should work on other devices.
4 |
5 |
6 |
7 |
8 |
9 | The source code that is included here can be built into an Android APK, pushed to the device and then run by a user. You can import the git repo directly from the Android Studio.
10 |
11 | # Prerequisites
12 |
13 | * You must be familiar with Android Studio to build the APK.
14 | * You have a device based on the Qualcomm chipset.
15 | * You must grant the app read/write permissions
16 |
17 | # Step-by-step
18 |
19 | ## Install Android Studio
20 |
21 | You can download the latest version of Android Studio [here](https://developer.android.com/studio/), and follow the instructions to install.
22 |
23 | ## Import the GitHub Repo
24 |
25 | You can directly import GitHub projects into Android Studio. In the Android Studio window, click VCS -> Checkout -> Git and import this repository address `https://github.com/harvard-edge/Gables`. The GitHub repo will be created as a new project in android studio. Alternatively, you can download the repo to your filesystem and manually import it as a new project into Android Studio. We recommend using the Git repo directly as you can get the latest updates.
26 |
27 | ## Build the APK
28 |
29 | Android Studio should automatically recognize the project is using the Gradle build system. If so you should be able to press `Build>Make Project` and it will attempt to build the project.
30 |
31 | We use CMake to build the C++ compenents of the app which interface with the Java code through the JNI. In order to build the app you should have CMake and the Android NDK installed and in your path. Usually Android studio will offer to install these automatically if you attempt to build without these available.
32 |
33 | ## Install the APK
34 |
35 | Once the build has completed successfully, you will be able to press `Run>Run 'app'` in the toolbar and then Android Studio will prompt you to select a device to install the APK on.
36 |
37 | We recommend running Gables on a real world device for testing. The device should have [developer options](https://developer.android.com/studio/debug/dev-options) enabled and USB debugging turned on. The device will then appear in the run prompt. Selecting this device will install the APK on it.
38 |
39 | If the name of the device doesn't appear correctly in the prompt, check that the device is conencted in the correct file transfer mode (this can usually be changed in a persistent notification on the device itself). The correct file transfer mode varies depending on device but once the correct mode is selected the device name will be visible in the run prompt.
40 |
41 | If you do wish to run Gables on an emulator, we currently only support emulator images based on the armeabi-v7a, or arm64-v8a instruction sets. Support for other architectures is coming soon.
42 |
43 | ## Run the APK
44 |
45 | The Gables app icon should now be visible in the launcher of the device in question.
46 |
47 | ## Generate the Plots
48 |
49 | The current version of the app first generates the data, and then processes the data offline to generate the plots. See [step-by-step](step_by_step.md) instructions on how to build, run and generate the offline plots.
50 |
51 | # Limitations and Restrictions
52 |
53 | The current version of the code has only been tested on devices that use the Qualcomm chipsets.
54 |
55 | If your smartphone or a development bboard that is based on some other chipsets (i.e., not Qualcomm chipsets), modifications may be needed to get the code running. Please contact us for help.
56 |
57 | Most users face trouble when it comes to running the code on the DSP. If you are on the phone, the DSP code will likely not work. This is because the DSP kernel library needs to be specially "signed" by Qualcomm to allow access to the DSP. So, the DSP code will not work out of the box. However, if you are on the development platform. The code should work.
58 |
59 | # FAQs
60 |
61 | > How do I install the APK?
62 |
63 | Please watch the video, or follow the step-by-step instructions on how to build and run the app.
64 |
65 | > After running the code, why is the plot not updating?
66 |
67 | Real-time plot updating is still work under progress. Please continue to use the offline plot generator. Stay tuned for updates as we are making progress toward releasing the updates soon.
68 |
69 | # Authors and Contributors
70 |
71 | * Vijay Janapa Reddi (Harvard University)
72 | * Daniel Inge (Harvard University)
73 | * Mark Hill (Univ. of Wisconsin)
74 | * Nikhita Kunati (Univ. of Wisconsin)
75 |
76 | Want to contribute something to the app? Please contact us, we would love the help!
77 |
78 | # Contact Us
79 |
80 | Please email your questions and concerns to vj@eecs.harvard.edu and dinge@college.harvard.edu.
81 |
82 | # Credits
83 |
84 | The inspiration for the mobile version of the code comes from the [CS Roofline Toolkit
85 | ](https://bitbucket.org/berkeleylab/cs-roofline-toolkit). The APK introduces updates and changes to the code, and includes numerous new code additions such as support for GPU OpenGL ES and the DSPs.
86 |
87 |
--------------------------------------------------------------------------------
/app/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 | include $(CLEAR_VARS)
3 | LOCAL_MODULE := roofline
4 | LOCAL_C_INCLUDES += ./src/main/jni/roofline/inc
5 | LOCAL_CFLAGS += -O3
6 | LOCAL_CFLAGS += -fopenmp
7 | LOCAL_LDFLAGS += -fopenmp
8 | LOCAL_SRC_FILES := ./src/main/jni/roofline/CPUdriver.cpp ./src/main/jni/roofline/CPUkernel.cpp ./src/main/jni/roofline/GPUdriver.cpp ./src/main/jni/roofline/Utils.cpp
9 | LOCAL_LDLIBS := -lGLESv3 -landroid -lEGL -llog
10 | include $(BUILD_SHARED_LIBRARY)
11 |
12 |
--------------------------------------------------------------------------------
/app/Application.mk:
--------------------------------------------------------------------------------
1 | APP_OPTIM := release # Build the target in debug mode.
2 | APP_ABI := arm64-v8a
3 | APP_PLATFORM := android-27
4 | APP_STL := c++_static
5 | APP_BUILD_SCRIPT := Android.mk
6 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'com.chaquo.python'
3 |
4 | android {
5 | signingConfigs {
6 | config {
7 | keyAlias 'key0'
8 | keyPassword 'password'
9 | storeFile file('/Users/dinge/Desktop/passwordkeystore')
10 | storePassword 'password'
11 | }
12 | }
13 | compileSdkVersion 27
14 | defaultConfig {
15 | applicationId "edu.harvard.seas.edge.gables"
16 | minSdkVersion 21
17 | targetSdkVersion 27
18 | versionCode 1
19 | versionName "1.0"
20 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
21 | ndk {
22 | abiFilters 'arm64-v8a'
23 | }
24 | // Encapsulates your external native build configurations.
25 | externalNativeBuild {
26 | // Encapsulates your CMake build configurations.
27 | cmake {
28 | // these flags are set in the CMake file, since they follow *after* default AndroidStudio args
29 | }
30 | }
31 | python {
32 | pip {
33 | install "numpy==1.14.2"
34 | install "matplotlib==2.2.2"
35 | }
36 | staticProxy("gables.gables_processor")
37 | }
38 | }
39 | buildTypes {
40 | release {
41 | minifyEnabled false
42 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
43 | signingConfig signingConfigs.config
44 | debuggable false
45 | jniDebuggable false
46 | }
47 | debug {
48 | debuggable true
49 | jniDebuggable true
50 | }
51 | }
52 | sourceSets {
53 | main {
54 | jni.srcDirs = ['src/main/jni']
55 | jniLibs.srcDirs = ['src/main/jniLibs']
56 | }
57 | }
58 | externalNativeBuild {
59 | ndkBuild {
60 | path 'Android.mk'
61 | }
62 | }
63 | }
64 |
65 | dependencies {
66 | implementation fileTree(include: ['*.jar'], dir: 'libs')
67 | implementation 'com.android.support:appcompat-v7:27.1.1'
68 | implementation 'com.android.support:design:27.1.1'
69 | implementation 'com.android.support.constraint:constraint-layout:1.1.0'
70 | testImplementation 'junit:junit:4.12'
71 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
72 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
73 | implementation 'com.jjoe64:graphview:4.2.2'
74 | implementation 'com.android.support:cardview-v7:27.1.1'
75 | implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
76 | implementation 'com.synnapps:carouselview:0.1.5'
77 | }
78 |
--------------------------------------------------------------------------------
/app/jniLibs/local/armeabi-v7a/libroofline.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/app/jniLibs/local/armeabi-v7a/libroofline.so
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/google/gables/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.google.gables;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.assertEquals;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.google.gables", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
16 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/assets/GPUkernel_template.comp:
--------------------------------------------------------------------------------
1 | #version 320 es
2 |
3 | #define KERNEL1(a,b,c) ((a) = (b) + (c))
4 | #define KERNEL2(a,b,c) ((a) = (a)*(b) + (c))
5 |
6 | #define REP2(S) S ; S
7 | #define REP4(S) REP2(S); REP2(S)
8 | #define REP8(S) REP4(S); REP4(S)
9 | #define REP16(S) REP8(S); REP8(S)
10 | #define REP32(S) REP16(S); REP16(S)
11 | #define REP64(S) REP32(S); REP32(S)
12 | #define REP128(S) REP64(S); REP64(S)
13 | #define REP256(S) REP128(S); REP128(S)
14 | #define REP512(S) REP256(S); REP256(S)
15 | #define REP1024(S) REP512(S); REP512(S)
16 | #define REP2048(S) REP1024(S); REP1024(S)
17 | #define REP4096(S) REP2048(S); REP2048(S)
18 | #define REP8192(S) REP4096(S); REP4096(S)
19 | #define REP16384(S) REP8192(S); REP8192(S)
20 | #define REP32768(S) REP16384(S); REP16384(S)
21 |
22 | layout(local_size_x = XXX_LAYOUT_SIZE_XXX, local_size_y = 1, local_size_z = 1) in;
23 |
24 | layout(binding = 0) readonly buffer Params {
25 | uint data[];
26 | } params;
27 | layout(binding = 1) readonly buffer IArray {
28 | float data[];
29 | } ibuff;
30 | layout(binding = 2) writeonly buffer OArray {
31 | uint data[];
32 | } retval;
33 |
34 | void main()
35 | {
36 | uint wsssize = params.data[0];
37 | uint ntrials = params.data[1];
38 |
39 | uint total_thr = gl_NumWorkGroups.x * gl_WorkGroupSize.x;
40 | uint elem_per_thr = (wsssize + (total_thr - 1u)) / total_thr;
41 |
42 | uint start_idx = gl_GlobalInvocationID.x;
43 | uint end_idx = start_idx + elem_per_thr * total_thr;
44 |
45 | uint stride_idx = total_thr;
46 |
47 | if (start_idx > wsssize)
48 | start_idx = wsssize;
49 | if (end_idx > wsssize)
50 | end_idx = wsssize;
51 |
52 | float alpha = 0.5;
53 | for (uint j = 0u; j < ntrials; ++j) {
54 | for (uint i = start_idx; i < end_idx; i += stride_idx) {
55 | float beta = 0.8;
56 | XXX_KERNEL_FLOPS_PREFIX_XXX(beta, ibuff.data[i], alpha)XXX_KERNEL_FLOPS_POSTFIX_XXX;
57 | retval.data[3] = uint(beta);
58 | }
59 | }
60 |
61 | retval.data[0] = 4u;
62 | retval.data[1] = 2u;
63 | retval.data[3] = 0u;
64 | }
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/app/src/main/ic_launcher-web.png
--------------------------------------------------------------------------------
/app/src/main/java/com/google/gables/CPURoofline.java:
--------------------------------------------------------------------------------
1 | package com.google.gables;
2 |
3 |
4 | import android.app.Activity;
5 | import android.app.ProgressDialog;
6 | import android.content.DialogInterface;
7 | import android.graphics.Bitmap;
8 | import android.graphics.BitmapFactory;
9 | import android.graphics.Color;
10 | import android.os.AsyncTask;
11 | import android.os.Bundle;
12 | import android.support.v4.app.Fragment;
13 | import android.system.ErrnoException;
14 | import android.system.Os;
15 | import android.util.Log;
16 | import android.view.LayoutInflater;
17 | import android.view.View;
18 | import android.view.ViewGroup;
19 | import android.widget.CompoundButton;
20 | import android.widget.ImageView;
21 | import android.widget.SeekBar;
22 | import android.widget.Switch;
23 | import android.widget.TextView;
24 | import android.widget.ToggleButton;
25 |
26 | import com.github.mikephil.charting.charts.LineChart;
27 | import com.github.mikephil.charting.components.AxisBase;
28 | import com.github.mikephil.charting.components.Description;
29 | import com.github.mikephil.charting.components.XAxis;
30 | import com.github.mikephil.charting.data.Entry;
31 | import com.github.mikephil.charting.data.LineData;
32 | import com.github.mikephil.charting.data.LineDataSet;
33 | import com.github.mikephil.charting.formatter.IAxisValueFormatter;
34 | import com.github.mikephil.charting.formatter.IndexAxisValueFormatter;
35 | import com.github.mikephil.charting.formatter.ValueFormatter;
36 | import com.jjoe64.graphview.GraphView;
37 | import com.jjoe64.graphview.GridLabelRenderer;
38 | import com.jjoe64.graphview.series.DataPoint;
39 | import com.jjoe64.graphview.series.LineGraphSeries;
40 | import com.synnapps.carouselview.CarouselView;
41 | import com.synnapps.carouselview.ImageListener;
42 |
43 | import org.w3c.dom.Text;
44 |
45 | import java.io.BufferedReader;
46 | import java.io.DataOutputStream;
47 | import java.io.File;
48 | import java.io.FileNotFoundException;
49 | import java.io.FileOutputStream;
50 | import java.io.IOException;
51 | import java.io.InputStreamReader;
52 | import java.text.DecimalFormat;
53 | import java.util.ArrayList;
54 | import java.util.Arrays;
55 | import java.util.List;
56 |
57 | import gables.gables_processor.GablesPython;
58 |
59 | import static com.google.gables.Roofline.CPU_Execute;
60 | import static com.google.gables.Utils.ExtStoragePermissions_t.EXT_STORAGE_RW;
61 | import static com.google.gables.Utils.MiB;
62 | import static com.google.gables.Utils.deleteDirectory;
63 | import static com.google.gables.Utils.getNumberOfCores;
64 | import static com.google.gables.Utils.isStorageAvailable;
65 | import static com.google.gables.Utils.log;
66 |
67 | public class CPURoofline extends Fragment {
68 | private static final String TAG = CPURoofline.class.getName();
69 | private ImageView chart;
70 | private ProgressDialog gProcessDialog;
71 | private String gResultsDir = "CPURoofline";
72 | private CarouselView slider;
73 | private TextView slidePrompt;
74 | private View edgeLogo;
75 |
76 | @Override
77 | public void onCreate(Bundle savedInstanceState) {
78 |
79 | super.onCreate(savedInstanceState);
80 | try {
81 | Os.setenv("OMP_PROC_BIND", "spread", true);
82 | Os.setenv("OMP_PLACES", "threads", true);
83 | } catch (ErrnoException e) {
84 | e.printStackTrace();
85 | }
86 | Log.e("shell", "hi");
87 | Log.e("shell", shellRoofline());
88 | Log.e("shell", "bye");
89 | }
90 |
91 | private float scaleCbr(double cbr) {
92 | return (float)(Math.log10(cbr));
93 | }
94 |
95 | private float unScaleCbr(double cbr) {
96 | double calcVal = Math.pow(10, cbr);
97 | return (float)(calcVal);
98 | }
99 |
100 | /**
101 | * Setup a button to trigger the activation of the roofline process
102 | *
103 | * @param rootView
104 | */
105 | void setupButton(final View rootView) {
106 | // Register a callback on the toggle button to turn ON/OFF cpu activity
107 | final ToggleButton button = rootView.findViewById(R.id.toggle_runRoofline);
108 | button.setTextOn("Busy!");
109 | button.setTextOff("Run");
110 | button.setChecked(false); // set the current state of a toggle button
111 |
112 | button.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
113 |
114 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
115 |
116 | if (isChecked) { // enabled
117 | final SeekBar seekBar_mem = rootView.findViewById(R.id.seekBar_threadMem);
118 | final SeekBar seekBar_cpu = rootView.findViewById(R.id.seekBar_maxThreads);
119 | final SeekBar seekBar_opi = rootView.findViewById(R.id.seekBar_opIntensity);
120 |
121 | final int maxMemory = (1 << seekBar_mem.getProgress()) * MiB; // converting to bytes
122 | final int nThreads = seekBar_cpu.getProgress() + 1; // remember that seekbar starts at 0
123 | final int nFlops = (1 << seekBar_opi.getProgress()); // remember that seekbar starts at 0
124 |
125 | // final Switch neonSwitch = rootView.findViewById(R.id.switch_neonMode);
126 | final boolean neonMode = false;
127 |
128 | CPURoofline(nThreads, maxMemory, nFlops, neonMode);
129 |
130 | button.setChecked(false);
131 | }
132 | }
133 | });
134 | }
135 |
136 | public void displayGraph(String filename, ImageView view) {
137 | File file = new File(filename);
138 | if (file.exists()) {
139 | Bitmap myBitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
140 | view.setImageBitmap(myBitmap);
141 | }
142 | }
143 |
144 | public String shellRoofline() {
145 | StringBuffer output = new StringBuffer();
146 |
147 | Process p;
148 | try {
149 | p = Runtime.getRuntime().exec("su -C ./data/local/tmp/stream");
150 | p.waitFor();
151 | BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
152 |
153 | String line = "";
154 | while ((line = reader.readLine())!= null) {
155 | output.append(line + "n");
156 | }
157 |
158 | } catch (Exception e) {
159 | Log.e("Oh no", e.getMessage());
160 | }
161 | String response = output.toString();
162 | return response;
163 | }
164 |
165 | public void RooflineCmdline() {
166 | File outputFile = new File("/data/data/com.google.gables/pixel.gables");
167 | try {
168 | ProcessBuilder pb = new ProcessBuilder("/data/data/com.google.gables/gables");
169 | pb.redirectOutput(outputFile);
170 |
171 | Log.i(TAG, "native started...");
172 | Process process = pb.start();
173 | BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
174 | String line;
175 | while ((line = reader.readLine()) != null) {
176 | Log.i(TAG, line);
177 | }
178 | process.waitFor();
179 | } catch (IOException e) {
180 | e.printStackTrace();
181 | } catch (InterruptedException e) {
182 | e.printStackTrace();
183 | }
184 | Log.i(TAG, "native finished...");
185 | }
186 |
187 | private void setupCPUSlider(final View rootView) {
188 | final SeekBar mSeekBar = rootView.findViewById(R.id.seekBar_maxThreads);
189 |
190 | int nCores = getNumberOfCores();
191 | mSeekBar.setProgress(nCores);
192 | mSeekBar.setMax(nCores - 1); // we start from 0, but we display +1
193 |
194 | TextView textView = rootView.findViewById(R.id.txtBox_maxThreads);
195 | textView.setText("Thread Count (" + Long.toString(mSeekBar.getProgress() + 1) + " Cores)"); // increment by 1 since bar starts from 0.
196 |
197 | final ToggleButton toggle = rootView.findViewById(R.id.toggle_runRoofline);
198 | mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
199 |
200 | @Override
201 | public void onStopTrackingTouch(SeekBar seekBar) {
202 | toggle.setChecked(false);
203 | }
204 |
205 | @Override
206 | public void onStartTrackingTouch(SeekBar seekBar) {
207 | toggle.setChecked(false);
208 | }
209 |
210 | @Override
211 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
212 | TextView textView = rootView.findViewById(R.id.txtBox_maxThreads);
213 | textView.setText("Thread Count (" + Long.toString(mSeekBar.getProgress() + 1) + " Cores)");
214 | }
215 | });
216 | }
217 |
218 | private void setupOpIntensity(final View rootView) {
219 | final SeekBar mSeekBar = rootView.findViewById(R.id.seekBar_opIntensity);
220 | mSeekBar.setProgress(4); //fixme debug version
221 |
222 | TextView textView = rootView.findViewById(R.id.txtBox_opIntensity);
223 | textView.setText("Ops (" + Long.toString(1 << mSeekBar.getProgress()) + " FLOPS/byte)");
224 |
225 | final ToggleButton toggle = rootView.findViewById(R.id.toggle_runRoofline);
226 | mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
227 |
228 | @Override
229 | public void onStopTrackingTouch(SeekBar seekBar) {
230 | toggle.setChecked(false);
231 | }
232 |
233 | @Override
234 | public void onStartTrackingTouch(SeekBar seekBar) {
235 | toggle.setChecked(false);
236 | }
237 |
238 | @Override
239 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
240 | TextView textView = rootView.findViewById(R.id.txtBox_opIntensity);
241 | textView.setText("Ops (" + Long.toString(1 << mSeekBar.getProgress()) + " FLOPS/byte)");
242 | }
243 | });
244 | }
245 |
246 | private void setupMemorySlider(final View rootView) {
247 | final SeekBar mSeekBar = rootView.findViewById(R.id.seekBar_threadMem);
248 |
249 | TextView textView = rootView.findViewById(R.id.txtBox_threadMem);
250 | textView.setText("Memory Alloc. (" + Long.toString(1 << mSeekBar.getProgress()) + " MB)");
251 |
252 | final ToggleButton toggle = rootView.findViewById(R.id.toggle_runRoofline);
253 |
254 | mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
255 |
256 | @Override
257 | public void onStopTrackingTouch(SeekBar seekBar) {
258 | toggle.setChecked(false);
259 | }
260 |
261 | @Override
262 | public void onStartTrackingTouch(SeekBar seekBar) {
263 | toggle.setChecked(false);
264 | }
265 |
266 | @Override
267 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
268 | TextView textView = rootView.findViewById(R.id.txtBox_threadMem);
269 | textView.setText("Memory Alloc. (" + Long.toString(1 << mSeekBar.getProgress()) + " MB)");
270 | }
271 | });
272 | }
273 |
274 | // private void setupSwitch(final View rootView) {
275 | // final Switch neonSwitch = rootView.findViewById(R.id.switch_neonMode);
276 | // final boolean neonMode = neonSwitch.isChecked();
277 | //
278 | // neonSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
279 | // public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
280 | // TextView textView = rootView.findViewById(R.id.txtBox_neonSwitch);
281 | // if (isChecked) {
282 | // textView.setText("NEON Vectorization (Enabled)");
283 | // } else {
284 | // //fixme: check to see how we can disable this for hardcore real.
285 | // textView.setText("NEON Vectorization (Disabled)");
286 | // }
287 | // }
288 | // });
289 | // }
290 |
291 | private void setupSliders(View rootView) {
292 | setupMemorySlider(rootView);
293 | setupCPUSlider(rootView);
294 | setupOpIntensity(rootView);
295 | // setupSwitch(rootView);
296 | }
297 |
298 | @Override
299 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
300 | Bundle savedInstanceState) {
301 | View rootView = inflater.inflate(R.layout.fragment_cpu_roofline, container, false);
302 | chart = rootView.findViewById(R.id.graph);
303 | setupSliders(rootView);
304 | setupButton(rootView);
305 | slider = rootView.findViewById(R.id.carouselView);
306 | slidePrompt = rootView.findViewById(R.id.swipe_prompt);
307 | edgeLogo = rootView.findViewById(R.id.edge_logo);
308 | return rootView;
309 | }
310 |
311 | private void writeToSDFile(File dir, String filename, String ostr) {
312 |
313 | boolean success = true;
314 | if (!dir.exists()) {
315 | success = dir.mkdir(); // FIXME: if this fails, then you might have to request permission in app settings.
316 | }
317 | if (success) {
318 | Log.i(TAG, "Output directory created.");
319 | } else {
320 | Log.i(TAG, "Output directory NOT created!");
321 | }
322 |
323 | File file = new File(dir, filename);
324 |
325 | try {
326 | FileOutputStream fos = new FileOutputStream(file);
327 | fos.write(ostr.getBytes());
328 | fos.close();
329 | } catch (FileNotFoundException e) {
330 | e.printStackTrace();
331 | Log.i(TAG, "******* File not found. Did you" +
332 | " add a WRITE_EXTERNAL_STORAGE permission to the manifest?");
333 | } catch (IOException e) {
334 | e.printStackTrace();
335 | }
336 | Log.i(TAG, "\n\nFile written to " + file);
337 | }
338 |
339 | public void CPURoofline(int nThreads, int maxMemory, int nFlops, boolean neon) {
340 | CPURooflineAsync rooflineATask = new CPURooflineAsync(getActivity(),
341 | nThreads, maxMemory, nFlops, neon);
342 |
343 | rooflineATask.execute();
344 | }
345 |
346 | class CPURooflineAsync extends AsyncTask {
347 | final int threads, mem, flops;
348 | final boolean neon;
349 | private AsyncTask currTask = null;
350 |
351 | public CPURooflineAsync(Activity activity, int nThreads, int threadMem, int maxFlops, boolean neon) {
352 | super();
353 |
354 | this.threads = nThreads;
355 | this.mem = threadMem;
356 | this.flops = maxFlops;
357 | this.neon = neon;
358 |
359 | gProcessDialog = new ProgressDialog(activity);
360 | }
361 |
362 | @Override
363 | protected void onPreExecute() {
364 | super.onPreExecute();
365 |
366 | currTask = this;
367 |
368 | gProcessDialog.setMax(100);
369 | gProcessDialog.setProgress(0);
370 | gProcessDialog.setTitle("Roofline in progress");
371 | gProcessDialog.setMessage("Starting up... ");
372 | gProcessDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
373 | gProcessDialog.setCancelable(false);
374 | gProcessDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
375 | @Override
376 | public void onClick(DialogInterface dialog, int which) {
377 | dialog.dismiss();
378 | currTask.cancel(true);
379 | }
380 | });
381 |
382 | gProcessDialog.show();
383 | }
384 |
385 | @Override
386 | protected String doInBackground(Void... params) {
387 | File root = android.os.Environment.getExternalStorageDirectory();
388 | File odir = new File(root.getAbsolutePath() + "/" + gResultsDir + "/");
389 | deleteDirectory(odir);
390 | Log.i(TAG, "Deleting the " + odir + " output directory.");
391 |
392 | // storage for updating progress of the work to progress bar
393 | int progressCounter = 0;
394 | final int progressTotal = (log(flops, 2) + 1) * threads;
395 |
396 | stop:
397 | // label to break out of inner loop if "cancel" was hit on progress bar.
398 | for (int i = 1; i <= flops; i = i * 2) {
399 | for (int j = threads; j <= threads; j++) { //FIXME: Fix this debug loop
400 | String strCurrProgress = String.valueOf(Math.round(100.0 * progressCounter / progressTotal));
401 | String message = "Running " + i + " FLOPS/byte with " + j + " threads.";
402 | publishProgress(strCurrProgress, message);
403 | publishProgress(strCurrProgress, message);
404 | Log.i(TAG, "Starting " + i + " FLOPS/byte with " + j + " threads.");
405 |
406 | String output = CPU_Execute(mem, j, i, neon);
407 |
408 | generatePlotData(processRawData(output));
409 |
410 | if (isCancelled()) {
411 | message = "Cancelling...";
412 | publishProgress(strCurrProgress, message);
413 | Log.i(TAG, "Terminating out of the loop.");
414 |
415 | break stop;
416 | }
417 |
418 | if (isStorageAvailable(EXT_STORAGE_RW)) {
419 | message = "Writing results to storage.";
420 | publishProgress(strCurrProgress, message);
421 |
422 | String ofilename = "threads-" + j + "_flops-" + i + "_neon-" + neon + ".gables";
423 | writeToSDFile(odir, ofilename, output);
424 | } else {
425 | Log.e(TAG, "Storage is not available for RW or is unavailable.");
426 | }
427 |
428 | // we've made progress so update
429 | progressCounter++;
430 | }
431 | }
432 |
433 | return "All done with AsyncTask!";
434 | }
435 |
436 | @Override
437 | protected void onProgressUpdate(String... msg) {
438 | super.onProgressUpdate(msg);
439 | gProcessDialog.setProgress(Integer.parseInt(msg[0]));
440 | gProcessDialog.setMessage(msg[1]);
441 | }
442 |
443 | // onCancelled() is called when the async task is cancelled.
444 | @Override
445 | protected void onCancelled(String result) {
446 | }
447 |
448 | protected void onPostExecute(String param) {
449 |
450 | gProcessDialog.setMessage("Finished processing data.");
451 | new GablesPython().processCPURoofline();
452 | setupSlider();
453 | if (gProcessDialog.isShowing()) {
454 | gProcessDialog.dismiss();
455 | }
456 | }
457 |
458 | private void setupSlider() {
459 | ImageListener imageListener = new ImageListener() {
460 | @Override
461 | public void setImageForPosition(int position, ImageView imageView) {
462 | String filename = "";
463 | switch (position) {
464 | case 0:
465 | default:
466 | filename = "/sdcard/CPURoofline/roofline.png";
467 | break;
468 | case 1:
469 | filename = "/sdcard/CPURoofline/bandwidth.png";
470 | break;
471 | }
472 | displayGraph(filename, imageView);
473 | }
474 | };
475 | slider.setImageListener(imageListener);
476 | slider.setPageCount(2);
477 | slider.setVisibility(View.VISIBLE);
478 | edgeLogo.setVisibility(View.GONE);
479 | slidePrompt.setVisibility(View.VISIBLE);
480 | }
481 | void generatePlotData(List values) {
482 | List gflops = new ArrayList<>();
483 | List flopsPerByte = new ArrayList<>();
484 | for (CPUDataPoint value : values) {
485 | gflops.add(value.getTotalFlops()/value.getTotalSeconds());
486 | flopsPerByte.add(value.getTotalFlops() / value.getTotalBytes());
487 | }
488 | System.out.println(gflops.toString());
489 | System.out.println(flopsPerByte.toString());
490 | }
491 |
492 | List processRawData(String data) {
493 | List rows = Arrays.asList(data.trim().split("\\s*\\n\\s*"));
494 | List points = new ArrayList<>();
495 | for (String row : rows) {
496 | if (row.contains("META_DATA")) {
497 | break;
498 | } else {
499 | points.add(CPUDataPoint.parseCPUDataPoint(row));
500 | }
501 | }
502 | return points;
503 | }
504 | }
505 |
506 | static class CPUDataPoint {
507 |
508 | double distinctBytes;
509 | double nTrials;
510 | double totalSeconds;
511 | double totalBytes;
512 | double totalFlops;
513 |
514 | public static CPUDataPoint parseCPUDataPoint(String input) {
515 | String[] values = input.split("\\s+");
516 | CPUDataPoint point = new CPUDataPoint();
517 | point.setDistinctBytes(Double.valueOf(values[0]));
518 | point.setnTrials(Double.valueOf(values[1]));
519 | point.setTotalSeconds(Double.valueOf(values[2]));
520 | point.setTotalBytes(Double.valueOf(values[3]));
521 | point.setTotalFlops(Double.valueOf(values[4]));
522 | return point;
523 | }
524 |
525 | public double getDistinctBytes() {
526 | return distinctBytes;
527 | }
528 |
529 | public void setDistinctBytes(double distinctBytes) {
530 | this.distinctBytes = distinctBytes;
531 | }
532 |
533 | public double getnTrials() {
534 | return nTrials;
535 | }
536 |
537 | public void setnTrials(double nTrials) {
538 | this.nTrials = nTrials;
539 | }
540 |
541 | public double getTotalSeconds() {
542 | return totalSeconds;
543 | }
544 |
545 | public void setTotalSeconds(double totalSeconds) {
546 | this.totalSeconds = totalSeconds;
547 | }
548 |
549 | public double getTotalBytes() {
550 | return totalBytes;
551 | }
552 |
553 | public void setTotalBytes(double totalBytes) {
554 | this.totalBytes = totalBytes;
555 | }
556 |
557 | public double getTotalFlops() {
558 | return totalFlops;
559 | }
560 |
561 | public void setTotalFlops(double totalFlops) {
562 | this.totalFlops = totalFlops;
563 | }
564 | }
565 | }
566 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/gables/DSPRoofline.java:
--------------------------------------------------------------------------------
1 | package com.google.gables;
2 |
3 |
4 | import android.app.Activity;
5 | import android.app.ProgressDialog;
6 | import android.content.DialogInterface;
7 | import android.graphics.Color;
8 | import android.os.AsyncTask;
9 | import android.os.Bundle;
10 | import android.support.v4.app.Fragment;
11 | import android.util.Log;
12 | import android.view.LayoutInflater;
13 | import android.view.View;
14 | import android.view.ViewGroup;
15 | import android.widget.CompoundButton;
16 | import android.widget.SeekBar;
17 | import android.widget.Switch;
18 | import android.widget.TextView;
19 | import android.widget.ToggleButton;
20 |
21 | import com.jjoe64.graphview.GraphView;
22 | import com.jjoe64.graphview.GridLabelRenderer;
23 | import com.jjoe64.graphview.series.DataPoint;
24 | import com.jjoe64.graphview.series.LineGraphSeries;
25 |
26 | import java.io.File;
27 | import java.io.FileNotFoundException;
28 | import java.io.FileOutputStream;
29 | import java.io.IOException;
30 |
31 | import static com.google.gables.Roofline.DSP_Execute;
32 | import static com.google.gables.Roofline.DSP_NumThreads;
33 | import static com.google.gables.Utils.MiB;
34 | import static com.google.gables.Utils.deleteDirectory;
35 |
36 | public class DSPRoofline extends Fragment {
37 | private static final String TAG = DSPRoofline.class.getName();
38 |
39 | private ProgressDialog gProcessDialog;
40 | private String gResultsDir = "DSPRoofline";
41 |
42 | @Override
43 | public void onCreate(Bundle savedInstanceState) {
44 |
45 | super.onCreate(savedInstanceState);
46 |
47 | }
48 |
49 | void drawGraph(View rootView) {
50 | // Setup a graph view
51 | GraphView graphview = rootView.findViewById(R.id.graph);
52 |
53 | // activate horizontal zooming and scrolling
54 | graphview.getViewport().setScalable(false);
55 | graphview.getViewport().setScrollable(true);
56 | graphview.getViewport().setScalableY(false);
57 | graphview.getViewport().setScrollableY(true);
58 |
59 | LineGraphSeries series = new LineGraphSeries<>(new DataPoint[]{
60 | new DataPoint(0, 1),
61 | new DataPoint(1, 2),
62 | new DataPoint(2, 3),
63 | new DataPoint(3, 4),
64 | new DataPoint(4, 4),
65 | new DataPoint(5, 4)
66 | });
67 |
68 | GridLabelRenderer gridLabel = graphview.getGridLabelRenderer();
69 | gridLabel.setHorizontalAxisTitle("Operational Intensity (FLOPS/byte)");
70 | gridLabel.setVerticalAxisTitle("Performance (GFLOPS)");
71 |
72 | graphview.setTitle("DSP Roofline");
73 |
74 | series.setTitle("DSP Roofline");
75 | series.setBackgroundColor(Color.GRAY);
76 | series.setColor(Color.BLACK);
77 | series.setDrawDataPoints(false);
78 | series.setDataPointsRadius(10);
79 | series.setThickness(7);
80 |
81 | graphview.addSeries(series);
82 | }
83 |
84 | /**
85 | * Setup a button to trigger the activation of the roofline process
86 | *
87 | * @param rootView
88 | */
89 | void setupButton(final View rootView) {
90 | // Register a callback on the toggle button to turn ON/OFF DSP activity
91 | final ToggleButton button = rootView.findViewById(R.id.toggle_runRoofline);
92 | button.setTextOn("Busy!");
93 | button.setTextOff("Run");
94 | button.setChecked(false); // set the current state of a toggle button
95 |
96 | button.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
97 |
98 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
99 |
100 | if (isChecked) { // enabled
101 | final SeekBar seekBar_mem = rootView.findViewById(R.id.seekBar_threadMem);
102 | final SeekBar seekBar_DSP = rootView.findViewById(R.id.seekBar_maxThreads);
103 | final SeekBar seekBar_opi = rootView.findViewById(R.id.seekBar_opIntensity);
104 |
105 | final int maxMemory = (1 << seekBar_mem.getProgress()) * MiB; // converting to bytes
106 | final int nThreads = seekBar_DSP.getProgress() + 1; // remember that seekbar starts at 0
107 | final int nFlops = (1 << seekBar_opi.getProgress()); // remember that seekbar starts at 0
108 |
109 | final Switch hvxSwitch = rootView.findViewById(R.id.switch_hvxMode);
110 | final boolean hvxMode = hvxSwitch.isChecked();
111 |
112 | DSPRoofline(nThreads, maxMemory, nFlops, hvxMode);
113 |
114 | button.setChecked(false);
115 | }
116 | }
117 | });
118 | }
119 |
120 | private void setupThreadCountSlider(final View rootView) {
121 | final SeekBar mSeekBar = rootView.findViewById(R.id.seekBar_maxThreads);
122 |
123 | final Switch toggle = rootView.findViewById(R.id.switch_hvxMode);
124 |
125 | int nCores = DSP_NumThreads(toggle.isChecked());
126 | mSeekBar.setProgress(nCores);
127 | mSeekBar.setMax(nCores - 1); // we start from 0, but we display +1
128 |
129 | TextView textView = rootView.findViewById(R.id.txtBox_maxThreads);
130 | textView.setText("Thread Count (" + Long.toString(mSeekBar.getProgress() + 1) + " Cores)"); // increment by 1 since bar starts from 0.
131 |
132 | mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
133 |
134 | public void onStopTrackingTouch(SeekBar seekBar) {
135 | }
136 |
137 | @Override
138 | public void onStartTrackingTouch(SeekBar seekBar) {
139 | }
140 |
141 | @Override
142 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
143 | TextView textView = rootView.findViewById(R.id.txtBox_maxThreads);
144 | textView.setText("Thread Count (" + Long.toString(mSeekBar.getProgress() + 1) + " Cores)");
145 | }
146 | });
147 | }
148 |
149 | private void setupOpIntensity(final View rootView) {
150 | final SeekBar mSeekBar = rootView.findViewById(R.id.seekBar_opIntensity);
151 | mSeekBar.setProgress(4); //fixme debug version
152 |
153 | TextView textView = rootView.findViewById(R.id.txtBox_opIntensity);
154 | textView.setText("Ops (" + Long.toString(1 << mSeekBar.getProgress()) + " FLOPS/byte)");
155 |
156 | final ToggleButton toggle = rootView.findViewById(R.id.toggle_runRoofline);
157 | mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
158 |
159 | @Override
160 | public void onStopTrackingTouch(SeekBar seekBar) {
161 | toggle.setChecked(false);
162 | }
163 |
164 | @Override
165 | public void onStartTrackingTouch(SeekBar seekBar) {
166 | toggle.setChecked(false);
167 | }
168 |
169 | @Override
170 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
171 | TextView textView = rootView.findViewById(R.id.txtBox_opIntensity);
172 | textView.setText("Ops (" + Long.toString(1 << mSeekBar.getProgress()) + " FLOPS/byte)");
173 | }
174 | });
175 | }
176 |
177 | private void setupMemorySlider(final View rootView) {
178 | final SeekBar mSeekBar = rootView.findViewById(R.id.seekBar_threadMem);
179 |
180 | TextView textView = rootView.findViewById(R.id.txtBox_threadMem);
181 | textView.setText("Memory Alloc. (" + Long.toString(1 << mSeekBar.getProgress()) + " MB)");
182 |
183 | final ToggleButton toggle = rootView.findViewById(R.id.toggle_runRoofline);
184 |
185 | mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
186 |
187 | @Override
188 | public void onStopTrackingTouch(SeekBar seekBar) {
189 | toggle.setChecked(false);
190 | }
191 |
192 | @Override
193 | public void onStartTrackingTouch(SeekBar seekBar) {
194 | toggle.setChecked(false);
195 | }
196 |
197 | @Override
198 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
199 | TextView textView = rootView.findViewById(R.id.txtBox_threadMem);
200 | textView.setText("Memory Alloc. (" + Long.toString(1 << mSeekBar.getProgress()) + " MB)");
201 | }
202 | });
203 | }
204 |
205 | private void setupSwitch(final View rootView) {
206 | final Switch hvxSwitch = rootView.findViewById(R.id.switch_hvxMode);
207 |
208 | hvxSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
209 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
210 | TextView textView = rootView.findViewById(R.id.txtBox_hvxSwitch);
211 | if (isChecked) {
212 | textView.setText("HVX Vectorization (Enabled)");
213 | } else {
214 | textView.setText("HVX Vectorization (Disabled)");
215 | }
216 |
217 | SeekBar mSeekBar = rootView.findViewById(R.id.seekBar_maxThreads);
218 | int nCores = DSP_NumThreads(isChecked);
219 | mSeekBar.setMax(nCores - 1); // we start from 0, but we display +1
220 | mSeekBar.setProgress(nCores - 1);
221 |
222 | TextView textView2 = rootView.findViewById(R.id.txtBox_maxThreads);
223 | textView2.setText("Thread Count (" + Long.toString(mSeekBar.getProgress() + 1) + " Cores)"); // increment by 1 since bar starts from 0.
224 | }
225 | });
226 | }
227 |
228 | @Override
229 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
230 | Bundle savedInstanceState) {
231 | View rootView = inflater.inflate(R.layout.fragment_dsp_roofline, container, false);
232 |
233 | drawGraph(rootView);
234 |
235 | setupMemorySlider(rootView);
236 | setupThreadCountSlider(rootView);
237 | setupOpIntensity(rootView);
238 |
239 | setupSwitch(rootView);
240 |
241 | setupButton(rootView);
242 |
243 | return rootView;
244 | }
245 |
246 | private void writeToSDFile(File dir, String filename, String ostr) {
247 |
248 | boolean success = true;
249 | if (!dir.exists()) {
250 | success = dir.mkdir(); // FIXME: if this fails, then you might have to request permission in app settings.
251 | }
252 | if (success) {
253 | Log.i(TAG, "Output directory created.");
254 | } else {
255 | Log.i(TAG, "Output directory NOT created!");
256 | }
257 |
258 | File file = new File(dir, filename);
259 |
260 | try {
261 | FileOutputStream fos = new FileOutputStream(file);
262 | fos.write(ostr.getBytes());
263 | fos.close();
264 | } catch (FileNotFoundException e) {
265 | e.printStackTrace();
266 | Log.i(TAG, "******* File not found. Did you" +
267 | " add a WRITE_EXTERNAL_STORAGE permission to the manifest?");
268 | } catch (IOException e) {
269 | e.printStackTrace();
270 | }
271 | Log.i(TAG, "\n\nFile written to " + file);
272 | }
273 |
274 | public void DSPRoofline(int nThreads, int maxMemory, int nFlops, boolean hvx) {
275 | DSPRooflineAsync rooflineATask = new DSPRooflineAsync(getActivity(),
276 | nThreads, maxMemory, nFlops, hvx);
277 |
278 | rooflineATask.execute();
279 | }
280 |
281 | class DSPRooflineAsync extends AsyncTask {
282 | final int threads, mem, flops;
283 | final boolean hvx;
284 | private AsyncTask currTask = null;
285 |
286 | public DSPRooflineAsync(Activity activity, int nThreads, int threadMem, int maxFlops, boolean hvx) {
287 | super();
288 |
289 | this.threads = nThreads;
290 | this.mem = threadMem;
291 | this.flops = maxFlops;
292 | this.hvx = hvx;
293 |
294 | gProcessDialog = new ProgressDialog(activity);
295 | }
296 |
297 | @Override
298 | protected void onPreExecute() {
299 | super.onPreExecute();
300 |
301 | currTask = this;
302 |
303 | gProcessDialog.setMax(100);
304 | gProcessDialog.setProgress(0);
305 | gProcessDialog.setTitle("Roofline in progress");
306 | gProcessDialog.setMessage("Starting up... ");
307 | gProcessDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
308 | gProcessDialog.setCancelable(false);
309 | gProcessDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
310 | @Override
311 | public void onClick(DialogInterface dialog, int which) {
312 | dialog.dismiss();
313 | currTask.cancel(true);
314 | }
315 | });
316 |
317 | gProcessDialog.show();
318 | }
319 |
320 | @Override
321 | protected String doInBackground(Void... params) {
322 | File root = android.os.Environment.getExternalStorageDirectory();
323 | File odir = new File(root.getAbsolutePath() + "/" + gResultsDir + "/");
324 | deleteDirectory(odir);
325 | Log.i(TAG, "Deleting the " + odir + " output directory.");
326 |
327 | // call some function that runs on the DSP
328 | DSP_Execute(mem, threads, flops, hvx);
329 |
330 | return "All done with AsyncTask!";
331 | }
332 |
333 | @Override
334 | protected void onProgressUpdate(String... msg) {
335 | super.onProgressUpdate(msg);
336 | gProcessDialog.setProgress(Integer.parseInt(msg[0]));
337 | gProcessDialog.setMessage(msg[1]);
338 | }
339 |
340 | // onCancelled() is called when the async task is cancelled.
341 | @Override
342 | protected void onCancelled(String result) {
343 | }
344 |
345 | protected void onPostExecute(String param) {
346 |
347 | gProcessDialog.setMessage("Finished processing data.");
348 |
349 | if (gProcessDialog.isShowing()) {
350 | gProcessDialog.dismiss();
351 | }
352 | }
353 | }
354 | }
355 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/gables/GPURoofline.java:
--------------------------------------------------------------------------------
1 | package com.google.gables;
2 |
3 |
4 | import android.app.Activity;
5 | import android.app.ProgressDialog;
6 | import android.content.DialogInterface;
7 | import android.content.res.AssetManager;
8 | import android.graphics.Bitmap;
9 | import android.graphics.BitmapFactory;
10 | import android.graphics.Color;
11 | import android.opengl.GLES31;
12 | import android.os.AsyncTask;
13 | import android.os.Bundle;
14 | import android.os.Environment;
15 | import android.support.v4.app.Fragment;
16 | import android.util.Log;
17 | import android.view.LayoutInflater;
18 | import android.view.View;
19 | import android.view.ViewGroup;
20 | import android.widget.CompoundButton;
21 | import android.widget.ImageView;
22 | import android.widget.SeekBar;
23 | import android.widget.TextView;
24 | import android.widget.ToggleButton;
25 |
26 | import com.jjoe64.graphview.GraphView;
27 | import com.jjoe64.graphview.GridLabelRenderer;
28 | import com.jjoe64.graphview.series.DataPoint;
29 | import com.jjoe64.graphview.series.LineGraphSeries;
30 | import com.synnapps.carouselview.CarouselView;
31 | import com.synnapps.carouselview.ImageListener;
32 |
33 | import java.io.File;
34 | import java.nio.IntBuffer;
35 |
36 | import gables.gables_processor.GablesPython;
37 |
38 | import static android.opengl.GLES31.GL_MAX_COMPUTE_WORK_GROUP_COUNT;
39 | import static android.opengl.GLES31.GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS;
40 | import static android.opengl.GLES31.GL_MAX_COMPUTE_WORK_GROUP_SIZE;
41 | import static com.google.gables.Roofline.GPU_Execute;
42 | import static com.google.gables.Roofline.GPU_Finish;
43 | import static com.google.gables.Roofline.GPU_Initialize;
44 | import static com.google.gables.Roofline.GPU_MaxWorkGroupCount;
45 | import static com.google.gables.Roofline.GPU_MaxWorkGroupSize;
46 | import static com.google.gables.Utils.ExtStoragePermissions_t.EXT_STORAGE_RW;
47 | import static com.google.gables.Utils.MiB;
48 | import static com.google.gables.Utils.deleteDirectory;
49 | import static com.google.gables.Utils.isStorageAvailable;
50 | import static com.google.gables.Utils.log;
51 | import static com.google.gables.Utils.writeToSDFile;
52 |
53 | public class GPURoofline extends Fragment {
54 | private static final String TAG = GPURoofline.class.getName();
55 |
56 | private ProgressDialog gProcessDialog;
57 | private String gResultsDir = "GPURoofline";
58 | private CarouselView slider;
59 | private View slidePrompt, edgeLogo;
60 | @Override
61 | public void onCreate(Bundle savedInstanceState) {
62 | super.onCreate(savedInstanceState);
63 | }
64 |
65 | // void drawGraph(View rootView) {
66 | // // Setup a graph view
67 | // GraphView graphview = rootView.findViewById(R.id.graph);
68 | //
69 | // // activate horizontal zooming and scrolling
70 | // graphview.getViewport().setScalable(false);
71 | // graphview.getViewport().setScrollable(true);
72 | // graphview.getViewport().setScalableY(false);
73 | // graphview.getViewport().setScrollableY(true);
74 | //
75 | // LineGraphSeries series = new LineGraphSeries<>(new DataPoint[]{
76 | // new DataPoint(0, 1),
77 | // new DataPoint(1, 2),
78 | // new DataPoint(2, 3)
79 | // });
80 | //
81 | // GridLabelRenderer gridLabel = graphview.getGridLabelRenderer();
82 | // gridLabel.setHorizontalAxisTitle("Operational Intensity (FLOPS/byte)");
83 | // gridLabel.setVerticalAxisTitle("Performance (GFLOPS)");
84 | //
85 | // graphview.setTitle("GPU Roofline");
86 | //
87 | // series.setTitle("GPU Roofline");
88 | // series.setBackgroundColor(Color.GRAY);
89 | // series.setColor(Color.BLACK);
90 | // series.setDrawDataPoints(false);
91 | // series.setDataPointsRadius(10);
92 | // series.setThickness(7);
93 | //
94 | // graphview.addSeries(series);
95 | //
96 | // Log.d(TAG, "Finished drawing graphview for GPU Roofline");
97 | // }
98 |
99 | void printOpenGLInfo() { //fixme, if this works i can get rid of the GPU JNI calls.
100 | IntBuffer work_grp_info = IntBuffer.allocate(3);
101 |
102 | // maximum global work group (total work in a dispatch)
103 | GLES31.glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_COUNT, work_grp_info);
104 | Log.i(TAG, "max global (total) work group size x:" + work_grp_info.get(0)
105 | + " y: " + work_grp_info.get(1)
106 | + " z: " + work_grp_info.get(2));
107 |
108 | // maximum local work group (one shader's slice)
109 | GLES31.glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_SIZE, work_grp_info);
110 | Log.i(TAG, "max local (in one shader) work group sizes x:" + work_grp_info.get(0)
111 | + " y: " + work_grp_info.get(1)
112 | + " z: " + work_grp_info.get(2));
113 |
114 | IntBuffer work_grp_invo = IntBuffer.allocate(1);
115 | // maximum compute shader invocations (x * y * z)
116 | GLES31.glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, work_grp_invo);
117 | Log.i(TAG, "max computer shader invocations: " + work_grp_invo.get(0));
118 | }
119 |
120 | /**
121 | * Setup a button to trigger the activation of the roofline process
122 | *
123 | * @param rootView
124 | */
125 | void setupButton(final View rootView) {
126 | // Register a callback on the toggle button to turn ON/OFF cpu activity
127 | final ToggleButton button = rootView.findViewById(R.id.toggle_runRoofline);
128 | button.setTextOn("Busy!");
129 | button.setTextOff("Run");
130 | button.setChecked(false); // set the current state of a toggle button
131 |
132 | button.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
133 |
134 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
135 |
136 | if (isChecked) { // enabled
137 | SeekBar seekBar_maxWorkGroupCount = rootView.findViewById(R.id.seekBar_maxWorkGroupCount);
138 | SeekBar seekBar_maxWorkGroupSize = rootView.findViewById(R.id.seekBar_maxWorkGroupSize);
139 | SeekBar seekBar_opIntensity = rootView.findViewById(R.id.seekBar_opIntensity);
140 | SeekBar seekBar_memSize = rootView.findViewById(R.id.seekBar_maxMemory);
141 |
142 | int nGroups = 1 << seekBar_maxWorkGroupCount.getProgress(); // 2^maxGroups
143 | int nThreads = 1 << seekBar_maxWorkGroupSize.getProgress(); // 2^maxThreads
144 | int nFlops = 1 << seekBar_opIntensity.getProgress(); // 2^flops
145 | int memSize = (1 << seekBar_memSize.getProgress()) * MiB; // MB
146 |
147 | GPURooflineAsync(nGroups, nThreads, nFlops, memSize);
148 |
149 | button.setChecked(false);
150 | }
151 | }
152 | });
153 | }
154 |
155 | public void GPURooflineAsync(int nGroups, int nThreads, int nFlops, int memSize) {
156 | GPURooflineAsyncTask rooflineATask = new GPURooflineAsyncTask(getActivity(),
157 | nGroups, nThreads, nFlops, memSize);
158 | rooflineATask.execute();
159 | }
160 |
161 | private void setupMemAllocSlider(final View rootView) {
162 | final SeekBar mSeekBar = rootView.findViewById(R.id.seekBar_maxMemory);
163 |
164 | TextView textView = rootView.findViewById(R.id.textView_maxMemory);
165 | textView.setText("Memory Alloc. (" + Long.toString(1 << mSeekBar.getProgress()) + " MB)");
166 |
167 | final ToggleButton toggle = rootView.findViewById(R.id.toggle_runRoofline);
168 |
169 | mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
170 |
171 | @Override
172 | public void onStopTrackingTouch(SeekBar seekBar) {
173 | toggle.setChecked(false);
174 | }
175 |
176 | @Override
177 | public void onStartTrackingTouch(SeekBar seekBar) {
178 | toggle.setChecked(false);
179 | }
180 |
181 | @Override
182 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
183 | TextView textView = rootView.findViewById(R.id.textView_maxMemory);
184 | textView.setText("Memory Alloc. (" + Long.toString(1 << mSeekBar.getProgress()) + " MB)");
185 | }
186 | });
187 | }
188 |
189 | private void setupOpIntensitySlider(final View rootView) {
190 | final SeekBar mSeekBar = rootView.findViewById(R.id.seekBar_opIntensity);
191 |
192 | mSeekBar.setProgress(mSeekBar.getMax()); //fixme: use setMin() but that's not available till API level 26
193 |
194 | TextView textView = rootView.findViewById(R.id.txtBox_opIntensity);
195 | textView.setText("Ops (" + Long.toString(1 << mSeekBar.getProgress()) + " FLOPS/byte)");
196 |
197 | final ToggleButton toggle = rootView.findViewById(R.id.toggle_runRoofline);
198 | mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
199 |
200 | @Override
201 | public void onStopTrackingTouch(SeekBar seekBar) {
202 | toggle.setChecked(false);
203 | }
204 |
205 | @Override
206 | public void onStartTrackingTouch(SeekBar seekBar) {
207 | toggle.setChecked(false);
208 | }
209 |
210 | @Override
211 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
212 | TextView textView = rootView.findViewById(R.id.txtBox_opIntensity);
213 | textView.setText("Ops (" + Long.toString(1 << mSeekBar.getProgress()) + " FLOPS/byte)");
214 | }
215 | });
216 | }
217 |
218 | private void setupMaxWorkGroupSizeSlider(final View rootView) {
219 | final SeekBar mSeekBar = rootView.findViewById(R.id.seekBar_maxWorkGroupSize);
220 |
221 | // determine the maximum number of threads per work group
222 | GPU_Initialize();
223 | int maxThreads = GPU_MaxWorkGroupSize(0);
224 | GPU_Finish();
225 |
226 | mSeekBar.setMax((int) Math.ceil(log(maxThreads, 2)));
227 | mSeekBar.setProgress((int) Math.ceil(log(256, 2)));
228 |
229 | TextView textView = rootView.findViewById(R.id.txtBox_maxThreads);
230 | textView.setText("Work Group Size (" + Integer.toString(1 << mSeekBar.getProgress()) + ")"); // increment by 1 since bar starts from 0.
231 |
232 | final ToggleButton toggle = rootView.findViewById(R.id.toggle_runRoofline);
233 | mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
234 |
235 | @Override
236 | public void onStopTrackingTouch(SeekBar seekBar) {
237 | toggle.setChecked(false);
238 | }
239 |
240 | @Override
241 | public void onStartTrackingTouch(SeekBar seekBar) {
242 | toggle.setChecked(false);
243 | }
244 |
245 | @Override
246 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
247 | TextView textView = rootView.findViewById(R.id.txtBox_maxThreads);
248 | int maxThreads = (int) Math.pow(2, mSeekBar.getProgress());
249 | textView.setText("Work Group Size (" + Integer.toString(maxThreads) + ")");
250 | }
251 | });
252 | }
253 |
254 | private void setupMaxWorkGroupCountSlider(final View rootView) {
255 | final SeekBar mSeekBar = rootView.findViewById(R.id.seekBar_maxWorkGroupCount);
256 |
257 | GPU_Initialize();
258 | int maxGroups = GPU_MaxWorkGroupCount(0);
259 | GPU_Finish();
260 |
261 | mSeekBar.setMax((int) Math.ceil(log(maxGroups, 2)));
262 | mSeekBar.setProgress((int) Math.ceil(log(1024, 2)));
263 |
264 | TextView textView = rootView.findViewById(R.id.txtBox_maxWorkGroups);
265 | textView.setText("Work Group Count (" + Integer.toString(1 << mSeekBar.getProgress()) + ")"); // increment by 1 since bar starts from 0.
266 |
267 | final ToggleButton toggle = rootView.findViewById(R.id.toggle_runRoofline);
268 | mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
269 |
270 | @Override
271 | public void onStopTrackingTouch(SeekBar seekBar) {
272 | toggle.setChecked(false);
273 | }
274 |
275 | @Override
276 | public void onStartTrackingTouch(SeekBar seekBar) {
277 | toggle.setChecked(false);
278 | }
279 |
280 | @Override
281 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
282 | TextView textView = rootView.findViewById(R.id.txtBox_maxWorkGroups);
283 | int maxGroups = (int) Math.pow(2, mSeekBar.getProgress());
284 | textView.setText("Work Group Count (" + Integer.toString(maxGroups) + ")");
285 | }
286 | });
287 | }
288 |
289 | @Override
290 | public void onDestroyView() {
291 | super.onDestroyView();
292 | Log.d(TAG, "onDestryView being called to terminate openGL.");
293 | }
294 |
295 | @Override
296 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
297 | Bundle savedInstanceState) {
298 | View rootView = inflater.inflate(R.layout.fragment_gpu_roofline, container, false);
299 |
300 | // drawGraph(rootView);
301 |
302 | setupMaxWorkGroupCountSlider(rootView);
303 | setupMaxWorkGroupSizeSlider(rootView);
304 | setupOpIntensitySlider(rootView);
305 | setupMemAllocSlider(rootView);
306 |
307 | setupButton(rootView);
308 |
309 | slider = rootView.findViewById(R.id.carouselView);
310 | slidePrompt = rootView.findViewById(R.id.swipe_prompt);
311 | edgeLogo = rootView.findViewById(R.id.edge_logo);
312 | return rootView;
313 | }
314 |
315 | private void setupSlider() {
316 | ImageListener imageListener = new ImageListener() {
317 | @Override
318 | public void setImageForPosition(int position, ImageView imageView) {
319 | String filename = "";
320 | switch (position) {
321 | case 0:
322 | default:
323 | filename = "/sdcard/GPURoofline/roofline.png";
324 | break;
325 | case 1:
326 | filename = "/sdcard/GPURoofline/bandwidth.png";
327 | break;
328 | }
329 | displayGraph(filename, imageView);
330 | }
331 | };
332 | slider.setImageListener(imageListener);
333 | slider.setPageCount(2);
334 | slider.setVisibility(View.VISIBLE);
335 | slidePrompt.setVisibility(View.VISIBLE);
336 | edgeLogo.setVisibility(View.GONE);
337 | }
338 |
339 | public void displayGraph(String filename, ImageView view) {
340 | File file = new File(filename);
341 | if (file.exists()) {
342 | Bitmap myBitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
343 | view.setImageBitmap(myBitmap);
344 | }
345 | }
346 | class GPURooflineAsyncTask extends AsyncTask {
347 | final int threads, groups, flops, mem;
348 | AssetManager mgr;
349 | private AsyncTask currTask = null;
350 |
351 |
352 | public GPURooflineAsyncTask(Activity activity, int nGroups, int nThreads, int maxFlops, int memSize) {
353 | super();
354 |
355 | this.groups = nGroups;
356 | this.threads = nThreads;
357 | this.flops = maxFlops;
358 | this.mgr = activity.getAssets();
359 | this.mem = memSize;
360 |
361 | gProcessDialog = new ProgressDialog(activity);
362 | }
363 |
364 | @Override
365 | protected void onPreExecute() {
366 | super.onPreExecute();
367 |
368 | currTask = this;
369 |
370 | gProcessDialog.setMax(100);
371 | gProcessDialog.setProgress(0);
372 | gProcessDialog.setTitle("Roofline in progress");
373 | gProcessDialog.setMessage("Starting up... ");
374 | gProcessDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
375 | gProcessDialog.setCancelable(false);
376 | gProcessDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
377 | @Override
378 | public void onClick(DialogInterface dialog, int which) {
379 | dialog.dismiss();
380 | currTask.cancel(true);
381 | }
382 | });
383 |
384 | gProcessDialog.show();
385 | }
386 |
387 | @Override
388 | protected String doInBackground(Void... params) {
389 | File root = Environment.getExternalStorageDirectory();
390 | File odir = new File(root.getAbsolutePath() + "/" + gResultsDir + "/");
391 | deleteDirectory(odir);
392 | Log.i(TAG, "Deleting the " + odir + " output directory.");
393 |
394 | // storage for updating progress of the work to progress bar
395 | int progressCounter = 0;
396 | final int progressTotal = (log(flops, 2) + 1)
397 | * (log(threads, 2) + 1)
398 | * (log(groups, 2) + 1);
399 |
400 | int g = groups;
401 | int f = flops;
402 | int t = threads;
403 | GPU_Initialize();
404 | if (g == 65536) { // fixme: make this more generic.
405 | g--;
406 | }
407 | String strCurrProgress = String.valueOf(Math.round(100.0 * progressCounter / progressTotal));
408 | String message = "Running " + f + " FLOPS/byte with " + "<" + g + ", " + t + ">.";
409 | publishProgress(strCurrProgress, message);
410 | Log.i(TAG, message);
411 |
412 | String output = GPU_Execute(mgr, g, t, f, mem);
413 | Log.d(TAG, "Finished " + message);
414 |
415 | if (isStorageAvailable(EXT_STORAGE_RW)) {
416 | message = "Writing results to storage.";
417 | publishProgress(strCurrProgress, message);
418 |
419 | String ofilename = "groups-" + g + "_threads-" + t + "_flops-" + f + ".gables";
420 | writeToSDFile(odir, ofilename, output);
421 | } else {
422 | Log.e(TAG, "Storage is not available for RW or is unavailable.");
423 | }
424 | // // we've made progress so update
425 | // progressCounter++;
426 | GPU_Finish();
427 | Log.i(TAG, "Finished doing all the sweeps.");
428 |
429 | return "All done with AsyncTask!";
430 | }
431 |
432 | @Override
433 | protected void onProgressUpdate(String... msg) {
434 | super.onProgressUpdate(msg);
435 | gProcessDialog.setProgress(Integer.parseInt(msg[0]));
436 | gProcessDialog.setMessage(msg[1]);
437 | }
438 |
439 | // onCancelled() is called when the async task is cancelled.
440 | @Override
441 | protected void onCancelled(String result) {
442 | }
443 |
444 | protected void onPostExecute(String param) {
445 |
446 | gProcessDialog.setMessage("Finished processing data.");
447 |
448 | new GablesPython().processGPURoofline();
449 | setupSlider();
450 |
451 | if (gProcessDialog.isShowing()) {
452 | gProcessDialog.dismiss();
453 | }
454 | }
455 | }
456 | }
457 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/gables/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.google.gables;
2 |
3 | import android.Manifest;
4 | import android.content.Context;
5 | import android.content.pm.PackageManager;
6 | import android.os.Bundle;
7 | import android.support.annotation.NonNull;
8 | import android.support.annotation.Nullable;
9 | import android.support.design.widget.FloatingActionButton;
10 | import android.support.design.widget.Snackbar;
11 | import android.support.design.widget.TabLayout;
12 | import android.support.v4.app.ActivityCompat;
13 | import android.support.v4.app.Fragment;
14 | import android.support.v4.app.FragmentManager;
15 | import android.support.v4.app.FragmentPagerAdapter;
16 | import android.support.v4.content.ContextCompat;
17 | import android.support.v4.view.ViewPager;
18 | import android.support.v7.app.AppCompatActivity;
19 | import android.util.AttributeSet;
20 | import android.view.Menu;
21 | import android.view.MenuItem;
22 | import android.view.MotionEvent;
23 | import android.view.View;
24 |
25 | import com.google.gables.utils.NonSwipeViewPager;
26 |
27 | public class MainActivity extends AppCompatActivity {
28 |
29 | static final Integer WRITE_EXST = 0x3;
30 | static final Integer READ_EXST = 0x4;
31 | /**
32 | * The {@link android.support.v4.view.PagerAdapter} that will provide
33 | * fragments for each of the sections. We use a
34 | * {@link FragmentPagerAdapter} derivative, which will keep every
35 | * loaded fragment in memory. If this becomes too memory intensive, it
36 | * may be best to switch to a
37 | * {@link android.support.v4.app.FragmentStatePagerAdapter}.
38 | */
39 | private SectionsPagerAdapter mSectionsPagerAdapter;
40 | /**
41 | * The {@link ViewPager} that will host the section contents.
42 | */
43 | private NonSwipeViewPager mViewPager;
44 |
45 | @Override
46 | protected void onCreate(Bundle savedInstanceState) {
47 | super.onCreate(savedInstanceState);
48 | setContentView(R.layout.activity_main);
49 |
50 | // Create the adapter that will return a fragment for each of the three
51 | // primary sections of the activity.
52 | mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
53 |
54 | // Set up the ViewPager with the sections adapter.
55 | mViewPager = findViewById(R.id.container);
56 | mViewPager.setAdapter(mSectionsPagerAdapter);
57 |
58 | TabLayout tabLayout = findViewById(R.id.tabs);
59 | tabLayout.setupWithViewPager(mViewPager);
60 |
61 | askForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, WRITE_EXST);
62 | askForPermission(Manifest.permission.READ_EXTERNAL_STORAGE, READ_EXST);
63 | }
64 |
65 | /**
66 | * This application stores data to the storage, and so we need to get access to that from the user.
67 | *
68 | * @param permission
69 | * @param requestCode
70 | */
71 | private void askForPermission(String permission, Integer requestCode) { // FIXME Need to check onRequestPermission
72 | if (ContextCompat.checkSelfPermission(MainActivity.this, permission) != PackageManager.PERMISSION_GRANTED) {
73 | // Should we show an explanation?
74 | if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, permission)) {
75 | //This is called if user has denied the permission before
76 | //In this case I am just asking the permission again
77 | ActivityCompat.requestPermissions(MainActivity.this, new String[]{permission}, requestCode);
78 | } else {
79 | ActivityCompat.requestPermissions(MainActivity.this, new String[]{permission}, requestCode);
80 | }
81 | }
82 | }
83 |
84 | @Override
85 | public boolean onCreateOptionsMenu(Menu menu) {
86 | // Inflate the menu; this adds items to the action bar if it is present.
87 | getMenuInflater().inflate(R.menu.menu_main, menu);
88 | return true;
89 | }
90 |
91 | @Override
92 | public boolean onTouchEvent(MotionEvent event) {
93 | return false;
94 | }
95 |
96 | @Override
97 | public boolean onOptionsItemSelected(MenuItem item) {
98 | // Handle action bar item clicks here. The action bar will
99 | // automatically handle clicks on the Home/Up button, so long
100 | // as you specify a parent activity in AndroidManifest.xml.
101 | int id = item.getItemId();
102 |
103 | //noinspection SimplifiableIfStatement
104 | if (id == R.id.action_settings) {
105 | return true;
106 | }
107 |
108 | return super.onOptionsItemSelected(item);
109 | }
110 | /**
111 | * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
112 | * one of the sections/tabs/pages.
113 | */
114 | public class SectionsPagerAdapter extends FragmentPagerAdapter {
115 |
116 | public SectionsPagerAdapter(FragmentManager fm) {
117 | super(fm);
118 | }
119 |
120 | @Override
121 | public Fragment getItem(int position) {
122 | // getItem is called to instantiate the fragment for the given page.
123 | // Return a PlaceholderFragment (defined as a static inner class below).
124 | switch (position) {
125 | // case 0:
126 | // DSPRoofline dspRoofline = new DSPRoofline();
127 | // return dspRoofline;
128 | // case 1:
129 | // SOCRoofline socRoofline = new SOCRoofline();
130 | // return socRoofline;
131 | case 0:
132 | CPURoofline cpuRoofline = new CPURoofline();
133 | return cpuRoofline;
134 | case 1:
135 | GPURoofline gpuRoofline = new GPURoofline();
136 | return gpuRoofline;
137 | default:
138 | return null;
139 | }
140 | }
141 |
142 | @Override
143 | public CharSequence getPageTitle(int position) {
144 | switch (position) {
145 | case 0:
146 | return "CPU Roofline";
147 | case 1:
148 | return "GPU Roofline";
149 | }
150 | return null;
151 | }
152 |
153 | @Override
154 | public int getCount() {
155 | return 2;
156 | }
157 |
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/gables/Roofline.java:
--------------------------------------------------------------------------------
1 | package com.google.gables;
2 |
3 | import android.content.res.AssetManager;
4 | import android.util.Log;
5 |
6 | public class Roofline {
7 | private static final String TAG = DSPRoofline.class.getName();
8 |
9 | /* ================================================================================= */
10 | /* Library providing functionality */
11 | /* ================================================================================= */
12 | static {
13 | String filename;
14 |
15 | filename = "roofline";
16 | try {
17 | System.loadLibrary(filename);
18 | Log.i(TAG, filename + " successfully loaded!");
19 | } catch (UnsatisfiedLinkError e) {
20 | Log.e(TAG, filename + " NOT successfully loaded: " + e);
21 | Log.e(TAG, "Terminating application because library not found.");
22 | android.os.Process.killProcess(android.os.Process.myPid());
23 | }
24 |
25 | // filename = "gables";
26 | // try {
27 | // System.loadLibrary(filename);
28 | // Log.i(TAG, filename + " successfully loaded!");
29 | // } catch (UnsatisfiedLinkError e) {
30 | // Log.e(TAG, filename + " NOT successfully loaded: " + e);
31 | // Log.e(TAG, "Terminating application because library not found.");
32 | // android.os.Process.killProcess(android.os.Process.myPid());
33 | // }
34 | }
35 |
36 | /* ================================================================================= */
37 | /* GPU code */
38 | /* ================================================================================= */
39 |
40 | public static boolean GPU_Initialize() {
41 | return new Roofline().GPUInitOpenGL();
42 | }
43 |
44 | public static boolean GPU_Finish() {
45 | return new Roofline().GPUFiniOpenGL();
46 | }
47 |
48 | public static int GPU_MaxWorkGroupSize(int dim) {
49 | return new Roofline().GPUMaxWorkGroupSize(dim);
50 | }
51 |
52 | public static int GPU_MaxWorkGroupCount(int dim) {
53 | return new Roofline().GPUMaxWorkGroupCount(dim);
54 | }
55 |
56 | public static int GPU_MaxThreadInnovations(int dim) {
57 | return new Roofline().GPUMaxThreadInnovations(dim);
58 | }
59 |
60 | public static String GPU_Execute(AssetManager mgr, int nGroups, int nThreads, int nFlops, int memSize) {
61 | return new Roofline().GPUExecute(mgr, nGroups, nThreads, nFlops, memSize);
62 | }
63 |
64 | public static String CPU_Execute(int memTotal, int nThreads, int nFlops, boolean neon) {
65 | return new Roofline().CPUExecute(memTotal, nThreads, nFlops, neon);
66 | }
67 |
68 | public static String DSP_Execute(int memTotal, int nThreads, int nFlops, boolean hvx) {
69 | return new Roofline().DSPExecute(memTotal, nThreads, nFlops, hvx);
70 | }
71 |
72 | public static int DSP_NumThreads(boolean hvx) {
73 | return new Roofline().DSPNumThreads(hvx);
74 | }
75 |
76 | public static String SOC_Mixer(int memTotal, int nFlops, float cpuWorkFraction, int cpuThreads, int gpuWorkGroupSize, int gpuWorkItemSize) {
77 | return new Roofline().SOCMixer(memTotal, nFlops, cpuWorkFraction, cpuThreads, gpuWorkGroupSize, gpuWorkItemSize);
78 | }
79 |
80 | public static int Utils_SetEnvLibraryPath(String var, String path) {
81 | return new Roofline().UtilsSetEnvLibraryPath(var, path);
82 | }
83 |
84 | /* ================================================================================= */
85 | /* GPU code */
86 | /* ================================================================================= */
87 | private native int GPUMaxWorkGroupSize(int dim);
88 |
89 | private native int GPUMaxWorkGroupCount(int dim);
90 |
91 | private native int GPUMaxThreadInnovations(int dim);
92 |
93 | private native boolean GPUInitOpenGL();
94 |
95 | private native boolean GPUFiniOpenGL();
96 |
97 | private native String GPUExecute(AssetManager mgr, int nGroups, int nThreads, int nFlops, int memSize);
98 |
99 | /* ================================================================================= */
100 | /* CPU code */
101 | /* ================================================================================= */
102 | private native String CPUExecute(int maxMem, int nThreads, int nFlops, boolean neon);
103 |
104 | /* ================================================================================= */
105 | /* DSP code */
106 | /* ================================================================================= */
107 | private native String DSPExecute(int maxMem, int nThreads, int nFlops, boolean hvx);
108 |
109 | private native int DSPNumThreads(boolean hvx);
110 |
111 | /* ================================================================================= */
112 | /* SOC code */
113 | /* ================================================================================= */
114 | private native String SOCMixer(int memTotal, int nFlops, float cpuWorkFraction, int cpuThreads, int gpuWorkGroupSize, int gpuWorkItemSize);
115 |
116 | /* ================================================================================= */
117 | /* Utils code
118 | /* ================================================================================= */
119 | private native int UtilsSetEnvLibraryPath(String var, String path);
120 | }
121 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/gables/SOCRoofline.java:
--------------------------------------------------------------------------------
1 | package com.google.gables;
2 |
3 | import android.app.Activity;
4 | import android.app.ProgressDialog;
5 | import android.content.DialogInterface;
6 | import android.graphics.Color;
7 | import android.graphics.PorterDuff;
8 | import android.os.AsyncTask;
9 | import android.os.Bundle;
10 | import android.support.v4.app.Fragment;
11 | import android.util.Log;
12 | import android.view.LayoutInflater;
13 | import android.view.View;
14 | import android.view.ViewGroup;
15 | import android.widget.CompoundButton;
16 | import android.widget.SeekBar;
17 | import android.widget.TextView;
18 | import android.widget.ToggleButton;
19 |
20 | import java.io.File;
21 |
22 | import static com.google.gables.Roofline.GPU_Finish;
23 | import static com.google.gables.Roofline.GPU_Initialize;
24 | import static com.google.gables.Roofline.GPU_MaxWorkGroupCount;
25 | import static com.google.gables.Roofline.GPU_MaxWorkGroupSize;
26 | import static com.google.gables.Roofline.SOC_Mixer;
27 | import static com.google.gables.Utils.ExtStoragePermissions_t.EXT_STORAGE_RW;
28 | import static com.google.gables.Utils.MiB;
29 | import static com.google.gables.Utils.deleteDirectory;
30 | import static com.google.gables.Utils.getNumberOfCores;
31 | import static com.google.gables.Utils.isStorageAvailable;
32 | import static com.google.gables.Utils.log;
33 | import static com.google.gables.Utils.writeToSDFile;
34 |
35 | public class SOCRoofline extends Fragment {
36 | private static final String TAG = SOCRoofline.class.getName();
37 |
38 | private ProgressDialog gProcessDialog;
39 | private String gResultsDir = "SOCRoofline";
40 |
41 | private void setupMemorySlider(final View rootView) {
42 | final SeekBar mSeekBar = rootView.findViewById(R.id.seekBar_totalMem);
43 |
44 | TextView textView = rootView.findViewById(R.id.txtBox_totalMem);
45 | textView.setText("Total Memory Alloc. (" + Long.toString(1 << mSeekBar.getProgress()) + " MB)");
46 |
47 | final ToggleButton toggle = rootView.findViewById(R.id.toggle_runMixer);
48 |
49 | mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
50 |
51 | @Override
52 | public void onStopTrackingTouch(SeekBar seekBar) {
53 | toggle.setChecked(false);
54 | }
55 |
56 | @Override
57 | public void onStartTrackingTouch(SeekBar seekBar) {
58 | toggle.setChecked(false);
59 | }
60 |
61 | @Override
62 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
63 | TextView textView = rootView.findViewById(R.id.txtBox_totalMem);
64 | textView.setText("Total Memory Alloc. (" + Long.toString(1 << mSeekBar.getProgress()) + " MB)");
65 |
66 | // need to update associated text
67 | setupWorkFractionSlider(rootView);
68 | }
69 | });
70 | }
71 |
72 | private void setupMaxWorkGroupSizeSlider(final View rootView) {
73 | final SeekBar mSeekBar = rootView.findViewById(R.id.seekBar_maxGPUWorkgroupSize);
74 |
75 | // determine the maximum number of threads per work group
76 | GPU_Initialize();
77 | int maxThreads = GPU_MaxWorkGroupCount(0);
78 | GPU_Finish();
79 |
80 | mSeekBar.setMax((int) Math.ceil(log(maxThreads, 2)));
81 |
82 | mSeekBar.setProgress((int) Math.ceil(log(1024, 2))); //fixme: remove hardcode
83 |
84 | TextView textView = rootView.findViewById(R.id.txtBox_maxThreads6);
85 | maxThreads = (int) Math.pow(2, mSeekBar.getProgress());
86 | textView.setText("GPU Work Group Size (" + Integer.toString(1 << mSeekBar.getProgress()) + ")"); // increment by 1 since bar starts from 0.
87 |
88 | final ToggleButton toggle = rootView.findViewById(R.id.toggle_runMixer);
89 | mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
90 |
91 | @Override
92 | public void onStopTrackingTouch(SeekBar seekBar) {
93 | toggle.setChecked(false);
94 | }
95 |
96 | @Override
97 | public void onStartTrackingTouch(SeekBar seekBar) {
98 | toggle.setChecked(false);
99 | }
100 |
101 | @Override
102 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
103 | TextView textView = rootView.findViewById(R.id.txtBox_maxThreads6);
104 | int currSize = (int) Math.pow(2, mSeekBar.getProgress());
105 | textView.setText("GPU Work Group Size (" + Integer.toString(currSize) + ")");
106 | }
107 | });
108 | }
109 |
110 | private void setupMaxWorkGroupItemsSlider(final View rootView) {
111 | final SeekBar mSeekBar = rootView.findViewById(R.id.seekBar_maxGPUWorkItems);
112 |
113 | GPU_Initialize();
114 | int maxGroups = GPU_MaxWorkGroupSize(0);
115 | GPU_Finish();
116 |
117 | mSeekBar.setMax((int) Math.ceil(log(maxGroups, 2)));
118 | mSeekBar.setProgress((int) Math.ceil(log(256, 2)));
119 |
120 | TextView textView = rootView.findViewById(R.id.txtBox_maxThreads4);
121 | textView.setText("GPU Work Items (" + Integer.toString(1 << mSeekBar.getProgress()) + ")"); // increment by 1 since bar starts from 0.
122 |
123 | final ToggleButton toggle = rootView.findViewById(R.id.toggle_runMixer);
124 | mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
125 |
126 | @Override
127 | public void onStopTrackingTouch(SeekBar seekBar) {
128 | toggle.setChecked(false);
129 | }
130 |
131 | @Override
132 | public void onStartTrackingTouch(SeekBar seekBar) {
133 | toggle.setChecked(false);
134 | }
135 |
136 | @Override
137 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
138 | TextView textView = rootView.findViewById(R.id.txtBox_maxThreads4);
139 | int currSize = (int) Math.pow(2, mSeekBar.getProgress());
140 | textView.setText("GPU Work Items (" + Integer.toString(currSize) + ")");
141 | }
142 | });
143 | }
144 |
145 | private void setupWorkFractionSlider(final View rootView) {
146 | final SeekBar mSeekBar = rootView.findViewById(R.id.seekBar_workFraction);
147 | final SeekBar seekBarTotalMem = rootView.findViewById(R.id.seekBar_totalMem);
148 |
149 | mSeekBar.getProgressDrawable().setColorFilter(Color.YELLOW, PorterDuff.Mode.MULTIPLY);
150 | mSeekBar.getThumb().setColorFilter(Color.LTGRAY, PorterDuff.Mode.MULTIPLY);
151 |
152 | final TextView cpuTextView = rootView.findViewById(R.id.txtBox_workFractionCPU);
153 | final TextView gpuTextView = rootView.findViewById(R.id.txtBox_workFractionGPU);
154 | final TextView wrkTextView = rootView.findViewById(R.id.txtBox_workFraction);
155 |
156 | final ToggleButton toggle = rootView.findViewById(R.id.toggle_runMixer);
157 |
158 | float cpu_frac = (float) mSeekBar.getProgress() / mSeekBar.getMax();
159 | int cpu_mb = (int) ((1 << seekBarTotalMem.getProgress()) * cpu_frac);
160 | int gpu_mb = (int) ((1 << seekBarTotalMem.getProgress()) * (1.0 - cpu_frac));
161 |
162 | cpuTextView.setText("CPU (" + cpu_mb + " MB)");
163 | gpuTextView.setText("GPU (" + gpu_mb + " MB)");
164 | wrkTextView.setText("Workload Offload Fraction (f): " + (int) ((1.0 - cpu_frac) * 100.0) + "%");
165 |
166 | mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
167 | @Override
168 | public void onStopTrackingTouch(SeekBar seekBar) {
169 | toggle.setChecked(false);
170 | }
171 |
172 | @Override
173 | public void onStartTrackingTouch(SeekBar seekBar) {
174 | toggle.setChecked(false);
175 | }
176 |
177 | @Override
178 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
179 | float cpu_frac = (float) mSeekBar.getProgress() / mSeekBar.getMax();
180 | int cpu_mb = (int) ((1 << seekBarTotalMem.getProgress()) * cpu_frac);
181 | int gpu_mb = (int) ((1 << seekBarTotalMem.getProgress()) * (1.0 - cpu_frac));
182 |
183 | cpuTextView.setText("CPU (" + Long.toString(cpu_mb) + " MB)");
184 | gpuTextView.setText("GPU (" + Long.toString(gpu_mb) + " MB)");
185 | wrkTextView.setText("Workload Offload Fraction (f): " + String.format("%.2f", (1.0 - cpu_frac) * 100.0) + "%");
186 | }
187 | });
188 | }
189 |
190 | private void setupFlopsSlider(final View rootView) {
191 | final SeekBar mSeekBar = rootView.findViewById(R.id.seekBar_nFlops);
192 |
193 | TextView textView = rootView.findViewById(R.id.txtBox_nFlops);
194 | textView.setText("Ops (" + Long.toString(1 << mSeekBar.getProgress()) + " FLOPS/byte)"); // increment by 1 since bar starts from 0.
195 |
196 | final ToggleButton toggle = rootView.findViewById(R.id.toggle_runMixer);
197 | mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
198 |
199 | @Override
200 | public void onStopTrackingTouch(SeekBar seekBar) {
201 | toggle.setChecked(false);
202 | }
203 |
204 | @Override
205 | public void onStartTrackingTouch(SeekBar seekBar) {
206 | toggle.setChecked(false);
207 | }
208 |
209 | @Override
210 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
211 | TextView textView = rootView.findViewById(R.id.txtBox_nFlops);
212 | textView.setText("Ops (" + Long.toString(1 << mSeekBar.getProgress()) + " FLOPS/byte)");
213 | }
214 | });
215 | }
216 |
217 | private void setupMaxCPUThreadSlider(final View rootView) {
218 | final SeekBar mSeekBar = rootView.findViewById(R.id.seekBar_maxCPUThreads);
219 |
220 | int nCores = getNumberOfCores();
221 | mSeekBar.setProgress(nCores);
222 | mSeekBar.setMax(nCores - 1); // we start from 0, but we display +1
223 |
224 | TextView textView = rootView.findViewById(R.id.txtBox_maxThreads2);
225 | textView.setText("CPU Thread Count (" + Long.toString(mSeekBar.getProgress() + 1) + " Cores)"); // increment by 1 since bar starts from 0.
226 |
227 | final ToggleButton toggle = rootView.findViewById(R.id.toggle_runMixer);
228 | mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
229 |
230 | @Override
231 | public void onStopTrackingTouch(SeekBar seekBar) {
232 | toggle.setChecked(false);
233 | }
234 |
235 | @Override
236 | public void onStartTrackingTouch(SeekBar seekBar) {
237 | toggle.setChecked(false);
238 | }
239 |
240 | @Override
241 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
242 | TextView textView = rootView.findViewById(R.id.txtBox_maxThreads2);
243 | textView.setText("CPU Thread Count (" + Long.toString(mSeekBar.getProgress() + 1) + " Cores)");
244 | }
245 | });
246 | }
247 |
248 | @Override
249 | public void onCreate(Bundle savedInstanceState) {
250 | super.onCreate(savedInstanceState);
251 | }
252 |
253 | @Override
254 | public void onDestroyView() {
255 | super.onDestroyView();
256 | }
257 |
258 | @Override
259 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
260 | Bundle savedInstanceState) {
261 | View rootView = inflater.inflate(R.layout.fragment_mixer_roofline, container, false);
262 |
263 | setupMemorySlider(rootView);
264 | setupMaxCPUThreadSlider(rootView);
265 | setupMaxWorkGroupSizeSlider(rootView);
266 | setupMaxWorkGroupItemsSlider(rootView);
267 | setupWorkFractionSlider(rootView);
268 | setupFlopsSlider(rootView);
269 | setupButton(rootView);
270 |
271 | return rootView;
272 | }
273 |
274 | void setupButton(final View rootView) {
275 | final ToggleButton button = rootView.findViewById(R.id.toggle_runMixer);
276 | button.setChecked(false); // set the current state of a toggle button
277 |
278 | button.setTextOn("Busy!");
279 | button.setTextOff("Run");
280 |
281 | button.setChecked(false);
282 |
283 | button.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
284 |
285 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
286 |
287 | if (isChecked) { // enabled
288 | SeekBar seekBar_split = rootView.findViewById(R.id.seekBar_workFraction);
289 | SeekBar seekBar_mem = rootView.findViewById(R.id.seekBar_totalMem);
290 | SeekBar seekBar_cpu = rootView.findViewById(R.id.seekBar_maxCPUThreads);
291 | SeekBar seekBar_gpuWorkGroupCount = rootView.findViewById(R.id.seekBar_maxGPUWorkgroupSize);
292 | SeekBar seekBar_gpuWorkGroupSize = rootView.findViewById(R.id.seekBar_maxGPUWorkItems);
293 | SeekBar seekBar_flops = rootView.findViewById(R.id.seekBar_nFlops);
294 |
295 | int memTotal = (1 << seekBar_mem.getProgress()) * MiB; // converting to bytes
296 | int gpuWorkGroupSize = 1 << seekBar_gpuWorkGroupCount.getProgress();
297 | int gpuWorkItemSize = 1 << seekBar_gpuWorkGroupSize.getProgress();
298 | int nFlops = 1 << seekBar_flops.getProgress();
299 | int cpuThreads = seekBar_cpu.getProgress() + 1; // seekbar starts at 0
300 |
301 | float cpuWorkFraction = ((float) seekBar_split.getProgress() / seekBar_split.getMax());
302 |
303 | Mixer(memTotal, cpuWorkFraction, nFlops, cpuThreads, gpuWorkGroupSize, gpuWorkItemSize);
304 |
305 | button.setChecked(false);
306 | }
307 | }
308 | });
309 | }
310 |
311 | public void Mixer(int memTotal, float cpuWorkFraction, int nFlops, int cpuThreads, int gpuWorkGroupSize, int gpuWorkItemSize) {
312 | SOCRoofline.MixerAsync mixerATask = new SOCRoofline.MixerAsync(getActivity(), memTotal, cpuWorkFraction, nFlops, cpuThreads, gpuWorkGroupSize, gpuWorkItemSize);
313 |
314 | mixerATask.execute();
315 | }
316 |
317 | class MixerAsync extends AsyncTask {
318 | final int memTotal, cpuThreads, gpuWorkGroupSize, gpuWorkItemSize, flops;
319 | final float cpuWorkFraction;
320 |
321 | private AsyncTask currTask = null;
322 |
323 | public MixerAsync(Activity activity, int memTotal, float cpuWorkFraction, int nFlops, int cpuThreads, int gpuWorkGroupSize, int gpuWorkItemSize) {
324 | super();
325 |
326 | this.flops = nFlops;
327 | this.memTotal = memTotal;
328 | this.cpuWorkFraction = cpuWorkFraction;
329 | this.cpuThreads = cpuThreads;
330 | this.gpuWorkGroupSize = gpuWorkGroupSize;
331 | this.gpuWorkItemSize = gpuWorkItemSize;
332 |
333 | gProcessDialog = new ProgressDialog(activity);
334 | }
335 |
336 | @Override
337 | protected void onPreExecute() {
338 | super.onPreExecute();
339 |
340 | currTask = this;
341 |
342 | gProcessDialog.setMax(100);
343 | gProcessDialog.setProgress(0);
344 | gProcessDialog.setTitle("Mixing in progress");
345 | gProcessDialog.setMessage("Starting up... ");
346 | gProcessDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
347 | gProcessDialog.setCancelable(false);
348 | gProcessDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
349 | @Override
350 | public void onClick(DialogInterface dialog, int which) {
351 | dialog.dismiss();
352 | currTask.cancel(true);
353 | }
354 | });
355 |
356 | gProcessDialog.show();
357 | }
358 |
359 | @Override
360 | protected String doInBackground(Void... params) {
361 | File root = android.os.Environment.getExternalStorageDirectory();
362 | File odir = new File(root.getAbsolutePath() + "/" + gResultsDir + "/");
363 | deleteDirectory(odir);
364 | Log.i(TAG, "Deleting the " + odir + " output directory.");
365 |
366 | String output = SOC_Mixer(memTotal, flops, cpuWorkFraction, cpuThreads, gpuWorkGroupSize, gpuWorkItemSize);
367 | Log.i(TAG, "Finished with mixing async task.");
368 |
369 | if (isStorageAvailable(EXT_STORAGE_RW)) {
370 | String ofilename = "mixer-CPUxGPU.txt";
371 | writeToSDFile(odir, ofilename, output);
372 | } else {
373 | Log.e(TAG, "Storage is not available for RW or is unavailable.");
374 | }
375 |
376 | return "All done with MixerTask!";
377 | }
378 |
379 | @Override
380 | protected void onProgressUpdate(String... msg) {
381 | super.onProgressUpdate(msg);
382 | gProcessDialog.setProgress(Integer.parseInt(msg[0]));
383 | gProcessDialog.setMessage(msg[1]);
384 | }
385 |
386 | // onCancelled() is called when the async task is cancelled.
387 | @Override
388 | protected void onCancelled(String result) {
389 | }
390 |
391 | protected void onPostExecute(String param) {
392 |
393 | gProcessDialog.setMessage("Finished processing data.");
394 |
395 | if (gProcessDialog.isShowing()) {
396 | gProcessDialog.dismiss();
397 | }
398 | }
399 | }
400 | }
401 |
--------------------------------------------------------------------------------
/app/src/main/java/com/google/gables/Utils.java:
--------------------------------------------------------------------------------
1 | package com.google.gables;
2 |
3 | import android.os.Build;
4 | import android.os.Environment;
5 | import android.util.Log;
6 |
7 | import java.io.File;
8 | import java.io.FileNotFoundException;
9 | import java.io.FileOutputStream;
10 | import java.io.IOException;
11 |
12 | import static com.google.gables.Utils.ExtStoragePermissions_t.EXT_STORAGE_AV;
13 | import static com.google.gables.Utils.ExtStoragePermissions_t.EXT_STORAGE_RD;
14 | import static com.google.gables.Utils.ExtStoragePermissions_t.EXT_STORAGE_RW;
15 |
16 | public class Utils {
17 |
18 | public static final int KiB = 1024;
19 | public static final int MiB = KiB * 1024;
20 | public static final int GiB = MiB * 1024;
21 | private static final String TAG = CPURoofline.class.getName();
22 |
23 | public static int getNumberOfCores() {
24 | int nCores = -1;
25 | if (Build.VERSION.SDK_INT >= 17) {
26 | nCores = Runtime.getRuntime().availableProcessors();
27 | } else {
28 | throw new UnsupportedOperationException("Not yet implemented");
29 | }
30 |
31 | return nCores;
32 | }
33 |
34 | public static int log(final int x, final int base) {
35 | return (int) (Math.log(x) / Math.log(base));
36 | }
37 |
38 | public static Boolean isStorageAvailable(ExtStoragePermissions_t typeCheck) {
39 | boolean mExternalStorageAvailable = false;
40 | boolean mExternalStorageWriteable = false;
41 | String state = Environment.getExternalStorageState();
42 |
43 | if (Environment.MEDIA_MOUNTED.equals(state)) {
44 | // Can read and write the media
45 | mExternalStorageAvailable = mExternalStorageWriteable = true;
46 | } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
47 | // Can only read the media
48 | mExternalStorageAvailable = true;
49 | mExternalStorageWriteable = false;
50 | } else {
51 | // Can't read or write
52 | mExternalStorageAvailable = mExternalStorageWriteable = false;
53 | }
54 | Log.i("", "\n\nExternal Media: readable="
55 | + mExternalStorageAvailable + " writable=" + mExternalStorageWriteable);
56 |
57 | if (typeCheck == EXT_STORAGE_RW)
58 | return (mExternalStorageAvailable && mExternalStorageWriteable);
59 | else if (typeCheck == EXT_STORAGE_RD)
60 | return (mExternalStorageAvailable && !mExternalStorageWriteable);
61 | else if (typeCheck == EXT_STORAGE_AV)
62 | return mExternalStorageAvailable;
63 |
64 | return false;
65 | }
66 |
67 | public static boolean deleteDirectory(File path) {
68 | if (path.exists()) {
69 | File[] files = path.listFiles();
70 | if (files == null) {
71 | return true;
72 | }
73 | for (int i = 0; i < files.length; i++) {
74 | if (files[i].isDirectory()) {
75 | deleteDirectory(files[i]);
76 | } else {
77 | files[i].delete();
78 | }
79 | }
80 | }
81 | return (path.delete());
82 | }
83 |
84 | public static void writeToSDFile(File dir, String filename, String ostr) {
85 |
86 | boolean success = true;
87 | if (!dir.exists()) {
88 | success = dir.mkdir(); // FIXME: if this fails, then you might have to request permission in app settings.
89 | }
90 | if (success) {
91 | Log.i("writeToSDFile", "Output directory created.");
92 | } else {
93 | Log.i("writeToSDFile", "Output directory NOT created!");
94 | }
95 |
96 | File file = new File(dir, filename);
97 |
98 | try {
99 | FileOutputStream fos = new FileOutputStream(file);
100 | fos.write(ostr.getBytes());
101 | fos.close();
102 | } catch (FileNotFoundException e) {
103 | e.printStackTrace();
104 | Log.i("writeToSDFile", "******* File not found. Did you" +
105 | " add a WRITE_EXTERNAL_STORAGE permission to the manifest?");
106 | } catch (IOException e) {
107 | e.printStackTrace();
108 | }
109 | Log.i("writeToSDFile", "\n\nFile written to " + file);
110 | }
111 |
112 | public enum ExtStoragePermissions_t {
113 | EXT_STORAGE_RD,
114 | EXT_STORAGE_RW,
115 | EXT_STORAGE_AV
116 | }
117 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/google/gables/utils/NonSwipeViewPager.java:
--------------------------------------------------------------------------------
1 | package com.google.gables.utils;
2 |
3 | import android.content.Context;
4 | import android.support.annotation.NonNull;
5 | import android.support.annotation.Nullable;
6 | import android.support.v4.view.ViewPager;
7 | import android.util.AttributeSet;
8 | import android.view.MotionEvent;
9 |
10 | public class NonSwipeViewPager extends ViewPager {
11 |
12 | public NonSwipeViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
13 | super(context, attrs);
14 | }
15 |
16 | @Override
17 | public boolean onTouchEvent(MotionEvent ev) {
18 | return false;
19 | }
20 |
21 | @Override
22 | public boolean onInterceptTouchEvent(MotionEvent ev) {
23 | return false;
24 | }
25 | }
--------------------------------------------------------------------------------
/app/src/main/jni/roofline/CPUdriver.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "CPUdriver.hpp"
3 | #include "CPUkernel.hpp"
4 |
5 | double getTime() {
6 | double time;
7 |
8 | time = omp_get_wtime();
9 | return time;
10 | }
11 |
12 | JNIEXPORT jstring JNICALL
13 | Java_com_google_gables_Roofline_CPUExecute(JNIEnv *env, jobject obj,
14 | jint memTotal, jint nThreads, jint nFlops,
15 | jboolean neon) {
16 | int id = 0;
17 |
18 | assert(nThreads >= 1);
19 |
20 | std::ostringstream results;
21 | results.str("");
22 | uint64_t TSIZE = 100000000;
23 |
24 | double *__restrict__ buf = (double *) malloc(TSIZE);
25 |
26 | if (buf == NULL) {
27 | std::string str = "Error in CPU Roofline!";
28 | return env->NewStringUTF("hi");
29 | }
30 |
31 | omp_set_dynamic(0); // Explicitly disable dynamic teams
32 | omp_set_num_threads(nThreads); // Use nThreads for all consecutive parallel regions
33 |
34 | // based on the number of flops specified, pick the appropriate kernel to run
35 | void (*kernelPtr)(uint64_t, uint64_t, double *__restrict__, int *, int *);
36 | switch (nFlops) {
37 | case 1:
38 | kernelPtr = &kernel_1FLOPS;
39 | break;
40 | case 2:
41 | kernelPtr = &kernel_2FLOPS;
42 | break;
43 | case 4:
44 | kernelPtr = &kernel_4FLOPS;
45 | break;
46 | case 8:
47 | kernelPtr = &kernel_8FLOPS;
48 | break;
49 | case 16:
50 | kernelPtr = &kernel_16FLOPS;
51 | break;
52 | case 32:
53 | kernelPtr = &kernel_32FLOPS;
54 | break;
55 | case 64:
56 | kernelPtr = &kernel_64FLOPS;
57 | break;
58 | case 128:
59 | kernelPtr = &kernel_128FLOPS;
60 | break;
61 | case 256:
62 | kernelPtr = &kernel_256FLOPS;
63 | break;
64 | case 512:
65 | kernelPtr = &kernel_512FLOPS;
66 | break;
67 | case 1024:
68 | kernelPtr = &kernel_1024FLOPS;
69 | break;
70 | default:
71 | assert (false);
72 | }
73 |
74 | #pragma omp parallel private(id) proc_bind(spread)
75 | {
76 | id = omp_get_thread_num();
77 |
78 | // determine thread offsets
79 | uint64_t nsize = TSIZE / nThreads;
80 | nsize = nsize & (~(32 - 1));
81 | nsize = nsize / sizeof(double);
82 | uint64_t nid = nsize * id;
83 |
84 | // initialize small chunck of buffer within each thread
85 | initialize(nsize, &buf[nid], 1.0);
86 |
87 | uint64_t nNew = 0;
88 | for (uint64_t n = 1; n <= nsize;) {
89 | uint64_t ntrials = nsize / n;
90 | if (ntrials < 1)
91 | ntrials = 1;
92 |
93 | for (uint64_t t = 1; t <= ntrials; t = t * 2) { // working set - ntrials
94 | double startTime, endTime;
95 | int bytes_per_elem, mem_accesses_per_elem;
96 |
97 | #pragma omp barrier
98 |
99 | if (id == 0) {
100 | startTime = getTime();
101 | }
102 |
103 | kernelPtr(n, t, &buf[nid], &bytes_per_elem, &mem_accesses_per_elem);
104 |
105 | #pragma omp barrier
106 |
107 | #pragma omp master
108 | if (id == 0) {
109 | endTime = getTime();
110 | double seconds = (double) (endTime - startTime);
111 | uint64_t working_set_size = n * nThreads;
112 | uint64_t total_bytes =
113 | t * working_set_size * bytes_per_elem * mem_accesses_per_elem;
114 | uint64_t total_flops = t * working_set_size * nFlops;
115 |
116 | results << std::right << std::setw(12) << working_set_size * bytes_per_elem
117 | << std::right << std::setw(12) << t
118 | << std::right << std::setw(15) << seconds * 1000000
119 | << std::right << std::setw(12) << total_bytes
120 | << std::right << std::setw(12) << total_flops
121 | << std::endl;
122 | }
123 | }
124 |
125 | nNew = 1.1 * n;
126 | if (nNew == n) {
127 | nNew = n + 1;
128 | }
129 |
130 | n = nNew;
131 | } // working set - nsize
132 |
133 | } // parallel region
134 |
135 | free(buf);
136 |
137 | results << std::endl;
138 | results << "META_DATA" << std::endl;
139 | results << "FLOPS " << nFlops << std::endl;
140 | results << "OPENMP_THREADS " << nThreads << std::endl;
141 | return env->NewStringUTF(results.str().c_str());
142 | }
143 |
--------------------------------------------------------------------------------
/app/src/main/jni/roofline/CPUkernel.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "rep.hpp"
6 | #include "CPUkernel.hpp"
7 |
8 | void initialize(uint64_t nsize,
9 | double *__restrict__ a,
10 | double value) {
11 | uint64_t i;
12 | for (i = 0; i < nsize; ++i) {
13 | a[i] = value;
14 | }
15 | }
16 |
17 | void kernel_1FLOPS(uint64_t nsize,
18 | uint64_t ntrials,
19 | double *__restrict__ A,
20 | int *bytes_per_elem,
21 | int *mem_accesses_per_elem) {
22 | *bytes_per_elem = sizeof(*A);
23 | *mem_accesses_per_elem = 2;
24 |
25 | double alpha = 0.5;
26 | uint64_t i, j;
27 | for (j = 0; j < ntrials; ++j) {
28 | for (i = 0; i < nsize; ++i) {
29 | double beta = 0.8;
30 | KERNEL1(beta, A[i], alpha);
31 | A[i] = beta;
32 | }
33 | alpha = alpha * (1 - 1e-8);
34 | }
35 | }
36 |
37 | void kernel_2FLOPS(uint64_t nsize,
38 | uint64_t ntrials,
39 | double *__restrict__ A,
40 | int *bytes_per_elem,
41 | int *mem_accesses_per_elem) {
42 | *bytes_per_elem = sizeof(*A);
43 | *mem_accesses_per_elem = 2;
44 |
45 | double alpha = 0.5;
46 | uint64_t i, j;
47 | for (j = 0; j < ntrials; ++j) {
48 | for (i = 0; i < nsize; ++i) {
49 | double beta = 0.8;
50 | KERNEL2(beta, A[i], alpha);
51 | A[i] = beta;
52 | }
53 | alpha = alpha * (1 - 1e-8);
54 | }
55 | }
56 |
57 | void kernel_4FLOPS(uint64_t nsize,
58 | uint64_t ntrials,
59 | double *__restrict__ A,
60 | int *bytes_per_elem,
61 | int *mem_accesses_per_elem) {
62 | *bytes_per_elem = sizeof(*A);
63 | *mem_accesses_per_elem = 2;
64 |
65 | double alpha = 0.5;
66 | uint64_t i, j;
67 | for (j = 0; j < ntrials; ++j) {
68 | for (i = 0; i < nsize; ++i) {
69 | double beta = 0.8;
70 | REP2(KERNEL2(beta, A[i], alpha));
71 | A[i] = beta;
72 | }
73 | alpha = alpha * (1 - 1e-8);
74 | }
75 | }
76 |
77 | void kernel_8FLOPS(uint64_t nsize,
78 | uint64_t ntrials,
79 | double *__restrict__ A,
80 | int *bytes_per_elem,
81 | int *mem_accesses_per_elem) {
82 | *bytes_per_elem = sizeof(*A);
83 | *mem_accesses_per_elem = 2;
84 |
85 | double alpha = 0.5;
86 | uint64_t i, j;
87 | for (j = 0; j < ntrials; ++j) {
88 | for (i = 0; i < nsize; ++i) {
89 | double beta = 0.8;
90 | REP4(KERNEL2(beta, A[i], alpha));
91 | A[i] = beta;
92 | }
93 | alpha = alpha * (1 - 1e-8);
94 | }
95 | }
96 |
97 | void kernel_16FLOPS(uint64_t nsize,
98 | uint64_t ntrials,
99 | double *__restrict__ A,
100 | int *bytes_per_elem,
101 | int *mem_accesses_per_elem) {
102 | *bytes_per_elem = sizeof(*A);
103 | *mem_accesses_per_elem = 2;
104 |
105 | double alpha = 0.5;
106 | uint64_t i, j;
107 | for (j = 0; j < ntrials; ++j) {
108 | for (i = 0; i < nsize; ++i) {
109 | double beta = 0.8;
110 | REP8(KERNEL2(beta, A[i], alpha));
111 | A[i] = beta;
112 | }
113 | alpha = alpha * (1 - 1e-8);
114 | }
115 | }
116 |
117 | void kernel_32FLOPS(uint64_t nsize,
118 | uint64_t ntrials,
119 | double *__restrict__ A,
120 | int *bytes_per_elem,
121 | int *mem_accesses_per_elem) {
122 | *bytes_per_elem = sizeof(*A);
123 | *mem_accesses_per_elem = 2;
124 |
125 | double alpha = 0.5;
126 | uint64_t i, j;
127 | for (j = 0; j < ntrials; ++j) {
128 | for (i = 0; i < nsize; ++i) {
129 | double beta = 0.8;
130 | REP16(KERNEL2(beta, A[i], alpha));
131 | A[i] = beta;
132 | }
133 | alpha = alpha * (1 - 1e-8);
134 | }
135 | }
136 |
137 | void kernel_64FLOPS(uint64_t nsize,
138 | uint64_t ntrials,
139 | double *__restrict__ A,
140 | int *bytes_per_elem,
141 | int *mem_accesses_per_elem) {
142 | *bytes_per_elem = sizeof(*A);
143 | *mem_accesses_per_elem = 2;
144 |
145 | double alpha = 0.5;
146 | uint64_t i, j;
147 | for (j = 0; j < ntrials; ++j) {
148 | for (i = 0; i < nsize; ++i) {
149 | double beta = 0.8;
150 | REP32(KERNEL2(beta, A[i], alpha));
151 | A[i] = beta;
152 | }
153 | alpha = alpha * (1 - 1e-8);
154 | }
155 | }
156 |
157 | void kernel_128FLOPS(uint64_t nsize,
158 | uint64_t ntrials,
159 | double *__restrict__ A,
160 | int *bytes_per_elem,
161 | int *mem_accesses_per_elem) {
162 | *bytes_per_elem = sizeof(*A);
163 | *mem_accesses_per_elem = 2;
164 |
165 | double alpha = 0.5;
166 | uint64_t i, j;
167 | for (j = 0; j < ntrials; ++j) {
168 | for (i = 0; i < nsize; ++i) {
169 | double beta = 0.8;
170 | REP64(KERNEL2(beta, A[i], alpha));
171 | A[i] = beta;
172 | }
173 | alpha = alpha * (1 - 1e-8);
174 | }
175 | }
176 |
177 | void kernel_256FLOPS(uint64_t nsize,
178 | uint64_t ntrials,
179 | double *__restrict__ A,
180 | int *bytes_per_elem,
181 | int *mem_accesses_per_elem) {
182 | *bytes_per_elem = sizeof(*A);
183 | *mem_accesses_per_elem = 2;
184 |
185 | double alpha = 0.5;
186 | uint64_t i, j;
187 | for (j = 0; j < ntrials; ++j) {
188 | for (i = 0; i < nsize; ++i) {
189 | double beta = 0.8;
190 | REP128(KERNEL2(beta, A[i], alpha));
191 | A[i] = beta;
192 | }
193 | alpha = alpha * (1 - 1e-8);
194 | }
195 | }
196 |
197 | void kernel_512FLOPS(uint64_t nsize,
198 | uint64_t ntrials,
199 | double *__restrict__ A,
200 | int *bytes_per_elem,
201 | int *mem_accesses_per_elem) {
202 | *bytes_per_elem = sizeof(*A);
203 | *mem_accesses_per_elem = 2;
204 |
205 | double alpha = 0.5;
206 | uint64_t i, j;
207 | for (j = 0; j < ntrials; ++j) {
208 | for (i = 0; i < nsize; ++i) {
209 | double beta = 0.8;
210 | REP256(KERNEL2(beta, A[i], alpha));
211 | A[i] = beta;
212 | }
213 | alpha = alpha * (1 - 1e-8);
214 | }
215 | }
216 |
217 | void kernel_1024FLOPS(uint64_t nsize,
218 | uint64_t ntrials,
219 | double *__restrict__ A,
220 | int *bytes_per_elem,
221 | int *mem_accesses_per_elem) {
222 | *bytes_per_elem = sizeof(*A);
223 | *mem_accesses_per_elem = 2;
224 |
225 | double alpha = 0.5;
226 | uint64_t i, j;
227 | for (j = 0; j < ntrials; ++j) {
228 | for (i = 0; i < nsize; ++i) {
229 | double beta = 0.8;
230 | REP512(KERNEL2(beta, A[i], alpha));
231 | A[i] = beta;
232 | }
233 | alpha = alpha * (1 - 1e-8);
234 | }
235 | }
236 |
--------------------------------------------------------------------------------
/app/src/main/jni/roofline/Utils.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #include "Utils.hpp"
8 |
9 | double getTime() {
10 | double time;
11 |
12 | struct timeval tm;
13 | gettimeofday(&tm, NULL);
14 | time = tm.tv_sec + (tm.tv_usec / 1000000.0);
15 |
16 | return time;
17 | }
18 |
19 | double getOMPTime() {
20 | double time;
21 |
22 | time = omp_get_wtime();
23 | return time;
24 | }
25 |
26 | //void initialize(uint64_t nsize,
27 | // double *__restrict__ A,
28 | // double value) {
29 | // uint64_t i;
30 | // for (i = 0; i < nsize; ++i) {
31 | // A[i] = value;
32 | // }
33 | //}
34 |
35 | JNIEXPORT jint JNICALL
36 | Java_com_google_gables_Roofline_UtilsSetEnvLibraryPath(JNIEnv *env, jobject thiz,
37 | jstring envVar,
38 | jstring envPath) {
39 |
40 | const char *nativeEnvVar = env->GetStringUTFChars(envVar, JNI_FALSE);
41 | const char *nativeEnvPath = env->GetStringUTFChars(envPath, JNI_FALSE);
42 |
43 | std::stringstream path;
44 | path << nativeEnvPath << ";/system/lib/rfsa/adsp;/system/vendor/lib/rfsa/adsp;/dsp";
45 |
46 | int ret = setenv(nativeEnvVar, path.str().c_str(), 1 /*override*/) == 0;
47 |
48 | env->ReleaseStringUTFChars(envVar, nativeEnvVar);
49 | env->ReleaseStringUTFChars(envPath, nativeEnvPath);
50 |
51 | return ret;
52 | }
--------------------------------------------------------------------------------
/app/src/main/jni/roofline/inc/CPUdriver.hpp:
--------------------------------------------------------------------------------
1 | #ifndef ERT_DRIVER_H
2 | #define ERT_DRIVER_H
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #include
16 |
17 | #include
18 |
19 |
20 | #ifdef __cplusplus
21 | extern "C" {
22 | #endif
23 |
24 | JNIEXPORT jstring JNICALL
25 | Java_com_google_gables_Roofline_CPUExecute(JNIEnv *env,
26 | jobject obj,
27 | jint memTotal,
28 | jint nThreads,
29 | jint nFlops,
30 | jboolean neon);
31 | #ifdef __cplusplus
32 | }
33 | #endif
34 |
35 | #endif
36 |
--------------------------------------------------------------------------------
/app/src/main/jni/roofline/inc/CPUkernel.hpp:
--------------------------------------------------------------------------------
1 | #ifndef KERNEL1_H
2 | #define KERNEL1_H
3 |
4 | #define KERNEL1(a, b, c) ((a) = (b) + (c))
5 | #define KERNEL2(a, b, c) ((a) = (a)*(b) + (c))
6 |
7 | #include "rep.hpp"
8 |
9 | void initialize(uint64_t nsize,
10 | double *__restrict__ array,
11 | double value);
12 |
13 | void kernel(uint64_t nsize,
14 | uint64_t ntrials,
15 | double *__restrict__ array,
16 | int *bytes_per_elem,
17 | int *mem_accesses_per_elem);
18 |
19 | void kernel_1FLOPS(uint64_t nsize,
20 | uint64_t ntrials,
21 | double *__restrict__ array,
22 | int *bytes_per_elem,
23 | int *mem_accesses_per_elem);
24 |
25 | void kernel_2FLOPS(uint64_t nsize,
26 | uint64_t ntrials,
27 | double *__restrict__ array,
28 | int *bytes_per_elem,
29 | int *mem_accesses_per_elem);
30 |
31 | void kernel_4FLOPS(uint64_t nsize,
32 | uint64_t ntrials,
33 | double *__restrict__ array,
34 | int *bytes_per_elem,
35 | int *mem_accesses_per_elem);
36 |
37 | void kernel_8FLOPS(uint64_t nsize,
38 | uint64_t ntrials,
39 | double *__restrict__ array,
40 | int *bytes_per_elem,
41 | int *mem_accesses_per_elem);
42 |
43 | void kernel_16FLOPS(uint64_t nsize,
44 | uint64_t ntrials,
45 | double *__restrict__ array,
46 | int *bytes_per_elem,
47 | int *mem_accesses_per_elem);
48 |
49 | void kernel_32FLOPS(uint64_t nsize,
50 | uint64_t ntrials,
51 | double *__restrict__ array,
52 | int *bytes_per_elem,
53 | int *mem_accesses_per_elem);
54 |
55 | void kernel_64FLOPS(uint64_t nsize,
56 | uint64_t ntrials,
57 | double *__restrict__ array,
58 | int *bytes_per_elem,
59 | int *mem_accesses_per_elem);
60 |
61 | void kernel_128FLOPS(uint64_t nsize,
62 | uint64_t ntrials,
63 | double *__restrict__ array,
64 | int *bytes_per_elem,
65 | int *mem_accesses_per_elem);
66 |
67 | void kernel_256FLOPS(uint64_t nsize,
68 | uint64_t ntrials,
69 | double *__restrict__ array,
70 | int *bytes_per_elem,
71 | int *mem_accesses_per_elem);
72 |
73 | void kernel_512FLOPS(uint64_t nsize,
74 | uint64_t ntrials,
75 | double *__restrict__ array,
76 | int *bytes_per_elem,
77 | int *mem_accesses_per_elem);
78 |
79 | void kernel_1024FLOPS(uint64_t nsize,
80 | uint64_t ntrials,
81 | double *__restrict__ array,
82 | int *bytes_per_elem,
83 | int *mem_accesses_per_elem);
84 |
85 | #endif
86 |
--------------------------------------------------------------------------------
/app/src/main/jni/roofline/inc/GPUdriver.hpp:
--------------------------------------------------------------------------------
1 | #ifndef GABLES_GPUDRIVER_H
2 | #define GABLES_GPUDRIVER_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | //#include "Utils.hpp"
25 |
26 | #ifdef __cplusplus
27 | extern "C" {
28 | #endif
29 |
30 | typedef GLuint GPUKernelPtr;
31 |
32 | bool GPUInitializeOpenGL();
33 | bool GPUShutdownOpenGL();
34 |
35 | GPUKernelPtr GPUBuildKernel(int wgThreads, int nFlops);
36 | void GPUConfigureSSBO(uint total_size, uint ntrials);
37 | void GPULaunchKernel(GPUKernelPtr computeKernel, uint wgSize);
38 |
39 | JNIEXPORT jboolean JNICALL
40 | Java_com_google_gables_Roofline_GPUInitOpenGL(JNIEnv *env, jobject thiz);
41 |
42 | JNIEXPORT jboolean JNICALL
43 | Java_com_google_gables_Roofline_GPUFiniOpenGL(JNIEnv *env, jobject thiz);
44 |
45 | JNIEXPORT jint JNICALL
46 | Java_com_google_gables_Roofline_GPUMaxWorkGroupCount(JNIEnv *env, jobject thiz, jint dim);
47 |
48 | JNIEXPORT jint JNICALL
49 | Java_com_google_gables_Roofline_GPUMaxWorkGroupSize(JNIEnv *env, jobject thiz, jint dim);
50 |
51 | JNIEXPORT jint JNICALL
52 | Java_com_google_gables_Roofline_GPUMaxThreadInnovations(JNIEnv *env, jobject thiz, jint dim);
53 |
54 | JNIEXPORT jstring JNICALL
55 | Java_com_google_gables_Roofline_GPUExecute(JNIEnv *env, jobject thiz, jobject assetManager,
56 | jint nGroups, jint nThreads, jint nFlops, jint memTotal);
57 |
58 | JNIEXPORT jstring JNICALL
59 | Java_com_google_gables_Roofline_GPUTest(JNIEnv *env, jobject thiz);
60 |
61 | #ifdef __cplusplus
62 | }
63 | #endif
64 |
65 | #endif //GABLES_GPUDRIVER_H
66 |
--------------------------------------------------------------------------------
/app/src/main/jni/roofline/inc/Utils.hpp:
--------------------------------------------------------------------------------
1 | #ifndef GABLES_UTILS_HPP
2 | #define GABLES_UTILS_HPP
3 |
4 | #define KiB (1024)
5 | #define MiB (KiB * KiB)
6 | #define GiB (MiB * KiB)
7 |
8 | #define ALIGN (32)
9 |
10 | #define GFLOPS (1000000000)
11 |
12 | #define LOG_TAG ("JNI")
13 |
14 | #define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, fmt, ##args)
15 | #define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##args)
16 | #define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, fmt, ##args)
17 |
18 | #ifdef __cplusplus
19 | extern "C" {
20 | #endif
21 |
22 | double getTime();
23 |
24 | double getOMPTime();
25 |
26 | //void initialize(uint64_t nsize,
27 | // float *__restrict__ array,
28 | // float value);
29 |
30 | JNIEXPORT jint JNICALL
31 | Java_com_google_gables_Roofline_UtilsSetEnvLibraryPath(JNIEnv *env, jobject thiz,
32 | jstring envVar,
33 | jstring envPath);
34 |
35 | #ifdef __cplusplus
36 | }
37 | #endif
38 |
39 | #endif //GABLES_UTILS_HPP
--------------------------------------------------------------------------------
/app/src/main/jni/roofline/inc/rep.hpp:
--------------------------------------------------------------------------------
1 | #ifndef REP_H
2 | #define REP_H
3 |
4 | #define REP2(S) S ; S
5 | #define REP4(S) REP2(S); REP2(S)
6 | #define REP8(S) REP4(S); REP4(S)
7 | #define REP16(S) REP8(S); REP8(S)
8 | #define REP32(S) REP16(S); REP16(S)
9 | #define REP64(S) REP32(S); REP32(S)
10 | #define REP128(S) REP64(S); REP64(S)
11 | #define REP256(S) REP128(S); REP128(S)
12 | #define REP512(S) REP256(S); REP256(S)
13 |
14 | #endif
15 |
--------------------------------------------------------------------------------
/app/src/main/python/gables/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/app/src/main/python/gables/__init__.py
--------------------------------------------------------------------------------
/app/src/main/python/gables/gables_processor.py:
--------------------------------------------------------------------------------
1 | from java import constructor, method, static_proxy, jint, jarray, jfloat, jvoid
2 | from java.lang import String
3 | from android.os import Environment
4 | import os
5 | import numpy as np
6 | import math
7 | import matplotlib.pyplot as plt
8 | import matplotlib
9 | import statistics
10 |
11 | class GablesPython(static_proxy()):
12 | @constructor([])
13 | def __init__(self):
14 | pass
15 |
16 | @method(jvoid, [])
17 | def processCPURoofline(self):
18 | try:
19 | os.chdir(os.path.join(str(Environment.getExternalStorageDirectory()), "CPURoofline/"))
20 | except:
21 | return None
22 | summaries = get_test_summaries()
23 | generate_roofline_plot(summaries)
24 | generate_bandwidth_plot(get_best_summary(summaries))
25 | print("Plotting complete")
26 |
27 | @method(jvoid, [])
28 | def processGPURoofline(self):
29 | try:
30 | os.chdir(os.path.join(str(Environment.getExternalStorageDirectory()), "GPURoofline/"))
31 | except:
32 | return None
33 | summaries = get_test_summaries()
34 | generate_roofline_plot(summaries)
35 | generate_bandwidth_plot(get_best_summary(summaries))
36 | print("Plotting complete")
37 |
38 |
39 | def smooth(y):
40 | ys = y[:]
41 |
42 | d = 0
43 |
44 | for i in range(len(ys)):
45 | num = min(len(ys),i+d+1) - max(0,i-d)
46 | total = sum(ys[max(0,i-d):min(len(ys),i+d+1)])
47 | ys[i] = total/float(num)
48 |
49 | return ys
50 |
51 | def grouper(iterable):
52 | prev = None
53 | group = []
54 | for item in iterable:
55 | if not prev or item - prev <= 2:
56 | group.append(item)
57 | else:
58 | yield group
59 | group = [item]
60 | prev = item
61 | if group:
62 | yield group
63 |
64 | def calculate_bandwidths(summary):
65 | max_band = max(summary.band)
66 | num_buckets = 10000
67 | threshold = 1.05
68 | buckets = [0] * num_buckets
69 | bucket_values = [0] * num_buckets
70 | band = summary.band[summary.band.index(max_band):]
71 | band = smooth(band)
72 | for i in range(0, num_buckets):
73 | value = (max_band / num_buckets) * i
74 | bucket_min = value/threshold
75 | bucket_max = value * threshold
76 | for b in band:
77 | if b > bucket_min and b < bucket_max:
78 | buckets[i] += 1
79 | bucket_values[i] = b
80 |
81 | band_list = [max_band]
82 | maxc = -1
83 | maxi = -1
84 |
85 | # Find all buckets with a large number of values
86 | for i in range(num_buckets-3,1,-1):
87 | if buckets[i] > 20:
88 | band_list.append(bucket_values[i])
89 |
90 | # Do some simple clustering
91 | THRESHOLD = 0.25
92 | prev = None
93 | final_band_list = []
94 |
95 | print("GROUPER BAND_LIST")
96 | grouped_dict = dict(enumerate(grouper(reversed(band_list)), 1))
97 | for key in grouped_dict.keys():
98 | final_band_list.append(statistics.mean(grouped_dict[key]))
99 | print(final_band_list)
100 |
101 | try:
102 | summary.max_dram = final_band_list[0]
103 | summary.max_l1 = final_band_list[1]
104 | summary.max_l2 = final_band_list[2]
105 | except:
106 | pass
107 |
108 | def calculate_weight(summary):
109 | weight = 0
110 | for i in range(0,len(summary.x)-1):
111 | x1 = math.log(summary.x[i])
112 | y1 = summary.band[i]
113 |
114 | x2 = math.log(summary.x[i+1])
115 | y2 = summary.band[i+1]
116 |
117 | weight += (y1+y2)/2.0 * (x2-x1)
118 | summary.weight = weight
119 |
120 | class RAW_INDEX:
121 | working_set_size = 0
122 | num_trials = 1
123 | time = 2
124 | bytes = 3
125 | flops=4
126 |
127 | class TestSummary(object):
128 | def __init__(self):
129 | self.max_gflops = -math.inf
130 | self.weight = None
131 | self.max_l1 = None
132 | self.max_l2 = None
133 | self.max_dram = None
134 | self.flops = None
135 | self.threads = None
136 | self.x = []
137 | self.band = []
138 | self.gflops = []
139 |
140 | def get_test_summaries():
141 | summaries = []
142 | # Parse raw test data into list of test summaries
143 | for filename in os.listdir():
144 | if filename.endswith(".png"):
145 | continue
146 | summary = TestSummary()
147 | with open(os.path.join(os.getcwd(), filename), 'r') as file:
148 | prev_values = None
149 | is_metadata = False
150 | for line in file.readlines():
151 | if line.strip() == "":
152 | continue
153 | if is_metadata:
154 | # Parse metadata
155 | values = line.strip().split()
156 | if values[0] == "FLOPS":
157 | summary.flops = float(values[1])
158 | continue
159 | else:
160 | summary.threads = float(values[1])
161 | break
162 | if line.strip() == "META_DATA":
163 | # We have reached meta data
164 | is_metadata = True
165 | continue
166 | # This is a normal line of data
167 | values = [float(x) for x in line.strip().split()]
168 | if values[RAW_INDEX.time] == 0:
169 | continue
170 | if not prev_values or prev_values[RAW_INDEX.num_trials] < values[RAW_INDEX.num_trials] or values == []:
171 | prev_values = values
172 | continue
173 | else:
174 | # We want to consider this value
175 | summary.max_gflops = max(summary.max_gflops, prev_values[RAW_INDEX.flops]/prev_values[RAW_INDEX.time])
176 | summary.x.append(prev_values[RAW_INDEX.working_set_size])
177 | summary.gflops.append((prev_values[RAW_INDEX.flops]/prev_values[RAW_INDEX.time])/1000)
178 | summary.band.append((prev_values[RAW_INDEX.bytes]/prev_values[RAW_INDEX.time])/1000)
179 | prev_values = values
180 | # Calculate max l1, l2 and dram bandwidth
181 | calculate_bandwidths(summary)
182 | # Calculate weight
183 | calculate_weight(summary)
184 | summaries.append(summary)
185 | print("SUM MAX GFLOPS = {}".format(summary.max_gflops))
186 | return summaries
187 |
188 | def get_best_summary(summaries):
189 | max_index = 0
190 | max_weight = -math.inf
191 |
192 | max_gflops = -math.inf
193 |
194 | for i, summary in enumerate(summaries):
195 | max_gflops = max(max_gflops, summary.max_gflops)
196 | if summary.weight > max_weight:
197 | max_index = i
198 | max_weight = summary.weight
199 | return summaries[max_index]
200 |
201 | def generate_roofline_plot(summaries):
202 | max_index = 0
203 | max_weight = -math.inf
204 |
205 | max_gflops = -math.inf
206 |
207 | for i, summary in enumerate(summaries):
208 | max_gflops = max(max_gflops, summary.max_gflops)
209 | if summary.weight > max_weight:
210 | max_index = i
211 | max_weight = summary.weight
212 | summary = summaries[max_index]
213 |
214 | x = np.logspace(-1, 5, 1000)
215 | plt.yscale("log")
216 | plt.xscale("log")
217 |
218 | if summary.max_dram:
219 | ys = np.minimum(summary.max_dram * x, np.repeat(summary.max_gflops, len(x)))
220 | # print(ys)
221 | plt.plot(x, ys, label="DRAM {} GB/s".format(summary.max_dram))
222 |
223 | if summary.max_l1:
224 | ys = np.minimum(summary.max_l1 * x, np.repeat(summary.max_gflops, len(x)))
225 | plt.plot(x, ys, label="L1 {} GB/s".format(summary.max_l1))
226 |
227 | if summary.max_l2:
228 | ys = np.minimum(summary.max_l2 * x, np.repeat(summary.max_gflops, len(x)))
229 | plt.plot(x, ys, label="L2 {} GB/s".format(summary.max_l2))
230 | print("MAX GFLOPS = {}".format(summary.max_gflops))
231 | plt.legend()
232 | plt.xlabel("Flops/byte")
233 | plt.ylabel("MFlops/second")
234 | plt.savefig('roofline.png')
235 | plt.close()
236 |
237 | def generate_bandwidth_plot(summary):
238 | plt.plot(summary.x, summary.band)
239 | plt.xscale("log", basex=2)
240 | plt.yscale("log", basey=10)
241 | plt.ylabel("Total Bandwidth (GB/s)")
242 | plt.xlabel("Working set size (bytes)")
243 | plt.savefig("bandwidth.png")
244 | plt.close()
245 |
246 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/harvard_edge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/app/src/main/res/drawable-v24/harvard_edge.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
23 |
24 |
28 |
29 |
33 |
34 |
38 |
39 |
40 |
41 |
42 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_cpu_roofline.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
18 |
19 |
32 |
33 |
40 |
41 |
45 |
46 |
47 |
52 |
53 |
57 |
58 |
63 |
64 |
68 |
69 |
74 |
75 |
76 |
84 |
85 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_dsp_roofline.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
24 |
25 |
35 |
36 |
46 |
47 |
57 |
58 |
70 |
71 |
76 |
77 |
91 |
92 |
101 |
102 |
113 |
114 |
126 |
127 |
136 |
137 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_gpu_roofline.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
18 |
19 |
32 |
33 |
40 |
41 |
45 |
46 |
51 |
52 |
56 |
57 |
62 |
63 |
67 |
68 |
73 |
74 |
78 |
79 |
84 |
85 |
93 |
94 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_mixer_roofline.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
20 |
21 |
31 |
32 |
45 |
46 |
47 |
57 |
58 |
68 |
69 |
79 |
80 |
90 |
91 |
101 |
102 |
114 |
115 |
128 |
129 |
142 |
143 |
156 |
157 |
162 |
163 |
171 |
172 |
180 |
181 |
189 |
190 |
203 |
204 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #A61D31
4 | #70000b
5 | #dd535a
6 | #000000
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 16dp
6 | 8dp
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 64
4 |
5 | 8
6 | 10
7 |
8 | 8
9 | 12
10 |
11 | 8
12 | 12
13 |
14 | 6
15 | 9
16 | 10
17 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Gables
3 | Settings
4 | Hello World from section: %1$d
5 | CPU Roofline
6 | GPU Roofline
7 | Gables
8 | Generate
9 |
10 |
11 | - CPU
12 | - CPU+GPU
13 | - Others
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
15 |
16 |
23 |
24 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/test/java/com/google/gables/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.google.gables;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.assertEquals;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 |
5 | repositories {
6 | google()
7 | jcenter()
8 | maven { url "https://chaquo.com/maven" }
9 | maven { url 'https://jitpack.io' }
10 | }
11 | dependencies {
12 | classpath 'com.android.tools.build:gradle:3.2.1'
13 |
14 | classpath "com.chaquo.python:gradle:6.0.0"
15 | // NOTE: Do not place your application dependencies here; they belong
16 | // in the individual module build.gradle files
17 | }
18 | }
19 |
20 | allprojects {
21 | repositories {
22 | google()
23 | jcenter()
24 | maven { url 'https://jitpack.io' }
25 | }
26 | }
27 |
28 | task clean(type: Delete) {
29 | delete rootProject.buildDir
30 | }
31 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Dec 06 13:07:46 PST 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/images/CPURooflineExamplePlot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harvard-edge/Gables/f869ec65bc7ea8920af049017355bfc9ed274346/images/CPURooflineExamplePlot.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/step_by_step.md:
--------------------------------------------------------------------------------
1 | # Step by step instructions on generating roofline plots
2 |
3 | ## Prerequisites
4 |
5 | Ensure that you have followed the steps in the [README](README.md) to build and install the APK onto a Android device. You should now be able to open the Gables app.
6 |
7 | In this example we will be generating a CPU rooline plot, but the process for generating a GPU roofline is very similar.
8 |
9 | ## Collecting data
10 |
11 | Open the Gables app and if necessary select yes on the prompt asking for permission to read and write files. Naviate to the `CPU ROOFLINE` tab of the app and select the test parameters. Once this has been done press run to perform the test. Once the test completes a number of files will have been written to a folder called `CPURoofline` in the `Internal Storage` directory of the device.
12 |
13 | ## Extracting Data
14 |
15 | You should transfer all of the files from the `CPURoofline` folder on the phone to a computer. You can do this in a couple of ways:
16 |
17 | 1. Use a file manager app to browse to the folder on the phone, highlight the files and then press `share` to share them with yourself.
18 | 2. Use [adb](https://developer.android.com/studio/command-line/adb) to extract the files. If you already have an Android device connected with USB debugging enabled, you can use the `adb` tool (located in the Android SDK) to extract the files to a folder on your computer called CPURoofline using the following command: `adb pull /sdcard/CPURoofline/ .`
19 |
20 | ## Processing Data
21 |
22 | The app currently uses a separate Python2 script to process the files generated when running a test in order to produce the roofline plots. The path to this Python script is `Gables/app/utils/plotting/scripts/gables.py`. In order to generate a plot from the files extracted in the previous section you can use the script as follows:
23 |
24 | `python gables.py -d [DIRECTORY_CONTAINING_EXTRACTED_FILES] -g ../gnuplots`
25 |
26 | This will produce a file `roofline.gnu` in the `output/` directory, which should automatically open. Alternatively the plot can be viewed manually using the [gnuplot](http://www.gnuplot.info/) tool using the following command:
27 |
28 | `gnuplot output/roofline.gnu -p`
29 |
30 | We see we have generated our CPU roofline graph:
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/utils/expprep.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -x
2 |
3 | ###############################################################################
4 | # ADB settings
5 | ###############################################################################
6 | adb root
7 |
8 | ###############################################################################
9 | # CPU, GPU and SYSTEM settings
10 | ###############################################################################
11 |
12 | # From Qualcomm® Snapdragon™ Mobile Platform OpenCL General Programming and Optimization performance mode
13 | adb shell "echo 0 > /sys/class/kgsl/kgsl-3d0/min_pwrlevel"
14 | adb shell "echo performance > /sys/class/kgsl/kgsl-3d0/devfreq/governor"
15 |
16 | adb shell "echo performance > /sys/class/devfreq/soc\:qcom,cpubw/governor"
17 | adb shell "echo performance > /sys/class/devfreq/soc\:qcom,gpubw/governor"
18 | adb shell "echo performance > /sys/class/devfreq/soc\:qcom,mincpubw/governor"
19 | adb shell "echo performance > /sys/class/devfreq/soc\:qcom,memlat-cpu0/governor"
20 | adb shell "echo performance > /sys/class/devfreq/soc\:qcom,memlat-cpu4/governor"
21 |
22 | adb shell "echo 1 > /sys/devices/system/cpu/cpu0/online"
23 | adb shell "echo 1 > /sys/devices/system/cpu/cpu1/online"
24 | adb shell "echo 1 > /sys/devices/system/cpu/cpu2/online"
25 | adb shell "echo 1 > /sys/devices/system/cpu/cpu3/online"
26 | adb shell "echo 1 > /sys/devices/system/cpu/cpu4/online"
27 | adb shell "echo 1 > /sys/devices/system/cpu/cpu5/online"
28 | adb shell "echo 1 > /sys/devices/system/cpu/cpu6/online"
29 | adb shell "echo 1 > /sys/devices/system/cpu/cpu7/online"
30 |
31 | #adb shell stop thermald
32 | #adb shell stop mpdecision
33 | #adb shell stop vendor.perfd
34 | #adb shell stop performanced
35 | #adb shell stop thermal-engine
36 | #adb shell stop vendor.thermal-engine
37 |
38 | #adb shell "cat /sys/class/kgsl/kgsl-3d0/gpuclk"
39 | #adb shell "echo 1 > /sys/class/kgsl/kgsl-3d0/force_clk_on"
40 | #adb shell "echo 1 > /sys/class/kgsl/kgsl-3d0/force_bus_on"
41 | #adb shell "echo 1 > /sys/class/kgsl/kgsl-3d0/force_rail_on"
42 | #adb shell "echo 1000000 > /sys/class/kgsl/kgsl-3d0/idle_timer"
43 |
44 | adb shell "echo 0 > /sys/class/kgsl/kgsl-3d0/min_pwrlevel"
45 | adb shell "echo 0 > /sys/class/kgsl/kgsl-3d0/max_pwrlevel"
46 |
47 | # disable "long instruction buffer detect" which kills(!) long running GPU kernels
48 | GPU_LONGIB_DETECT="/sys/class/kgsl/kgsl-3d0/ft_long_ib_detect"
49 | adb shell "echo 0 > $GPU_LONGIB_DETECT"
50 |
51 | # disable sepolicy to allow access to DSP
52 | adb shell setenforce 0
53 |
--------------------------------------------------------------------------------
/utils/plotting/gnuplots/band-vs-wss.gnu.template:
--------------------------------------------------------------------------------
1 | #!/usr/bin/gnuplot -persist
2 | #
3 | #
4 | # G N U P L O T
5 | # Version 4.2 patchlevel 6
6 | # last modified Sep 2009
7 | # System: Linux 2.6.32-53-generic
8 | #
9 | # Copyright (C) 1986 - 1993, 1998, 2004, 2007 - 2009
10 | # Thomas Williams, Colin Kelley and many others
11 | #
12 | # Type `help` to access the on-line reference manual.
13 | # The gnuplot FAQ is available from http://www.gnuplot.info/faq/
14 | #
15 | # Send bug reports and suggestions to
16 | #
17 | unset clip points
18 | set clip one
19 | unset clip two
20 | set bar 1.000000
21 | set xdata
22 | set ydata
23 | set zdata
24 | set x2data
25 | set y2data
26 | set boxwidth
27 | set style fill empty border
28 | set dummy x,y
29 | set format x "%.0e"
30 | set format y "%.0e"
31 | set format x2 "% g"
32 | set format y2 "% g"
33 | set format z "% g"
34 | set format cb "% g"
35 | set angles radians
36 | set grid nopolar
37 | set grid xtics mxtics ytics mytics noztics nomztics \
38 | nox2tics nomx2tics noy2tics nomy2tics nocbtics nomcbtics
39 | set grid layerdefault linetype 0 linewidth 1.000, linetype 0 linewidth 1.000
40 | set key title ""
41 | unset key
42 | unset label
43 | unset arrow
44 | unset style line
45 | unset style arrow
46 | unset logscale
47 | set logscale x 10
48 | set logscale y 10
49 | set offsets 0, 0, 0, 0
50 | set pointsize 1
51 | set encoding default
52 | unset polar
53 | unset parametric
54 | unset decimalsign
55 | set view 60, 30, 1, 1
56 | set samples 100, 100
57 | set isosamples 10, 10
58 | set surface
59 | unset contour
60 | set clabel '%8.3g'
61 | set mapping cartesian
62 | set datafile separator whitespace
63 | unset hidden3d
64 | set cntrparam order 4
65 | set cntrparam linear
66 | set cntrparam levels auto 5
67 | set cntrparam points 5
68 | set size ratio 0 1,1
69 | set origin 0,0
70 | set style data lines
71 | set style function lines
72 | set xzeroaxis linetype -2 linewidth 1.000
73 | set yzeroaxis linetype -2 linewidth 1.000
74 | set x2zeroaxis linetype -2 linewidth 1.000
75 | set y2zeroaxis linetype -2 linewidth 1.000
76 | set ticslevel 0.5
77 | set mxtics 10.000000
78 | set mytics 10.000000
79 | set mztics default
80 | set mx2tics default
81 | set my2tics default
82 | set mcbtics default
83 | set nox2tics
84 | set noy2tics
85 | set title "ERT_TITLE"
86 | set timestamp bottom
87 | set timestamp ""
88 | set rrange [ * : * ] noreverse nowriteback # (currently [0.00000:10.0000] )
89 | set trange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] )
90 | set urange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] )
91 | set vrange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] )
92 | set xlabel "Working Set Size (bytes)"
93 | set x2label ""
94 | set xrange [ERT_XRANGE_MIN : ERT_XRANGE_MAX] noreverse nowriteback # (currently [-10.0000:10.0000] )
95 | set x2range [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
96 | set ylabel "Total Bandwidth (GB/s)"
97 | set y2label ""
98 | set yrange [ERT_YRANGE_MIN : ERT_YRANGE_MAX] noreverse nowriteback # (currently [-10.0000:10.0000] )
99 | set y2range [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
100 | set zlabel ""
101 | set zrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
102 | set cblabel ""
103 | set cbrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
104 | set zero 1e-08
105 | set lmargin -1
106 | set bmargin -1
107 | set rmargin -1
108 | set tmargin -1
109 | set locale "C"
110 | set pm3d explicit at s
111 | set pm3d scansautomatic
112 | set palette positive nops_allcF maxcolors 0 gamma 1.5 color model RGB
113 | set palette rgbformulae 7, 5, 15
114 | set colorbox default
115 | set loadpath
116 | set fit noerrorvariables
117 | set terminal postscript solid color
118 | set terminal postscript enhanced eps
119 | set term postscript solid color rounded
120 | set output "ERT_GRAPH.eps"
121 | plot "ERT_RAW_DATA" using 1:7 with linespoints pt 7 ps 0.4
122 | #EOF
123 |
--------------------------------------------------------------------------------
/utils/plotting/gnuplots/band-vs-wss_max.gnu.template:
--------------------------------------------------------------------------------
1 | #!/usr/bin/gnuplot -persist
2 | #
3 | #
4 | # G N U P L O T
5 | # Version 4.2 patchlevel 6
6 | # last modified Sep 2009
7 | # System: Linux 2.6.32-53-generic
8 | #
9 | # Copyright (C) 1986 - 1993, 1998, 2004, 2007 - 2009
10 | # Thomas Williams, Colin Kelley and many others
11 | #
12 | # Type `help` to access the on-line reference manual.
13 | # The gnuplot FAQ is available from http://www.gnuplot.info/faq/
14 | #
15 | # Send bug reports and suggestions to
16 | #
17 | unset clip points
18 | set clip one
19 | unset clip two
20 | set bar 1.000000
21 | set xdata
22 | set ydata
23 | set zdata
24 | set x2data
25 | set y2data
26 | set boxwidth
27 | set style fill empty border
28 | set dummy x,y
29 | set format x "%.0e"
30 | set format y "%.0e"
31 | set format x2 "% g"
32 | set format y2 "% g"
33 | set format z "% g"
34 | set format cb "% g"
35 | set angles radians
36 | set grid nopolar
37 | set grid xtics mxtics ytics mytics noztics nomztics \
38 | nox2tics nomx2tics noy2tics nomy2tics nocbtics nomcbtics
39 | set grid layerdefault linetype 0 linewidth 1.000, linetype 0 linewidth 1.000
40 | set key title ""
41 | unset key
42 | unset label
43 | unset arrow
44 | unset style line
45 | unset style arrow
46 | unset logscale
47 | set logscale x 10
48 | set logscale y 10
49 | set offsets 0, 0, 0, 0
50 | set pointsize 1
51 | set encoding default
52 | unset polar
53 | unset parametric
54 | unset decimalsign
55 | set view 60, 30, 1, 1
56 | set samples 100, 100
57 | set isosamples 10, 10
58 | set surface
59 | unset contour
60 | set clabel '%8.3g'
61 | set mapping cartesian
62 | set datafile separator whitespace
63 | unset hidden3d
64 | set cntrparam order 4
65 | set cntrparam linear
66 | set cntrparam levels auto 5
67 | set cntrparam points 5
68 | set size ratio 0 1,1
69 | set origin 0,0
70 | set style data lines
71 | set style function lines
72 | set xzeroaxis linetype -2 linewidth 1.000
73 | set yzeroaxis linetype -2 linewidth 1.000
74 | set x2zeroaxis linetype -2 linewidth 1.000
75 | set y2zeroaxis linetype -2 linewidth 1.000
76 | set ticslevel 0.5
77 | set mxtics 10.000000
78 | set mytics 10.000000
79 | set mztics default
80 | set mx2tics default
81 | set my2tics default
82 | set mcbtics default
83 | set nox2tics
84 | set noy2tics
85 | set title "ERT_TITLE"
86 | set timestamp bottom
87 | set timestamp ""
88 | set rrange [ * : * ] noreverse nowriteback # (currently [0.00000:10.0000] )
89 | set trange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] )
90 | set urange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] )
91 | set vrange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] )
92 | set xlabel "Working Set Size (bytes)"
93 | set x2label ""
94 | set xrange [ERT_XRANGE_MIN : ERT_XRANGE_MAX] noreverse nowriteback # (currently [-10.0000:10.0000] )
95 | set x2range [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
96 | set ylabel "Total Bandwidth (GB/s)"
97 | set y2label ""
98 | set yrange [ERT_YRANGE_MIN : ERT_YRANGE_MAX] noreverse nowriteback
99 | set y2range [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
100 | set zlabel ""
101 | set zrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
102 | set cblabel ""
103 | set cbrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
104 | set zero 1e-08
105 | set lmargin -1
106 | set bmargin -1
107 | set rmargin -1
108 | set tmargin -1
109 | set locale "C"
110 | set pm3d explicit at s
111 | set pm3d scansautomatic
112 | set palette positive nops_allcF maxcolors 0 gamma 1.5 color model RGB
113 | set palette rgbformulae 7, 5, 15
114 | set colorbox default
115 | set loadpath
116 | set fit noerrorvariables
117 | set terminal postscript solid color
118 | set terminal postscript enhanced eps
119 | set term postscript solid color rounded
120 | set output "ERT_GRAPH.eps"
121 | plot "ERT_MAX_DATA" using 1:7 with linespoints pt 7 ps 0.4
122 | #EOF
123 |
--------------------------------------------------------------------------------
/utils/plotting/gnuplots/flops-vs-wss.gnu.template:
--------------------------------------------------------------------------------
1 | #!/usr/bin/gnuplot -persist
2 | #
3 | #
4 | # G N U P L O T
5 | # Version 4.2 patchlevel 6
6 | # last modified Sep 2009
7 | # System: Linux 2.6.32-53-generic
8 | #
9 | # Copyright (C) 1986 - 1993, 1998, 2004, 2007 - 2009
10 | # Thomas Williams, Colin Kelley and many others
11 | #
12 | # Type `help` to access the on-line reference manual.
13 | # The gnuplot FAQ is available from http://www.gnuplot.info/faq/
14 | #
15 | # Send bug reports and suggestions to
16 | #
17 | unset clip points
18 | set clip one
19 | unset clip two
20 | set bar 1.000000
21 | set xdata
22 | set ydata
23 | set zdata
24 | set x2data
25 | set y2data
26 | set boxwidth
27 | set style fill empty border
28 | set dummy x,y
29 | set format x "%.0e"
30 | set format y "%.0e"
31 | set format x2 "% g"
32 | set format y2 "% g"
33 | set format z "% g"
34 | set format cb "% g"
35 | set angles radians
36 | set grid nopolar
37 | set grid xtics mxtics ytics mytics noztics nomztics \
38 | nox2tics nomx2tics noy2tics nomy2tics nocbtics nomcbtics
39 | set grid layerdefault linetype 0 linewidth 1.000, linetype 0 linewidth 1.000
40 | set key title ""
41 | unset key
42 | unset label
43 | unset arrow
44 | unset style line
45 | unset style arrow
46 | unset logscale
47 | set logscale x 10
48 | set logscale y 10
49 | set offsets 0, 0, 0, 0
50 | set pointsize 1
51 | set encoding default
52 | unset polar
53 | unset parametric
54 | unset decimalsign
55 | set view 60, 30, 1, 1
56 | set samples 100, 100
57 | set isosamples 10, 10
58 | set surface
59 | unset contour
60 | set clabel '%8.3g'
61 | set mapping cartesian
62 | set datafile separator whitespace
63 | unset hidden3d
64 | set cntrparam order 4
65 | set cntrparam linear
66 | set cntrparam levels auto 5
67 | set cntrparam points 5
68 | set size ratio 0 1,1
69 | set origin 0,0
70 | set style data lines
71 | set style function lines
72 | set xzeroaxis linetype -2 linewidth 1.000
73 | set yzeroaxis linetype -2 linewidth 1.000
74 | set x2zeroaxis linetype -2 linewidth 1.000
75 | set y2zeroaxis linetype -2 linewidth 1.000
76 | set ticslevel 0.5
77 | set mxtics 10.000000
78 | set mytics 10.000000
79 | set mztics default
80 | set mx2tics default
81 | set my2tics default
82 | set mcbtics default
83 | set nox2tics
84 | set noy2tics
85 | set title "ERT_TITLE"
86 | set timestamp bottom
87 | set timestamp ""
88 | set rrange [ * : * ] noreverse nowriteback # (currently [0.00000:10.0000] )
89 | set trange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] )
90 | set urange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] )
91 | set vrange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] )
92 | set xlabel "Working Set Size (bytes)"
93 | set x2label ""
94 | set xrange [ERT_XRANGE_MIN : ERT_XRANGE_MAX] noreverse nowriteback # (currently [-10.0000:10.0000] )
95 | set x2range [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
96 | set ylabel "GFLOPs / sec"
97 | set y2label ""
98 | set yrange [ERT_YRANGE_MIN : ERT_YRANGE_MAX] noreverse nowriteback
99 | set y2range [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
100 | set zlabel ""
101 | set zrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
102 | set cblabel ""
103 | set cbrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
104 | set zero 1e-08
105 | set lmargin -1
106 | set bmargin -1
107 | set rmargin -1
108 | set tmargin -1
109 | set locale "C"
110 | set pm3d explicit at s
111 | set pm3d scansautomatic
112 | set palette positive nops_allcF maxcolors 0 gamma 1.5 color model RGB
113 | set palette rgbformulae 7, 5, 15
114 | set colorbox default
115 | set loadpath
116 | set fit noerrorvariables
117 | set terminal postscript enhanced eps
118 | set terminal postscript solid color
119 | set term postscript solid color rounded
120 | set output "ERT_GRAPH.eps"
121 | plot "ERT_MAX_DATA" using 1:10 with linespoints pt 7 ps 0.4
122 | #EOF
123 |
--------------------------------------------------------------------------------
/utils/plotting/gnuplots/roofline.gnu.template:
--------------------------------------------------------------------------------
1 | #!/usr/bin/gnuplot -persist
2 | #
3 | #
4 | # G N U P L O T
5 | # Version 4.2 patchlevel 6
6 | # last modified Sep 2009
7 | # System: Linux 2.6.32-55-generic
8 | #
9 | # Copyright (C) 1986 - 1993, 1998, 2004, 2007 - 2009
10 | # Thomas Williams, Colin Kelley and many others
11 | #
12 | # Type `help` to access the on-line reference manual.
13 | # The gnuplot FAQ is available from http://www.gnuplot.info/faq/
14 | #
15 | # Send bug reports and suggestions to
16 | #
17 | unset clip points
18 | set clip one
19 | unset clip two
20 | set bar 1.000000
21 | set xdata
22 | set ydata
23 | set zdata
24 | set x2data
25 | set y2data
26 | set boxwidth
27 | set style fill empty border
28 | set dummy x,y
29 | set format x "% g"
30 | set format y "% g"
31 | set format x2 "% g"
32 | set format y2 "% g"
33 | set format z "% g"
34 | set format cb "% g"
35 | set angles radians
36 | set grid nopolar
37 | set grid xtics mxtics ytics mytics noztics nomztics \
38 | nox2tics nomx2tics noy2tics nomy2tics nocbtics nomcbtics
39 | set grid layerdefault linetype 0 linewidth 1.000, linetype 0 linewidth 1.000
40 | set key title ""
41 | set key off
42 | unset label
43 | unset arrow
44 | unset style line
45 | unset style arrow
46 | unset logscale
47 | set logscale x 10
48 | set logscale y 10
49 | set offsets 0, 0, 0, 0
50 | set pointsize 1
51 | set encoding default
52 | unset polar
53 | unset parametric
54 | unset decimalsign
55 | set view 60, 30, 1, 1
56 | set samples 1000, 1000
57 | set isosamples 10, 10
58 | set surface
59 | unset contour
60 | set clabel '%8.3g'
61 | set mapping cartesian
62 | set datafile separator whitespace
63 | unset hidden3d
64 | set cntrparam order 4
65 | set cntrparam linear
66 | set cntrparam levels auto 5
67 | set cntrparam points 5
68 | #set size ratio -1 1,1
69 | set size ratio 1
70 | set origin 0,0
71 | set style data lines
72 | set style function lines
73 | set xzeroaxis linetype -2 linewidth 1.000
74 | set yzeroaxis linetype -2 linewidth 1.000
75 | set x2zeroaxis linetype -2 linewidth 1.000
76 | set y2zeroaxis linetype -2 linewidth 1.000
77 | set ticslevel 0.5
78 | set mxtics 10
79 | set mytics 10
80 | set mztics default
81 | set mx2tics default
82 | set my2tics default
83 | set mcbtics default
84 | set xtics autofreq
85 | set ytics autofreq
86 | set ztics autofreq
87 | set nox2tics
88 | set noy2tics
89 | set cbtics autofreq
90 | set title "ERT_TITLE"
91 | set timestamp bottom
92 | set timestamp ""
93 | set rrange [ * : * ] noreverse nowriteback # (currently [0.00000:10.0000] )
94 | set trange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] )
95 | set urange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] )
96 | set vrange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] )
97 | set xlabel "FLOPs / Byte"
98 | set x2label ""
99 | set xrange [ERT_XRANGE_MIN : ERT_XRANGE_MAX] noreverse nowriteback
100 | set x2range [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
101 | set ylabel "GFLOPs / sec"
102 | set y2label ""
103 | set yrange [ERT_YRANGE_MIN : ERT_YRANGE_MAX] noreverse nowriteback
104 | set y2range [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
105 | set zlabel ""
106 | set zrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
107 | set cblabel ""
108 | set cbrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
109 | set zero 1e-08
110 | set lmargin -1
111 | set bmargin -1
112 | set rmargin -1
113 | set tmargin -1
114 | set locale "C"
115 | set pm3d explicit at s
116 | set pm3d scansautomatic
117 | set palette positive nops_allcF maxcolors 0 gamma 1.5 color model RGB
118 | set palette rgbformulae 7, 5, 15
119 | set colorbox default
120 | set loadpath
121 | set fit noerrorvariables
122 |
123 | set terminal postscript enhanced eps
124 | set term postscript solid color rounded
125 | set output "ERT_GRAPH.eps"
126 |
127 | # Plotting goes after this...
128 |
--------------------------------------------------------------------------------
/utils/plotting/gnuplots/secs-vs-trials.gnu.template:
--------------------------------------------------------------------------------
1 | #!/usr/bin/gnuplot -persist
2 | #
3 | #
4 | # G N U P L O T
5 | # Version 4.2 patchlevel 6
6 | # last modified Sep 2009
7 | # System: Linux 2.6.32-53-generic
8 | #
9 | # Copyright (C) 1986 - 1993, 1998, 2004, 2007 - 2009
10 | # Thomas Williams, Colin Kelley and many others
11 | #
12 | # Type `help` to access the on-line reference manual.
13 | # The gnuplot FAQ is available from http://www.gnuplot.info/faq/
14 | #
15 | # Send bug reports and suggestions to
16 | #
17 | unset clip points
18 | set clip one
19 | unset clip two
20 | set bar 1.000000
21 | set xdata
22 | set ydata
23 | set zdata
24 | set x2data
25 | set y2data
26 | set boxwidth
27 | set style fill empty border
28 | set dummy x,y
29 | set format x "%.0e"
30 | set format y "%.0e"
31 | set format x2 "% g"
32 | set format y2 "% g"
33 | set format z "% g"
34 | set format cb "% g"
35 | set angles radians
36 | set grid nopolar
37 | set grid xtics mxtics ytics mytics noztics nomztics \
38 | nox2tics nomx2tics noy2tics nomy2tics nocbtics nomcbtics
39 | set grid layerdefault linetype 0 linewidth 1.000, linetype 0 linewidth 1.000
40 | set key title ""
41 | unset key
42 | unset label
43 | unset arrow
44 | unset style line
45 | unset style arrow
46 | unset logscale
47 | set logscale x 10
48 | set logscale y 10
49 | set offsets 0, 0, 0, 0
50 | set pointsize 1
51 | set encoding default
52 | unset polar
53 | unset parametric
54 | unset decimalsign
55 | set view 60, 30, 1, 1
56 | set samples 100, 100
57 | set isosamples 10, 10
58 | set surface
59 | unset contour
60 | set clabel '%8.3g'
61 | set mapping cartesian
62 | set datafile separator whitespace
63 | unset hidden3d
64 | set cntrparam order 4
65 | set cntrparam linear
66 | set cntrparam levels auto 5
67 | set cntrparam points 5
68 | set size ratio 0 1,1
69 | set origin 0,0
70 | set style data lines
71 | set style function lines
72 | set xzeroaxis linetype -2 linewidth 1.000
73 | set yzeroaxis linetype -2 linewidth 1.000
74 | set x2zeroaxis linetype -2 linewidth 1.000
75 | set y2zeroaxis linetype -2 linewidth 1.000
76 | set ticslevel 0.5
77 | set mxtics 10.000000
78 | set mytics 10.000000
79 | set mztics default
80 | set mx2tics default
81 | set my2tics default
82 | set mcbtics default
83 | set nox2tics
84 | set noy2tics
85 | set title "ERT_TITLE"
86 | set timestamp bottom
87 | set timestamp ""
88 | set rrange [ * : * ] noreverse nowriteback # (currently [0.00000:10.0000] )
89 | set trange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] )
90 | set urange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] )
91 | set vrange [ * : * ] noreverse nowriteback # (currently [-5.00000:5.00000] )
92 | set xlabel "Number Of Trials"
93 | set x2label ""
94 | set xrange [ERT_XRANGE_MIN : ERT_XRANGE_MAX] noreverse nowriteback # (currently [-10.0000:10.0000] )
95 | set x2range [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
96 | set ylabel "Seconds"
97 | set y2label ""
98 | set yrange [ERT_YRANGE_MIN : ERT_YRANGE_MAX] noreverse nowriteback # (currently [-10.0000:10.0000] )
99 | set y2range [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
100 | set zlabel ""
101 | set zrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
102 | set cblabel ""
103 | set cbrange [ * : * ] noreverse nowriteback # (currently [-10.0000:10.0000] )
104 | set zero 1e-08
105 | set lmargin -1
106 | set bmargin -1
107 | set rmargin -1
108 | set tmargin -1
109 | set locale "C"
110 | set pm3d explicit at s
111 | set pm3d scansautomatic
112 | set palette positive nops_allcF maxcolors 0 gamma 1.5 color model RGB
113 | set palette rgbformulae 7, 5, 15
114 | set colorbox default
115 | set loadpath
116 | set fit noerrorvariables
117 | #GNUTERM = "wxt"
118 | set terminal postscript solid color
119 | set output "ERT_GRAPH.ps"
120 | plot "ERT_RAW_DATA" using 2:4
121 | #EOF
122 |
--------------------------------------------------------------------------------