tfjs does not work with hermes engine
See original GitHub issueSystem information
- Have I written custom code (as opposed to using a stock example script provided in TensorFlow.js): No
- OS Platform and Distribution (e.g., Linux Ubuntu 16.04): MacOS 12.2.1 (21D62), M1
- Mobile device (e.g. iPhone 8, Pixel 2, Samsung Galaxy) if the issue happens on mobile device: NA
- TensorFlow.js installed from (npm or script link): npm
- TensorFlow.js version (use command below): 3.18.0
- Browser version: NA
- Tensorflow.js Converter Version: NA
Describe the current behavior
When using tfjs for React Native, tfjs does not work when using hermes JavaScript engine. It works with the default jsc
engine.
It fails at instanceof Tensor
assertion, even though the constructor
is correctly identified as Tensor
:
Describe the expected behavior
tfjs should run without errors when using hermes
engine.
Standalone code to reproduce the issue
Minimum reproduction repo: https://github.com/paradite/tfjs-hermes-bug
From the repo, running npm run test:hermes
throws an error:
tensor.js:1:1: error: class declaration exports are unsupported
This means that probably the original code was transformed by babel/typescript before reaching hermes
and caused the instance of
assertion to fail.
I should raise an issue in https://github.com/facebook/hermes, but it is hard to reproduce the exact issue when tfjs uses a lot of import across different files (hermes-cli needs to take input of all files being imported).
On the other hand, the fix for this issue on tfjs side is easy:
Other info / logs
I have tried a hacky fix and it seems to work:
Instead of using
if (x instanceof Tensor) {
assertDtype(parseAsDtype, x.dtype, argName, functionName);
return x;
}
, use
if (x instanceof Tensor || x.constructor.name === 'Tensor') {
assertDtype(parseAsDtype, x.dtype, argName, functionName);
return x;
}
Issue Analytics
- State:
- Created a year ago
- Reactions:1
- Comments:8 (1 by maintainers)
Top GitHub Comments
@mattsoulanille thanks for taking a look.
I want to share a walkaround that I found to be working for my use case:
node_modules/@tensorflow/tfjs/dist/tf.node.js
npm i
/yarn
I am using yarn v1 so I ran
The additional setup in
package.json
looks like this:I did also spent a few hours digging into this issue but did not make much progress. Some findings:
@tensorflow/tfjs-react-native
package does not matter. the issue happens with or without itTensor
was returned by some operation and then theTensor
instance chains other operations such asargMax
ormul
, which leads togetGlobalTensorClass
call:tensor.argMax(-1)
intotf.argMax(tensor, -1)
seems to solve the issue for that particular instance, as I was getting different errors after the rewriteTensor
object from@tensorflow/tfjs
,@tensorflow/tfjs/dist/tf.node
and@tensorflow/tfjs-core/dist/tf-core.node
appear to be identical on Hermes in my testing:Sorry for the lack of updates. We would like to support Hermes, if possible, but it’s not at the top of our priority list right now.
Looking at the error message, this seems to be a case of having multiple versions of the
Tensor
class, possibly due to importingTensor
from@tensorflow/tfjs-core
, which points to a rollup bundle, and from@tensorflow/tfjs-core/dist/tensor
, which points to a file. If you . In the future, we may add anexports
field to thepackage.json
file, which should prevent these kinds of imports by only allowing a set of imports we specify.I expect this change will fix the issue here or at least reveal what’s causing it.I took a quick look at the reproduction (thanks for posting one!), and it seems like it’s not using tfjs (It has its own tensor class). I don’t think Hermes supports exporting classes yet, but the example might work if it’s compiled down to use prototypes instead of classes (es5 I think).
I also tried getting hermes to import
@tensorflow/tfjs
. Here are a few fixes we need to make in tfjs to make this happen:globalThis
as the global variable in getGlobalNamespace (For my test, I replacedglobal
withglobalThis
innode_modules/@tensorflow/tfjs/dist/tf.js
bundle)print
instead ofconsole.log
- We should probably add a log function to the Platform interface (For my test, I just string-replaced console.log with print innode_modules/@tensorflow/tfjs/dist/tf.js
).After these changes, the following test code works (on my linux machine):
However, I’m not able to load any tfjs backends, so all I can do is print the size.
Edit: Actually, I’m able to load the CPU backend, but it seems as though the weak map that holds tensor data is losing the data too early when I try to run
readSync
.Please leave this issue open so I can take another look when I have some time.