9
9
package org .pytorch .executorch ;
10
10
11
11
import android .util .Log ;
12
+ import com .facebook .jni .HybridData ;
13
+ import com .facebook .jni .annotations .DoNotStrip ;
12
14
import com .facebook .soloader .nativeloader .NativeLoader ;
13
15
import com .facebook .soloader .nativeloader .SystemDelegate ;
14
16
import java .io .File ;
24
26
@ Experimental
25
27
public class Module {
26
28
29
+ static {
30
+ if (!NativeLoader .isInitialized ()) {
31
+ NativeLoader .init (new SystemDelegate ());
32
+ }
33
+ // Loads libexecutorch.so from jniLibs
34
+ NativeLoader .loadLibrary ("executorch" );
35
+ }
36
+
27
37
/** Load mode for the module. Load the whole file as a buffer. */
28
38
public static final int LOAD_MODE_FILE = 0 ;
29
39
@@ -36,10 +46,17 @@ public class Module {
36
46
/** Load mode for the module. Use memory locking and ignore errors. */
37
47
public static final int LOAD_MODE_MMAP_USE_MLOCK_IGNORE_ERRORS = 3 ;
38
48
39
- /** Reference to the NativePeer object of this module. */
40
- private NativePeer mNativePeer ;
49
+ private final HybridData mHybridData ;
50
+
51
+ @ DoNotStrip
52
+ private static native HybridData initHybrid (
53
+ String moduleAbsolutePath , int loadMode , int initHybrid );
41
54
42
- /** Lock protecting the non-thread safe methods in NativePeer. */
55
+ private Module (String moduleAbsolutePath , int loadMode , int numThreads ) {
56
+ mHybridData = initHybrid (moduleAbsolutePath , loadMode , numThreads );
57
+ }
58
+
59
+ /** Lock protecting the non-thread safe methods in mHybridData. */
43
60
private Lock mLock = new ReentrantLock ();
44
61
45
62
/**
@@ -63,14 +80,11 @@ public static Module load(final String modelPath, int loadMode) {
63
80
* @return new {@link org.pytorch.executorch.Module} object which owns the model module.
64
81
*/
65
82
public static Module load (final String modelPath , int loadMode , int numThreads ) {
66
- if (!NativeLoader .isInitialized ()) {
67
- NativeLoader .init (new SystemDelegate ());
68
- }
69
83
File modelFile = new File (modelPath );
70
84
if (!modelFile .canRead () || !modelFile .isFile ()) {
71
85
throw new RuntimeException ("Cannot load model path " + modelPath );
72
86
}
73
- return new Module (new NativePeer ( modelPath , loadMode , numThreads ) );
87
+ return new Module (modelPath , loadMode , numThreads );
74
88
}
75
89
76
90
/**
@@ -83,10 +97,6 @@ public static Module load(final String modelPath) {
83
97
return load (modelPath , LOAD_MODE_FILE );
84
98
}
85
99
86
- Module (NativePeer nativePeer ) {
87
- this .mNativePeer = nativePeer ;
88
- }
89
-
90
100
/**
91
101
* Runs the 'forward' method of this module with the specified arguments.
92
102
*
@@ -96,16 +106,7 @@ public static Module load(final String modelPath) {
96
106
* @return return value from the 'forward' method.
97
107
*/
98
108
public EValue [] forward (EValue ... inputs ) {
99
- try {
100
- mLock .lock ();
101
- if (mNativePeer == null ) {
102
- Log .e ("ExecuTorch" , "Attempt to use a destroyed module" );
103
- return new EValue [0 ];
104
- }
105
- return mNativePeer .forward (inputs );
106
- } finally {
107
- mLock .unlock ();
108
- }
109
+ return execute ("forward" , inputs );
109
110
}
110
111
111
112
/**
@@ -118,16 +119,19 @@ public EValue[] forward(EValue... inputs) {
118
119
public EValue [] execute (String methodName , EValue ... inputs ) {
119
120
try {
120
121
mLock .lock ();
121
- if (mNativePeer == null ) {
122
+ if (! mHybridData . isValid () ) {
122
123
Log .e ("ExecuTorch" , "Attempt to use a destroyed module" );
123
124
return new EValue [0 ];
124
125
}
125
- return mNativePeer . execute (methodName , inputs );
126
+ return executeNative (methodName , inputs );
126
127
} finally {
127
128
mLock .unlock ();
128
129
}
129
130
}
130
131
132
+ @ DoNotStrip
133
+ private native EValue [] executeNative (String methodName , EValue ... inputs );
134
+
131
135
/**
132
136
* Load a method on this module. This might help with the first time inference performance,
133
137
* because otherwise the method is loaded lazily when it's execute. Note: this function is
@@ -140,31 +144,36 @@ public EValue[] execute(String methodName, EValue... inputs) {
140
144
public int loadMethod (String methodName ) {
141
145
try {
142
146
mLock .lock ();
143
- if (mNativePeer == null ) {
147
+ if (! mHybridData . isValid () ) {
144
148
Log .e ("ExecuTorch" , "Attempt to use a destroyed module" );
145
149
return 0x2 ; // InvalidState
146
150
}
147
- return mNativePeer . loadMethod (methodName );
151
+ return loadMethodNative (methodName );
148
152
} finally {
149
153
mLock .unlock ();
150
154
}
151
155
}
152
156
157
+ @ DoNotStrip
158
+ private native int loadMethodNative (String methodName );
159
+
153
160
/**
154
161
* Returns the names of the methods in a certain method.
155
162
*
156
163
* @param methodName method name to query
157
164
* @return an array of backend name
158
165
*/
159
- public String [] getUsedBackends (String methodName ) {
160
- return mNativePeer .getUsedBackends (methodName );
161
- }
166
+ @ DoNotStrip
167
+ public native String [] getUsedBackends (String methodName );
162
168
163
169
/** Retrieve the in-memory log buffer, containing the most recent ExecuTorch log entries. */
164
170
public String [] readLogBuffer () {
165
- return mNativePeer . readLogBuffer ();
171
+ return readLogBufferNative ();
166
172
}
167
173
174
+ @ DoNotStrip
175
+ private native String [] readLogBufferNative ();
176
+
168
177
/**
169
178
* Dump the ExecuTorch ETRecord file to /data/local/tmp/result.etdump.
170
179
*
@@ -173,9 +182,8 @@ public String[] readLogBuffer() {
173
182
* @return true if the etdump was successfully written, false otherwise.
174
183
*/
175
184
@ Experimental
176
- public boolean etdump () {
177
- return mNativePeer .etdump ();
178
- }
185
+ @ DoNotStrip
186
+ public native boolean etdump ();
179
187
180
188
/**
181
189
* Explicitly destroys the native Module object. Calling this method is not required, as the
@@ -186,13 +194,11 @@ public boolean etdump() {
186
194
public void destroy () {
187
195
if (mLock .tryLock ()) {
188
196
try {
189
- mNativePeer .resetNative ();
197
+ mHybridData .resetNative ();
190
198
} finally {
191
- mNativePeer = null ;
192
199
mLock .unlock ();
193
200
}
194
201
} else {
195
- mNativePeer = null ;
196
202
Log .w (
197
203
"ExecuTorch" ,
198
204
"Destroy was called while the module was in use. Resources will not be immediately"
0 commit comments