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