lcmialichi / php-gpu-tensors
Native PHP tensor extension with pluggable backend contracts and CUDA-accelerated computing.
Package info
github.com/lcmialichi/php-gpu-tensors
Language:C
Type:php-ext
Ext name:ext-phptensors
pkg:composer/lcmialichi/php-gpu-tensors
Requires
- php: >=8.1 <8.6
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
- ext-cuda: *
This package is auto-updated.
Last update: 2026-10-21 18:42:44 UTC
README
Write tensor math in PHP. Run it on the CPU or an NVIDIA GPU.
Fuse repeated expressions without leaving PHP. No Python runtime required.
PHP Tensors is a native PHP extension for numerical computing, GPU tensor operations and building machine-learning experiments. Start with CPU arrays, move data explicitly to CUDA, or compile reusable computation plans with Fusion. It is a low-level tensor library, not a complete ML framework.
Beta | Linux | PHP 8.1-8.5 | NTS/ZTS builds | CUDA optional
Get started · CPU tensors · GPU and Fusion · Capabilities · Examples · API map · Full guide · Contribute
Why PHP Tensors?
- Familiar expressions: write
$a + $b * $c, with broadcasting and typed storage. - A useful CPU backend: views, floating-point arithmetic, comparisons, selection, reductions and batched matrix multiplication without CUDA.
- Opt-in GPU acceleration: keep tensors on the device and choose when to transfer.
- Optional kernel fusion: capture a callback, compile once and replay it; supported elementwise work is fused around native operation boundaries.
- Tools beyond array math: reverse-mode autograd, functional SGD/AdamW, runtime-compiled CUDA C++ kernels and optional cuDNN CNN inference.
- Inspectable execution: examine generated source, plan boundaries and backend diagnostics instead of relying on hidden device migration.
Get started
Build without a GPU
You need Linux, PHP development headers, phpize, php-config, a C/C++
compiler, make and autoconf. No CUDA installation is needed for this path.
git clone https://github.com/lcmialichi/php-gpu-tensors.git cd php-gpu-tensors ./compile.sh --cpu-only ./run-tests.sh --cpu-only PHP_VERSION=$(php-config --version | cut -d. -f1,2) EXTENSION="$PWD/phptensors_build-${PHP_VERSION}/modules/phptensors.so" php -n -d extension="$EXTENSION" -r 'var_dump(extension_loaded("phptensors"));'
The last command should print bool(true). Load that module when running the
examples below, for example php -n -d extension="$EXTENSION" your-script.php.
The extension name is phptensors; its PHP namespace is PhpTensors.
Enable the CUDA backend
Install a CUDA Toolkit with NVRTC and development libraries, then run
./compile.sh without --cpu-only. GPU execution additionally requires a
compatible NVIDIA driver and a visible CUDA-capable GPU.
./compile.sh ./run-tests.sh --require-gpu
The build auto-detects the Toolkit and otherwise selects CPU-only mode. Native Windows and macOS builds are not supported.
For PIE installation, PHP binary selection, Docker and PHP-FPM setup, see the
installation guide. The published package baseline is
lcmialichi/php-gpu-tensors:0.1.0-beta.5; this checkout contains newer work.
CPU tensors
use PhpTensors\HostArray; $a = new HostArray([[1, 2, 3], [4, 5, 6]], 'float32'); $bias = new HostArray([10, 20, 30], 'float32'); $result = $a + $bias; // Broadcast the row across both rows. print_r($result->toArray()); // [[11, 22, 33], [14, 25, 36]] $features = $a->matmul($a->transpose())->tanh(); print_r($features->getShape()); // [2, 2]
HostArray stores all 13 supported dtypes at their native widths. Arithmetic
supports the four floating dtypes; other operations have their own dtype
contracts. See the CPU operation table.
GPU tensors and optional Fusion
use PhpTensors\CudaArray; use PhpTensors\Fusion; $a = CudaArray::ones([4]); $b = CudaArray::full([1], 2.0); // Broadcasts to [4]. $c = CudaArray::full([4], 3.0); $eager = $a + $b * $c; // Normal GPU execution; no capture required. $plan = Fusion::compile( fn($x, $y, $z) => $x + $y * $z, inputs: [$a, $b, $c] ); $fused = $plan->run($a, $b, $c); // Reuse the plan with compatible inputs. print_r($fused->toArray()); // [7, 7, 7, 7]; explicitly downloads to PHP.
Eager execution is the default. For a scoped, one-shot capture, use
Fusion::run(fn() => $a + $b * $c). Compiled plans also support
async replay and compatible CUDA Graphs.
The callback runs during capture, not on each replay. Not every operation is
fusible, and a plan may contain multiple kernels and native boundaries.
Data placement is explicit: HostArray::toGpu() uploads,
CudaArray::toHost() downloads, and toArray() exports PHP values. CPU
operations do not silently migrate to the GPU, or vice versa.
What can it do?
| Capability | CPU HostArray |
CUDA backend |
|---|---|---|
| Typed storage, imports/exports, copy and safe casts | 13 dtypes | 13 dtypes |
| Floating arithmetic and broadcasting | FP16, BF16, FP32, FP64 | Supported; operation-dependent dtype rules |
Retained views, comparisons and where |
Supported core | Supported, with a wider transform/indexing API |
| Reductions | sum, mean, min, max |
Also scans, statistics and discrete reductions |
| Batched matrix multiplication | Matching FP16/BF16/FP32, rank >= 2 | Matching FP16/BF16/FP32; accelerated compatible paths |
| Reverse-mode autograd and SGD/AdamW | Not supported | Supported operation/dtype subsets; first-order gradients |
| Fusion, async replay and CUDA Graphs | Not supported | Opt-in; compatibility depends on the plan |
| Custom CUDA C++ kernels compiled with NVRTC | Not supported | Supported |
| CNN inference | Not supported | Contiguous FP32; optional cuDNN, native CUDA alternative |
This is an overview, not a promise that every dtype works with every operation. See the API and runtime limits, autograd contracts and 1.0 readiness checklist before relying on a beta API. CUDA uses one owning device and thread per PHP process; concurrent CUDA calls from PHP/ZTS threads are not supported. PHP-FPM workers must fork before CUDA initialization. Shapes have at most 10 axes. See the guide for lifecycle rules.
Learn by example
| Start here | Learn |
|---|---|
| Tensor basics | Allocation, arithmetic and data transfer |
| Math and reductions | Numerical operations and aggregation |
| Views and broadcasting | Shape and layout manipulation |
| Custom kernels | Compile CUDA C++ from PHP |
| Async launches | Submit work, poll and synchronize |
| Fusion and CUDA Graphs | Capture, inspect and replay plans |
| Train an MLP | MNIST in one readable loop: autograd, AdamW and Fusion replay |
The runnable examples above require the CUDA backend and a working GPU. See the examples guide for setup and the full usage guide for CPU and custom-backend examples.
A measured Fusion workload
An earlier 256-unit MLP experiment on a GeForce MX570 A (4 GB), PHP 8.3 NTS, CUDA runtime 12.3 measured 4.08 ms/step eager versus 0.66 ms/step with Fusion replay, with the same 77.29% accuracy and 0.853 ROC AUC. This used handcrafted PatchCamelyon features, not an end-to-end image CNN. It is one workload, not a universal speedup or a benchmark of this exact checkout.
Use the kernel benchmark to measure your workload, or explore the separate benchmark reports. For data movement, use the transfer-cost benchmark: it separates host staging from GPU copies and reports latency, throughput and explicit memory/allocation scope.
API map for developers and AI tools
The authoritative signatures live in stubs/cuda.stub.php. Prefer those over inferring methods from examples. The CPU-only build exposes a CUDA-unavailable guard, not the full CUDA API.
| Entry point | Purpose |
|---|---|
PhpTensors\HostArray, PhpTensors\CudaArray |
Explicit CPU/GPU storage and operations |
PhpTensors\Fusion, FusionGraph, FusionExecution |
Capture, compiled plans and pending results |
PhpTensors\Compiler, CompiledModule |
NVRTC compilation and kernel launches |
PhpTensors\Optimizer, NN |
Functional optimizers and CUDA CNN inference |
PhpTensors\Tensor, BackendInterface |
Metadata/transfer and optional custom-backend contracts |
PhpTensors\OperatorOverload |
Base class for arithmetic hooks in userland PHP |
cuda_*() functions |
Devices, synchronization, memory and diagnostics |
OperatorOverloadable is a marker; it does not install operator dispatch.
Custom arithmetic objects extend OperatorOverload. See the
working custom tensor example and operator contract.
Native metadata is generated from the stubs and checked against loaded-extension
reflection. Development and API checks
explain how to keep those contracts aligned.
Validation and release status
CPU build/tests run in CI for PHP 8.1-8.5, NTS and ZTS. A separate CUDA-profile job builds and checks metadata and host-side behavior without executing GPU work. Current local CPU validation includes PHP 8.4/8.5 ZTS; earlier milestones also ran real-GPU suites.
Local Docker GPU passthrough now works under WSL 2. CPU/CUDA numerical parity, transfer correctness and healthy lifetime/ordering checks pass on the MX570 A. Release validation is not all green: the selected run has 16 passed, five failed fault-injection tests and zero skips; GPU memory/race acceptance remains open. Historical SDK-stub runs are host-only evidence, not GPU coverage. See the validation history and open gates in TODO.md for the scope of each run.
Help build it
Found a use case? Try an example, share your PHP/GPU configuration, or open an issue. Tests, documentation, CPU-only work and reproducible benchmarks are valuable contributions; owning an NVIDIA GPU is not required to contribute.
Read the contribution guide, follow the release checklist, and explore the longer-term roadmap. If the project is useful to you, a GitHub star helps others discover it.
License
MIT.
