Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] Error running a transformer decoder-based neural network #8665

Open
adonnini opened this issue Feb 25, 2025 · 48 comments
Open

[Android] Error running a transformer decoder-based neural network #8665

adonnini opened this issue Feb 25, 2025 · 48 comments
Assignees
Labels
module: android Issues related to Android code, build, and execution module: user experience Issues related to reducing friction for users triaged This issue has been looked at a team member, and triaged and prioritized into an appropriate module

Comments

@adonnini
Copy link

adonnini commented Feb 25, 2025

Hi,

@kirklandsign I have been developing on Android for more than 15 years. I am familiar with dependencies etc., etc. The issue 8636 had to do with packaging.

I guess you did not see my last comment in
#8636

Here it is again:

Hi Update #2

I worked around the classNotFound exception by creating a java.org.pytorch.executorch package containing all the source files from
executorch/extension/android/src/main/java/org/pytorch/executorch

Now execution fails producing the error log reported below.

I built ```libexecutorch.so``` following the instructions in
https://pytorch.org/executorch/stable/demo-apps-android.html

Package name is the same as expected (and used in the android demo app), i.e. ```org.pytorch.executorch```

The dependencies are
                implementation 'com.facebook.fbjni:fbjni-java-only:0.2.2'
                implementation 'com.facebook.soloader:nativeloader:0.10.5'

as in the android demo app

At this point, I am at a loss as to what I am doing wrong and what I should try next.

Should I add and android module to my project just as there is one in the android demo app. In the android demo app, the android module contains all the modules necessary to use the executorch runtime (e.g. NativePeer) in the application.

I think the issue may be related to multi-project set-up which I do not use in my application (although I do have multiple modules within the project.

Generally speaking, I still have the sense that the set-up to use the executorch runtime on Android applications could/should be simpler, for example not requiring the use of the wrapper modules in org.pytorch.executorch

Please let me know if you need additional information.

Thanks

ERROR LOG

02-23 16:41:41.176: W/libc(25151): Access denied finding property "ro.mediatek.platform"
02-23 16:41:41.176: W/libc(25151): Access denied finding property "ro.chipname"
02-23 16:41:41.177: E/audit(1210): type=1400 audit(1740325301.170:52396): avc:  denied  { read } for  pid=25151 comm="Thread-2" name="u:object_r:media_plat_prop:s0" dev="tmpfs" ino=315 scontext=u:r:untrusted_app_30:s0:c45,c258,c512,c768 tcontext=u:object_r:media_plat_prop:s0 tclass=file permissive=0 SEPF_SM-S908B_12_0001 audit_filtered
02-23 16:41:41.177: E/audit(1210): type=1400 audit(1740325301.170:52397): avc:  denied  { read } for  pid=25151 comm="Thread-2" name="u:object_r:chipname_prop:s0" dev="tmpfs" ino=165 scontext=u:r:untrusted_app_30:s0:c45,c258,c512,c768 tcontext=u:object_r:chipname_prop:s0 tclass=file permissive=0 SEPF_SM-S908B_12_0001 audit_filtered
02-23 16:41:41.179: D/nativeloader(25151): Load /data/app/~~CzYQ5jB-bXszoW-cWE7uUg==/com.android.contextq-B_Rwji2_VyK2Jx3NvUwN1A==/base.apk!/lib/arm64-v8a/libexecutorch.so using ns clns-5 from class loader (caller=/data/app/~~CzYQ5jB-bXszoW-cWE7uUg==/com.android.contextq-B_Rwji2_VyK2Jx3NvUwN1A==/base.apk): ok
02-23 16:41:41.179: W/lNetworkService(25151): CheckJNI: method to register "initHybrid" not in the given class. This is slow, consider changing your RegisterNatives calls.
02-23 16:41:41.183: E/lNetworkService(25151): ----- class 'Lorg/pytorch/executorch/NativePeer;' cl=0x140133a8 -----
02-23 16:41:41.183: E/lNetworkService(25151):   objectSize=240 (224 from super)
02-23 16:41:41.183: E/lNetworkService(25151):   access=0x0000.0000
02-23 16:41:41.183: E/lNetworkService(25151):   super='java.lang.Class<java.lang.Object>' (cl=0x0)
02-23 16:41:41.183: E/lNetworkService(25151):   interfaces (1):
02-23 16:41:41.183: E/lNetworkService(25151):      0: java.lang.Class<org.pytorch.executorch.INativePeer> (cl=0x140133a8)
02-23 16:41:41.183: E/lNetworkService(25151):   vtable (2 entries, 11 in super):
02-23 16:41:41.183: E/lNetworkService(25151):      0: org.pytorch.executorch.EValue org.pytorch.executorch.NativePeer.forward(org.pytorch.executorch.EValue[])
02-23 16:41:41.183: E/lNetworkService(25151):      1: void org.pytorch.executorch.NativePeer.resetNative()
02-23 16:41:41.183: E/lNetworkService(25151):   direct methods (3 entries):
02-23 16:41:41.183: E/lNetworkService(25151):      0: void org.pytorch.executorch.NativePeer.<clinit>()
02-23 16:41:41.183: E/lNetworkService(25151):      1: void org.pytorch.executorch.NativePeer.<init>(java.lang.String, java.util.Map)
02-23 16:41:41.183: E/lNetworkService(25151):      2: com.facebook.jni.HybridData org.pytorch.executorch.NativePeer.initHybrid(java.lang.String, java.util.Map)
02-23 16:41:41.183: E/lNetworkService(25151):   instance fields (1 entries):
02-23 16:41:41.183: E/lNetworkService(25151):      0: com.facebook.jni.HybridData org.pytorch.executorch.NativePeer.mHybridData
02-23 16:41:41.183: E/lNetworkService(25151): Failed to register native method org.pytorch.executorch.NativePeer.initHybrid(Ljava/lang/String;I)Lcom/facebook/jni/HybridData; in /data/data/com.android.contextq/code_cache/.overlay/base.apk/classes14.dex
02-23 16:41:41.184: E/log(25151): error java.lang.NoSuchMethodError: no static or non-static method "Lorg/pytorch/executorch/NativePeer;.initHybrid(Ljava/lang/String;I)Lcom/facebook/jni/HybridData;"
02-23 16:41:41.185: A/lNetworkService(25151): java_vm_ext.cc:616] JNI DETECTED ERROR IN APPLICATION: JNI NewGlobalRef called with pending exception java.lang.NoSuchMethodError: no static or non-static method "Lorg/pytorch/executorch/NativePeer;.initHybrid(Ljava/lang/String;I)Lcom/facebook/jni/HybridData;"
02-23 16:41:41.185: A/lNetworkService(25151): java_vm_ext.cc:616] (Throwable with no stack trace)
02-23 16:41:41.185: A/lNetworkService(25151): java_vm_ext.cc:616] 
02-23 16:41:41.185: A/lNetworkService(25151): java_vm_ext.cc:616]     in call to NewGlobalRef
02-23 16:41:41.185: A/lNetworkService(25151): java_vm_ext.cc:616]     from java.lang.String java.lang.Runtime.nativeLoad(java.lang.String, java.lang.ClassLoader, java.lang.Class)

cc @kirklandsign @cbilgin @mergennachin @byjlw

@guangy10
Copy link
Contributor

Can you please include your dev env and commit hash on main, in case developers need to reproduce the issue?

@guangy10 guangy10 added the module: android Issues related to Android code, build, and execution label Feb 25, 2025
@guangy10 guangy10 added the need-user-input The issue needs more information from the reporter before moving forward label Feb 25, 2025
@kirklandsign
Copy link
Contributor

kirklandsign commented Feb 25, 2025

Hi @adonnini

Currently the demo app doesn't copy java sources (modules) (e.g. NativePeer) but use the AAR instead

cp "$BUILD_AAR_DIR/executorch.aar" "$BASEDIR"/app/libs/executorch.aar

and the AAR contains .so and .jar (which contains all compiled java file)

And you can include AAR in your project by

implementation(files("libs/executorch.aar"))

@adonnini
Copy link
Author

Hi @guangy10 ,
I do not have a commit hash for this. I am not sure which commit hash you are referring to. Could you please clarify?
My development environment:

  • Debian bookworm
  • Android Studio ladybug patch 2
    Do you need any other information regarding my development environment?
    Thanks

@adonnini
Copy link
Author

@kirklandsign Thanks.
I will add the dependency. Where can I find a copy of the .aar? There is no libs directory in executorch/extension/benchmark/android/benchmark/app
Did I look in the wrong place? Or, do I need to just build the benchmark app?
Sorry about these questions. Thanks,

P.S. Is the information in your message anywhere in the documentation? Could you please send me a link, if there is? Thanks

@adonnini
Copy link
Author

adonnini commented Feb 25, 2025 via email

@mergennachin mergennachin added the module: user experience Issues related to reducing friction for users label Feb 25, 2025
@github-project-automation github-project-automation bot moved this to To triage in ExecuTorch DevX Feb 25, 2025
@adonnini
Copy link
Author

@kirklandsign

I apologize in advance for the (very) long message. Please read it to the end.

I tried running setup.sh from both the LlamaDemo and ExecutorchDemo directories. They both failed.

  • setup.sh in ExecutorchDemo directory failed with this error:
CMake Error: The source directory "/home/adonnini1/Development/ContextQSourceCode/NeuralNetworks/LocationPredictionContextQ/executorch/examples/demo-apps/android/ExecuTorchDemo" does not appear to contain CMakeLists.txt.

I checked. There is no CMakeLists.txt in the directory

  • setup.sh in lLamaDemo directory fails with this error:
/home/adonnini1/Development/ContextQSourceCode/NeuralNetworks/LocationPredictionContextQ/executorch/examples/demo-apps/android/LlamaDemo/../../../../build/build_android_llm_demo.sh: line 11: pushd: extension/android: No such file or directory

the executorch/extension/android does exist.

In setting up exeutorch I followed the instruction in
https://pytorch.org/executorch/stable/getting-started-setup.html
Everything worked with no errors.

However, I must have done something wrong, not sure what. I am not familiar shell scripting. I did not make any changes to the two scripts.

As a workaround, I ran download_prebuilt_lib.sh found in the LlamaDemo directory. Then, I copied the executorch.aar which was downloaded to the libs folder in my application and added the dependency.

Android Studio reports the following error:

Cannot resolve method 'toTensor' in 'EValue'

in this line

outputTensor = mModule.forward(EValue.from(arrDataPytorch)).toTensor();

Note that there is a line like this in
executorch/examples/demo-apps/android/ExecuTorchDemo/app/src/main/java/com/example/executorchdemo/MainActivity.java
Tensor outputTensor = mModule.forward(EValue.from(inputTensor))[0].toTensor();

I also checked the contents of EValue.class in executorch.aar. It does contain a toTensor method.

However, application build was successful.

When I ran the application, execution still failed when attempting to load the module. Please see the error log below.

Is the executorch.aar I downloaded not the right one for non-lLama applications?

Please let me know what I should do next.

Thanks

ERROR LOG

02-25 16:04:43.057: W/lNetworkService(22959): CheckJNI: method to register "initHybrid" not in the given class. This is slow, consider changing your RegisterNatives calls.
02-25 16:04:43.060: E/lNetworkService(22959): ----- class 'Lorg/pytorch/executorch/NativePeer;' cl=0x14013570 -----
02-25 16:04:43.060: E/lNetworkService(22959):   objectSize=240 (224 from super)
02-25 16:04:43.060: E/lNetworkService(22959):   access=0x0000.0000
02-25 16:04:43.060: E/lNetworkService(22959):   super='java.lang.Class<java.lang.Object>' (cl=0x0)
02-25 16:04:43.060: E/lNetworkService(22959):   interfaces (1):
02-25 16:04:43.060: E/lNetworkService(22959):      0: java.lang.Class<org.pytorch.executorch.INativePeer> (cl=0x14013570)
02-25 16:04:43.060: E/lNetworkService(22959):   vtable (2 entries, 11 in super):
02-25 16:04:43.060: E/lNetworkService(22959):      0: org.pytorch.executorch.EValue org.pytorch.executorch.NativePeer.forward(org.pytorch.executorch.EValue[])
02-25 16:04:43.060: E/lNetworkService(22959):      1: void org.pytorch.executorch.NativePeer.resetNative()
02-25 16:04:43.060: E/lNetworkService(22959):   direct methods (3 entries):
02-25 16:04:43.060: E/lNetworkService(22959):      0: void org.pytorch.executorch.NativePeer.<clinit>()
02-25 16:04:43.060: E/lNetworkService(22959):      1: void org.pytorch.executorch.NativePeer.<init>(java.lang.String, java.util.Map)
02-25 16:04:43.060: E/lNetworkService(22959):      2: com.facebook.jni.HybridData org.pytorch.executorch.NativePeer.initHybrid(java.lang.String, java.util.Map)
02-25 16:04:43.060: E/lNetworkService(22959):   instance fields (1 entries):
02-25 16:04:43.060: E/lNetworkService(22959):      0: com.facebook.jni.HybridData org.pytorch.executorch.NativePeer.mHybridData
02-25 16:04:43.060: E/lNetworkService(22959): Failed to register native method org.pytorch.executorch.NativePeer.initHybrid(Ljava/lang/String;I)Lcom/facebook/jni/HybridData; in /data/app/~~S2GUziV5tYf4zysXextUOw==/com.android.contextq-TWkeFJwpSdRUaY6I1r-k_A==/base.apk!classes14.dex
02-25 16:04:43.061: E/log(22959): error java.lang.NoSuchMethodError: no static or non-static method "Lorg/pytorch/executorch/NativePeer;.initHybrid(Ljava/lang/String;I)Lcom/facebook/jni/HybridData;"
02-25 16:04:43.061: A/lNetworkService(22959): java_vm_ext.cc:616] JNI DETECTED ERROR IN APPLICATION: JNI NewGlobalRef called with pending exception java.lang.NoSuchMethodError: no static or non-static method "Lorg/pytorch/executorch/NativePeer;.initHybrid(Ljava/lang/String;I)Lcom/facebook/jni/HybridData;"
02-25 16:04:43.061: A/lNetworkService(22959): java_vm_ext.cc:616] (Throwable with no stack trace)
02-25 16:04:43.061: A/lNetworkService(22959): java_vm_ext.cc:616] 
02-25 16:04:43.061: A/lNetworkService(22959): java_vm_ext.cc:616]     in call to NewGlobalRef
02-25 16:04:43.061: A/lNetworkService(22959): java_vm_ext.cc:616]     from java.lang.String java.lang.Runtime.nativeLoad(java.lang.String, java.lang.ClassLoader, java.lang.Class)
02-25 16:04:43.250: A/lNetworkService(22959): runtime.cc:708] Runtime aborting...

@guangy10
Copy link
Contributor

@kirklandsign

I apologize in advance for the (very) long message. Please read it to the end.

I tried running setup.sh from both the LlamaDemo and ExecutorchDemo directories. They both failed.

  • setup.sh in ExecutorchDemo directory failed with this error:
CMake Error: The source directory "/home/adonnini1/Development/ContextQSourceCode/NeuralNetworks/LocationPredictionContextQ/executorch/examples/demo-apps/android/ExecuTorchDemo" does not appear to contain CMakeLists.txt.

I checked. There is no CMakeLists.txt in the directory

  • setup.sh in lLamaDemo directory fails with this error:
/home/adonnini1/Development/ContextQSourceCode/NeuralNetworks/LocationPredictionContextQ/executorch/examples/demo-apps/android/LlamaDemo/../../../../build/build_android_llm_demo.sh: line 11: pushd: extension/android: No such file or directory

the executorch/extension/android does exist.

In setting up exeutorch I followed the instruction in https://pytorch.org/executorch/stable/getting-started-setup.html Everything worked with no errors.

However, I must have done something wrong, not sure what. I am not familiar shell scripting. I did not make any changes to the two scripts.

As a workaround, I ran download_prebuilt_lib.sh found in the LlamaDemo directory. Then, I copied the executorch.aar which was downloaded to the libs folder in my application and added the dependency.

Android Studio reports the following error:

Cannot resolve method 'toTensor' in 'EValue'

in this line

outputTensor = mModule.forward(EValue.from(arrDataPytorch)).toTensor();

Note that there is a line like this in executorch/examples/demo-apps/android/ExecuTorchDemo/app/src/main/java/com/example/executorchdemo/MainActivity.java Tensor outputTensor = mModule.forward(EValue.from(inputTensor))[0].toTensor();

I also checked the contents of EValue.class in executorch.aar. It does contain a toTensor method.

However, application build was successful.

When I ran the application, execution still failed when attempting to load the module. Please see the error log below.

Is the executorch.aar I downloaded not the right one for non-lLama applications?

Please let me know what I should do next.

Thanks

ERROR LOG

02-25 16:04:43.057: W/lNetworkService(22959): CheckJNI: method to register "initHybrid" not in the given class. This is slow, consider changing your RegisterNatives calls.
02-25 16:04:43.060: E/lNetworkService(22959): ----- class 'Lorg/pytorch/executorch/NativePeer;' cl=0x14013570 -----
02-25 16:04:43.060: E/lNetworkService(22959):   objectSize=240 (224 from super)
02-25 16:04:43.060: E/lNetworkService(22959):   access=0x0000.0000
02-25 16:04:43.060: E/lNetworkService(22959):   super='java.lang.Class<java.lang.Object>' (cl=0x0)
02-25 16:04:43.060: E/lNetworkService(22959):   interfaces (1):
02-25 16:04:43.060: E/lNetworkService(22959):      0: java.lang.Class<org.pytorch.executorch.INativePeer> (cl=0x14013570)
02-25 16:04:43.060: E/lNetworkService(22959):   vtable (2 entries, 11 in super):
02-25 16:04:43.060: E/lNetworkService(22959):      0: org.pytorch.executorch.EValue org.pytorch.executorch.NativePeer.forward(org.pytorch.executorch.EValue[])
02-25 16:04:43.060: E/lNetworkService(22959):      1: void org.pytorch.executorch.NativePeer.resetNative()
02-25 16:04:43.060: E/lNetworkService(22959):   direct methods (3 entries):
02-25 16:04:43.060: E/lNetworkService(22959):      0: void org.pytorch.executorch.NativePeer.<clinit>()
02-25 16:04:43.060: E/lNetworkService(22959):      1: void org.pytorch.executorch.NativePeer.<init>(java.lang.String, java.util.Map)
02-25 16:04:43.060: E/lNetworkService(22959):      2: com.facebook.jni.HybridData org.pytorch.executorch.NativePeer.initHybrid(java.lang.String, java.util.Map)
02-25 16:04:43.060: E/lNetworkService(22959):   instance fields (1 entries):
02-25 16:04:43.060: E/lNetworkService(22959):      0: com.facebook.jni.HybridData org.pytorch.executorch.NativePeer.mHybridData
02-25 16:04:43.060: E/lNetworkService(22959): Failed to register native method org.pytorch.executorch.NativePeer.initHybrid(Ljava/lang/String;I)Lcom/facebook/jni/HybridData; in /data/app/~~S2GUziV5tYf4zysXextUOw==/com.android.contextq-TWkeFJwpSdRUaY6I1r-k_A==/base.apk!classes14.dex
02-25 16:04:43.061: E/log(22959): error java.lang.NoSuchMethodError: no static or non-static method "Lorg/pytorch/executorch/NativePeer;.initHybrid(Ljava/lang/String;I)Lcom/facebook/jni/HybridData;"
02-25 16:04:43.061: A/lNetworkService(22959): java_vm_ext.cc:616] JNI DETECTED ERROR IN APPLICATION: JNI NewGlobalRef called with pending exception java.lang.NoSuchMethodError: no static or non-static method "Lorg/pytorch/executorch/NativePeer;.initHybrid(Ljava/lang/String;I)Lcom/facebook/jni/HybridData;"
02-25 16:04:43.061: A/lNetworkService(22959): java_vm_ext.cc:616] (Throwable with no stack trace)
02-25 16:04:43.061: A/lNetworkService(22959): java_vm_ext.cc:616] 
02-25 16:04:43.061: A/lNetworkService(22959): java_vm_ext.cc:616]     in call to NewGlobalRef
02-25 16:04:43.061: A/lNetworkService(22959): java_vm_ext.cc:616]     from java.lang.String java.lang.Runtime.nativeLoad(java.lang.String, java.lang.ClassLoader, java.lang.Class)
02-25 16:04:43.250: A/lNetworkService(22959): runtime.cc:708] Runtime aborting...

Thank you for reporting the issue with detailed steps for repro. The Android apps are built and running continuously in our CI, so likely what you see is due to some setup issue. To help us better understand your setup, you can attach you dev env by running the following commands:

wget https://raw.githubusercontent.com/pytorch/pytorch/main/torch/utils/collect_env.py
# For security purposes, please check the contents of collect_env.py before running it.
python collect_env.py

@kirklandsign
Copy link
Contributor

Hi @adonnini

I tried running setup.sh from both the LlamaDemo and ExecutorchDemo directories. They both failed.

Please run from root directory.

For prebuilt AAR, maybe use this 0.5 release?

Docs: https://pytorch.org/executorch/0.5/android-prebuilt-library.html#using-prebuilt-libraries

BTW the AAR is same for both llama and non-llama. The docs above is not updated. I will update docs.

@guangy10
Copy link
Contributor

@guangy10 here is collect_env.py

# mypy: allow-untyped-defs

# Unlike the rest of the PyTorch this file must be python2 compliant.
# This script outputs relevant system environment info
# Run it with `python collect_env.py` or `python -m torch.utils.collect_env`
import datetime
import json
import locale
import re
import subprocess
import sys
import os
from collections import namedtuple


try:
    import torch
    TORCH_AVAILABLE = True
except (ImportError, NameError, AttributeError, OSError):
    TORCH_AVAILABLE = False

# System Environment Information
SystemEnv = namedtuple('SystemEnv', [
    'torch_version',
    'is_debug_build',
    'cuda_compiled_version',
    'gcc_version',
    'clang_version',
    'cmake_version',
    'os',
    'libc_version',
    'python_version',
    'python_platform',
    'is_cuda_available',
    'cuda_runtime_version',
    'cuda_module_loading',
    'nvidia_driver_version',
    'nvidia_gpu_models',
    'cudnn_version',
    'pip_version',  # 'pip' or 'pip3'
    'pip_packages',
    'conda_packages',
    'hip_compiled_version',
    'hip_runtime_version',
    'miopen_runtime_version',
    'caching_allocator_config',
    'is_xnnpack_available',
    'cpu_info',
])

COMMON_PATTERNS = [
    "torch",
    "numpy",
    "triton",
    "optree",
]

NVIDIA_PATTERNS = [
    "cuda-cudart",
    "cuda-cupti",
    "cuda-libraries",
    "cuda-opencl",
    "cuda-nvrtc",
    "cuda-runtime",
    "cublas",
    "cudnn",
    "cufft",
    "curand",
    "cusolver",
    "cusparse",
    "nccl",
    "nvjitlink",
    "nvtx",
]

CONDA_PATTERNS = [
    "cudatoolkit",
    "soumith",
    "mkl",
    "magma",
]

PIP_PATTERNS = [
    "mypy",
    "flake8",
    "onnx",
]


def run(command):
    """Return (return-code, stdout, stderr)."""
    shell = True if type(command) is str else False
    p = subprocess.Popen(command, stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE, shell=shell)
    raw_output, raw_err = p.communicate()
    rc = p.returncode
    if get_platform() == 'win32':
        enc = 'oem'
    else:
        enc = locale.getpreferredencoding()
    output = raw_output.decode(enc)
    err = raw_err.decode(enc)
    return rc, output.strip(), err.strip()


def run_and_read_all(run_lambda, command):
    """Run command using run_lambda; reads and returns entire output if rc is 0."""
    rc, out, _ = run_lambda(command)
    if rc != 0:
        return None
    return out


def run_and_parse_first_match(run_lambda, command, regex):
    """Run command using run_lambda, returns the first regex match if it exists."""
    rc, out, _ = run_lambda(command)
    if rc != 0:
        return None
    match = re.search(regex, out)
    if match is None:
        return None
    return match.group(1)

def run_and_return_first_line(run_lambda, command):
    """Run command using run_lambda and returns first line if output is not empty."""
    rc, out, _ = run_lambda(command)
    if rc != 0:
        return None
    return out.split('\n')[0]


def get_conda_packages(run_lambda, patterns=None):
    if patterns is None:
        patterns = CONDA_PATTERNS + COMMON_PATTERNS + NVIDIA_PATTERNS
    conda = os.environ.get('CONDA_EXE', 'conda')
    out = run_and_read_all(run_lambda, "{} list".format(conda))
    if out is None:
        return out

    return "\n".join(
        line
        for line in out.splitlines()
        if not line.startswith("#")
        and any(name in line for name in patterns)
    )

def get_gcc_version(run_lambda):
    return run_and_parse_first_match(run_lambda, 'gcc --version', r'gcc (.*)')

def get_clang_version(run_lambda):
    return run_and_parse_first_match(run_lambda, 'clang --version', r'clang version (.*)')


def get_cmake_version(run_lambda):
    return run_and_parse_first_match(run_lambda, 'cmake --version', r'cmake (.*)')


def get_nvidia_driver_version(run_lambda):
    if get_platform() == 'darwin':
        cmd = 'kextstat | grep -i cuda'
        return run_and_parse_first_match(run_lambda, cmd,
                                         r'com[.]nvidia[.]CUDA [(](.*?)[)]')
    smi = get_nvidia_smi()
    return run_and_parse_first_match(run_lambda, smi, r'Driver Version: (.*?) ')


def get_gpu_info(run_lambda):
    if get_platform() == 'darwin' or (TORCH_AVAILABLE and hasattr(torch.version, 'hip') and torch.version.hip is not None):
        if TORCH_AVAILABLE and torch.cuda.is_available():
            if torch.version.hip is not None:
                prop = torch.cuda.get_device_properties(0)
                if hasattr(prop, "gcnArchName"):
                    gcnArch = " ({})".format(prop.gcnArchName)
                else:
                    gcnArch = "NoGCNArchNameOnOldPyTorch"
            else:
                gcnArch = ""
            return torch.cuda.get_device_name(None) + gcnArch
        return None
    smi = get_nvidia_smi()
    uuid_regex = re.compile(r' \(UUID: .+?\)')
    rc, out, _ = run_lambda(smi + ' -L')
    if rc != 0:
        return None
    # Anonymize GPUs by removing their UUID
    return re.sub(uuid_regex, '', out)


def get_running_cuda_version(run_lambda):
    return run_and_parse_first_match(run_lambda, 'nvcc --version', r'release .+ V(.*)')


def get_cudnn_version(run_lambda):
    """Return a list of libcudnn.so; it's hard to tell which one is being used."""
    if get_platform() == 'win32':
        system_root = os.environ.get('SYSTEMROOT', 'C:\\Windows')
        cuda_path = os.environ.get('CUDA_PATH', "%CUDA_PATH%")
        where_cmd = os.path.join(system_root, 'System32', 'where')
        cudnn_cmd = '{} /R "{}\\bin" cudnn*.dll'.format(where_cmd, cuda_path)
    elif get_platform() == 'darwin':
        # CUDA libraries and drivers can be found in /usr/local/cuda/. See
        # https://docs.nvidia.com/cuda/cuda-installation-guide-mac-os-x/index.html#install
        # https://docs.nvidia.com/deeplearning/sdk/cudnn-install/index.html#installmac
        # Use CUDNN_LIBRARY when cudnn library is installed elsewhere.
        cudnn_cmd = 'ls /usr/local/cuda/lib/libcudnn*'
    else:
        cudnn_cmd = 'ldconfig -p | grep libcudnn | rev | cut -d" " -f1 | rev'
    rc, out, _ = run_lambda(cudnn_cmd)
    # find will return 1 if there are permission errors or if not found
    if len(out) == 0 or (rc != 1 and rc != 0):
        l = os.environ.get('CUDNN_LIBRARY')
        if l is not None and os.path.isfile(l):
            return os.path.realpath(l)
        return None
    files_set = set()
    for fn in out.split('\n'):
        fn = os.path.realpath(fn)  # eliminate symbolic links
        if os.path.isfile(fn):
            files_set.add(fn)
    if not files_set:
        return None
    # Alphabetize the result because the order is non-deterministic otherwise
    files = sorted(files_set)
    if len(files) == 1:
        return files[0]
    result = '\n'.join(files)
    return 'Probably one of the following:\n{}'.format(result)


def get_nvidia_smi():
    # Note: nvidia-smi is currently available only on Windows and Linux
    smi = 'nvidia-smi'
    if get_platform() == 'win32':
        system_root = os.environ.get('SYSTEMROOT', 'C:\\Windows')
        program_files_root = os.environ.get('PROGRAMFILES', 'C:\\Program Files')
        legacy_path = os.path.join(program_files_root, 'NVIDIA Corporation', 'NVSMI', smi)
        new_path = os.path.join(system_root, 'System32', smi)
        smis = [new_path, legacy_path]
        for candidate_smi in smis:
            if os.path.exists(candidate_smi):
                smi = '"{}"'.format(candidate_smi)
                break
    return smi


# example outputs of CPU infos
#  * linux
#    Architecture:            x86_64
#      CPU op-mode(s):        32-bit, 64-bit
#      Address sizes:         46 bits physical, 48 bits virtual
#      Byte Order:            Little Endian
#    CPU(s):                  128
#      On-line CPU(s) list:   0-127
#    Vendor ID:               GenuineIntel
#      Model name:            Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz
#        CPU family:          6
#        Model:               106
#        Thread(s) per core:  2
#        Core(s) per socket:  32
#        Socket(s):           2
#        Stepping:            6
#        BogoMIPS:            5799.78
#        Flags:               fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr
#                             sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon rep_good nopl
#                             xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq monitor ssse3 fma cx16
#                             pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand
#                             hypervisor lahf_lm abm 3dnowprefetch invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced
#                             fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid avx512f avx512dq rdseed adx smap
#                             avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1
#                             xsaves wbnoinvd ida arat avx512vbmi pku ospke avx512_vbmi2 gfni vaes vpclmulqdq
#                             avx512_vnni avx512_bitalg tme avx512_vpopcntdq rdpid md_clear flush_l1d arch_capabilities
#    Virtualization features:
#      Hypervisor vendor:     KVM
#      Virtualization type:   full
#    Caches (sum of all):
#      L1d:                   3 MiB (64 instances)
#      L1i:                   2 MiB (64 instances)
#      L2:                    80 MiB (64 instances)
#      L3:                    108 MiB (2 instances)
#    NUMA:
#      NUMA node(s):          2
#      NUMA node0 CPU(s):     0-31,64-95
#      NUMA node1 CPU(s):     32-63,96-127
#    Vulnerabilities:
#      Itlb multihit:         Not affected
#      L1tf:                  Not affected
#      Mds:                   Not affected
#      Meltdown:              Not affected
#      Mmio stale data:       Vulnerable: Clear CPU buffers attempted, no microcode; SMT Host state unknown
#      Retbleed:              Not affected
#      Spec store bypass:     Mitigation; Speculative Store Bypass disabled via prctl and seccomp
#      Spectre v1:            Mitigation; usercopy/swapgs barriers and __user pointer sanitization
#      Spectre v2:            Mitigation; Enhanced IBRS, IBPB conditional, RSB filling, PBRSB-eIBRS SW sequence
#      Srbds:                 Not affected
#      Tsx async abort:       Not affected
#  * win32
#    Architecture=9
#    CurrentClockSpeed=2900
#    DeviceID=CPU0
#    Family=179
#    L2CacheSize=40960
#    L2CacheSpeed=
#    Manufacturer=GenuineIntel
#    MaxClockSpeed=2900
#    Name=Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz
#    ProcessorType=3
#    Revision=27142
#
#    Architecture=9
#    CurrentClockSpeed=2900
#    DeviceID=CPU1
#    Family=179
#    L2CacheSize=40960
#    L2CacheSpeed=
#    Manufacturer=GenuineIntel
#    MaxClockSpeed=2900
#    Name=Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz
#    ProcessorType=3
#    Revision=27142

def get_cpu_info(run_lambda):
    rc, out, err = 0, '', ''
    if get_platform() == 'linux':
        rc, out, err = run_lambda('lscpu')
    elif get_platform() == 'win32':
        rc, out, err = run_lambda(
            'powershell.exe "gwmi -Class Win32_Processor | Select-Object -Property Name,Manufacturer,Family,\
            Architecture,ProcessorType,DeviceID,CurrentClockSpeed,MaxClockSpeed,L2CacheSize,L2CacheSpeed,Revision\
            | ConvertTo-Json"'
        )
        if rc == 0:
            lst = []
            try:
                obj = json.loads(out)
                if type(obj) is list:
                    for o in obj:
                        lst.append("----------------------")
                        lst.extend([f"{k}: {v}" for (k, v) in o.items()])
                else:
                    lst.extend([f"{k}: {v}" for (k, v) in obj.items()])
            except ValueError as e:
                lst.append(out)
                lst.append(str(e))
            out = "\n".join(lst)
    elif get_platform() == 'darwin':
        rc, out, err = run_lambda("sysctl -n machdep.cpu.brand_string")
    cpu_info = 'None'
    if rc == 0:
        cpu_info = out
    else:
        cpu_info = err
    return cpu_info


def get_platform():
    if sys.platform.startswith('linux'):
        return 'linux'
    elif sys.platform.startswith('win32'):
        return 'win32'
    elif sys.platform.startswith('cygwin'):
        return 'cygwin'
    elif sys.platform.startswith('darwin'):
        return 'darwin'
    else:
        return sys.platform


def get_mac_version(run_lambda):
    return run_and_parse_first_match(run_lambda, 'sw_vers -productVersion', r'(.*)')


def get_windows_version(run_lambda):
    ret = run_and_read_all(
        run_lambda,
        'powershell.exe "gwmi -Class Win32_OperatingSystem | Select-Object -Property Caption,\
        OSArchitecture,Version | ConvertTo-Json"',
    )
    try:
        obj = json.loads(ret)
        ret = f'{obj["Caption"]} ({obj["Version"]} {obj["OSArchitecture"]})'
    except ValueError as e:
        ret += f"\n{str(e)}"
    return ret


def get_lsb_version(run_lambda):
    return run_and_parse_first_match(run_lambda, 'lsb_release -a', r'Description:\t(.*)')


def check_release_file(run_lambda):
    return run_and_parse_first_match(run_lambda, 'cat /etc/*-release',
                                     r'PRETTY_NAME="(.*)"')


def get_os(run_lambda):
    from platform import machine
    platform = get_platform()

    if platform == 'win32' or platform == 'cygwin':
        return get_windows_version(run_lambda)

    if platform == 'darwin':
        version = get_mac_version(run_lambda)
        if version is None:
            return None
        return 'macOS {} ({})'.format(version, machine())

    if platform == 'linux':
        # Ubuntu/Debian based
        desc = get_lsb_version(run_lambda)
        if desc is not None:
            return '{} ({})'.format(desc, machine())

        # Try reading /etc/*-release
        desc = check_release_file(run_lambda)
        if desc is not None:
            return '{} ({})'.format(desc, machine())

        return '{} ({})'.format(platform, machine())

    # Unknown platform
    return platform


def get_python_platform():
    import platform
    return platform.platform()


def get_libc_version():
    import platform
    if get_platform() != 'linux':
        return 'N/A'
    return '-'.join(platform.libc_ver())


def get_pip_packages(run_lambda, patterns=None):
    """Return `pip list` output. Note: will also find conda-installed pytorch and numpy packages."""
    if patterns is None:
        patterns = PIP_PATTERNS + COMMON_PATTERNS + NVIDIA_PATTERNS

    pip_version = 'pip3' if sys.version[0] == '3' else 'pip'

    os.environ['PIP_DISABLE_PIP_VERSION_CHECK'] = '1'
    # People generally have pip as `pip` or `pip3`
    # But here it is invoked as `python -mpip`
    out = run_and_read_all(run_lambda, [sys.executable, '-mpip', 'list', '--format=freeze'])
    filtered_out = '\n'.join(
        line
        for line in out.splitlines()
        if any(name in line for name in patterns)
    )

    return pip_version, filtered_out


def get_cachingallocator_config():
    ca_config = os.environ.get('PYTORCH_CUDA_ALLOC_CONF', '')
    return ca_config


def get_cuda_module_loading_config():
    if TORCH_AVAILABLE and torch.cuda.is_available():
        torch.cuda.init()
        config = os.environ.get('CUDA_MODULE_LOADING', '')
        return config
    else:
        return "N/A"


def is_xnnpack_available():
    if TORCH_AVAILABLE:
        import torch.backends.xnnpack
        return str(torch.backends.xnnpack.enabled)  # type: ignore[attr-defined]
    else:
        return "N/A"

def get_env_info():
    """
    Collects environment information to aid in debugging.

    The returned environment information contains details on torch version, is debug build
    or not, cuda compiled version, gcc version, clang version, cmake version, operating
    system, libc version, python version, python platform, CUDA availability, CUDA
    runtime version, CUDA module loading config, GPU model and configuration, Nvidia
    driver version, cuDNN version, pip version and versions of relevant pip and
    conda packages, HIP runtime version, MIOpen runtime version,
    Caching allocator config, XNNPACK availability and CPU information.

    Returns:
        SystemEnv (namedtuple): A tuple containining various environment details
            and system information.
    """
    run_lambda = run
    pip_version, pip_list_output = get_pip_packages(run_lambda)

    if TORCH_AVAILABLE:
        version_str = torch.__version__
        debug_mode_str = str(torch.version.debug)
        cuda_available_str = str(torch.cuda.is_available())
        cuda_version_str = torch.version.cuda
        if not hasattr(torch.version, 'hip') or torch.version.hip is None:  # cuda version
            hip_compiled_version = hip_runtime_version = miopen_runtime_version = 'N/A'
        else:  # HIP version
            def get_version_or_na(cfg, prefix):
                _lst = [s.rsplit(None, 1)[-1] for s in cfg if prefix in s]
                return _lst[0] if _lst else 'N/A'

            cfg = torch._C._show_config().split('\n')
            hip_runtime_version = get_version_or_na(cfg, 'HIP Runtime')
            miopen_runtime_version = get_version_or_na(cfg, 'MIOpen')
            cuda_version_str = 'N/A'
            hip_compiled_version = torch.version.hip
    else:
        version_str = debug_mode_str = cuda_available_str = cuda_version_str = 'N/A'
        hip_compiled_version = hip_runtime_version = miopen_runtime_version = 'N/A'

    sys_version = sys.version.replace("\n", " ")

    conda_packages = get_conda_packages(run_lambda)

    return SystemEnv(
        torch_version=version_str,
        is_debug_build=debug_mode_str,
        python_version='{} ({}-bit runtime)'.format(sys_version, sys.maxsize.bit_length() + 1),
        python_platform=get_python_platform(),
        is_cuda_available=cuda_available_str,
        cuda_compiled_version=cuda_version_str,
        cuda_runtime_version=get_running_cuda_version(run_lambda),
        cuda_module_loading=get_cuda_module_loading_config(),
        nvidia_gpu_models=get_gpu_info(run_lambda),
        nvidia_driver_version=get_nvidia_driver_version(run_lambda),
        cudnn_version=get_cudnn_version(run_lambda),
        hip_compiled_version=hip_compiled_version,
        hip_runtime_version=hip_runtime_version,
        miopen_runtime_version=miopen_runtime_version,
        pip_version=pip_version,
        pip_packages=pip_list_output,
        conda_packages=conda_packages,
        os=get_os(run_lambda),
        libc_version=get_libc_version(),
        gcc_version=get_gcc_version(run_lambda),
        clang_version=get_clang_version(run_lambda),
        cmake_version=get_cmake_version(run_lambda),
        caching_allocator_config=get_cachingallocator_config(),
        is_xnnpack_available=is_xnnpack_available(),
        cpu_info=get_cpu_info(run_lambda),
    )

env_info_fmt = """
PyTorch version: {torch_version}
Is debug build: {is_debug_build}
CUDA used to build PyTorch: {cuda_compiled_version}
ROCM used to build PyTorch: {hip_compiled_version}

OS: {os}
GCC version: {gcc_version}
Clang version: {clang_version}
CMake version: {cmake_version}
Libc version: {libc_version}

Python version: {python_version}
Python platform: {python_platform}
Is CUDA available: {is_cuda_available}
CUDA runtime version: {cuda_runtime_version}
CUDA_MODULE_LOADING set to: {cuda_module_loading}
GPU models and configuration: {nvidia_gpu_models}
Nvidia driver version: {nvidia_driver_version}
cuDNN version: {cudnn_version}
HIP runtime version: {hip_runtime_version}
MIOpen runtime version: {miopen_runtime_version}
Is XNNPACK available: {is_xnnpack_available}

CPU:
{cpu_info}

Versions of relevant libraries:
{pip_packages}
{conda_packages}
""".strip()


def pretty_str(envinfo):
    def replace_nones(dct, replacement='Could not collect'):
        for key in dct.keys():
            if dct[key] is not None:
                continue
            dct[key] = replacement
        return dct

    def replace_bools(dct, true='Yes', false='No'):
        for key in dct.keys():
            if dct[key] is True:
                dct[key] = true
            elif dct[key] is False:
                dct[key] = false
        return dct

    def prepend(text, tag='[prepend]'):
        lines = text.split('\n')
        updated_lines = [tag + line for line in lines]
        return '\n'.join(updated_lines)

    def replace_if_empty(text, replacement='No relevant packages'):
        if text is not None and len(text) == 0:
            return replacement
        return text

    def maybe_start_on_next_line(string):
        # If `string` is multiline, prepend a \n to it.
        if string is not None and len(string.split('\n')) > 1:
            return '\n{}\n'.format(string)
        return string

    mutable_dict = envinfo._asdict()

    # If nvidia_gpu_models is multiline, start on the next line
    mutable_dict['nvidia_gpu_models'] = \
        maybe_start_on_next_line(envinfo.nvidia_gpu_models)

    # If the machine doesn't have CUDA, report some fields as 'No CUDA'
    dynamic_cuda_fields = [
        'cuda_runtime_version',
        'nvidia_gpu_models',
        'nvidia_driver_version',
    ]
    all_cuda_fields = dynamic_cuda_fields + ['cudnn_version']
    all_dynamic_cuda_fields_missing = all(
        mutable_dict[field] is None for field in dynamic_cuda_fields)
    if TORCH_AVAILABLE and not torch.cuda.is_available() and all_dynamic_cuda_fields_missing:
        for field in all_cuda_fields:
            mutable_dict[field] = 'No CUDA'
        if envinfo.cuda_compiled_version is None:
            mutable_dict['cuda_compiled_version'] = 'None'

    # Replace True with Yes, False with No
    mutable_dict = replace_bools(mutable_dict)

    # Replace all None objects with 'Could not collect'
    mutable_dict = replace_nones(mutable_dict)

    # If either of these are '', replace with 'No relevant packages'
    mutable_dict['pip_packages'] = replace_if_empty(mutable_dict['pip_packages'])
    mutable_dict['conda_packages'] = replace_if_empty(mutable_dict['conda_packages'])

    # Tag conda and pip packages with a prefix
    # If they were previously None, they'll show up as ie '[conda] Could not collect'
    if mutable_dict['pip_packages']:
        mutable_dict['pip_packages'] = prepend(mutable_dict['pip_packages'],
                                               '[{}] '.format(envinfo.pip_version))
    if mutable_dict['conda_packages']:
        mutable_dict['conda_packages'] = prepend(mutable_dict['conda_packages'],
                                                 '[conda] ')
    mutable_dict['cpu_info'] = envinfo.cpu_info
    return env_info_fmt.format(**mutable_dict)


def get_pretty_env_info():
    """
    Returns a pretty string of environment information.

    This function retrieves environment information by calling the `get_env_info` function
    and then formats the information into a human-readable string. The retrieved environment
    information is listed in the document of `get_env_info`.
    This function is used in `python collect_env.py` that should be executed when reporting a bug.

    Returns:
        str: A pretty string of the environment information.
    """
    return pretty_str(get_env_info())


def main():
    print("Collecting environment information...")
    output = get_pretty_env_info()
    print(output)

    if TORCH_AVAILABLE and hasattr(torch, 'utils') and hasattr(torch.utils, '_crash_handler'):
        minidump_dir = torch.utils._crash_handler.DEFAULT_MINIDUMP_DIR
        if sys.platform == "linux" and os.path.exists(minidump_dir):
            dumps = [os.path.join(minidump_dir, dump) for dump in os.listdir(minidump_dir)]
            latest = max(dumps, key=os.path.getctime)
            ctime = os.path.getctime(latest)
            creation_time = datetime.datetime.fromtimestamp(ctime).strftime('%Y-%m-%d %H:%M:%S')
            msg = "\n*** Detected a minidump at {} created on {}, ".format(latest, creation_time) + \
                  "if this is related to your bug please include it when you file a report ***"
            print(msg, file=sys.stderr)



if __name__ == '__main__':
    main()

@adonnini Could you please run the script and attach the outputs?

@adonnini
Copy link
Author

@kirklandsign thanks for the quick response. All set wrt exeuctorch.aar

The .aar I downloaded with the workaround I used is the correct one. Thanks for confirming that.

Now, it's a question of resolving the error in the subject line of this issue

@adonnini
Copy link
Author

@guangy10 Sorry!! Here is the output. Please let me know if I messed up again. Thanks

Please let me know if you need additional information to resolve the ``NoSuchMethodError```

Collecting environment information...
PyTorch version: 2.2.1+cu121
Is debug build: False
CUDA used to build PyTorch: 12.1
ROCM used to build PyTorch: N/A

OS: Debian GNU/Linux 12 (bookworm) (x86_64)
GCC version: (Debian 12.2.0-14) 12.2.0
Clang version: Could not collect
CMake version: version 3.27.7
Libc version: glibc-2.36

Python version: 3.9.18 (main, Sep 11 2023, 13:41:44)  [GCC 11.2.0] (64-bit runtime)
Python platform: Linux-6.1.0-31-amd64-x86_64-with-glibc2.36
Is CUDA available: False
CUDA runtime version: No CUDA
CUDA_MODULE_LOADING set to: N/A
GPU models and configuration: No CUDA
Nvidia driver version: No CUDA
cuDNN version: No CUDA
HIP runtime version: N/A
MIOpen runtime version: N/A
Is XNNPACK available: True

CPU:
Architecture:                         x86_64
CPU op-mode(s):                       32-bit, 64-bit
Address sizes:                        46 bits physical, 48 bits virtual
Byte Order:                           Little Endian
CPU(s):                               32
On-line CPU(s) list:                  0-31
Vendor ID:                            GenuineIntel
Model name:                           13th Gen Intel(R) Core(TM) i9-13950HX
CPU family:                           6
Model:                                183
Thread(s) per core:                   2
Core(s) per socket:                   24
Socket(s):                            1
Stepping:                             1
CPU(s) scaling MHz:                   25%
CPU max MHz:                          5500.0000
CPU min MHz:                          800.0000
BogoMIPS:                             4838.40
Flags:                                fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr ibt flush_l1d arch_capabilities
Virtualization:                       VT-x
L1d cache:                            896 KiB (24 instances)
L1i cache:                            1.3 MiB (24 instances)
L2 cache:                             32 MiB (12 instances)
L3 cache:                             36 MiB (1 instance)
NUMA node(s):                         1
NUMA node0 CPU(s):                    0-31
Vulnerability Gather data sampling:   Not affected
Vulnerability Itlb multihit:          Not affected
Vulnerability L1tf:                   Not affected
Vulnerability Mds:                    Not affected
Vulnerability Meltdown:               Not affected
Vulnerability Mmio stale data:        Not affected
Vulnerability Reg file data sampling: Mitigation; Clear Register File
Vulnerability Retbleed:               Not affected
Vulnerability Spec rstack overflow:   Not affected
Vulnerability Spec store bypass:      Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:             Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2:             Mitigation; Enhanced / Automatic IBRS; IBPB conditional; RSB filling; PBRSB-eIBRS SW sequence; BHI BHI_DIS_S
Vulnerability Srbds:                  Not affected
Vulnerability Tsx async abort:        Not affected

Versions of relevant libraries:
[pip3] executorch==0.1.0
[pip3] flake8==6.0.0
[pip3] mypy==1.8.0
[pip3] mypy-extensions==1.0.0
[pip3] numpy==1.26.4
[pip3] numpydoc==1.5.0
[pip3] nvidia-cublas-cu12==12.1.3.1
[pip3] nvidia-cuda-cupti-cu12==12.1.105
[pip3] nvidia-cuda-nvrtc-cu12==12.1.105
[pip3] nvidia-cuda-runtime-cu12==12.1.105
[pip3] nvidia-cudnn-cu12==8.9.2.26
[pip3] nvidia-cufft-cu12==11.0.2.54
[pip3] nvidia-curand-cu12==10.3.2.106
[pip3] nvidia-cusolver-cu12==11.4.5.107
[pip3] nvidia-cusparse-cu12==12.1.0.106
[pip3] nvidia-nccl-cu12==2.19.3
[pip3] nvidia-nvjitlink-cu12==12.4.99
[pip3] nvidia-nvtx-cu12==12.1.105
[pip3] pytorch-lightning==1.9.5
[pip3] torch==2.2.1
[pip3] torchaudio==2.2.0.dev20240209+cpu
[pip3] torchmetrics==1.3.1
[pip3] torchsr==1.0.4
[pip3] torchvision==0.17.1
[pip3] triton==2.2.0
[conda] _anaconda_depends         2024.02              py39_mkl_1  
[conda] blas                      1.0                         mkl  
[conda] cudatoolkit               11.3.1               h2bc3f7f_2  
[conda] executorch                0.1.0                    pypi_0    pypi
[conda] mkl                       2023.1.0         h213fc3f_46344  
[conda] mkl-service               2.4.0            py39h5eee18b_1  
[conda] mkl_fft                   1.3.8            py39h5eee18b_0  
[conda] mkl_random                1.2.4            py39hdb19cb5_0  
[conda] numpy                     1.26.4           py39h5f9d8c6_0  
[conda] numpy-base                1.26.4           py39hb5e798b_0  
[conda] numpydoc                  1.5.0            py39h06a4308_0  
[conda] nvidia-cublas-cu12        12.1.3.1                 pypi_0    pypi
[conda] nvidia-cuda-cupti-cu12    12.1.105                 pypi_0    pypi
[conda] nvidia-cuda-nvrtc-cu12    12.1.105                 pypi_0    pypi
[conda] nvidia-cuda-runtime-cu12  12.1.105                 pypi_0    pypi
[conda] nvidia-cudnn-cu12         8.9.2.26                 pypi_0    pypi
[conda] nvidia-cufft-cu12         11.0.2.54                pypi_0    pypi
[conda] nvidia-curand-cu12        10.3.2.106               pypi_0    pypi
[conda] nvidia-cusolver-cu12      11.4.5.107               pypi_0    pypi
[conda] nvidia-cusparse-cu12      12.1.0.106               pypi_0    pypi
[conda] nvidia-nccl-cu12          2.19.3                   pypi_0    pypi
[conda] nvidia-nvjitlink-cu12     12.4.99                  pypi_0    pypi
[conda] nvidia-nvtx-cu12          12.1.105                 pypi_0    pypi
[conda] pytorch-lightning         1.9.5                    pypi_0    pypi
[conda] pytorch-mutex             1.0                        cuda    pytorch
[conda] torch                     2.2.1                    pypi_0    pypi
[conda] torchaudio                2.2.0.dev20240209+cpu          pypi_0    pypi
[conda] torchmetrics              1.3.1                    pypi_0    pypi
[conda] torchsr                   1.0.4                    pypi_0    pypi
[conda] torchvision               0.17.1                   pypi_0    pypi
[conda] triton                    2.2.0                    pypi_0    pypi

@guangy10 guangy10 added triaged This issue has been looked at a team member, and triaged and prioritized into an appropriate module and removed need-user-input The issue needs more information from the reporter before moving forward labels Feb 25, 2025
@kirklandsign
Copy link
Contributor

Hi @adonnini

Let's confirm the SHA of executorch.aar is
b778e651f614ed33581d51da43d554515f84dd74 executorch.aar

Also I have the following deps in build.gradle.kts

   implementation(files("libs/executorch.aar"))
   implementation("com.facebook.soloader:soloader:0.10.5")
   implementation("com.facebook.fbjni:fbjni:0.5.1")

@adonnini
Copy link
Author

@kirklandsign

0117e35fce58f5e4f8edebc231450d33704829e60fa021cea8dc8418e437a292 executorch.aar
of the executorch.aar I downloaded

My dependencies

                implementation 'com.facebook.fbjni:fbjni-java-only:0.2.2'
                implementation 'com.facebook.soloader:nativeloader:0.10.5'
                implementation files('../libs/executorch.aar')

I will change the dependencies to match yours and change the executorch.aar using this

https://pytorch.org/executorch/0.5/android-prebuilt-library.html#using-prebuilt-libraries

Thanks

@adonnini
Copy link
Author

@kirklandsign I changed the dependencies and downloaded the aar using the instructions in

https://pytorch.org/executorch/0.5/android-prebuilt-library.html#using-prebuilt-libraries

I have no way to verify the SHA of the aar I downloaded using the instructions above.

BTW, the actual download command from the docs is:

curl https://ossci-android.s3.amazonaws.com/executorch/release/v0.5.0-rc3/executorch.aar -o app/libs/executorch.aar

Is there a release newer than v0.5.0-rc3?

My dependencies in build.gradle

                implementation(files("../libs/executorch.aar"))
                implementation("com.facebook.soloader:soloader:0.10.5")
                implementation("com.facebook.fbjni:fbjni:0.5.1")

Application compile fails with the following error

Cannot resolve method 'toTensor' in 'EValue'

@adonnini
Copy link
Author

@kirklandsign

I did some more digging.

The ExecuTorchDemo android application builds successfully. No Cannot resolve method 'toTensor' in 'EValue' error.

The executorch dependencies in the build.gradle files of my application and ExecuTorchDemo are the same.

A far as I can tell, the main differences are:

  1. ExecuTorchDemo project includes module android from executorch/extension/android

  2. settings.gradle for ExecuTorchDemo has this line, which obviously is not in settings.gradle for my application:
    includeBuild("../../../../extension/android")

  3. the build.gradle.kts for app in ExecuTorchDemo includes

  implementation("org.pytorch.executorch:executorch") {
    exclude("com.facebook.fbjni", "fbjni-java-only")
  }

If I add this dependency to build.gradle in my application, gradle sync fails with the following error:

> Could not find method exclude() for arguments [com.facebook.fbjni, fbjni-java-only] on DefaultExternalModuleDependency{group='org.pytorch.executorch', name='executorch', version='null', configuration='default'} of type org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency.

If I remove the exclude clause, and just use implementation("org.pytorch.executorch:executorch") (tried just to see what would happen) application build fails with many errors not seen previously.

@kirklandsign
Copy link
Contributor

Hi @adonnini

Thank you for your updates! Sorry would you mind using https://github.com/pytorch/executorch/tree/main/extension/benchmark/android/benchmark as an example, instead of ExecuTorchDemo? I used includeBuild("../../../../extension/android") in the past and didn't have a chance to fix it. We should always use the AAR.

@kirklandsign
Copy link
Contributor

No Cannot resolve method 'toTensor' in 'EValue' error.

I probably saw this kind of error from android studio in the past but I can finally compile. Is it android studio code analysis, or real compilation error?

@kirklandsign
Copy link
Contributor

Is there a release newer than v0.5.0-rc3?

0.6 not yet available.

@adonnini
Copy link
Author

adonnini commented Feb 27, 2025

@kirklandsign Thanks!
My set-up is lthe same as the benchmark application, with regards to Executorch. Unfortunately, no change. I'll look and see whether it is an analysis error or a real compile error. I suspect it is the latter.
Thanks

@adonnini
Copy link
Author

adonnini commented Feb 27, 2025

@kirklandsign
When I right click on EValue in my code to select a method, toTensor is not in the list of available methods.
When I extract EValue.class from the aar, and open it, the method toTensor is in the code.
The error cannot resolve method 'toTensor' is a compilation error not from code analysis. It happens during the build.

I also tried Android Studio restart invalidating caches and deleted the build folder for app. made no difference.

So, I am stuck. Not quite.

I made the following change:
FROM
outputTensor = mModule.forward(EValue.from(arrDataPytorch)).toTensor();
TO
outputTensor = mModule.forward(EValue.from(arrDataPytorch))[0].toTensor();

The error cannot resolve method 'toTensor' no longer occurs and the application builds successfully.

I am not familiar enough with Tensor constructs to determine how accessing the data at location [0] affects the outcome. Any ideas? Thoughts?

Thanks

@kirklandsign
Copy link
Contributor

Hi @adonnini

forward() returns EValue[] so most likely you want mModule.forward(EValue.from(arrDataPytorch))[0].toTensor();

However, seems that forward didn't run successfully. Error is InvalidArgument = 0x12

@kirklandsign
Copy link
Contributor

May I ask what kind of model and input did you use?

@kirklandsign
Copy link
Contributor

Seems that your input is a tensor right? May I ask what is inside arrDataPytorch?

@adonnini
Copy link
Author

adonnini commented Feb 27, 2025

@kirklandsign

I do have mModule.forward(EValue.from(arrDataPytorch))[0].toTensor(); in my code. Here is the code fragment: which should contain the answers to all your questions above:

			tmpData = new float[neuralNetworkUserLocationsInsideEstimationRadius.size()][6];

			float[] flat = flatten(tmpData);
			final long[]  shapeArrDataPytorchFlattened = new long[]{tmpData.length, 6, 1};
			arrDataPytorch = Tensor.fromBlob(flat, shapeArrDataPytorchFlattened);

			Tensor outputTensor = null;

			try {
				Log.i(TAG, " - neuralNetworkloadAndRunPytorch - Abut to run inference --- ");
				outputTensor = mModule.forward(EValue.from(arrDataPytorch))[0].toTensor();   //EXECUTORCH
			} catch (Exception e) {
				Log.i(TAG, " - neuralNetworkloadAndRunPytorch - Inference FAILED --- ");
				throw new RuntimeException(e);
			}

tmpData is a two-dimensional float array. It contains the input for the model.

shapeArrDataPytorchFlattened is a long array because Tensor.fromBlob requires it.

the model itself is a transformer decoder-based neural network. (https://arxiv.org/abs/2210.04095).

@kirklandsign
Copy link
Contributor

for tmpData
dimensions: {neuralNetworkUserLocationsInsideEstimationRadius.size(), 6}

do you need the last 1 dimension in shapeArrDataPytorchFlattened = new long[]{tmpData.length, 6, 1}; ?

Does the model need a 3-D input?

@kirklandsign
Copy link
Contributor

Also, let's do a really fast sanity check, what about you use forward() without argument? (will be filled with ones implicitly)

outputTensor = mModule.forward()[0].toTensor();   //EXECUTORCH

@adonnini
Copy link
Author

@kirklandsign Thanks again for your help. I really appreciate it.
I changed the code as you suggested:

            float[] flat = flatten(tmpData);
			final long[]  shapeArrDataPytorchFlattened = new long[]{tmpData.length, 6};
			arrDataPytorch = Tensor.fromBlob(flat, shapeArrDataPytorchFlattened);
			locationInformationNeuralNetworkFeaturesFlattenedPytorch = Tensor.fromBlob(flat, shapeArrDataPytorchFlattened);

						try {
				Log.i(TAG, " - neuralNetworkloadAndRunPytorch - Abut to run inference --- ");
				outputTensor = mModule.forward()[0].toTensor();   //EXECUTORCH
				Log.i(TAG, " - neuralNetworkloadAndRunPytorch - outputTensor - "+outputTensor);

				outputTensor = mModule.forward(EValue.from(arrDataPytorch))[0].toTensor();   //EXECUTORCH
				Log.i(TAG, " - neuralNetworkloadAndRunPytorch - outputTensor - "+outputTensor);
			} catch (Exception e) {
				Log.i(TAG, " - neuralNetworkloadAndRunPytorch - Inference FAILED --- ");
				throw new RuntimeException(e);
			}

I changed to 2-d input, just in case it made a difference although for my model I am pretty sure I do need 3-d input.

Unfortunately, the result is the same, Please see the error log below. The sanity check you suggested worked (see output of first Log.i(TAG, " - neuralNetworkloadAndRunPytorch - outputTensor - "+outputTensor); below)

I also added output to verify that arrDataPytorch is not empty

02-28 07:38:06.059: I/NeuralNetworkService(5425):  - NeuralNetworkInputPreparationLocationPredictionPytorch - arrDataPytorch - Tensor([30598, 6], dtype=torch.float32)
02-28 07:38:06.059: I/NeuralNetworkService(5425):  - NeuralNetworkInputPreparationLocationPredictionPytorch - arrDataPytorch.shape()[0] - 30598

What do you think is going on?

Thanks

ERROR LOG

02-28 07:02:02.933: I/NeuralNetworkService(3800):  - neuralNetworkloadAndRunPytorch - outputTensor - Tensor([2, 3], dtype=torch.float32)
02-28 07:02:02.933: E/ExecuTorch(3800): input 1 is none
02-28 07:02:02.934: I/NeuralNetworkService(3800):  - neuralNetworkloadAndRunPytorch - Inference FAILED --- 
02-28 07:02:02.934: W/System.err(3800): java.lang.RuntimeException: java.lang.Exception: Execution of method forward failed with status 0x12
02-28 07:02:02.935: W/System.err(3800): 	at com.android.contextq.neuralNetwork.NeuralNetworkService.neuralNetworkloadAndRunPytorch(NeuralNetworkService.java:2942)
02-28 07:02:02.935: W/System.err(3800): 	at com.android.contextq.neuralNetwork.NeuralNetworkService$NeuralNetworkServiceRunnable.run(NeuralNetworkService.java:9850)
02-28 07:02:02.935: W/System.err(3800): 	at java.lang.Thread.run(Thread.java:1012)
02-28 07:02:02.935: W/System.err(3800): Caused by: java.lang.Exception: Execution of method forward failed with status 0x12
02-28 07:02:02.935: W/System.err(3800): 	at org.pytorch.executorch.NativePeer.forward(Native Method)
02-28 07:02:02.935: W/System.err(3800): 	at org.pytorch.executorch.Module.forward(Module.java:75)
02-28 07:02:02.935: W/System.err(3800): 	at com.android.contextq.neuralNetwork.NeuralNetworkService.neuralNetworkloadAndRunPytorch(NeuralNetworkService.java:2935)
02-28 07:02:02.935: W/System.err(3800): 	... 2 more

@adonnini
Copy link
Author

adonnini commented Feb 28, 2025

@kirklandsign
I found two issues which I think might be related to the 0x12 error
#3636
#3848

This one may also be related (I opened it)
#2163

@kirklandsign
Copy link
Contributor

So it means the model can run if all inputs are ones if the dimension of the input tensor is correct, unless there is a dynamic shape in the model (is this the case?)

Do you know how you exported the model? What's the sample input when you export?

@adonnini
Copy link
Author

adonnini commented Feb 28, 2025

@kirklandsign

Here is the code I use to export the model:

        pre_autograd_aten_dialect = torch.export.export(model, args=(x, x_dict), strict=False)

        edge_program: EdgeProgramManager = to_edge(pre_autograd_aten_dialect)

        to_be_lowered_module = edge_program.exported_program()

        from executorch.exir.backend.backend_api import LoweredBackendModule, to_backend

        lowered_module = edge_program.to_backend(XnnpackPartitioner())
        print(" - train_minimum - Lowering the Whole Module - lowered_module - ", lowered_module)
        
        save_path = save_path = "/home/adonnini1/Development/ContextQSourceCode/NeuralNetworks/LocationPrediction/loweredModels/tpt_delegate.pte"
        with open(save_path, "wb") as f:
            f.write(lowered_module.to_executorch(ExecutorchBackendConfig(remove_view_copy=False)).buffer)

Please note that the code above did produce a .pte file. Do you want me to send it to you?

YES, there are dynamic shapes in the models I use. I don't know how many times your colleagues have asked me this question!
(please see
#2163 - closed (kind of)
#6782
#1350
pytorch/pytorch#134616)

There is a long history of (a few) issues I created related to the models I use and dynamic shapes, etc., etc.

I don't know how any changes I made to the model export code. Frankly, at least in some instances it looked like the change I was asked to make was just for the sake of trying something to see what would happen (not taking in consideration my time)

Unfortunately, all of the issues I created except for (#2163) are still open. I am still waiting for someone/anyone to get back to me.

I think that if you put yourself in my place, you would feel at least a little exasperated.

Did you take a look at the issue which I thought might possibly be related to the latest problem I have run into (perhaps with the exception of #2163)?

Thanks

@kirklandsign
Copy link
Contributor

args=(x, x_dict)

Does it mean the model takes two parameters? Do you know what is the type and dimensions of x, x_dict?

Basically we need mModule.forward(x, x_dict)

@adonnini
Copy link
Author

adonnini commented Mar 1, 2025

@kirklandsign

  1. Dimensions of the input data are dynamic

I need your help. I work in Java not Python.

  1. (x, x_dict) is the input of the Transencoder (TransEncoder(config=config, total_loc_num=config.total_loc_num)
    re_autograd_aten_dialect = torch.export.export(model, args=(x, x_dict), strict=False)

  2. x, y, x_dict = send_to_device(input_data, device, config)
    where, I think, input_data would be arrDataPytorch
    How would you implement the above line in Java?
    where
    ( the case networkName is equal to deepmove can be ignored, and to(device) is not necessary)

def send_to_device(inputs, device, config):
    global input_data
    input_data = inputs
    x, y, x_dict = inputs
    if config.networkName == "deepmove":
        x = (x[0].to(device), x[1].to(device))

        for key in x_dict[0]:
            x_dict[0][key] = x_dict[0][key].to(device)
        for key in x_dict[1]:
            x_dict[1][key] = x_dict[1][key].to(device)
    else:
        x = x.to(device)
        for key in x_dict:
            x_dict[key] = x_dict[key].to(device)
    y = y.to(device)

    return x, y, x_dict

AND

        from easydict import EasyDict as edict
        config = load_config("./config/geolife/transformer.yml")
        config = edict(config)

where

def load_config(path):
    """
    Loads config file:
    Args:
        path (str): path to the config file
    Returns:
        config (dict): dictionary of the configuration parameters, merge sub_dicts
    """
    with open(path, "r") as f:
        cfg = yaml.safe_load(f)

    config = dict()
    for _, value in cfg.items():
        for k, v in value.items():
            config[k] = v

    return config
  1. How would you implement
    outputTensor = mModule.forward(EValue.from(arrDataPytorch))[0].toTensor();
    replacing arrDataPytorch with x, x_dict

Given the above, it might not be possible for me to use Executorch to run my model for inference in my Android application. Please let me know what you think.

Thanks

@kirklandsign
Copy link
Contributor

To make sure things work, mModule.forward(...) needs to take in the parameter exactly the same as when you export the model, which means it takes two args, x, x_dict. Are you saying it's not possible to prepare for arguments x, x_dict directly in java layer? If it were python or c++, do you know how to get it?

@kirklandsign
Copy link
Contributor

Basically you need to transform arrDataPytorch into x, y, x_dict and discard y, and feed in x, x_dict into forward right?

If you have an idea how to do it in python or c++, it is the same in java.

forward itself doesn't have the magic to do send_to_device() to split into multiple inputs for you.

@adonnini
Copy link
Author

adonnini commented Mar 2, 2025

@kirklandsign

A couple of things:

  1. In my comment above I sent you all the code (in python) that would need to be implemented in Java and asked for your help in doing that as I am not a python developer. So, I don't understand it when you say "If you have an idea how to do it in python". I do. I sent you the code!. What do you mean by "It's the same in Java"? Conceptually, I am well aware it is.
    By the way, there is the "little" complication that there is no EasyDict for Java. It may be possible to do without it.

  2. Unless I am mistaken, the forward method takes a single parameter of type EValue and the from method takes a single Tensor parameter. How do you suggest I turn x, xdict into a single Tensor parameter?

Frankly, I am getting close to the point of giving up and look for alternatives. I know you are very busy and am grateful for you support.

Thanks

@adonnini
Copy link
Author

adonnini commented Mar 2, 2025

@kirklandsign

Below you will find a first attempt at Java code to create x, xdict.

Two unanswered (unsolved) questions:

  1. Unless I am mistaken, the forward method takes a single parameter of type EValue and the from method takes a single Tensor parameter. How do you suggest I turn x, xdict into a single Tensor parameter?

  2. I think I should be able to do without Edict. However, if it turns out I can't, I may well have an issue that's difficult to resolve.

A couple of things to note about the code below:

a) It is not done

b) I may need to define a Config class containing all the fields in the config in the Python code.

I would appreciate your feedback. In my opinion, unless I am really missing something point 1) above may be a show stopper.

Thanks

JAVA CODE TO PRODUCE X, XDICT

import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.yaml.snakeyaml.Yaml;
import java.util.Map;

    public static Map<String, Object> loadConfig(String path) {
        Map<String, Object> config = new HashMap<>();
        Yaml yaml = new Yaml();
        
        try (FileReader reader = new FileReader(path)) {
            Map<String, Map<String, Object>> cfg = yaml.load(reader);
            
            for (Map<String, Object> subMap : cfg.values()) {
                config.putAll(subMap);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        return config;
    }

    public static class Inputs {
        public Object x;
        public Map<String, Object> xDict;
    }
    
    public static Inputs createXXDict(Inputs inputs, Object config) {
        // Assigning values as per the Python logic
        Object x = inputs.x;
        Map<String, Object> xDict = inputs.xDict;
        
        for (String key : xDict.keySet()) {
            xDict.put(key, xDict.get(key));
        }
        
        Inputs result = new Inputs();
        result.x = x;
        result.xDict = xDict;
        
        return result;
    }

@kirklandsign
Copy link
Contributor

Unless I am mistaken, the forward method takes a single parameter of type EValue and the from method takes a single Tensor parameter. How do you suggest I turn x, xdict into a single Tensor parameter?

forward() takes variable arguments, so you can do forward(x, x_dict). I'm not sure about the type of x_dict, but seems that it's a Map<String, Object> right? Unfortunately I don't think it's supported. The list of supported evalue types are in

#define EXECUTORCH_FORALL_TAGS(_) \
_(None) \
_(Tensor) \
_(String) \
_(Double) \
_(Int) \
_(Bool) \
_(ListBool) \
_(ListDouble) \
_(ListInt) \
_(ListTensor) \
_(ListScalar) \
_(ListOptionalTensor)

Therefore I guess when you export the model, it's as if x_dict were a constant. cc @JacobSzwejbka to confirm.

send_to_device, as well as your java code like loadConfig and createXXDict, are helper functions to prepare the input data. Unfortunately we don't have the full context and knowledge about how the data preparation works for your specific model.

@kirklandsign kirklandsign changed the title error java.lang.NoSuchMethodError: no static or non-static method "Lorg/pytorch/executorch/NativePeer [Android] Error running a transformer decoder-based neural network Mar 2, 2025
@adonnini
Copy link
Author

adonnini commented Mar 3, 2025

@kirklandsign

Thanks. I just want to make sure I understand correctly what you say about the forward method.

Input can be (float[][], constant) where constant is of type from the list you referred to in your comment above.

Is this right?

Where can I find the documentation about this?

Thanks

@kirklandsign
Copy link
Contributor

I mean this is how you exported the model right?

pre_autograd_aten_dialect = torch.export.export(model, args=(x, x_dict), strict=False)

Here x_dict is a dict, and I'm not sure if torch.export really takes it as a variable of dict (cc @JacobSzwejbka please correct me), so honestly I don't know the expected behavior when we export the model (my guess is it's not really a used variable, but a export-time const).

Therefore, the input for forward might be EValue(Tensor(float[][])), EValue(None), but again I am not sure about how the second argument is used.

@kirklandsign
Copy link
Contributor

Input can be (float[][], constant) where constant is of type from the list you referred to in your comment above.

* @param inputs arguments for the ExecuTorch module's 'forward' method. Note: if method 'forward'
* requires inputs but no inputs are given, the function will not error out, but run 'forward'
* with sample inputs.
* @return return value from the 'forward' method.
*/
public EValue[] forward(EValue... inputs) {
return mNativePeer.forward(inputs);
}

And see

https://www.geeksforgeeks.org/variable-arguments-varargs-in-java/

@adonnini
Copy link
Author

adonnini commented Mar 3, 2025

@kirklandsign

This repository contains my updated model (python)
https://github.com/adonnini/LocationPredictionContextQ

I am familiar with varargs thanks. I was looking for documentation on inputs arguments for the forward method.

x_dict is the "dictionary" containing all the configuration variables (the map where each key is a variable name). I will need to figure out how to implement it in Java. I'll need to figure out whether your guess "(my guess is it's not really a used variable, but a export-time const)." is correct.

Thanks again for your help.

@adonnini
Copy link
Author

adonnini commented Mar 3, 2025

@kirklandsign

I tried the following:

outputTensor = mModule.forward(EValue.from(arrDataPytorch), EValue.from(0))[0].toTensor(); 

Execution failed producing the error log you will find below.

When I ran

outputTensor = mModule.forward(EValue.from(arrDataPytorch))[0].toTensor(); 

the only difference in the error log was this line

03-03 15:40:48.408: E/ExecuTorch(26369): input 1 is none

Doesn't this mean that the error reported in the error log below is not related to the number of parameters in the forward call? What am I missing?

Thanks

ERROR LOG

03-03 15:18:47.869: E/ExecuTorch(23178): input 2 is none
03-03 15:18:47.870: I/NeuralNetworkService(23178):  - neuralNetworkloadAndRunPytorch - Inference FAILED --- 
03-03 15:18:47.870: W/System.err(23178): java.lang.RuntimeException: java.lang.Exception: Execution of method forward failed with status 0x12
03-03 15:18:47.870: W/System.err(23178): 	at com.android.contextq.neuralNetwork.NeuralNetworkService.neuralNetworkloadAndRunPytorch(NeuralNetworkService.java:2942)
03-03 15:18:47.870: W/System.err(23178): 	at com.android.contextq.neuralNetwork.NeuralNetworkService$NeuralNetworkServiceRunnable.run(NeuralNetworkService.java:9857)
03-03 15:18:47.870: W/System.err(23178): 	at java.lang.Thread.run(Thread.java:1012)
03-03 15:18:47.870: W/System.err(23178): Caused by: java.lang.Exception: Execution of method forward failed with status 0x12
03-03 15:18:47.870: W/System.err(23178): 	at org.pytorch.executorch.NativePeer.forward(Native Method)
03-03 15:18:47.870: W/System.err(23178): 	at org.pytorch.executorch.Module.forward(Module.java:75)
03-03 15:18:47.870: W/System.err(23178): 	at com.android.contextq.neuralNetwork.NeuralNetworkService.neuralNetworkloadAndRunPytorch(NeuralNetworkService.java:2935)
03-03 15:18:47.870: W/System.err(23178): 	... 2 more

@JacobSzwejbka
Copy link
Contributor

JacobSzwejbka commented Mar 3, 2025

Here x_dict is a dict, and I'm not sure if torch.export really takes it as a variable of dict (cc @JacobSzwejbka please correct me)

The way torch.export works (and therefore ExecuTorch) is it flattens all data structures. Heres a doc explaining the concept if you are unfamiliar (it's from JAX but the principal is the same in PyTorch) https://docs.jax.dev/en/latest/pytrees.html.

What this practically means is that the key set of your dict needs to be fixed/static. The value's shapes can still be dynamic afaik if that matters for your model.

Then at runtime you will need to manually flatten your structure before converting the values to EValues and passing to ET. I see this stack is about android so we probably don't have java bindings for our cpp flattening lib today. https://github.com/pytorch/executorch/tree/main/extension/pytree

@adonnini
Copy link
Author

adonnini commented Mar 3, 2025

@JacobSzwejbka

Thanks for the information/explanation.

In my application, I do what you say should be done:
"you will need to manually flatten your structure before converting the values to EValues and passing to ET"

For my model the export works as far as I can tell as the process produces a .pte file

The shapes in my model are dynamic.

The key set of the dict xdict is fixed/static. However, it is not a single constant. It'a a Map<String,String>. This is where I am stuck.

When I export the model, the inputs are the input data x and xdict, and everything seems to work (the.pte is produced)

When I run Module.forward in my Android application, after loading the model, the problem is that unless I am mistaken EValue.from (the forward parameter type) does not take a Map as an argument.

I am not sure what I should do next.

@kirklandsign
Copy link
Contributor

My understanding is we need to implement flattening a dict to support this.

@adonnini
Copy link
Author

adonnini commented Mar 4, 2025

@kirklandsign OK. But doesn't the fact that the 0x12 error occur also when I use two parameters in the forwad call seem to indicate that the error is not related to the fact that I did not use xdict? When I used two paramters in the forward call the failure should have occurred when actually running for inference. That was not the case.

Please I would like to understand what is wrong with my reasoning. If what I say is correct, then what I do next is under my control, once the 0x12 error issue is resolved.

Thanks

@kirklandsign
Copy link
Contributor

EValue.from (the forward parameter type) does not take a Map as an argument

Correct, that's the current issue.

@JacobSzwejbka should we

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
module: android Issues related to Android code, build, and execution module: user experience Issues related to reducing friction for users triaged This issue has been looked at a team member, and triaged and prioritized into an appropriate module
Projects
Status: To triage
Development

No branches or pull requests

5 participants