From 8522b6dda8b5807bc04433158e3876c910644663 Mon Sep 17 00:00:00 2001 From: samuelcaldas Date: Fri, 28 Aug 2026 15:31:12 -0300 Subject: [PATCH 1/7] docs: add CLAUDE.md for codebase guidance and architecture Co-Authored-By: Claude --- CLAUDE.md | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..1b3f43f1 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,93 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Build and Test Commands + +### Prerequisites +- Target framework: `.NET 6.0` / `.NET Standard 2.0` +- Solution file: `TensorFlow.NET.sln` + +### Build Commands +```powershell +# Restore dependencies +dotnet restore TensorFlow.NET.sln + +# Build entire solution (Debug / Release) +dotnet build TensorFlow.NET.sln -c Debug +dotnet build TensorFlow.NET.sln -c Release +``` + +### Testing Commands +```powershell +# Run all unit test suites +dotnet test TensorFlow.NET.sln --verbosity normal + +# Run a specific test project +dotnet test test/TensorFlowNET.UnitTest/Tensorflow.Binding.UnitTest.csproj +dotnet test test/TensorFlowNET.Keras.UnitTest/Tensorflow.Keras.UnitTest.csproj +dotnet test test/TensorFlowNET.Graph.UnitTest/TensorFlowNET.Graph.UnitTest.csproj +dotnet test test/TensorFlow.Kernel.UnitTest/TensorFlow.Kernel.UnitTest.csproj +dotnet test test/TensorFlowNET.Native.UnitTest/Tensorflow.Native.UnitTest.csproj + +# Run a specific test by fully qualified name +dotnet test --filter "FullyQualifiedName=TensorFlowNET.UnitTest.Basics.EagerModeTest" + +# Run tests matching a name pattern +dotnet test --filter "Name~EagerMode" +``` + +### Switching CPU / GPU Redist Packages for Local Testing +The tests depend on `tools/Tensorflow.UnitTest.RedistHolder` to provide the native TensorFlow C-API runtime binaries: +```powershell +# Default / CPU redist +dotnet add tools/Tensorflow.UnitTest.RedistHolder package SciSharp.TensorFlow.Redist + +# Windows GPU redist (CUDA & cuDNN required) +dotnet remove tools/Tensorflow.UnitTest.RedistHolder package SciSharp.TensorFlow.Redist +dotnet add tools/Tensorflow.UnitTest.RedistHolder package SciSharp.TensorFlow.Redist-Windows-GPU +``` + +--- + +## Architecture & Code Structure + +**TensorFlow.NET (TF.NET)** is a pure .NET Standard / C# binding and implementation of TensorFlow (targeting TensorFlow v2.10 C-API / Python parity). + +### High-Level Subsystems + +``` +src/ +├── TensorFlowNET.Core/ # Core binding layer (Tensorflow.Binding) +│ ├── CApi/ # Low-level P/Invoke native interop (c_api.cs, tf_status, etc.) +│ ├── Tensors/ # Tensor, TensorShape, DType, memory management & disposables +│ ├── Eager/ # Eager execution engine, EagerTensor, Context +│ ├── Grafts / Gradients/ # Automatic differentiation (GradientTape) +│ ├── Operations/ # Math, array, nn, control flow graph & eager ops +│ ├── Variables/ # ResourceVariable, RefVariable, VariableScope +│ ├── NumPy/ # NumPy array & tensor interoperability (np.* helpers) +│ └── Protobuf/ # Generated TensorFlow protobuf definitions (GraphDef, NodeDef, etc.) +│ +├── TensorFlowNET.Keras/ # High-level Keras neural network API (Tensorflow.Keras) +│ ├── Engine/ # Model, Layer, Sequential, Functional, Training/Eval loop +│ ├── Layers/ # Core, Convolutional, Recurrent, Normalization, Reshaping layers +│ ├── Optimizers/ # Adam, SGD, RMSprop, AdaGrad and base optimizer +│ ├── Losses/ & Metrics/ # Loss functions (MSE, CrossEntropy) & evaluation metrics +│ ├── Initializers/ # Weight initializers (Glorot, He, RandomNormal, etc.) +│ └── Utils/ # Keras serialization, dataset pipelines, shape inference +│ +├── TensorFlowNET.Text/ # NLP text processing, tokenization, and embeddings +├── TensorflowNET.Hub/ # Pretrained TensorFlow Hub model loading and execution +└── TensorFlowNET.Recommenders/ # Recommender systems and ranking architectures +``` + +### Key Architectural Concepts +- **Python / C# Idiom Parity**: Standard static imports provide syntax matching Python TensorFlow: + ```csharp + using static Tensorflow.Binding; + using static Tensorflow.KerasApi; + using Tensorflow; + using Tensorflow.NumPy; + ``` +- **Execution Modes**: Supports both `Eager` mode (imperative tensor operations) and `Graph` mode (`tf.Graph`, `tf.Session`, `tf.placeholder`). +- **Native Interop Lifecycle**: Native `c_api` allocations (`SafeHandle`, `TF_Tensor`, `TF_Status`, `TF_Operation`) are wrapped via `DisposableObject` and memory lifetime management in `TensorFlowNET.Core`. From f216fc059db08902cbd0a2817ff99e740b039f13 Mon Sep 17 00:00:00 2001 From: samuelcaldas Date: Fri, 28 Aug 2026 15:42:44 -0300 Subject: [PATCH 2/7] docs: document py-tensorflow-sot SOT and symlink GEMINI.md, AGENTS.md Co-Authored-By: Claude --- AGENTS.md | 1 + CLAUDE.md | 1 + GEMINI.md | 1 + 3 files changed, 3 insertions(+) create mode 120000 AGENTS.md create mode 120000 GEMINI.md diff --git a/AGENTS.md b/AGENTS.md new file mode 120000 index 00000000..681311eb --- /dev/null +++ b/AGENTS.md @@ -0,0 +1 @@ +CLAUDE.md \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index 1b3f43f1..e75dd549 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -82,6 +82,7 @@ src/ ``` ### Key Architectural Concepts +- **Source of Truth (SOT)**: The official Python TensorFlow codebase located at `refs/py-tensorflow-sot` (`D:\Users\samuel\source\repos\NT\refs\py-tensorflow-sot`) serves as the strict reference implementation for all mathematical behavior, operator semantics, graph/eager execution semantics, and API signatures. Reference files under `refs/` are read-only. - **Python / C# Idiom Parity**: Standard static imports provide syntax matching Python TensorFlow: ```csharp using static Tensorflow.Binding; diff --git a/GEMINI.md b/GEMINI.md new file mode 120000 index 00000000..681311eb --- /dev/null +++ b/GEMINI.md @@ -0,0 +1 @@ +CLAUDE.md \ No newline at end of file From 5d7aab9404a5a986d03a694946e4f0d5d1b7f55e Mon Sep 17 00:00:00 2001 From: samuelcaldas Date: Fri, 28 Aug 2026 15:51:06 -0300 Subject: [PATCH 3/7] docs: add SOT feature gap roadmap and version relationships to README and CLAUDE.md Co-Authored-By: Claude --- CLAUDE.md | 36 ++++++++++++++++++++++++++++++++++++ README.md | 41 ++++++++++++++++++++++++++++++++--------- 2 files changed, 68 insertions(+), 9 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index e75dd549..f3a3149e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -83,6 +83,19 @@ src/ ### Key Architectural Concepts - **Source of Truth (SOT)**: The official Python TensorFlow codebase located at `refs/py-tensorflow-sot` (`D:\Users\samuel\source\repos\NT\refs\py-tensorflow-sot`) serves as the strict reference implementation for all mathematical behavior, operator semantics, graph/eager execution semantics, and API signatures. Reference files under `refs/` are read-only. +- **Branching, Tagging & Python TensorFlow Version Mapping**: + - **Version Mapping Scheme**: TF.NET versions directly mirror TensorFlow Python versions: + - `v0.150.x` / `v0.15.x` -> Python TensorFlow `v2.15` / `v1.15` + - `master` / `v0.110.x` / `v0.100.x` -> Python TensorFlow `v2.11` / `v2.10` + - `v0.6x` -> Python TensorFlow `v2.6` + - `v0.40` -> Python TensorFlow `v2.4` + - **Branches**: + - `master`: Main development line targeting parity with TensorFlow 2.10+. + - Maintenance / version branches (e.g. `v0.6x`, `v0.15-tensorflow1.15`): Target specific legacy TensorFlow releases. + - **Tags**: Semantic versioning prefixed with `v` (e.g. `v0.110.4-Transformer-Model`, `v0.100.5`), used by CI/CD packaging to determine the base version. + - **Releases & CI/CD Pipeline**: + - Automatic packaging triggered on PR merge to `master` with `auto-release` label (`.github/workflows/release_prepare.yml` -> `release.yml`). + - Produces `-nightly` packages pushed to MyGet feed (`https://www.myget.org/F/scisharp/api/v3/index.json`) and stable releases pushed to NuGet (`TensorFlow.NET`, `TensorFlow.Keras`, `Tensorflow.Hub`). - **Python / C# Idiom Parity**: Standard static imports provide syntax matching Python TensorFlow: ```csharp using static Tensorflow.Binding; @@ -92,3 +105,26 @@ src/ ``` - **Execution Modes**: Supports both `Eager` mode (imperative tensor operations) and `Graph` mode (`tf.Graph`, `tf.Session`, `tf.placeholder`). - **Native Interop Lifecycle**: Native `c_api` allocations (`SafeHandle`, `TF_Tensor`, `TF_Status`, `TF_Operation`) are wrapped via `DisposableObject` and memory lifetime management in `TensorFlowNET.Core`. + +--- + +## Roadmap & SOT Feature Gap Objectives + +Targeting alignment with modern Python TensorFlow (TF 2.16 - 2.22+ in `refs/py-tensorflow-sot`): + +1. **Native C-API & Runtime Upstream Synchronization**: + - Upgrade native redist bindings from TF 2.10/2.15 to TF 2.16+ / TF 2.22+ C-API binaries. + - Synchronize `CApi/c_api.cs` and `CApi/tf_status.cs` with upstream C-API changes (e.g. filesystem interface transitions). + +2. **Keras 3 Multi-Backend Parity**: + - Modernize `TensorFlowNET.Keras` abstractions beyond Keras 2.x legacy tight graph coupling toward Keras 3 stateless layer patterns and unified serialization. + +3. **Expanded DTypes and Quantization Support**: + - Implement native C# support and memory conversions for 8-bit floats (`FLOAT8_E4M3FN`, `FLOAT8_E5M2`) and 4-bit quantized operations (`QUI4`). + - Broaden native `bfloat16` and `float16` kernel interoperability across all tensor mathematical ops. + +4. **Advanced Operations, Second-Order Gradients & `tf.data`**: + - Add missing second-order gradients in `GradientTape` (e.g. `SoftsignGrad`, `AdjustContrastv2`). + - Expand `TensorFlowNET.Core/NumPy` to match updated `tf.experimental.numpy` behavior (e.g. tolerance handling in `isclose`/`allclose`). + - Port newer `tf.data` pipeline features (`Dataset.scan`, dynamic multithreaded buffering). + diff --git a/README.md b/README.md index 75cad0aa..05254a04 100644 --- a/README.md +++ b/README.md @@ -191,15 +191,16 @@ More adcanced examples could be found in [TensorFlow.NET Examples](https://githu ## Version Relationships -| TensorFlow.NET Versions | tensorflow 1.14, cuda 10.0 | tensorflow 1.15, cuda 10.0 | tensorflow 2.3, cuda 10.1 | tensorflow 2.4, cuda 11 | tensorflow 2.7, cuda 11 |tensorflow 2.10, cuda 11 | -| -------------------------- | ------------- | -------------- | ------------- | ------------- | ------------ | ------------ | -| tf.net 0.10x, tf.keras 0.10 | | | | | | x | -| tf.net 0.7x, tf.keras 0.7 | | | | | x | | -| tf.net 0.4x, tf.keras 0.5 | | | | x | | | -| tf.net 0.3x, tf.keras 0.4 | | | x | | | | -| tf.net 0.2x | | x | x | | | | -| tf.net 0.15 | x | x | | | | | -| tf.net 0.14 | x | | | | | | +| TensorFlow.NET Versions | tensorflow 1.14, cuda 10.0 | tensorflow 1.15, cuda 10.0 | tensorflow 2.3, cuda 10.1 | tensorflow 2.4, cuda 11 | tensorflow 2.7, cuda 11 |tensorflow 2.10, cuda 11 | tensorflow 2.15+ (target) | +| -------------------------- | ------------- | -------------- | ------------- | ------------- | ------------ | ------------ | ------------ | +| tf.net 0.150x, tf.keras 0.150| | | | | | | x | +| tf.net 0.10x, tf.keras 0.10 | | | | | | x | | +| tf.net 0.7x, tf.keras 0.7 | | | | | x | | | +| tf.net 0.4x, tf.keras 0.5 | | | | x | | | | +| tf.net 0.3x, tf.keras 0.4 | | | x | | | | | +| tf.net 0.2x | | x | x | | | | | +| tf.net 0.15 | x | x | | | | | | +| tf.net 0.14 | x | | | | | | | ``` @@ -207,6 +208,28 @@ tf.net 0.4x -> tf native 2.4 tf.net 0.6x -> tf native 2.6 tf.net 0.7x -> tf native 2.7 tf.net 0.10x -> tf native 2.10 +tf.net 0.150x -> tf native 2.15 +``` + +## Roadmap & SOT Objectives (TensorFlow 2.16 - 2.22+ Parity) + +Based on the official Python TensorFlow reference implementation (Source of Truth): + +1. **Native C-API & Runtime Upstream Synchronization**: + - Upgrade native redist bindings from TF 2.10/2.15 to TF 2.16+ / TF 2.22+ C-API binaries. + - Synchronize `CApi/c_api.cs` and `CApi/tf_status.cs` with upstream C-API changes. + +2. **Keras 3 Multi-Backend Parity**: + - Modernize `TensorFlowNET.Keras` abstractions toward Keras 3 stateless layer patterns and unified serialization. + +3. **Expanded DTypes and Quantization Support**: + - Add native C# support for 8-bit floats (`FLOAT8_E4M3FN`, `FLOAT8_E5M2`) and 4-bit quantized operations (`QUI4`). + - Broaden native `bfloat16` and `float16` kernel interoperability across all tensor mathematical ops. + +4. **Advanced Operations, Second-Order Gradients & `tf.data`**: + - Implement missing second-order gradients in `GradientTape` (e.g. `SoftsignGrad`, `AdjustContrastv2`). + - Align `TensorFlowNET.Core/NumPy` with updated `tf.experimental.numpy` behavior. + - Port modern `tf.data` pipeline features (`Dataset.scan`, dynamic multithreaded buffering). ... ``` From 80286f3bea85ee0e5479bba4f0004f8817f83239 Mon Sep 17 00:00:00 2001 From: samuelcaldas Date: Fri, 28 Aug 2026 17:44:08 -0300 Subject: [PATCH 4/7] docs: add engineering roadmap for next TensorFlow.NET release Co-Authored-By: Claude --- docs/plans/zippy-puzzling-knuth.md | 125 +++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 docs/plans/zippy-puzzling-knuth.md diff --git a/docs/plans/zippy-puzzling-knuth.md b/docs/plans/zippy-puzzling-knuth.md new file mode 100644 index 00000000..16d4d655 --- /dev/null +++ b/docs/plans/zippy-puzzling-knuth.md @@ -0,0 +1,125 @@ +# Comprehensive Roadmap: Next Version Release of TensorFlow.NET (TF 2.16 - 2.22+ Parity) + +## Context & Objectives +This document establishes the official engineering roadmap to release the next major generation of **TensorFlow.NET** (`TensorFlow.NET`, `TensorFlow.Keras`, and `SciSharp.TensorFlow.Redist`). + +The overarching goal is to achieve architectural, mathematical, and behavioral parity with modern Python TensorFlow (v2.16 LTS through v2.22+ located in `refs/py-tensorflow-sot`), transitioning to a modern **.NET 8.0 / .NET 9.0** high-performance runtime baseline while preserving backward compatibility for existing enterprise consumers. + +--- + +## Architectural Decisions & Foundations (Settled Design Tree) + +1. **Target SOT Baseline**: Staged rollout starting with **TensorFlow 2.16 LTS** (Milestone 1: Keras 3 engine + C-API modernization) progressing to **TensorFlow 2.22** (Milestone 2: Sub-byte FP8/Int4 quantization + latest TSL kernels). +2. **Runtime Framework**: Pure **.NET 8.0 / .NET 9.0** baseline. Drops `.NET Standard 2.0` and `.NET 6.0` legacy constraints to leverage `System.Runtime.Intrinsics` (AVX-512 / ARM Neon), zero-copy `Span` / `Memory`, and native `Half` / `Int128`. +3. **Keras Modernization**: Complete clean-room rewrite of **Keras 3** as primary (`Tensorflow.Keras.*`), featuring pure symbolic `KerasTensor` DAGs, stateless layers, and universal `.keras` zip archive serialization. Legacy Keras 2.x code is segregated into `Tensorflow.Keras.Legacy` with `[Obsolete]` migration guides for seamless retro-compatibility. +4. **Gradient Parity**: Programmatic generation of all ~382 op gradients via a dedicated C# Roslyn CLI tool (`tools/TensorFlow.GradientGen`) parsing Python SOT AST. +5. **Memory & Buffer Lifecycle**: Zero-copy unmanaged memory managers (`UnmanagedMemoryManager`), strict `SafeHandle` wrapping for native pointers, and SIMD hardware acceleration. +6. **Testing & Parity Verification**: Hybrid verification strategy using static golden fixtures (`.npy`/`.json`) for 100% headless CI runs and a live Python SOT dual-runner tool for active development. + +--- + +## Phased Implementation Roadmap + +### Phase 1: Runtime Baseline & Foundational C-API / DTypes + +#### 1.1 Project & Solution Modernization (.NET 8.0 / 9.0) +- Update `Directory.Build.props`, `TensorFlow.NET.sln`, and all `.csproj` files: + - Target `net8.0;net9.0`. + - Enable `true` and `enable`. +- Refactor `tools/Tensorflow.UnitTest.RedistHolder` and `src/SciSharp.TensorFlow.Redist/` to download and package prebuilt TensorFlow 2.16+ / 2.22 C-API runtime binaries (`tensorflow.dll`, `libtensorflow.so`, `libtensorflow.dylib` for x64 and ARM64). + +#### 1.2 Native C-API Bindings & Status Payloads +- **Status Interop (`src/TensorFlowNET.Core/Status/c_api.status.cs`)**: + - Implement P/Invoke for `TF_SetPayload`, `TF_GetPayload`, `TF_ErasePayload`, `TF_ForEachPayload`, and `TF_SetStatusFromIOError`. + - Enhance `Status.cs` to surface rich upstream error payloads and stack traces. +- **Memory & Tensor Allocators (`src/TensorFlowNET.Core/Tensors/c_api.tensor.cs`)**: + - Implement `TF_TensorBitcastFrom`, `TF_TensorIsAligned`, `TF_TensorDefaultAlignment`, and `TF_TensorElementCount`. + - Implement zero-copy `UnmanagedMemoryManager` wrapping native `TF_TensorData` pointers into `Memory` and `Span`. + - Align string tensor handling with TensorFlow 2.x `TF_TString` small-string optimization (SSO). + +#### 1.3 DType Modernization & Bug Fixes +- **Fix `bfloat16` and `float16` Mapping Bug**: + - In `src/TensorFlowNET.Core/Tensors/dtypes.cs`, ensure `"float16"` maps to `TF_DataType.TF_HALF` and `"bfloat16"` maps to `TF_DataType.TF_BFLOAT16`. +- **FP8 & Sub-Byte Quantized Types**: + - Extend `src/TensorFlowNET.Core/Tensors/TF_DataType.cs` and `dtypes.cs`: + - FP8: `TF_FLOAT8_E5M2` (19), `TF_FLOAT8_E4M3FN` (20), `TF_FLOAT8_E4M3B11FNUZ` (23), `TF_FLOAT8_E4M3FNUZ` (24), `TF_FLOAT8_E5M2FNUZ` (25). + - Sub-Byte: `TF_INT4` (21), `TF_UINT4` (22), `TF_INT2` (31), `TF_UINT2` (32), `TF_FLOAT4_E2M1FN` (33). + - Implement native type mappings, bitcast unpacking helpers, and string aliases. + +--- + +### Phase 2: Op Gradients Programmatic Generator & NumPy Parity + +#### 2.1 Programmatic Gradient Generation Tool (`tools/TensorFlow.GradientGen`) +- Develop standalone CLI tool `tools/TensorFlow.GradientGen` to: + - Parse Python AST and gradient registration decorators (`@ops.RegisterGradient`) across all files in `refs/py-tensorflow-sot/tensorflow/python/ops/*_grad.py`. + - Emit idiomatic C# partial classes in `src/TensorFlowNET.Core/Gradients/Generated/` implementing `[RegisterGradient("OpName")]`. + - Expand registration from current 92 ops to full SOT parity (~382 ops) across math, nn, image, linalg, sparse, and tensor arrays. +- **Second-Order Gradients**: + - Implement nested gradient formulations for `SoftsignGrad`, `ReluGrad`, `TanhGrad`, `SoftplusGrad`, `SigmoidGrad`, `SqrtGrad`, and `FusedBatchNormGrad`. + +#### 2.2 NumPy Operators & Multi-Axis Slicing Parity +- **Numerical Parity (`np.isclose` & `np.allclose`)**: + - Implement complete tolerance math in `src/TensorFlowNET.Core/NumPy/Numpy.cs` and `NumPy.Logical.cs`: + $$\text{diff} \le \text{atol} + \text{rtol} \times |b|$$ + - Implement integer overflow prevention (`maximum(a, b) - minimum(a, b)`) and `equal_nan` handling. +- **Dynamic Multidimensional Slicing (`src/TensorFlowNET.Core/Tensors/Tensor.Indexing.cs`)**: + - Add full support for Ellipsis (`...`), `NewAxis` / `None`, negative step strides, and dynamic tensor-valued slice indices using the native `StridedSlice` kernel. + +--- + +### Phase 3: Clean-Room Keras 3 Engine & Modern Serialization + +#### 3.1 Symbolic Tracing DAG (`KerasTensor`) +- Decouple Keras functional construction from active native C-API `tf.Graph` instances. +- Introduce `KerasTensor` representing symbolic shapes, dtypes, and inbound/outbound node connections. +- Implement topological sort in `src/TensorFlowNET.Keras/Engine/Functional.cs` to resolve `Functional` execution graphs purely from `KerasTensor` outputs. +- Move legacy graph-coupled Keras 2 classes to `src/TensorFlowNET.Keras/Legacy/` (`Tensorflow.Keras.Legacy` namespace) and tag with `[Obsolete]` migration attributes. + +#### 3.2 Universal `.keras` Zip Archive Serialization +- Implement native `.keras` zip archive reading and writing in `src/TensorFlowNET.Keras/Saving/`: + - `config.json`: Model topology and layer hyperparameters. + - `metadata.json`: Keras version, build timestamp, framework signatures. + - `model.weights.h5` / `variables.safetensors`: Serialized weight arrays. +- Align `get_config()` and `from_config()` serialization schemas across all layers, optimizers, losses, and metrics with Python Keras 3. +- Maintain legacy loaders for SavedModel (`saved_model.pb`) and `.h5`. + +#### 3.3 Modular Step Execution Loop +- Refactor `Model` execution pipeline into modular, overridable step methods: + - `train_step(data)` + - `test_step(data)` + - `predict_step(data)` +- Refactor `LossesContainer` and `MetricsContainer` for consistent reduction, masking, and sample weight support. + +--- + +### Phase 4: Verification, Parity Test Harness & Release Pipeline + +#### 4.1 Hybrid Parity Test Harness +- **Static Golden Fixtures (`test/TensorFlowNET.UnitTest/Parity/`)**: + - Generate golden test vectors (`.npy`/`.json`) from Python SOT for all newly generated op gradients, NumPy operators, and Keras 3 layers. + - Ensure fast, deterministic, 100% headless CI test execution. +- **Live Dual-Runner Tool (`tools/TensorFlow.ParityRunner`)**: + - CLI tool running side-by-side execution in C# and Python (via local `.venv`), asserting identical outputs within numerical tolerances for new ops. + +#### 4.2 Release Packaging & Publishing +- Bump version to `v0.200.0` (or `v1.0.0`) in `Directory.Build.props`. +- Update GitHub Actions CI/CD workflows (`.github/workflows/build_and_test.yml`, `release.yml`): + - Add multi-platform matrix builds (Windows, Linux, macOS ARM64/x64). + - Package and publish nightly builds to MyGet and stable packages to NuGet (`TensorFlow.NET`, `TensorFlow.Keras`, `SciSharp.TensorFlow.Redist`). + +--- + +### Key File Locations for Changes + +| Subsystem | Target Files | +| :--- | :--- | +| **Project & Build** | `Directory.Build.props`, `TensorFlow.NET.sln`, `.github/workflows/build_and_test.yml` | +| **C-API & Status** | `src/TensorFlowNET.Core/Status/c_api.status.cs`, `Status.cs`, `c_api.tensor.cs` | +| **DTypes & Memory** | `src/TensorFlowNET.Core/Tensors/dtypes.cs`, `TF_DataType.cs`, `Tensor.cs` | +| **Gradient Generator** | `tools/TensorFlow.GradientGen/`, `src/TensorFlowNET.Core/Gradients/Generated/` | +| **NumPy & Slicing** | `src/TensorFlowNET.Core/NumPy/Numpy.cs`, `NumPy.Logical.cs`, `Tensor.Indexing.cs` | +| **Keras 3 Engine** | `src/TensorFlowNET.Keras/Engine/KerasTensor.cs`, `Functional.cs`, `Layer.cs`, `Model.cs` | +| **Keras Legacy** | `src/TensorFlowNET.Keras/Legacy/` | +| **Serialization** | `src/TensorFlowNET.Keras/Saving/KerasZipSaver.cs`, `Saving/KerasZipLoader.cs` | +| **Test Harness** | `tools/TensorFlow.ParityRunner/`, `test/TensorFlowNET.UnitTest/Parity/` | From 831177793e98a1b87dfaf1881f19bf31d625cbba Mon Sep 17 00:00:00 2001 From: samuelcaldas Date: Fri, 28 Aug 2026 18:04:10 -0300 Subject: [PATCH 5/7] feat(core): implement Phase 1 runtime baseline (.NET 8/9, C-API payloads, DTypes) - Upgrade TargetFrameworks to net8.0;net9.0 across core and test projects - Add P/Invoke bindings for TF_SetPayload, TF_ForEachPayload, TF_SetStatusFromIOError - Add P/Invoke bindings for TF_TensorBitcastFrom, TF_TensorIsAligned, TF_TensorDefaultAlignment, TF_TensorElementCount - Add FP8 and Sub-Byte DTypes to TF_DataType aligned with TF 2.22 SOT - Fix float16 / bfloat16 mapping bug in dtypes.cs - Resolve C# 13 operator ambiguity in GradientTest and GradientEagerTest Co-Authored-By: Claude --- Directory.Build.props | 2 + src/TensorFlowNET.Core/Status/Status.cs | 32 ++++++++ src/TensorFlowNET.Core/Status/c_api.status.cs | 33 ++++++++ .../Tensorflow.Binding.csproj | 65 +++++++++++++++- src/TensorFlowNET.Core/Tensors/TF_DataType.cs | 10 +++ .../Tensors/c_api.tensor.cs | 38 ++++++++++ src/TensorFlowNET.Core/Tensors/dtypes.cs | 61 ++++++++++++++- .../Tensorflow.Keras.csproj | 76 +++++++++++++++++-- .../Tensorflow.Recommenders.csproj | 2 +- src/TensorFlowNET.Text/Tensorflow.Text.csproj | 2 +- src/TensorflowNET.Hub/Tensorflow.Hub.csproj | 3 +- .../TensorFlow.Kernel.UnitTest.csproj | 2 +- .../TensorFlowNET.Graph.UnitTest.csproj | 2 +- .../Tensorflow.Keras.UnitTest.csproj | 2 +- .../Tensorflow.Native.UnitTest.csproj | 2 +- .../GradientTest/GradientEagerTest.cs | 2 +- .../ManagedAPI/GradientTest.cs | 2 +- .../Tensorflow.Binding.UnitTest.csproj | 2 +- .../Tensorflow.UnitTest.csproj | 2 +- .../Tensorflow.Hub.Unittest.csproj | 2 +- .../Tensorflow.Benchmark.csproj | 2 +- .../Tensorflow.Console.csproj | 2 +- .../Tensorflow.CodeGen.csproj | 2 +- ...orflow.Redist.NativeLibrarySplitter.csproj | 2 +- 24 files changed, 322 insertions(+), 28 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 065690ec..92e0544e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -12,6 +12,8 @@ --> true $(NoWarn),1573,1591,1712 + true + 13.0 diff --git a/src/TensorFlowNET.Core/Status/Status.cs b/src/TensorFlowNET.Core/Status/Status.cs index 12b6fba2..501cd327 100644 --- a/src/TensorFlowNET.Core/Status/Status.cs +++ b/src/TensorFlowNET.Core/Status/Status.cs @@ -65,6 +65,38 @@ public void SetStatus(TF_Code code, string msg) TF_SetStatus(_handle, code, msg); } + /// + /// Attaches a key/value payload to this status. No-op when status is OK. + /// Overwrites any existing payload for the same key. + /// + /// payload key + /// payload value + public void SetPayload(string key, string value) + { + TF_SetPayload(_handle, key, value); + } + + /// + /// Iterates over all stored payloads, invoking visitor(key, value, capture) for each. + /// key and value IntPtrs are only valid during the callback. + /// + /// callback invoked per payload entry + /// passed to visitor unmodified + public void ForEachPayload(c_api.TF_PayloadVisitor visitor, IntPtr capture) + { + TF_ForEachPayload(_handle, visitor, capture); + } + + /// + /// Sets status from an I/O error code (e.g., errno). Clears previous info. + /// + /// errno-style error code + /// operation context description + public void SetFromIOError(int errorCode, string context) + { + TF_SetStatusFromIOError(_handle, errorCode, context); + } + public bool ok() => Code == TF_Code.TF_OK; /// diff --git a/src/TensorFlowNET.Core/Status/c_api.status.cs b/src/TensorFlowNET.Core/Status/c_api.status.cs index 7854481d..631d3ddc 100644 --- a/src/TensorFlowNET.Core/Status/c_api.status.cs +++ b/src/TensorFlowNET.Core/Status/c_api.status.cs @@ -62,5 +62,38 @@ public partial class c_api /// [DllImport(TensorFlowLibName)] public static extern void TF_SetStatus(SafeStatusHandle s, TF_Code code, string msg); + + /// + /// Record <key, value> as a payload in *s. Overwrites previous payload with same key. + /// No-op when status is TF_OK. + /// + /// TF_Status* + /// null-terminated key string + /// null-terminated value string + [DllImport(TensorFlowLibName)] + public static extern void TF_SetPayload(SafeStatusHandle s, string key, string value); + + /// + /// Iterates over stored payloads and calls visitor(key, value, capture) for each one. + /// key and value are only valid during the callback. + /// + /// const TF_Status* + /// callback invoked per payload entry + /// passed to visitor unmodified + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void TF_PayloadVisitor(IntPtr key, IntPtr value, IntPtr capture); + + [DllImport(TensorFlowLibName)] + public static extern void TF_ForEachPayload(SafeStatusHandle s, TF_PayloadVisitor visitor, IntPtr capture); + + /// + /// Converts from an I/O error code (e.g., errno) to a TF_Status value. + /// Any previous information is lost. Prefer over TF_SetStatus for I/O errors. + /// + /// TF_Status* + /// errno-style error code + /// null-terminated context string + [DllImport(TensorFlowLibName)] + public static extern void TF_SetStatusFromIOError(SafeStatusHandle s, int error_code, string context); } } diff --git a/src/TensorFlowNET.Core/Tensorflow.Binding.csproj b/src/TensorFlowNET.Core/Tensorflow.Binding.csproj index 42c0399d..ce3d9468 100644 --- a/src/TensorFlowNET.Core/Tensorflow.Binding.csproj +++ b/src/TensorFlowNET.Core/Tensorflow.Binding.csproj @@ -1,12 +1,11 @@  - netstandard2.0;net6.0 + netstandard2.0;net8.0;net9.0 Tensorflow.Binding Tensorflow 2.15.0 0.150.0 - 10.0 enable Haiping Chen, Eli Belash, Yaohui Liu, Meinrad Recheis SciSharp STACK @@ -153,6 +152,68 @@ https://tensorflownet.readthedocs.io $(NoWarn),1570,1573,1591,1712,8603,8604,8625,CS0612 + + + 1 + $(NoWarn),1570,1573,1591,1712,8603,8604,8625,CS0612 + + + + 1 + $(NoWarn),1570,1573,1591,1712,8603,8604,8625,CS0612 + + + + 1 + $(NoWarn),1570,1573,1591,1712,8603,8604,8625,CS0612 + + + + 1 + $(NoWarn),1570,1573,1591,1712,8603,8604,8625,CS0612 + + + + 1 + $(NoWarn),1570,1573,1591,1712,8603,8604,8625,CS0612 + + + + 1 + $(NoWarn),1570,1573,1591,1712,8603,8604,8625,CS0612 + + + + + 1 + $(NoWarn),1570,1573,1591,1712,8603,8604,8625,CS0612 + + + + 1 + $(NoWarn),1570,1573,1591,1712,8603,8604,8625,CS0612 + + + + 1 + $(NoWarn),1570,1573,1591,1712,8603,8604,8625,CS0612 + + + + 1 + $(NoWarn),1570,1573,1591,1712,8603,8604,8625,CS0612 + + + + 1 + $(NoWarn),1570,1573,1591,1712,8603,8604,8625,CS0612 + + + + 1 + $(NoWarn),1570,1573,1591,1712,8603,8604,8625,CS0612 + + diff --git a/src/TensorFlowNET.Core/Tensors/TF_DataType.cs b/src/TensorFlowNET.Core/Tensors/TF_DataType.cs index 2a6f7114..6a6ed1c5 100644 --- a/src/TensorFlowNET.Core/Tensors/TF_DataType.cs +++ b/src/TensorFlowNET.Core/Tensors/TF_DataType.cs @@ -35,6 +35,16 @@ public enum TF_DataType TF_VARIANT = 21, TF_UINT32 = 22, TF_UINT64 = 23, + TF_FLOAT8_E5M2 = 24, // 5 exponent bits, 2 mantissa bits + TF_FLOAT8_E4M3FN = 25, // 4 exponent bits, 3 mantissa bits, finite-only, 2 NaNs + TF_FLOAT8_E4M3FNUZ = 26, // 4 exponent bits, 3 mantissa bits, finite-only, with NaN + TF_FLOAT8_E4M3B11FNUZ = 27, // 4 exponent bits, 3 mantissa bits, 11-bit bias, finite-only, NaNs + TF_FLOAT8_E5M2FNUZ = 28, // 5 exponent bits, 2 mantissa bits, finite-only, with NaN + TF_INT4 = 29, + TF_UINT4 = 30, + TF_INT2 = 31, + TF_UINT2 = 32, + TF_FLOAT4_E2M1FN = 33, // 2 exponent bits, 1 mantissa bit, finite-only DtFloatRef = 101, // DT_FLOAT_REF DtDoubleRef = 102, // DT_DOUBLE_REF diff --git a/src/TensorFlowNET.Core/Tensors/c_api.tensor.cs b/src/TensorFlowNET.Core/Tensors/c_api.tensor.cs index 3779ddcf..c97920d0 100644 --- a/src/TensorFlowNET.Core/Tensors/c_api.tensor.cs +++ b/src/TensorFlowNET.Core/Tensors/c_api.tensor.cs @@ -156,6 +156,44 @@ public static unsafe SafeTensorHandle TF_NewTensor(T value) [DllImport(TensorFlowLibName)] public static extern void TF_SetShape(SafeTensorHandle tensor, long[] dims, int num_dims); + /// + /// Returns the alignment in bytes required for allocating aligned tensors. + /// Use with TF_NewTensor to satisfy TensorFlow memory alignment preferences. + /// + [DllImport(TensorFlowLibName)] + public static extern ulong TF_TensorDefaultAlignment(); + + /// + /// Returns the number of elements in the tensor. + /// + /// const TF_Tensor* + /// element count + [DllImport(TensorFlowLibName)] + public static extern long TF_TensorElementCount(SafeTensorHandle tensor); + + /// + /// Copies the internal data representation of into + /// with a new shape and type. Both tensors must occupy the same number of bytes. + /// Sets *status to TF_INVALID_ARGUMENT on incompatible size or zero-size dtypes. + /// + /// source tensor (const TF_Tensor*) + /// new TF_DataType for the destination tensor + /// destination tensor (TF_Tensor*) + /// new shape dims array (const int64_t*) + /// number of dimensions + /// TF_Status* set to TF_OK on success + [DllImport(TensorFlowLibName)] + public static extern void TF_TensorBitcastFrom(SafeTensorHandle from, TF_DataType type, SafeTensorHandle to, long[] new_dims, int num_new_dims, SafeStatusHandle status); + + /// + /// Returns true iff the tensor buffer satisfies TensorFlow's alignment requirements. + /// + /// const TF_Tensor* + /// non-zero when aligned + [DllImport(TensorFlowLibName)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool TF_TensorIsAligned(SafeTensorHandle tensor); + /// /// Return the size in bytes required to encode a string `len` bytes long into a /// TF_STRING tensor. diff --git a/src/TensorFlowNET.Core/Tensors/dtypes.cs b/src/TensorFlowNET.Core/Tensors/dtypes.cs index 5b4db53b..b1db0927 100644 --- a/src/TensorFlowNET.Core/Tensors/dtypes.cs +++ b/src/TensorFlowNET.Core/Tensors/dtypes.cs @@ -32,12 +32,25 @@ public static class dtypes public static TF_DataType uint64 = TF_DataType.TF_UINT64; public static TF_DataType float32 = TF_DataType.TF_FLOAT; // is that float32? public static TF_DataType float16 = TF_DataType.TF_HALF; + public static TF_DataType bfloat16 = TF_DataType.TF_BFLOAT16; public static TF_DataType float64 = TF_DataType.TF_DOUBLE; public static TF_DataType complex = TF_DataType.TF_COMPLEX; public static TF_DataType complex64 = TF_DataType.TF_COMPLEX64; public static TF_DataType complex128 = TF_DataType.TF_COMPLEX128; public static TF_DataType variant = TF_DataType.TF_VARIANT; public static TF_DataType resource = TF_DataType.TF_RESOURCE; + public static TF_DataType int16 = TF_DataType.TF_INT16; + public static TF_DataType uint16 = TF_DataType.TF_UINT16; + public static TF_DataType float8_e5m2 = TF_DataType.TF_FLOAT8_E5M2; + public static TF_DataType float8_e4m3fn = TF_DataType.TF_FLOAT8_E4M3FN; + public static TF_DataType float8_e4m3fnuz = TF_DataType.TF_FLOAT8_E4M3FNUZ; + public static TF_DataType float8_e4m3b11fnuz = TF_DataType.TF_FLOAT8_E4M3B11FNUZ; + public static TF_DataType float8_e5m2fnuz = TF_DataType.TF_FLOAT8_E5M2FNUZ; + public static TF_DataType int4 = TF_DataType.TF_INT4; + public static TF_DataType uint4 = TF_DataType.TF_UINT4; + public static TF_DataType int2 = TF_DataType.TF_INT2; + public static TF_DataType uint2 = TF_DataType.TF_UINT2; + public static TF_DataType float4_e2m1fn = TF_DataType.TF_FLOAT4_E2M1FN; /// /// @@ -159,13 +172,25 @@ public static TF_DataType tf_dtype_from_name(string name) "uint32" => TF_DataType.TF_UINT32, "int64" => TF_DataType.TF_INT64, "uint64" => TF_DataType.TF_UINT64, - "float16" => TF_DataType.TF_BFLOAT16, + "float16" => TF_DataType.TF_HALF, + "half" => TF_DataType.TF_HALF, + "bfloat16" => TF_DataType.TF_BFLOAT16, "float32" => TF_DataType.TF_FLOAT, "single" => TF_DataType.TF_FLOAT, "float64" => TF_DataType.TF_DOUBLE, "double" => TF_DataType.TF_DOUBLE, "complex" => TF_DataType.TF_COMPLEX128, "string" => TF_DataType.TF_STRING, + "float8_e5m2" => TF_DataType.TF_FLOAT8_E5M2, + "float8_e4m3fn" => TF_DataType.TF_FLOAT8_E4M3FN, + "float8_e4m3fnuz" => TF_DataType.TF_FLOAT8_E4M3FNUZ, + "float8_e4m3b11fnuz" => TF_DataType.TF_FLOAT8_E4M3B11FNUZ, + "float8_e5m2fnuz" => TF_DataType.TF_FLOAT8_E5M2FNUZ, + "int4" => TF_DataType.TF_INT4, + "uint4" => TF_DataType.TF_UINT4, + "int2" => TF_DataType.TF_INT2, + "uint2" => TF_DataType.TF_UINT2, + "float4_e2m1fn" => TF_DataType.TF_FLOAT4_E2M1FN, _ => TF_DataType.DtInvalid }; @@ -226,18 +251,35 @@ public static string as_python_name(this TF_DataType type) public static int get_datatype_size(this TF_DataType type) => type.as_base_dtype() switch { + TF_DataType.TF_STRING => 8, TF_DataType.TF_BOOL => sizeof(bool), TF_DataType.TF_UINT8 => sizeof(byte), TF_DataType.TF_INT8 => sizeof(sbyte), TF_DataType.TF_UINT16 => sizeof(ushort), TF_DataType.TF_INT16 => sizeof(short), + TF_DataType.TF_BFLOAT16 => 2, + TF_DataType.TF_HALF => 2, TF_DataType.TF_UINT32 => sizeof(uint), TF_DataType.TF_INT32 => sizeof(int), TF_DataType.TF_UINT64 => sizeof(ulong), TF_DataType.TF_INT64 => sizeof(long), TF_DataType.TF_FLOAT => sizeof(float), TF_DataType.TF_DOUBLE => sizeof(double), - _ => throw new NotImplementedException("") + // 8-bit floats: 1 byte each + TF_DataType.TF_FLOAT8_E5M2 => 1, + TF_DataType.TF_FLOAT8_E4M3FN => 1, + TF_DataType.TF_FLOAT8_E4M3FNUZ => 1, + TF_DataType.TF_FLOAT8_E4M3B11FNUZ => 1, + TF_DataType.TF_FLOAT8_E5M2FNUZ => 1, + // sub-byte types: C-API reports 1 byte (storage unit) + // ponytail: true sub-byte packing (TF_INT4=4-bit) needs C-API TF_DataTypeSize; + // use 1 here as safe .NET allocation unit until redist ≥ TF 2.16 + TF_DataType.TF_INT4 => 1, + TF_DataType.TF_UINT4 => 1, + TF_DataType.TF_INT2 => 1, + TF_DataType.TF_UINT2 => 1, + TF_DataType.TF_FLOAT4_E2M1FN => 1, + _ => throw new NotImplementedException($"get_datatype_size not implemented for {type}") }; public static Type as_numpy_dtype(this DataType type) @@ -314,7 +356,16 @@ public static bool is_bool(this TF_DataType type) public static bool is_floating(this TF_DataType type) { - return type == TF_DataType.TF_HALF || type == TF_DataType.TF_FLOAT || type == TF_DataType.TF_DOUBLE; + return type == TF_DataType.TF_HALF + || type == TF_DataType.TF_FLOAT + || type == TF_DataType.TF_DOUBLE + || type == TF_DataType.TF_BFLOAT16 + || type == TF_DataType.TF_FLOAT8_E5M2 + || type == TF_DataType.TF_FLOAT8_E4M3FN + || type == TF_DataType.TF_FLOAT8_E4M3FNUZ + || type == TF_DataType.TF_FLOAT8_E4M3B11FNUZ + || type == TF_DataType.TF_FLOAT8_E5M2FNUZ + || type == TF_DataType.TF_FLOAT4_E2M1FN; } public static bool is_ref_dtype(this TF_DataType type) @@ -340,7 +391,9 @@ public static TF_DataType real_dtype(this TF_DataType self) public static bool is_value_dtype(this TF_DataType type) { - return ((int)type >= 1 && (int)type <= 19) + // covers TF_FLOAT(1)..TF_FLOAT4_E2M1FN(33) and the out-of-sequence UINT32/UINT64 + int v = (int)type; + return (v >= 1 && v <= 33) || type == TF_DataType.TF_UINT32 || type == TF_DataType.TF_UINT64; } diff --git a/src/TensorFlowNET.Keras/Tensorflow.Keras.csproj b/src/TensorFlowNET.Keras/Tensorflow.Keras.csproj index eb8ebf93..16d1d7bd 100644 --- a/src/TensorFlowNET.Keras/Tensorflow.Keras.csproj +++ b/src/TensorFlowNET.Keras/Tensorflow.Keras.csproj @@ -1,9 +1,8 @@  - netstandard2.0;net6.0 + netstandard2.0;net8.0;net9.0 Tensorflow.Keras - 10.0 enable Tensorflow.Keras AnyCPU;x64 @@ -51,16 +50,13 @@ Keras is an API designed for human beings, not machines. Keras follows best prac DEBUG;TRACE - false DEBUG;TRACE - false - false @@ -143,6 +139,76 @@ Keras is an API designed for human beings, not machines. Keras follows best prac $(NoWarn),1573,1591,1712,8602,8603,8625,CS0612 + + + True + 1 + $(NoWarn),1573,1591,1712,8602,8603,8625,CS0612 + + + + True + 1 + $(NoWarn),1573,1591,1712,8602,8603,8625,CS0612 + + + + False + 1 + $(NoWarn),1573,1591,1712,8602,8603,8625,CS0612 + + + + False + 1 + $(NoWarn),1573,1591,1712,8602,8603,8625,CS0612 + + + + 1 + $(NoWarn),1573,1591,1712,8602,8603,8625,CS0612 + + + + 1 + $(NoWarn),1573,1591,1712,8602,8603,8625,CS0612 + + + + + True + 1 + $(NoWarn),1573,1591,1712,8602,8603,8625,CS0612 + + + + True + 1 + $(NoWarn),1573,1591,1712,8602,8603,8625,CS0612 + + + + False + 1 + $(NoWarn),1573,1591,1712,8602,8603,8625,CS0612 + + + + False + 1 + $(NoWarn),1573,1591,1712,8602,8603,8625,CS0612 + + + + 1 + $(NoWarn),1573,1591,1712,8602,8603,8625,CS0612 + + + + 1 + $(NoWarn),1573,1591,1712,8602,8603,8625,CS0612 + + diff --git a/src/TensorFlowNET.Recommenders/Tensorflow.Recommenders.csproj b/src/TensorFlowNET.Recommenders/Tensorflow.Recommenders.csproj index e3374f95..269a5af3 100644 --- a/src/TensorFlowNET.Recommenders/Tensorflow.Recommenders.csproj +++ b/src/TensorFlowNET.Recommenders/Tensorflow.Recommenders.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.0;net8.0;net9.0 0.0.1 TensorFlow Recommenders is a library for building recommender system models using TensorFlow. LICENSE diff --git a/src/TensorFlowNET.Text/Tensorflow.Text.csproj b/src/TensorFlowNET.Text/Tensorflow.Text.csproj index f27f680e..77ca84b1 100644 --- a/src/TensorFlowNET.Text/Tensorflow.Text.csproj +++ b/src/TensorFlowNET.Text/Tensorflow.Text.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.0;net8.0;net9.0 Tensorflow.Text Tensorflow.Text true diff --git a/src/TensorflowNET.Hub/Tensorflow.Hub.csproj b/src/TensorflowNET.Hub/Tensorflow.Hub.csproj index efa37598..9d9fa631 100644 --- a/src/TensorflowNET.Hub/Tensorflow.Hub.csproj +++ b/src/TensorflowNET.Hub/Tensorflow.Hub.csproj @@ -1,8 +1,7 @@  - netstandard2.0;net6 - 10 + netstandard2.0;net8.0;net9.0 enable 1.0.0 TensorFlow.Hub diff --git a/test/TensorFlow.Kernel.UnitTest/TensorFlow.Kernel.UnitTest.csproj b/test/TensorFlow.Kernel.UnitTest/TensorFlow.Kernel.UnitTest.csproj index 46199340..db68a2bf 100644 --- a/test/TensorFlow.Kernel.UnitTest/TensorFlow.Kernel.UnitTest.csproj +++ b/test/TensorFlow.Kernel.UnitTest/TensorFlow.Kernel.UnitTest.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 enable enable diff --git a/test/TensorFlowNET.Graph.UnitTest/TensorFlowNET.Graph.UnitTest.csproj b/test/TensorFlowNET.Graph.UnitTest/TensorFlowNET.Graph.UnitTest.csproj index 40dd53f7..2d3d4192 100644 --- a/test/TensorFlowNET.Graph.UnitTest/TensorFlowNET.Graph.UnitTest.csproj +++ b/test/TensorFlowNET.Graph.UnitTest/TensorFlowNET.Graph.UnitTest.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 9.0 false TensorFlowNET.UnitTest diff --git a/test/TensorFlowNET.Keras.UnitTest/Tensorflow.Keras.UnitTest.csproj b/test/TensorFlowNET.Keras.UnitTest/Tensorflow.Keras.UnitTest.csproj index edac1c2f..a9ea6650 100644 --- a/test/TensorFlowNET.Keras.UnitTest/Tensorflow.Keras.UnitTest.csproj +++ b/test/TensorFlowNET.Keras.UnitTest/Tensorflow.Keras.UnitTest.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 false AnyCPU;x64 diff --git a/test/TensorFlowNET.Native.UnitTest/Tensorflow.Native.UnitTest.csproj b/test/TensorFlowNET.Native.UnitTest/Tensorflow.Native.UnitTest.csproj index c054a870..7d01d09d 100644 --- a/test/TensorFlowNET.Native.UnitTest/Tensorflow.Native.UnitTest.csproj +++ b/test/TensorFlowNET.Native.UnitTest/Tensorflow.Native.UnitTest.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 false diff --git a/test/TensorFlowNET.UnitTest/GradientTest/GradientEagerTest.cs b/test/TensorFlowNET.UnitTest/GradientTest/GradientEagerTest.cs index 1cfceb3e..208ce984 100644 --- a/test/TensorFlowNET.UnitTest/GradientTest/GradientEagerTest.cs +++ b/test/TensorFlowNET.UnitTest/GradientTest/GradientEagerTest.cs @@ -108,7 +108,7 @@ public void HighGradient() var x = tf.Variable(1.0f); using var tape1 = tf.GradientTape(); using var tape2 = tf.GradientTape(); - var y = x * x * x; + var y = (Tensor)x * (Tensor)x * (Tensor)x; var dy_dx = tape2.gradient(y, x); Assert.AreEqual((float)dy_dx, 3.0f); var d2y_d2x = tape1.gradient(dy_dx, x); diff --git a/test/TensorFlowNET.UnitTest/ManagedAPI/GradientTest.cs b/test/TensorFlowNET.UnitTest/ManagedAPI/GradientTest.cs index 902bcdbf..448fb657 100644 --- a/test/TensorFlowNET.UnitTest/ManagedAPI/GradientTest.cs +++ b/test/TensorFlowNET.UnitTest/ManagedAPI/GradientTest.cs @@ -44,7 +44,7 @@ public void GradientOperatorMulTest() var x = tf.constant(0f); var w = tf.Variable(new float[] { 1, 1 }); using var gt = tf.GradientTape(); - var y = x * w; + var y = x * (Tensor)w; var gr = gt.gradient(y, w); Assert.AreEqual(new float[] { 0, 0 }, gr.numpy()); } diff --git a/test/TensorFlowNET.UnitTest/Tensorflow.Binding.UnitTest.csproj b/test/TensorFlowNET.UnitTest/Tensorflow.Binding.UnitTest.csproj index 5264cb10..9d6a00cb 100644 --- a/test/TensorFlowNET.UnitTest/Tensorflow.Binding.UnitTest.csproj +++ b/test/TensorFlowNET.UnitTest/Tensorflow.Binding.UnitTest.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 false false false diff --git a/test/Tensorflow.UnitTest/Tensorflow.UnitTest.csproj b/test/Tensorflow.UnitTest/Tensorflow.UnitTest.csproj index 9ad6bc7a..f5cd3217 100644 --- a/test/Tensorflow.UnitTest/Tensorflow.UnitTest.csproj +++ b/test/Tensorflow.UnitTest/Tensorflow.UnitTest.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 enable enable diff --git a/test/TensorflowNET.Hub.Unittest/Tensorflow.Hub.Unittest.csproj b/test/TensorflowNET.Hub.Unittest/Tensorflow.Hub.Unittest.csproj index c93b8925..d242b92e 100644 --- a/test/TensorflowNET.Hub.Unittest/Tensorflow.Hub.Unittest.csproj +++ b/test/TensorflowNET.Hub.Unittest/Tensorflow.Hub.Unittest.csproj @@ -1,7 +1,7 @@  - net6 + net8.0 enable enable diff --git a/tools/TensorFlowNET.Benchmarks/Tensorflow.Benchmark.csproj b/tools/TensorFlowNET.Benchmarks/Tensorflow.Benchmark.csproj index dd6f9538..e2e301b7 100644 --- a/tools/TensorFlowNET.Benchmarks/Tensorflow.Benchmark.csproj +++ b/tools/TensorFlowNET.Benchmarks/Tensorflow.Benchmark.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net8.0 AnyCPU;x64 diff --git a/tools/TensorFlowNET.Console/Tensorflow.Console.csproj b/tools/TensorFlowNET.Console/Tensorflow.Console.csproj index bb60b6b6..9e48fcee 100644 --- a/tools/TensorFlowNET.Console/Tensorflow.Console.csproj +++ b/tools/TensorFlowNET.Console/Tensorflow.Console.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net8.0 Tensorflow Tensorflow AnyCPU;x64 diff --git a/tools/Tensorflow.CodeGen/Tensorflow.CodeGen.csproj b/tools/Tensorflow.CodeGen/Tensorflow.CodeGen.csproj index 2afc68a3..22035a96 100644 --- a/tools/Tensorflow.CodeGen/Tensorflow.CodeGen.csproj +++ b/tools/Tensorflow.CodeGen/Tensorflow.CodeGen.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net8.0 enable enable diff --git a/tools/Tensorflow.Redist.NativeLibrarySplitter/Tensorflow.Redist.NativeLibrarySplitter.csproj b/tools/Tensorflow.Redist.NativeLibrarySplitter/Tensorflow.Redist.NativeLibrarySplitter.csproj index 74abf5c9..91b464af 100644 --- a/tools/Tensorflow.Redist.NativeLibrarySplitter/Tensorflow.Redist.NativeLibrarySplitter.csproj +++ b/tools/Tensorflow.Redist.NativeLibrarySplitter/Tensorflow.Redist.NativeLibrarySplitter.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net8.0 enable enable From c2efabddc282aca9cfdd0d7ffff97b7e766d5828 Mon Sep 17 00:00:00 2001 From: samuelcaldas Date: Fri, 28 Aug 2026 18:09:34 -0300 Subject: [PATCH 6/7] docs: extract full engineering roadmap to ROADMAP.md and link references Co-Authored-By: Claude --- CLAUDE.md | 17 +-------- README.md | 18 +--------- ROADMAP.md | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 33 deletions(-) create mode 100644 ROADMAP.md diff --git a/CLAUDE.md b/CLAUDE.md index f3a3149e..87a0678c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -110,21 +110,6 @@ src/ ## Roadmap & SOT Feature Gap Objectives -Targeting alignment with modern Python TensorFlow (TF 2.16 - 2.22+ in `refs/py-tensorflow-sot`): +The official engineering roadmap targeting modern Python TensorFlow (v2.16 LTS through v2.22+) parity and .NET 8/9 runtime modernization is maintained in **[ROADMAP.md](ROADMAP.md)**. -1. **Native C-API & Runtime Upstream Synchronization**: - - Upgrade native redist bindings from TF 2.10/2.15 to TF 2.16+ / TF 2.22+ C-API binaries. - - Synchronize `CApi/c_api.cs` and `CApi/tf_status.cs` with upstream C-API changes (e.g. filesystem interface transitions). - -2. **Keras 3 Multi-Backend Parity**: - - Modernize `TensorFlowNET.Keras` abstractions beyond Keras 2.x legacy tight graph coupling toward Keras 3 stateless layer patterns and unified serialization. - -3. **Expanded DTypes and Quantization Support**: - - Implement native C# support and memory conversions for 8-bit floats (`FLOAT8_E4M3FN`, `FLOAT8_E5M2`) and 4-bit quantized operations (`QUI4`). - - Broaden native `bfloat16` and `float16` kernel interoperability across all tensor mathematical ops. - -4. **Advanced Operations, Second-Order Gradients & `tf.data`**: - - Add missing second-order gradients in `GradientTape` (e.g. `SoftsignGrad`, `AdjustContrastv2`). - - Expand `TensorFlowNET.Core/NumPy` to match updated `tf.experimental.numpy` behavior (e.g. tolerance handling in `isclose`/`allclose`). - - Port newer `tf.data` pipeline features (`Dataset.scan`, dynamic multithreaded buffering). diff --git a/README.md b/README.md index 05254a04..6b129961 100644 --- a/README.md +++ b/README.md @@ -213,23 +213,7 @@ tf.net 0.150x -> tf native 2.15 ## Roadmap & SOT Objectives (TensorFlow 2.16 - 2.22+ Parity) -Based on the official Python TensorFlow reference implementation (Source of Truth): - -1. **Native C-API & Runtime Upstream Synchronization**: - - Upgrade native redist bindings from TF 2.10/2.15 to TF 2.16+ / TF 2.22+ C-API binaries. - - Synchronize `CApi/c_api.cs` and `CApi/tf_status.cs` with upstream C-API changes. - -2. **Keras 3 Multi-Backend Parity**: - - Modernize `TensorFlowNET.Keras` abstractions toward Keras 3 stateless layer patterns and unified serialization. - -3. **Expanded DTypes and Quantization Support**: - - Add native C# support for 8-bit floats (`FLOAT8_E4M3FN`, `FLOAT8_E5M2`) and 4-bit quantized operations (`QUI4`). - - Broaden native `bfloat16` and `float16` kernel interoperability across all tensor mathematical ops. - -4. **Advanced Operations, Second-Order Gradients & `tf.data`**: - - Implement missing second-order gradients in `GradientTape` (e.g. `SoftsignGrad`, `AdjustContrastv2`). - - Align `TensorFlowNET.Core/NumPy` with updated `tf.experimental.numpy` behavior. - - Port modern `tf.data` pipeline features (`Dataset.scan`, dynamic multithreaded buffering). +The official engineering roadmap targeting modern Python TensorFlow (v2.16 LTS through v2.22+) parity and .NET 8/9 runtime modernization is maintained in **[ROADMAP.md](ROADMAP.md)**. ... ``` diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 00000000..d9ea62c3 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,104 @@ +# Comprehensive Roadmap: Next Version Release of TensorFlow.NET (TF 2.16 - 2.22+ Parity) + +## Context & Objectives +This document establishes the official engineering roadmap to release the next major generation of **TensorFlow.NET** (`TensorFlow.NET`, `TensorFlow.Keras`, and `SciSharp.TensorFlow.Redist`). + +The overarching goal is to achieve architectural, mathematical, and behavioral parity with modern Python TensorFlow (v2.16 LTS through v2.22+ located in `refs/py-tensorflow-sot`), transitioning to a modern **.NET 8.0 / .NET 9.0** high-performance runtime baseline while preserving backward compatibility for existing enterprise consumers. + +--- + +## Architectural Decisions & Foundations (Settled Design Tree) + +1. **Target SOT Baseline**: Staged rollout starting with **TensorFlow 2.16 LTS** (Milestone 1: Keras 3 engine + C-API modernization) progressing to **TensorFlow 2.22** (Milestone 2: Sub-byte FP8/Int4 quantization + latest TSL kernels). +2. **Runtime Framework**: Pure **.NET 8.0 / .NET 9.0** baseline. Drops `.NET Standard 2.0` and `.NET 6.0` legacy constraints to leverage `System.Runtime.Intrinsics` (AVX-512 / ARM Neon), zero-copy `Span` / `Memory`, and native `Half` / `Int128`. +3. **Keras Modernization**: Complete clean-room rewrite of **Keras 3** as primary (`Tensorflow.Keras.*`), featuring pure symbolic `KerasTensor` DAGs, stateless layers, and universal `.keras` zip archive serialization. Legacy Keras 2.x code is segregated into `Tensorflow.Keras.Legacy` with `[Obsolete]` migration guides for seamless retro-compatibility. +4. **Gradient Parity**: Programmatic generation of all ~382 op gradients via a dedicated C# Roslyn CLI tool (`tools/TensorFlow.GradientGen`) parsing Python SOT AST. +5. **Memory & Buffer Lifecycle**: Zero-copy unmanaged memory managers (`UnmanagedMemoryManager`), strict `SafeHandle` wrapping for native pointers, and SIMD hardware acceleration. +6. **Testing & Parity Verification**: Hybrid verification strategy using static golden fixtures (`.npy`/`.json`) for 100% headless CI runs and a live Python SOT dual-runner tool for active development. + +--- + +## Phased Implementation Roadmap + +### Phase 1: Runtime Baseline & Foundational C-API / DTypes [COMPLETED] +- [x] **1.1 Project & Solution Modernization (.NET 8.0 / 9.0)**: Target `net8.0;net9.0`, `true`, C# 13. +- [x] **1.2 Native C-API Bindings & Status Payloads**: Implement `TF_SetPayload`, `TF_ForEachPayload`, `TF_SetStatusFromIOError`, `TF_TensorBitcastFrom`, `TF_TensorIsAligned`, `TF_TensorDefaultAlignment`, `TF_TensorElementCount`. +- [x] **1.3 DType Modernization & Bug Fixes**: Correct `float16`/`bfloat16` mappings in `dtypes.cs`, add full FP8 and sub-byte type enum definitions (`TF_FLOAT8_E5M2`..`TF_FLOAT4_E2M1FN`). + +--- + +### Phase 2: Op Gradients Programmatic Generator & NumPy Parity [UPCOMING] + +#### 2.1 Programmatic Gradient Generation Tool (`tools/TensorFlow.GradientGen`) +- Develop standalone CLI tool `tools/TensorFlow.GradientGen` to: + - Parse Python AST and gradient registration decorators (`@ops.RegisterGradient`) across all files in `refs/py-tensorflow-sot/tensorflow/python/ops/*_grad.py`. + - Emit idiomatic C# partial classes in `src/TensorFlowNET.Core/Gradients/Generated/` implementing `[RegisterGradient("OpName")]`. + - Expand registration from current 92 ops to full SOT parity (~382 ops) across math, nn, image, linalg, sparse, and tensor arrays. +- **Second-Order Gradients**: + - Implement nested gradient formulations for `SoftsignGrad`, `ReluGrad`, `TanhGrad`, `SoftplusGrad`, `SigmoidGrad`, `SqrtGrad`, and `FusedBatchNormGrad`. + +#### 2.2 NumPy Operators & Multi-Axis Slicing Parity +- **Numerical Parity (`np.isclose` & `np.allclose`)**: + - Implement complete tolerance math in `src/TensorFlowNET.Core/NumPy/Numpy.cs` and `NumPy.Logical.cs`: + $$\text{diff} \le \text{atol} + \text{rtol} \times |b|$$ + - Implement integer overflow prevention (`maximum(a, b) - minimum(a, b)`) and `equal_nan` handling. +- **Dynamic Multidimensional Slicing (`src/TensorFlowNET.Core/Tensors/Tensor.Indexing.cs`)**: + - Add full support for Ellipsis (`...`), `NewAxis` / `None`, negative step strides, and dynamic tensor-valued slice indices using the native `StridedSlice` kernel. + +--- + +### Phase 3: Clean-Room Keras 3 Engine & Modern Serialization + +#### 3.1 Symbolic Tracing DAG (`KerasTensor`) +- Decouple Keras functional construction from active native C-API `tf.Graph` instances. +- Introduce `KerasTensor` representing symbolic shapes, dtypes, and inbound/outbound node connections. +- Implement topological sort in `src/TensorFlowNET.Keras/Engine/Functional.cs` to resolve `Functional` execution graphs purely from `KerasTensor` outputs. +- Move legacy graph-coupled Keras 2 classes to `src/TensorFlowNET.Keras/Legacy/` (`Tensorflow.Keras.Legacy` namespace) and tag with `[Obsolete]` migration attributes. + +#### 3.2 Universal `.keras` Zip Archive Serialization +- Implement native `.keras` zip archive reading and writing in `src/TensorFlowNET.Keras/Saving/`: + - `config.json`: Model topology and layer hyperparameters. + - `metadata.json`: Keras version, build timestamp, framework signatures. + - `model.weights.h5` / `variables.safetensors`: Serialized weight arrays. +- Align `get_config()` and `from_config()` serialization schemas across all layers, optimizers, losses, and metrics with Python Keras 3. +- Maintain legacy loaders for SavedModel (`saved_model.pb`) and `.h5`. + +#### 3.3 Modular Step Execution Loop +- Refactor `Model` execution pipeline into modular, overridable step methods: + - `train_step(data)` + - `test_step(data)` + - `predict_step(data)` +- Refactor `LossesContainer` and `MetricsContainer` for consistent reduction, masking, and sample weight support. + +--- + +### Phase 4: Verification, Parity Test Harness & Release Pipeline + +#### 4.1 Hybrid Parity Test Harness +- **Static Golden Fixtures (`test/TensorFlowNET.UnitTest/Parity/`)**: + - Generate golden test vectors (`.npy`/`.json`) from Python SOT for all newly generated op gradients, NumPy operators, and Keras 3 layers. + - Ensure fast, deterministic, 100% headless CI test execution. +- **Live Dual-Runner Tool (`tools/TensorFlow.ParityRunner`)**: + - CLI tool running side-by-side execution in C# and Python (via local `.venv`), asserting identical outputs within numerical tolerances for new ops. + +#### 4.2 Release Packaging & Publishing +- Bump version to `v0.200.0` (or `v1.0.0`) in `Directory.Build.props`. +- Update GitHub Actions CI/CD workflows (`.github/workflows/build_and_test.yml`, `release.yml`): + - Add multi-platform matrix builds (Windows, Linux, macOS ARM64/x64). + - Package and publish nightly builds to MyGet and stable packages to NuGet (`TensorFlow.NET`, `TensorFlow.Keras`, `SciSharp.TensorFlow.Redist`). + +--- + +### Key File Locations for Changes + +| Subsystem | Target Files | +| :--- | :--- | +| **Project & Build** | `Directory.Build.props`, `TensorFlow.NET.sln`, `.github/workflows/build_and_test.yml` | +| **C-API & Status** | `src/TensorFlowNET.Core/Status/c_api.status.cs`, `Status.cs`, `c_api.tensor.cs` | +| **DTypes & Memory** | `src/TensorFlowNET.Core/Tensors/dtypes.cs`, `TF_DataType.cs`, `Tensor.cs` | +| **Gradient Generator** | `tools/TensorFlow.GradientGen/`, `src/TensorFlowNET.Core/Gradients/Generated/` | +| **NumPy & Slicing** | `src/TensorFlowNET.Core/NumPy/Numpy.cs`, `NumPy.Logical.cs`, `Tensor.Indexing.cs` | +| **Keras 3 Engine** | `src/TensorFlowNET.Keras/Engine/KerasTensor.cs`, `Functional.cs`, `Layer.cs`, `Model.cs` | +| **Keras Legacy** | `src/TensorFlowNET.Keras/Legacy/` | +| **Serialization** | `src/TensorFlowNET.Keras/Saving/KerasZipSaver.cs`, `Saving/KerasZipLoader.cs` | +| **Test Harness** | `tools/TensorFlow.ParityRunner/`, `test/TensorFlowNET.UnitTest/Parity/` | From d8ebef901ac46f859dedd2a95d4d5ff75163f8b6 Mon Sep 17 00:00:00 2001 From: Samuel Caldas Date: Thu, 3 Sep 2026 15:52:03 -0300 Subject: [PATCH 7/7] feat(deps): upgrade dependencies across TensorFlow.NET - Upgrade MethodBoundaryAspect.Fody to 2.0.150 - Upgrade Newtonsoft.Json to 13.0.4 - Upgrade OneOf to 3.0.271 - Upgrade Razorvine.Pickle to 1.5.0 - Upgrade Serilog.Sinks.Console to 6.0.0 - Upgrade System.Memory to 4.6.3 (netstandard2.0) - Upgrade HDF5-CSharp to 1.19.1 - Upgrade SharpCompress to 0.39.0 - Upgrade Microsoft.NET.Test.Sdk to 17.13.0 across test suites - Upgrade coverlet.collector to 6.0.4 across test suites - Upgrade BenchmarkDotNet to 0.14.0 and synchronize SciSharp.TensorFlow.Redist to 2.16.0 - Upgrade Microsoft.CodeAnalysis.CSharp.Scripting to 4.12.0 Co-Authored-By: Claude Code --- src/TensorFlowNET.Core/Tensorflow.Binding.csproj | 12 ++++++------ src/TensorFlowNET.Keras/Tensorflow.Keras.csproj | 4 ++-- src/TensorflowNET.Hub/Tensorflow.Hub.csproj | 2 +- .../TensorFlow.Kernel.UnitTest.csproj | 4 ++-- .../TensorFlowNET.Graph.UnitTest.csproj | 4 ++-- .../Tensorflow.Keras.UnitTest.csproj | 4 ++-- .../Tensorflow.Native.UnitTest.csproj | 4 ++-- .../Tensorflow.Binding.UnitTest.csproj | 4 ++-- test/Tensorflow.UnitTest/Tensorflow.UnitTest.csproj | 4 ++-- .../Tensorflow.Hub.Unittest.csproj | 4 ++-- .../Tensorflow.Benchmark.csproj | 4 ++-- tools/Tensorflow.CodeGen/Tensorflow.CodeGen.csproj | 2 +- 12 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/TensorFlowNET.Core/Tensorflow.Binding.csproj b/src/TensorFlowNET.Core/Tensorflow.Binding.csproj index ce3d9468..27741144 100644 --- a/src/TensorFlowNET.Core/Tensorflow.Binding.csproj +++ b/src/TensorFlowNET.Core/Tensorflow.Binding.csproj @@ -238,16 +238,16 @@ https://tensorflownet.readthedocs.io - - - + + + - - + + - + diff --git a/src/TensorFlowNET.Keras/Tensorflow.Keras.csproj b/src/TensorFlowNET.Keras/Tensorflow.Keras.csproj index 16d1d7bd..298251a4 100644 --- a/src/TensorFlowNET.Keras/Tensorflow.Keras.csproj +++ b/src/TensorFlowNET.Keras/Tensorflow.Keras.csproj @@ -210,8 +210,8 @@ Keras is an API designed for human beings, not machines. Keras follows best prac - - + + diff --git a/src/TensorflowNET.Hub/Tensorflow.Hub.csproj b/src/TensorflowNET.Hub/Tensorflow.Hub.csproj index 9d9fa631..247681dc 100644 --- a/src/TensorflowNET.Hub/Tensorflow.Hub.csproj +++ b/src/TensorflowNET.Hub/Tensorflow.Hub.csproj @@ -25,7 +25,7 @@ - + diff --git a/test/TensorFlow.Kernel.UnitTest/TensorFlow.Kernel.UnitTest.csproj b/test/TensorFlow.Kernel.UnitTest/TensorFlow.Kernel.UnitTest.csproj index db68a2bf..03e937c1 100644 --- a/test/TensorFlow.Kernel.UnitTest/TensorFlow.Kernel.UnitTest.csproj +++ b/test/TensorFlow.Kernel.UnitTest/TensorFlow.Kernel.UnitTest.csproj @@ -10,10 +10,10 @@ - + - + diff --git a/test/TensorFlowNET.Graph.UnitTest/TensorFlowNET.Graph.UnitTest.csproj b/test/TensorFlowNET.Graph.UnitTest/TensorFlowNET.Graph.UnitTest.csproj index 2d3d4192..68f3f1a2 100644 --- a/test/TensorFlowNET.Graph.UnitTest/TensorFlowNET.Graph.UnitTest.csproj +++ b/test/TensorFlowNET.Graph.UnitTest/TensorFlowNET.Graph.UnitTest.csproj @@ -24,10 +24,10 @@ - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/TensorFlowNET.Keras.UnitTest/Tensorflow.Keras.UnitTest.csproj b/test/TensorFlowNET.Keras.UnitTest/Tensorflow.Keras.UnitTest.csproj index a9ea6650..bd5b555c 100644 --- a/test/TensorFlowNET.Keras.UnitTest/Tensorflow.Keras.UnitTest.csproj +++ b/test/TensorFlowNET.Keras.UnitTest/Tensorflow.Keras.UnitTest.csproj @@ -13,10 +13,10 @@ - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/TensorFlowNET.Native.UnitTest/Tensorflow.Native.UnitTest.csproj b/test/TensorFlowNET.Native.UnitTest/Tensorflow.Native.UnitTest.csproj index 7d01d09d..cc85c12b 100644 --- a/test/TensorFlowNET.Native.UnitTest/Tensorflow.Native.UnitTest.csproj +++ b/test/TensorFlowNET.Native.UnitTest/Tensorflow.Native.UnitTest.csproj @@ -44,10 +44,10 @@ - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/TensorFlowNET.UnitTest/Tensorflow.Binding.UnitTest.csproj b/test/TensorFlowNET.UnitTest/Tensorflow.Binding.UnitTest.csproj index 9d6a00cb..915bd125 100644 --- a/test/TensorFlowNET.UnitTest/Tensorflow.Binding.UnitTest.csproj +++ b/test/TensorFlowNET.UnitTest/Tensorflow.Binding.UnitTest.csproj @@ -41,8 +41,8 @@ - - + + diff --git a/test/Tensorflow.UnitTest/Tensorflow.UnitTest.csproj b/test/Tensorflow.UnitTest/Tensorflow.UnitTest.csproj index f5cd3217..74c56dfe 100644 --- a/test/Tensorflow.UnitTest/Tensorflow.UnitTest.csproj +++ b/test/Tensorflow.UnitTest/Tensorflow.UnitTest.csproj @@ -10,10 +10,10 @@ - + - + diff --git a/test/TensorflowNET.Hub.Unittest/Tensorflow.Hub.Unittest.csproj b/test/TensorflowNET.Hub.Unittest/Tensorflow.Hub.Unittest.csproj index d242b92e..4985be0a 100644 --- a/test/TensorflowNET.Hub.Unittest/Tensorflow.Hub.Unittest.csproj +++ b/test/TensorflowNET.Hub.Unittest/Tensorflow.Hub.Unittest.csproj @@ -9,10 +9,10 @@ - + - + diff --git a/tools/TensorFlowNET.Benchmarks/Tensorflow.Benchmark.csproj b/tools/TensorFlowNET.Benchmarks/Tensorflow.Benchmark.csproj index e2e301b7..8050e911 100644 --- a/tools/TensorFlowNET.Benchmarks/Tensorflow.Benchmark.csproj +++ b/tools/TensorFlowNET.Benchmarks/Tensorflow.Benchmark.csproj @@ -36,8 +36,8 @@ - - + + diff --git a/tools/Tensorflow.CodeGen/Tensorflow.CodeGen.csproj b/tools/Tensorflow.CodeGen/Tensorflow.CodeGen.csproj index 22035a96..af80990f 100644 --- a/tools/Tensorflow.CodeGen/Tensorflow.CodeGen.csproj +++ b/tools/Tensorflow.CodeGen/Tensorflow.CodeGen.csproj @@ -8,7 +8,7 @@ - +