It just works also on crappy Droids! Kudos

#1
by MataNata - opened

Amazing. It should not work on

fastfetch
u0_a278@localhost
-----------------
OS: Android REL 11 aarch64
Host: realme 8 (RMX3085)
Kernel: Linux 4.14.186+
Uptime: 1 day, 13 hours, 16 mins
Packages: 832 (dpkg), 142 (pacman)
Shell: bash 5.3.15
DE: RMX3085_11_A.26
WM: WindowManager (SurfaceFlinger)
Terminal: Termux 0.118.3
Terminal Font: UbuntuMono Nerd Font Mono
CPU: MT6785V/CD (2+6) @ 2.05 GHz
GPU: ARM Mali-G76 MC4 r0p0 (4) @ 0.01 GHz [Integrated]
Memory: 3.35 GiB / 5.51 GiB (61%)
Swap: 3.90 GiB / 6.00 GiB (65%)
...
cpu-info
SoC name: MediaTek MT6785V/CD
Microarchitectures:
        2x Cortex-A76
        6x Cortex-A55
Cores:
        0: 1 processor (0), ARM Cortex-A76
        1: 1 processor (1), ARM Cortex-A76
        2: 1 processor (2), ARM Cortex-A55
        3: 1 processor (3), ARM Cortex-A55
        4: 1 processor (4), ARM Cortex-A55
        5: 1 processor (5), ARM Cortex-A55
        6: 1 processor (6), ARM Cortex-A55
        7: 1 processor (7), ARM Cortex-A55
Clusters:
        0: 2 processors (0-1),  0: 2 cores (0-1), ARM Cortex-A76
        1: 6 processors (2-7),  1: 6 cores (2-7), ARM Cortex-A55
Logical processors (System ID)😀 

and yet, out of the box, no tricks (apart from that sudo level swap) , the models left even on FUSE-d sdcard, to maoe it even more fragile ;) + Kiwi etc at background, see the log below. No OOM yet.

Heffalumps are a tad more tricky (take longer to produce) to the model, but a heffalumpish critter indeed:

hefalumf_1

root@localhost:/storage/5951-9E0F/LLMs/Bonsai-Image-ternary-4B# ls
README.md           pipeline_meta.json              tokenizer
dit_int4b32.tflite  quality_grid.png                vae_dec_fp32.tflite
fox.png             textenc_int4.tflite
generate.py         textenc_int8_weightonly.tflite
root@localhost:/storage/5951-9E0F/LLMs/Bonsai-Image-ternary-4B# python generate.py
usage: generate.py [-h] --model-dir MODEL_DIR [--prompt PROMPT]
                   [--out OUT] [--steps STEPS] [--seed SEED]
                   [--threads THREADS]
generate.py: error: the following arguments are required: --model-dir
root@localhost:/storage/5951-9E0F/LLMs/Bonsai-Image-ternary-4B# time python generate.py --model-dir . --prompt "a red fox sitting in fresh snow at sunrise" --seed 42 --out fox.png
INFO: Created TensorFlow Lite XNNPACK delegate for CPU.
prompt encoded 34.5s
DiT loaded 36.6s
step 1/4 sigma 1.000 84.5s
step 2/4 sigma 0.958 84.0s
step 3/4 sigma 0.884 96.1s
step 4/4 sigma 0.717 104.3s
VAE decoded 82.1s
saved fox.png
        Command being timed: "python generate.py --model-dir . --prompt a red fox sitting in fresh snow at sunrise --seed 42 --out fox.png"
        User time (seconds): 2710.64
        System time (seconds): 78.99
        Percent of CPU this job got: 404%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 11:29.78
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 3057916
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 882
        Minor (reclaiming a frame) page faults: 2411362
        Voluntary context switches: 619830
        Involuntary context switches: 823636
        Swaps: 0
        File system inputs: 10515181
        File system outputs: 816
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0
root@localhost:/storage/5951-9E0F/LLMs/Bonsai-Image-ternary-4B# time python generate.py --model-dir . --prompt "a violet heffalump sitting in icy snow at sunrise" --seed 42 --out hefalumf_1.png
INFO: Created TensorFlow Lite XNNPACK delegate for CPU.
prompt encoded 33.8s
DiT loaded 36.8s
step 1/4 sigma 1.000 80.7s
step 2/4 sigma 0.958 105.7s
step 3/4 sigma 0.884 145.8s
step 4/4 sigma 0.717 150.8s
VAE decoded 96.2s
saved hefalumf_1.png
        Command being timed: "python generate.py --model-dir . --prompt a violet heffalump sitting in icy snow at sunrise --seed 42 --out hefalumf_1.png"
        User time (seconds): 2935.71
        System time (seconds): 289.24
        Percent of CPU this job got: 387%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 13:52.50
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 2928780
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 892
        Minor (reclaiming a frame) page faults: 3596989
        Voluntary context switches: 1368032
        Involuntary context switches: 1080518
        Swaps: 0
        File system inputs: 16646853
        File system outputs: 808
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0
root@localhost:/storage/5951-9E0F/LLMs/Bonsai-Image-ternary-4B#

Best case scenario:
Phone rebooted, models on ext4 partition, nothing running at background:

                 root@localhost:/data/data/com.termux/files/home/Downloads/LLMs/Bonsai-Image-ternary-4B# time python generate.py --model-dir . --prompt "a violet heffalump sitting in icy mountain hotel at sunrise" --seed 42 --out hefalumf_2.png
INFO: Created TensorFlow Lite XNNPACK delegate for CPU.
prompt encoded 16.8s
DiT loaded 11.4s
step 1/4 sigma 1.000 77.5s
^[[6~step 2/4 sigma 0.958 76.7s
step 3/4 sigma 0.884 76.6s
step 4/4 sigma 0.717 76.2s
VAE decoded 68.0s
saved hefalumf_2.png
        Command being timed: "python generate.py --model-dir . --prompt a violet heffalump sitting in icy mountain hotel at sunrise --seed 42 --out hefalumf_2.png"
        User time (seconds): 2360.72
        System time (seconds): 54.20
        Percent of CPU this job got: 414%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 9:43.01
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 3300340
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 722
        Minor (reclaiming a frame) page faults: 1424547
        Voluntary context switches: 483910
        Involuntary context switches: 1202531
        Swaps: 0
        File system inputs: 9320896
        File system outputs: 912
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0
root@localhost:/data/data/com.termux/files/home/Downloads/LLMs/Bonsai-Image-ternary-4B#

hefalumf_2

Plus Gemini AI musing about the (yet informal) tests on two crappy Droids vs HP Notebook (no GPUs in either):

Bonsai Image 4B - Real-World Benchmarks & Architecture Notes

This document contains real-world performance benchmarks across different hardware configurations (Ubuntu x86 vs. Android ARM), along with notes on why specific architectures perform the way they do with this model.

Model Components Breakdown

Before diving into benchmarks, here is what each file in this directory does:

  • dit_int4b32.tflite (2.11 GiB): The core Diffusion Transformer (DiT). It generates the image by progressively removing noise. It uses ternary weights that fit losslessly into this int4 container.
  • textenc_int4.tflite (1.68 GiB): The default text encoder (Qwen3-4B compressed to 4-bit). It translates your text prompt into embeddings. Provides the smallest memory footprint with great quality.
  • textenc_int8_weightonly.tflite (2.91 GiB): A higher-fidelity 8-bit text encoder. You can use this for slightly better prompt adherence by running: python generate.py --model-dir . --textenc textenc_int8_weightonly.tflite [Note: I asked Gemini to tweak up the .py code for such A/B tests] .
  • vae_dec_fp32.tflite (0.19 GiB): The VAE Decoder. It runs in full 32-bit floating point precision (uncompressed) to translate the DiT's final latent output into crisp, artifact-free RGB pixels.

Architectural Insights: Why ARM Competes with x86 Here

You might notice in the benchmarks below that an older Android device (Droid A) matches or even slightly beats a 40W undervolted Intel i5-8265U, despite the Intel chip having more than double the raw floating-point performance (220 GFLOP/s vs 96 GFLOP/s). Here is why:

  1. XNNPACK & ARM NEON: TensorFlow Lite and its XNNPACK delegate are fundamentally designed for mobile ARM architectures. While XNNPACK supports x86 AVX2, its ARM NEON instruction optimizations are vastly superior.
  2. Integer Math vs. Floating Point: peakperf measures raw floating-point operations. However, this model relies heavily on highly compressed integer (int4) math. The MediaTek ARM processor is highly efficient at these specific integer tensor operations via XNNPACK.
  3. Sustained Loads: The HP laptop maintains a respectable 2100 MHz sustained clock thanks to a -99.61 mV undervolt and unlocked power limits (up to 40W/200W). Even without thermal throttling bringing it to its base 1.6GHz speed, the pure algorithmic advantage of XNNPACK's ARM optimization allows the passive-cooled phone chip to pull ahead on the heavy DiT math steps.

Benchmarks

1. Ubuntu (HP Pavilion 14)

  • OS: Ubuntu 24.04.4 LTS x86_64
  • CPU: Intel(R) Core(TM) i5-8265U (8 threads) @ ~2.10 GHz sustained (Undervolted -99.61 mV)
  • RAM: 7.64 GiB
  • Peakperf (AVX2): ~220 GFLOP/s

Results (Run Time: ~7m 28s):

  • Prompt Encoded: 21.6s
  • DiT Loaded: 16.5s
  • DiT Steps (4): 87.0s, 89.5s, 92.1s, 90.9s
  • VAE Decoded: 27.6s
  • Max RAM used: ~4.9 GiB

2. Droid A (Ext4 Native Storage)

  • OS: Debian GNU/Linux 13 (aarch64 via PRoot)
  • CPU: MediaTek MT6785V/CD (Helio G90 series, 8 threads) @ 2.05 GHz
  • RAM: 5.51 GiB
  • Peakperf (ARM NEON): ~96 GFLOP/s

Results (Run Time: ~6m 3s):

  • Prompt Encoded: 20.6s
  • DiT Loaded: 13.9s
  • DiT Steps (4): 90.8s, 82.5s, 78.8s, 77.7s
  • (Note: DiT steps are ~10-15 seconds faster per step than the Intel i5)

3. Droid A (FUSE External SD Card)

Running the models off a FUSE-mounted external SD card introduces minor I/O bottlenecks during loading, but compute times remain similar.

Results:

  • Prompt Encoded: 34.9s
  • DiT Loaded: 40.0s
  • DiT Steps (4): 74.9s, 74.0s, 74.0s, 78.4s
  • VAE Decoded: 75.5s
  • Observation: Slower initial loading (I/O limit), but DiT math execution remains incredibly fast.

4. Droid B (realme RMX3085 - FUSE External SD Card)

  • OS: Debian GNU/Linux 13 (aarch64 via PRoot)
  • CPU: MediaTek MT6785V/CD (8 threads) @ 1.618 GHz
  • RAM: 3.54 GiB (Heavy swap usage required)

Results (Run Time: ~14m 47s):

  • Prompt Encoded: 65.0s
  • DiT Loaded: 137.5s
  • DiT Steps (4): 140.0s, 119.3s, 106.9s, 130.1s
  • VAE Decoded: 112.3s
  • Max RAM used: ~1.88 GiB
  • Observation: The combination of lower clock speeds, limited RAM (causing swap thrashing), and FUSE I/O overhead severely impacts overall time compared to Droid A.
MataNata changed discussion status to closed
MataNata changed discussion status to open

Sign up or log in to comment