Skip to content

Latest commit

 

History

15 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 

Repository files navigation

tensorflow-nonavx

Reproducible build recipe and prebuilt release artifact for TensorFlow 2.20 on Linux x86_64 systems that do not support AVX instructions.

This project exists because the official TensorFlow 2.20 Linux wheel terminates with:

Illegal instruction (core dumped)

on older Intel CPUs such as the Xeon X7560 / Westmere generation.

The repository contains the pinned build configuration and source patches used to produce a TensorFlow CPU wheel that was successfully executed on actual non-AVX Xeon X7560 hardware.

Current release

Release:

v2.20.0-nonavx.1

TensorFlow package version:

2.20.0.dev0+selfbuilt

Wheel:

tensorflow_cpu-2.20.0.dev0+selfbuilt-cp312-cp312-linux_x86_64.whl

Python ABI:

cp312

Architecture:

linux_x86_64

SHA256:

b5c0ca166e83b67c0c038b84bca5b4f4426669da86187a047ed2b64e01dca949

Release page:

https://github.com/leg3/tensorflow-nonavx/releases/tag/v2.20.0-nonavx.1

Direct wheel download:

https://github.com/leg3/tensorflow-nonavx/releases/download/v2.20.0-nonavx.1/tensorflow_cpu-2.20.0.dev0+selfbuilt-cp312-cp312-linux_x86_64.whl

Checksum manifest:

https://github.com/leg3/tensorflow-nonavx/releases/download/v2.20.0-nonavx.1/SHA256SUMS

Target CPU

The validated deployment target is:

Intel Xeon X7560
Westmere
Linux x86_64

The target supports the x86-64-v2 CPU baseline, including instructions such as:

  • SSSE3
  • SSE4.1
  • SSE4.2
  • POPCNT

It does not support AVX.

The build therefore uses an explicit CPU baseline rather than optimizing for the build host.

CPU compiler configuration

The primary compiler flags are:

-march=x86-64-v2
-mno-avx
-mno-avx2
-mno-fma
-mno-f16c

The build intentionally does not use:

-march=native

The build host may support newer CPU instructions than the deployment target. Using -march=native could therefore silently produce a binary that works on the build machine but fails on the intended non-AVX system.

Reproducible build identity

The current build pins the following versions:

TensorFlow:       2.20.0
TensorFlow SHA:   72fbba3d20f4616d7312b5e2b7f79daf6e82f2fa
Python:           3.12.9
Python ABI:       cp312
Bazel:            7.4.1
Clang:            18.1.8
Architecture:     x86_64
CPU baseline:     x86-64-v2

TensorFlow build image:

tensorflow/build:2.20-python3.12

Pinned image digest:

sha256:9a9722d3e6d10fce276e6e6396c4faea6be96ce471d9a40de33fce0433780e99

The pinned values are stored in:

build/tensorflow-nonavx/versions.env

Repository layout

build/
└── tensorflow-nonavx/
    ├── build.sh
    ├── versions.env
    └── patches/
        ├── absl-nonavx.patch
        ├── boringssl-nonavx.patch
        ├── highwayhash-nonavx.patch
        ├── ruy-nonavx.patch
        ├── tensorflow-nonavx.patch
        └── xnnpack-nonavx.patch

The repository contains the build recipe and patches.

The compiled TensorFlow wheel is distributed as a GitHub Release asset rather than committed to Git history.

Why global compiler flags are not enough

TensorFlow includes a large third-party dependency graph.

Several dependencies can independently enable newer CPU instructions through:

  • dependency-specific compiler options;
  • Bazel target configuration;
  • architecture-specific assembly;
  • per-function compiler attributes;
  • template specialization; and
  • runtime CPU dispatch.

As a result, adding -mno-avx at the top-level TensorFlow build is not sufficient by itself.

The current recipe includes targeted configuration and patches for components encountered during the TensorFlow 2.20 build.

TensorFlow build configuration

The build disables oneDNN:

--define=disable_onednn=true
--@local_xla//xla/tsl/framework/contraction:disable_onednn_contraction_kernel=True

libjpeg-turbo SIMD assembly is disabled with:

--@libjpeg_turbo//:noasm=yes

XNNPACK AVX-family implementations are explicitly disabled through Bazel configuration in addition to the XNNPACK patch.

Third-party dependency patches

XNNPACK

XNNPACK contains architecture-specific optimized microkernels and its own CPU feature configuration.

The build disables AVX-family XNNPACK variants and applies a source/build patch to prevent those implementations from entering the build graph.

BoringSSL

BoringSSL can include architecture-specific assembly independently of TensorFlow's general compiler flags.

The non-AVX patch disables the affected assembly path and defines:

OPENSSL_NO_ASM

ruy

ruy contains target-specific compiler options that can explicitly add flags including:

-mavx
-mavx2
-mfma

The non-AVX patch prevents those AVX-family compiler-option helpers from introducing unsupported instructions.

Abseil

Abseil CRC code contained a function-level AVX implementation using a compiler target attribute.

Function-level attributes can generate AVX instructions even when the surrounding project is compiled with a non-AVX baseline.

The patch disables the forced AVX implementation so a compatible fallback path is used.

HighwayHash

HighwayHash was the most subtle source of residual AVX2 instructions during development.

Removing the obvious AVX2 Bazel dependency was not sufficient because HighwayHash runtime-dispatch code still instantiated the AVX2 implementation.

The final patch addresses both:

  1. the AVX2 dependency path; and
  2. the source-level runtime dispatch that could instantiate or advertise the AVX2 implementation.

SSE4.1 and Portable implementations remain available.

This is an important consideration for future TensorFlow versions: a clean dependency graph does not necessarily prove that template or runtime-dispatch code cannot still reference an unsupported implementation.

Building

The build requires Docker and Git.

From the repository root:

./build/tensorflow-nonavx/build.sh

By default, build work is stored under:

~/build-work/tensorflow-nonavx

The build script recreates the TensorFlow source checkout and output directory for each build while retaining the Bazel cache.

The completed wheel is copied to:

~/build-work/tensorflow-nonavx/dist/

The host-side dist/ directory is the canonical build output.

Do not rely on Docker-internal or Bazel-internal bazel-bin paths when consuming the artifact from the host.

Bazel cache behavior

The build retains:

~/build-work/tensorflow-nonavx/bazel-home

so subsequent builds can reuse previously compiled objects.

This significantly reduces rebuild time when only targeted dependencies or patches change.

Avoid deleting the Bazel cache unless there is evidence that the cache itself is invalid.

Installing the released wheel

Download the release artifact:

curl -fLO https://github.com/leg3/tensorflow-nonavx/releases/download/v2.20.0-nonavx.1/tensorflow_cpu-2.20.0.dev0+selfbuilt-cp312-cp312-linux_x86_64.whl

Download the checksum manifest:

curl -fLO https://github.com/leg3/tensorflow-nonavx/releases/download/v2.20.0-nonavx.1/SHA256SUMS

Verify the artifact before installation:

sha256sum -c SHA256SUMS

Expected result:

tensorflow_cpu-2.20.0.dev0+selfbuilt-cp312-cp312-linux_x86_64.whl: OK

Install into a Python 3.12 environment:

python3.12 -m pip install \
  ./tensorflow_cpu-2.20.0.dev0+selfbuilt-cp312-cp312-linux_x86_64.whl

Runtime validation

The exact released wheel was copied to and tested on an Intel Xeon X7560 system without AVX support.

It was installed into a clean Python 3.12 virtual environment and tested with:

python -c "import tensorflow as tf; print(tf.__version__); print(tf.constant([1,2,3]))"

TensorFlow reported:

2.20.0-dev0+selfbuilt

and successfully returned:

tf.Tensor([1 2 3], shape=(3,), dtype=int32)

The Illegal instruction (core dumped) failure encountered with the official TensorFlow wheel did not occur.

Static binary validation

The completed wheel was extracted and its native shared libraries were inspected for AVX-family instruction mnemonics.

The final validation scan did not identify AVX-family instruction hits.

Static inspection should be treated as supporting evidence rather than a replacement for runtime testing on actual non-AVX hardware.

Runtime execution on the target CPU remains the primary acceptance test.

Release integrity

The current release artifact was verified through the following chain:

build artifact
    ↓
SHA256 verification on build host
    ↓
copy to Xeon X7560 target
    ↓
SHA256 verification
    ↓
runtime TensorFlow validation
    ↓
GitHub Release publication
    ↓
unauthenticated public download using curl
    ↓
SHA256 verification

The final public download produced the same SHA256 as the originally validated wheel.

Release policy

Published binary releases are intended to be immutable.

The current release:

v2.20.0-nonavx.1

corresponds to the exact wheel with SHA256:

b5c0ca166e83b67c0c038b84bca5b4f4426669da86187a047ed2b64e01dca949

If TensorFlow 2.20.0 is rebuilt and the resulting binary has different contents, it should receive a new release identity such as:

v2.20.0-nonavx.2

rather than replacing the existing release asset.

A future TensorFlow version would follow the same pattern, for example:

v2.21.0-nonavx.1

Future TensorFlow upgrades

The current patches should be treated as an implementation reference, not as patches guaranteed to apply unchanged to future TensorFlow releases.

For a future TensorFlow upgrade:

  1. Pin the TensorFlow source commit and build-image digest.
  2. Record the required Python, Bazel, and Clang versions.
  3. Confirm the intended CPU baseline.
  4. Re-audit TensorFlow build configuration for AVX-enabling options.
  5. Determine the exact third-party dependency revisions used by the new release.
  6. Re-audit XNNPACK, BoringSSL, ruy, Abseil, HighwayHash, libjpeg-turbo, and oneDNN.
  7. Search source and Bazel rules for:
    • -mavx
    • -mavx2
    • -mfma
    • AVX-512 options
    • per-function target attributes
    • architecture-specific assembly
    • runtime CPU dispatch.
  8. Validate each existing patch against the new dependency revision before applying it.
  9. Build and inspect suspicious individual libraries where practical.
  10. Build the complete wheel.
  11. Extract and scan its native shared libraries.
  12. Verify the artifact checksum.
  13. Install the exact artifact on actual non-AVX hardware.
  14. Require TensorFlow import and representative computation to complete without SIGILL / Illegal instruction.
  15. Publish the artifact under a new immutable release version.

Scope

This repository exists only to build and distribute the custom TensorFlow dependency.

It does not contain:

  • SVRaaS;
  • SVRaaS model runners;
  • the SVRaaS API;
  • the SVRaaS orchestrator; or
  • the downstream Docker runner implementation.

Projects such as SVRaaS consume the released wheel as a pinned external dependency and should verify its SHA256 before installation.

About

Reproducible TensorFlow 2.20 CPU build and prebuilt wheel for Linux x86_64 systems without AVX support, validated on Intel Xeon X7560 / Westmere hardware.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages