Skip to content

Commit

Permalink
[RPC] Android RPC Performance Regression Fix, Update Android RPC to u…
Browse files Browse the repository at this point in the history
…se Tracker (#1457)
  • Loading branch information
eqy authored and tqchen committed Jul 20, 2018
1 parent 5f7b4d5 commit 5c84a98
Show file tree
Hide file tree
Showing 21 changed files with 625 additions and 288 deletions.
15 changes: 8 additions & 7 deletions apps/android_rpc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,15 @@ Here's a piece of example for `config.mk`.

```makefile
APP_ABI = arm64-v8a

APP_PLATFORM = android-17

# whether enable OpenCL during compile
USE_OPENCL = 1

# the additional include headers you want to add, e.g., SDK_PATH/adrenosdk/Development/Inc
ADD_C_INCLUDES = /opt/adrenosdk-osx/Development/Inc

# the additional link libs you want to add, e.g., ANDROID_LIB_PATH/libOpenCL.so
ADD_LDLIBS = libOpenCL.so
```
Expand All @@ -85,13 +85,14 @@ If everything goes well, you will find compile tools in `/opt/android-toolchain-

### Cross Compile and Upload to the Android Device

First start a proxy server using `python -m tvm.exec.rpc_proxy` and make your Android device connect to this proxy server via TVM RPC application.
First start an RPC tracker using `python -m tvm.exec.rpc_tracker --port [PORT]` and make your Android device connect to this RPC tracker via TVM RPC application.

Then checkout [android\_rpc/tests/android\_rpc\_test.py](https://github.com/dmlc/tvm/blob/master/apps/android_rpc/tests/android_rpc_test.py) and run,

```bash
# Specify the proxy host
export TVM_ANDROID_RPC_PROXY_HOST=0.0.0.0
# Specify the RPC tracker
export TVM_TRACKER_HOST=0.0.0.0
export TVM_TRACKER_PORT=[PORT]
# Specify the standalone Android C++ compiler
export TVM_NDK_CC=/opt/android-toolchain-arm64/bin/aarch64-linux-android-g++
python android_rpc_test.py
Expand Down
2 changes: 1 addition & 1 deletion apps/android_rpc/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ android {
buildToolsVersion "26.0.1"
defaultConfig {
applicationId "ml.dmlc.tvm.tvmrpc"
minSdkVersion 17
minSdkVersion 24
targetSdkVersion 26
versionCode 1
versionName "1.0"
Expand Down
13 changes: 10 additions & 3 deletions apps/android_rpc/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,16 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".RPCService"
android:process=":RPCServiceProcess"
android:permission="android.permission.BIND_JOB_SERVICE" />
<service android:name=".RPCWatchdogService"
android:process=":RPCWatchdogServiceProcess"
android:permission="android.permission.BIND_JOB_SERVICE" />
<activity
android:name=".RPCActivity"
android:process=":RPCProcess"
android:label="@string/rpc_name"
android:theme="@style/AppTheme.NoActionBar"
android:screenOrientation="portrait">
</activity>
</application>

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,18 @@
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.Switch;
import android.widget.Button;
import android.view.View;
import android.content.Intent;
import android.app.NotificationChannel;
import android.app.NotificationManager;


public class MainActivity extends AppCompatActivity {
private boolean skipRelaunch = true;
// wait time before automatic restart of RPC Activity
public static final int HANDLER_RESTART_DELAY = 5000;

private RPCWatchdog watchdog;

private void showDialog(String title, String msg) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
Expand All @@ -52,73 +58,107 @@ public void onClick(DialogInterface dialog, int id) {
builder.create().show();
}

public Intent updateRPCPrefs() {
System.err.println("updating preferences...");
EditText edProxyAddress = findViewById(R.id.input_address);
EditText edProxyPort = findViewById(R.id.input_port);
EditText edAppKey = findViewById(R.id.input_key);
Switch inputSwitch = findViewById(R.id.switch_persistent);

final String proxyHost = edProxyAddress.getText().toString();
final int proxyPort = Integer.parseInt(edProxyPort.getText().toString());
final String key = edAppKey.getText().toString();
final boolean isChecked = inputSwitch.isChecked();

SharedPreferences pref = getApplicationContext().getSharedPreferences("RPCProxyPreference", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putString("input_address", proxyHost);
editor.putString("input_port", edProxyPort.getText().toString());
editor.putString("input_key", key);
editor.putBoolean("input_switch", isChecked);
editor.commit();

Intent intent = new Intent(this, RPCActivity.class);
intent.putExtra("host", proxyHost);
intent.putExtra("port", proxyPort);
intent.putExtra("key", key);
return intent;
}

private void setupRelaunch() {
final Context context = this;
final Switch switchPersistent = findViewById(R.id.switch_persistent);
final Runnable rPCStarter = new Runnable() {
public void run() {
if (switchPersistent.isChecked()) {
System.err.println("relaunching RPC activity in 5s...");
Intent intent = ((MainActivity) context).updateRPCPrefs();
startActivity(intent);
}
}
};
Handler handler = new Handler();
handler.postDelayed(rPCStarter, HANDLER_RESTART_DELAY);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final Context context = this;

Switch switchConnect = findViewById(R.id.switch_connect);
switchConnect.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
Switch switchPersistent = findViewById(R.id.switch_persistent);
switchPersistent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
enableInputView(false);
connectProxy();
System.err.println("automatic RPC restart enabled...");
updateRPCPrefs();
} else {
disconnect();
enableInputView(true);
System.err.println("automatic RPC restart disabled...");
updateRPCPrefs();
}
}
});

enableInputView(true);

Button startRPC = findViewById(R.id.button_start_rpc);
startRPC.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = ((MainActivity) context).updateRPCPrefs();
startActivity(intent);
}
});

enableInputView(true);
}

@Override
protected void onDestroy() {
super.onDestroy();
if (watchdog != null) {
watchdog.disconnect();
watchdog = null;
protected void onResume() {
System.err.println("MainActivity onResume...");
System.err.println("skipRelaunch: " + skipRelaunch);
// if this is the first time onResume is called, do nothing, otherwise we
// may double launch
if (!skipRelaunch) {
enableInputView(true);
setupRelaunch();
} else {
skipRelaunch = false;
}
super.onResume();
}

private void connectProxy() {
EditText edProxyAddress = findViewById(R.id.input_address);
EditText edProxyPort = findViewById(R.id.input_port);
EditText edAppKey = findViewById(R.id.input_key);
final String proxyHost = edProxyAddress.getText().toString();
final int proxyPort = Integer.parseInt(edProxyPort.getText().toString());
final String key = edAppKey.getText().toString();

System.err.println("creating watchdog thread...");
watchdog = new RPCWatchdog(proxyHost, proxyPort, key, this);

System.err.println("starting watchdog thread...");
watchdog.start();

SharedPreferences pref = getApplicationContext().getSharedPreferences("RPCProxyPreference", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putString("input_address", proxyHost);
editor.putString("input_port", edProxyPort.getText().toString());
editor.putString("input_key", key);
editor.commit();
}

private void disconnect() {
if (watchdog != null) {
watchdog.disconnect();
watchdog = null;
}
@Override
protected void onDestroy() {
super.onDestroy();
}

private void enableInputView(boolean enable) {
EditText edProxyAddress = findViewById(R.id.input_address);
EditText edProxyPort = findViewById(R.id.input_port);
EditText edAppKey = findViewById(R.id.input_key);
Switch input_switch = findViewById(R.id.switch_persistent);
edProxyAddress.setEnabled(enable);
edProxyPort.setEnabled(enable);
edAppKey.setEnabled(enable);
Expand All @@ -134,6 +174,8 @@ private void enableInputView(boolean enable) {
String inputKey = pref.getString("input_key", null);
if (null != inputKey)
edAppKey.setText(inputKey);
boolean isChecked = pref.getBoolean("input_switch", false);
input_switch.setChecked(isChecked);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package ml.dmlc.tvm.tvmrpc;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.content.Intent;
import android.widget.Button;
import android.view.View;

public class RPCActivity extends AppCompatActivity {
private RPCProcessor tvmServerWorker;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rpc);

Button stopRPC = findViewById(R.id.button_stop_rpc);
stopRPC.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
System.err.println(tvmServerWorker == null);
if (tvmServerWorker != null) {
// currently will raise a socket closed exception
tvmServerWorker.disconnect();
}
finish();
// prevent Android from recycling the process
System.exit(0);
}
});

System.err.println("rpc activity onCreate...");
Intent intent = getIntent();
String host = intent.getStringExtra("host");
int port = intent.getIntExtra("port", 9090);
String key = intent.getStringExtra("key");

tvmServerWorker = new RPCProcessor();
tvmServerWorker.setDaemon(true);
tvmServerWorker.start();
tvmServerWorker.connect(host, port, key);
}

@Override
protected void onDestroy() {
System.err.println("rpc activity onDestroy");
tvmServerWorker.disconnect();
super.onDestroy();
}
}
Loading

0 comments on commit 5c84a98

Please sign in to comment.