nbxtensor 0.0.4__tar.gz → 0.0.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/CHANGELOG.md +20 -1
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/PKG-INFO +7 -7
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/README.md +6 -6
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/pyproject.toml +1 -1
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/__init__.py +1 -1
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/__main__.py +1 -1
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/cpu/blas.py +11 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/launcher.py +3 -2
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/level_zero.py +2 -2
- nbxtensor-0.0.5/src/nbxtensor/backend/libnames.py +26 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/replay_graph.py +2 -1
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/runtime.py +9 -6
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/io/read_rate.py +14 -3
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/io/safetensors.py +35 -2
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/autotune_certified.py +18 -8
- nbxtensor-0.0.5/tests/test_a_setting_not_served_says_why.py +32 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_install_metal_fetches_only_what_it_names.py +1 -1
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/.github/PULL_REQUEST_TEMPLATE/certificate.md +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/CONTRIBUTING.md +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/LICENSE +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/THIRD_PARTY_NOTICES.md +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/assets/logo.png +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/__init__.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/capabilities.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/cpu/__init__.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/cpu/pool.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/cpu_backend.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/device_facts.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/device_files.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/device_names.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/amd/cdna.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/amd/cdna2.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/amd/cdna3.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/amd/cdna4.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/amd/rdna3.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/amd/rdna4.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m1.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m1_max.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m1_pro.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m1_ultra.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m2.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m2_max.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m2_pro.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m2_ultra.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m3.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m3_max.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m3_pro.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m3_ultra.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m4.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m4_max.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m4_pro.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m5.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m5_max.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m5_pro.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m5_ultra.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_m6.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/apple/apple_silicon.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/intel/bmg.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/intel/dg2.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/intel/lnl.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/intel/pvc.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/nvidia/ampere.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/nvidia/hopper.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/devices/nvidia/volta.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/faults.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/host_memory.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/install_help.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/install_metal.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/install_steps.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/launcher_contract.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/level_zero_driver.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/metal_backend.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/metal_device.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/process_memory.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/backend/triton_ext_driver.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/dtype/__init__.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/dtype/convert.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/dtype/dtypes.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/dtype/itemsize.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/dtype/nbx_dtype.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/dtype/operands.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/dtype/outputs.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/dtype/policy.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/dtype/policy.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/dtype/promotion.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/host.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/io/__init__.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/memory/__init__.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/memory/allocator.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/memory/arena.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/memory/device_memory.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/memory/device_transfer.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/memory/layout.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/memory/memory_pool.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/memory/metal.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/memory/oom_advice.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/memory/pointer_tables.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/memory/pool.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/memory/shadow.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/memory/slab.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/memory/trace_replay.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/memory/traces/sana-video-2b-720p.16g.2026-11-02.tsv +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/memory/vmm.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/__init__.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/_autotune_policy.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/_common.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/_configs.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/_cost.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/abs.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/adaptive_avg_pool2d.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/add.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/addcdiv.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/addcmul.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/addmv_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/addr.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/all_reduce.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/amax.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/any_reduce.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/arange_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/argmax.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/argmin.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/atan2.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/attention_wrappers.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/autotune_bucket.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/autotune_cache.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/autotune_refusals.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/autotune_settings.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/avg_pool2d.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/baddbmm_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/batch_norm.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/binary_strided.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/bitwise_and.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/bitwise_left_shift.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/bitwise_not.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/bitwise_or.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/bitwise_right_shift.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/bucketize.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/cat_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/celu.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/certified_index.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/clamp.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/clamp_min.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/conv2d.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/conv2d_m8n8k4.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/conv_depthwise2d.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/conv_transpose2d.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/conv_wrappers.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/copy.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/copy_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/cos.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/count_nonzero.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/cross_entropy.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/cummax.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/cummin.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/cumsum.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/decode_attn_vec.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/depthwise_conv2d.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/dequant_gemv.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/dft.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/dispatch.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/div.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/dot_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/dropout.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/dtype_convert.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/elementwise_launch.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/elementwise_wrappers.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/elu.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/embedding.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/eq.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/erf.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/exp.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/exp2.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/fft_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/fill_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/flash_attention.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/flash_attention_m8n8k4.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/flash_decode.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/flip_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/floor.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/full_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/fused_moe.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/fused_moe_m8n8k4.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/fused_upsample_conv.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/gather_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/ge.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/gelu.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/gemv_vec.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/glu.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/grid_sampler.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/group_norm_tiled.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/groupnorm.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/gt.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/hardsigmoid.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/hardswish.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/im2col.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/index_add.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/index_put_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/index_select.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/index_wrappers.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/isfinite.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/isinf.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/isnan.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/launch_keys.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/launch_observer.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/layernorm.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/le.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/leaky_relu.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/lerp.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/linalg_wrappers.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/linspace_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/log.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/log_sigmoid.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/logical_and.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/logical_not.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/logical_or.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/logical_xor.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/loss_wrappers.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/lt.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/masked_fill.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/matmul.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/matmul_m8n8k4.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/max_pool2d.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/max_pool3d.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/max_reduce.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/maximum.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/mean.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/min_reduce.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/minimum.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/mish.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/mma_m8n8k4.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/moe_align.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/moe_decode_vec.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/moe_device_residency.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/moe_wrappers.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/mse_loss.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/mul.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/nan_to_num.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/ne.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/neg.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/nllloss.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/nonzero.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/nonzero_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/norm_wrappers.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/ones_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/oracles/__init__.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/oracles/conv2d_fp64.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/pad_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/paged_decode_attn.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/pixel_shuffle.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/pixel_unshuffle.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/pow.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/prod.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/rand_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/random_wrappers.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/reciprocal.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/reduction_wrappers.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/relu.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/remainder.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/repeat_interleave.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/repeat_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/residual_chain.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/rmsnorm.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/rope.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/rsqrt.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/scaled_softmax.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/scatter_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/screen_oracle.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/selu.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/shape_wrappers.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/sigmoid.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/silu.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/sin.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/softmax.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/softplus.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/sort_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/spectral_wrappers.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/sqrt.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/stack_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/std.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/strided_copy.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/sub.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/sum.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/tan.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/tanh.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/threshold.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/tiling.yml +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/tiling_policy.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/tiling_sizes.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/topk.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/trace_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/tril.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/triu.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/unfold_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/unique_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/upsample_bilinear2d.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/upsample_nearest2d.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/upsample_nearest3d.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/var.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/vector_norm.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/weight_norm.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/where.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/wrappers.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/ops/zeros_op.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/quant/__init__.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/quant/quantized_tensor.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/random/__init__.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/random/mt_randn.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/random/rng_pin.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/random/rng_stream.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/random/seeded_draw.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/shape/__init__.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/src/nbxtensor/tensor.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_a_small_tensor_never_pins_a_large_block.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_a_sweep_refused_everywhere_says_so.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_a_triton_kernel_compiles_for_amd_and_launches_through_hip.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_allocator_interceptor.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_array_api_promotion.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_cpu_pool.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_device_facts.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_device_files.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_device_memory.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_dtype_convert.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_dtype_outputs.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_dtype_promotion.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_host.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_io_bf16_split.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_io_read_rate.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_it_installs_on_a_mac.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_nbx_dtype.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_no_environment_switch_changes_a_kernel.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_ops_cost.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_policy.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_readme.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_shape.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_the_backend_is_the_card_on_the_machine.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_the_compiler_key_is_prewarmed.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_the_hip_driver_keeps_the_launch_contract.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_the_launcher_refuses_a_backend_it_has_no_driver_for.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_the_level_zero_backend_keeps_its_contracts.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_the_malloc_trace_names_the_wrapper.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_the_metal_dispatch_facts_are_declared_or_refused.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_third_party_notices.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tests/test_version.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tools/device_key_census.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tools/device_key_trace.py +0 -0
- {nbxtensor-0.0.4 → nbxtensor-0.0.5}/tools/scatter_scan.py +0 -0
|
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.0.5] - 2026-11-07
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **The library runs on Windows**: weights are read at their offset without `os.preadv` (Windows' `ReadFile` with an
|
|
14
|
+
OVERLAPPED offset), the BLAS's thread control is found beside numpy (`numpy.libs`) instead of through /proc, and the
|
|
15
|
+
GPU libraries are opened by their Windows names (nvcuda.dll, cudart64_12.dll from the runtime wheel's `bin`, nvml.dll,
|
|
16
|
+
amdhip64_6.dll, ze_loader.dll, OpenCL.dll). Written and tested with Windows simulated: the project has no Windows
|
|
17
|
+
machine yet.
|
|
18
|
+
- **`python -m nbxtensor doctor` on a Mac without Triton exits 1**: it named the fix and exited 0, so a script could
|
|
19
|
+
not tell that nothing could run yet.
|
|
20
|
+
- **The library imports on Windows**: its page size came from `os.sysconf`, which Windows does not have; and the code
|
|
21
|
+
generator's identity now reads a backend's files as `/` paths with its `.pyd` and `.dll` binaries, so the same code
|
|
22
|
+
has the same identity on every system.
|
|
23
|
+
- **A certified setting that is not served says why**: where the directory holds a key proven under another code
|
|
24
|
+
generator than the running one, the line named a memory class that matched ("certified for 18 GB, this card is
|
|
25
|
+
18 GB, not served"); it now names both generators and the re-proof command. A setting proven on another memory class
|
|
26
|
+
is still said as such.
|
|
27
|
+
|
|
10
28
|
## [0.0.4] - 2026-11-07
|
|
11
29
|
|
|
12
30
|
### Added
|
|
@@ -162,7 +180,8 @@ memory; the fix is in test).
|
|
|
162
180
|
- **`flash_decode_split_kernel` and its route**: armed only by an environment switch (`NBX_FLASH_DECODE`, with `NBX_FD_BLOCK_N` and `NBX_FD_SEG`) and measured slower than the vector decode kernels; `flash_decode.py` keeps the fixed-order reduce they share.
|
|
163
181
|
- **`conv1d_forward_kernel`**: launched by no route (a 1-D convolution runs through `conv2d`).
|
|
164
182
|
|
|
165
|
-
[Unreleased]: https://github.com/NeuroBrix/nbxtensor/compare/v0.0.
|
|
183
|
+
[Unreleased]: https://github.com/NeuroBrix/nbxtensor/compare/v0.0.5...HEAD
|
|
184
|
+
[0.0.5]: https://github.com/NeuroBrix/nbxtensor/compare/v0.0.4...v0.0.5
|
|
166
185
|
[0.0.4]: https://github.com/NeuroBrix/nbxtensor/compare/v0.0.3...v0.0.4
|
|
167
186
|
[0.0.3]: https://github.com/NeuroBrix/nbxtensor/compare/v0.0.2...v0.0.3
|
|
168
187
|
[0.0.2]: https://github.com/NeuroBrix/nbxtensor/compare/v0.0.1...v0.0.2
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: nbxtensor
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.5
|
|
4
4
|
Summary: Run AI models without PyTorch: tensors, Triton kernels, planned memory and certified tuning, wherever Triton runs — NVIDIA, AMD, Intel and Apple GPUs.
|
|
5
5
|
Project-URL: Homepage, https://github.com/NeuroBrix/nbxtensor
|
|
6
6
|
Project-URL: Source, https://github.com/NeuroBrix/nbxtensor
|
|
@@ -25,7 +25,7 @@ Description-Content-Type: text/markdown
|
|
|
25
25
|
|
|
26
26
|
Run AI models without PyTorch, on any GPU Triton supports: tensors, Triton kernels, planned memory and certified tuning.
|
|
27
27
|
|
|
28
|
-
Runs wherever Triton runs — NVIDIA, AMD, Intel and Apple Silicon GPUs. Inference first; training is not in this
|
|
28
|
+
Runs wherever Triton runs — NVIDIA, AMD, Intel and Apple Silicon GPUs, on Linux, Windows and macOS. Inference first; training is not in this
|
|
29
29
|
release. Found a bug on your hardware? [Open an issue](https://github.com/NeuroBrix/nbxtensor/issues) — we fix fast.
|
|
30
30
|
|
|
31
31
|
[](https://pypi.org/project/nbxtensor/)
|
|
@@ -156,10 +156,10 @@ install commands when one is not.
|
|
|
156
156
|
|
|
157
157
|
**From the NeuroBrix repository** (contributors): `pip install -e nbxtensor`.
|
|
158
158
|
|
|
159
|
-
**macOS, Apple silicon (Metal).** PyPI publishes no Triton for macOS. `install-metal` installs
|
|
160
|
-
|
|
161
|
-
`TRITON_EXT_ENABLED=1
|
|
162
|
-
|
|
159
|
+
**macOS, Apple silicon (Metal).** PyPI publishes no Triton for macOS. `install-metal` installs NeuroBrix's Triton
|
|
160
|
+
build for Apple GPUs, [NeuroBrix/triton-ext](https://github.com/NeuroBrix/triton-ext) (Triton built with
|
|
161
|
+
`TRITON_EXT_ENABLED=1` and the `nbx-triton-apple` backend; upstream:
|
|
162
|
+
[triton-lang/triton-ext#126](https://github.com/triton-lang/triton-ext/pull/126)); each wheel is checked against the
|
|
163
163
|
sha256 written in the library (Python 3.12, macOS 15 or later):
|
|
164
164
|
|
|
165
165
|
```
|
|
@@ -500,7 +500,7 @@ with the tensor class (API.md §4).
|
|
|
500
500
|
|
|
501
501
|
## Versions
|
|
502
502
|
|
|
503
|
-
The first publication was **0.0.1**; this is **0.0.
|
|
503
|
+
The first publication was **0.0.1**; this is **0.0.5**. Each fix published after it increments the number (0.0.6,
|
|
504
504
|
…), with no alpha or beta label. The rewrite of the core in Rust will be **2.0.0**. `nbxtensor.__version__` is the
|
|
505
505
|
installed version.
|
|
506
506
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
Run AI models without PyTorch, on any GPU Triton supports: tensors, Triton kernels, planned memory and certified tuning.
|
|
6
6
|
|
|
7
|
-
Runs wherever Triton runs — NVIDIA, AMD, Intel and Apple Silicon GPUs. Inference first; training is not in this
|
|
7
|
+
Runs wherever Triton runs — NVIDIA, AMD, Intel and Apple Silicon GPUs, on Linux, Windows and macOS. Inference first; training is not in this
|
|
8
8
|
release. Found a bug on your hardware? [Open an issue](https://github.com/NeuroBrix/nbxtensor/issues) — we fix fast.
|
|
9
9
|
|
|
10
10
|
[](https://pypi.org/project/nbxtensor/)
|
|
@@ -135,10 +135,10 @@ install commands when one is not.
|
|
|
135
135
|
|
|
136
136
|
**From the NeuroBrix repository** (contributors): `pip install -e nbxtensor`.
|
|
137
137
|
|
|
138
|
-
**macOS, Apple silicon (Metal).** PyPI publishes no Triton for macOS. `install-metal` installs
|
|
139
|
-
|
|
140
|
-
`TRITON_EXT_ENABLED=1
|
|
141
|
-
|
|
138
|
+
**macOS, Apple silicon (Metal).** PyPI publishes no Triton for macOS. `install-metal` installs NeuroBrix's Triton
|
|
139
|
+
build for Apple GPUs, [NeuroBrix/triton-ext](https://github.com/NeuroBrix/triton-ext) (Triton built with
|
|
140
|
+
`TRITON_EXT_ENABLED=1` and the `nbx-triton-apple` backend; upstream:
|
|
141
|
+
[triton-lang/triton-ext#126](https://github.com/triton-lang/triton-ext/pull/126)); each wheel is checked against the
|
|
142
142
|
sha256 written in the library (Python 3.12, macOS 15 or later):
|
|
143
143
|
|
|
144
144
|
```
|
|
@@ -479,7 +479,7 @@ with the tensor class (API.md §4).
|
|
|
479
479
|
|
|
480
480
|
## Versions
|
|
481
481
|
|
|
482
|
-
The first publication was **0.0.1**; this is **0.0.
|
|
482
|
+
The first publication was **0.0.1**; this is **0.0.5**. Each fix published after it increments the number (0.0.6,
|
|
483
483
|
…), with no alpha or beta label. The rewrite of the core in Rust will be **2.0.0**. `nbxtensor.__version__` is the
|
|
484
484
|
installed version.
|
|
485
485
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "nbxtensor"
|
|
7
|
-
version = "0.0.
|
|
7
|
+
version = "0.0.5"
|
|
8
8
|
description = "Run AI models without PyTorch: tensors, Triton kernels, planned memory and certified tuning, wherever Triton runs — NVIDIA, AMD, Intel and Apple GPUs."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "Apache-2.0" }
|
|
@@ -11,7 +11,7 @@ def doctor() -> int:
|
|
|
11
11
|
from nbxtensor.backend.metal_backend import is_apple_silicon, triton_metal_available
|
|
12
12
|
if is_apple_silicon() and not triton_metal_available():
|
|
13
13
|
print("Apple GPU found; Triton for Metal not installed — run: python -m nbxtensor install-metal")
|
|
14
|
-
return
|
|
14
|
+
return 1 # nothing can run yet: a script reads it from the exit status
|
|
15
15
|
try:
|
|
16
16
|
backend = runtime.gpu_backend()
|
|
17
17
|
print(f"backend in force: {backend}" + (" (the Apple GPU, through Metal)" if backend == "metal" else ""))
|
|
@@ -20,6 +20,7 @@ from __future__ import annotations
|
|
|
20
20
|
import ctypes
|
|
21
21
|
import functools
|
|
22
22
|
import platform
|
|
23
|
+
import sys
|
|
23
24
|
from pathlib import Path
|
|
24
25
|
from typing import Optional, Tuple
|
|
25
26
|
|
|
@@ -33,6 +34,16 @@ _OPENBLAS_GET = ("scipy_openblas_get_num_threads64_", "scipy_openblas_get_num_th
|
|
|
33
34
|
|
|
34
35
|
|
|
35
36
|
def _loaded_openblas() -> Optional[str]:
|
|
37
|
+
if sys.platform == "win32":
|
|
38
|
+
# no /proc on Windows: numpy's wheel ships its OpenBLAS beside the package (`numpy.libs`, older wheels
|
|
39
|
+
# `numpy/.libs`), loaded with numpy; ctypes opening the same path returns the module already in the process
|
|
40
|
+
import numpy
|
|
41
|
+
root = Path(numpy.__file__).resolve().parent
|
|
42
|
+
for d in (root.parent / "numpy.libs", root / ".libs"):
|
|
43
|
+
hits = sorted(d.glob("*openblas*.dll")) if d.is_dir() else []
|
|
44
|
+
if hits:
|
|
45
|
+
return str(hits[0])
|
|
46
|
+
return None
|
|
36
47
|
maps = Path("/proc/self/maps")
|
|
37
48
|
if not maps.is_file():
|
|
38
49
|
return None
|
|
@@ -488,14 +488,15 @@ class CudaDriver(_ModuleDriver):
|
|
|
488
488
|
|
|
489
489
|
def __init__(self) -> None:
|
|
490
490
|
lib = None
|
|
491
|
-
|
|
491
|
+
from nbxtensor.backend.libnames import CUDA_DRIVER
|
|
492
|
+
for name in CUDA_DRIVER:
|
|
492
493
|
try:
|
|
493
494
|
lib = ctypes.CDLL(name)
|
|
494
495
|
break
|
|
495
496
|
except OSError:
|
|
496
497
|
continue
|
|
497
498
|
if lib is None:
|
|
498
|
-
raise RuntimeError("NeuroBrix launcher:
|
|
499
|
+
raise RuntimeError(f"NeuroBrix launcher: the CUDA driver library not found (tried {CUDA_DRIVER})")
|
|
499
500
|
self.lib = lib
|
|
500
501
|
self._check(lib.cuInit(0), "cuInit")
|
|
501
502
|
# ctypes infers the type of every argument at every call unless the signature is
|
|
@@ -27,7 +27,7 @@ import threading
|
|
|
27
27
|
from typing import Dict, Optional, Tuple
|
|
28
28
|
|
|
29
29
|
#: the Level Zero loader (`libze1` on Ubuntu), tried in order
|
|
30
|
-
|
|
30
|
+
from nbxtensor.backend.libnames import LEVEL_ZERO as LIBS # noqa: E402
|
|
31
31
|
|
|
32
32
|
# ZE_STRUCTURE_TYPE_* (ze.py)
|
|
33
33
|
_ST_DRIVER_PROPERTIES, _ST_DEVICE_COMPUTE, _ST_QUEUE_GROUP, _ST_DEVICE_MEMORY = 0x1, 0x4, 0x6, 0x7
|
|
@@ -558,7 +558,7 @@ def runtime() -> LevelZeroRuntime:
|
|
|
558
558
|
|
|
559
559
|
|
|
560
560
|
#: the OpenCL ICD loader (`ocl-icd-libopencl1`; Intel's runtime registers itself in it with intel-opencl-icd)
|
|
561
|
-
|
|
561
|
+
from nbxtensor.backend.libnames import OPENCL as OPENCL_LIBS # noqa: E402
|
|
562
562
|
_CL_DEVICE_TYPE_GPU, _CL_DEVICE_VENDOR_ID, _CL_DEVICE_EXTENSIONS, _CL_DEVICE_ID_INTEL = 4, 0x1001, 0x1030, 0x4251
|
|
563
563
|
|
|
564
564
|
#: target facts Intel's compiler reads (intel/backend/compiler.py `parse_target`) -> the OpenCL extension that states
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""The vendor libraries the backends open through ctypes, named as each system names them: a shared object on Linux
|
|
2
|
+
(`libcuda.so.1`), a DLL on Windows (`nvcuda.dll`). Read by the backend tables (`backend.runtime`), the launch driver
|
|
3
|
+
(`backend.launcher`), the graph replay (`backend.replay_graph`), the expandable pool (`memory.vmm`) and Level Zero
|
|
4
|
+
(`backend.level_zero`). Windows' names are the vendors' (NVIDIA: nvcuda.dll in System32 with the driver, cudart64_12.dll
|
|
5
|
+
in the CUDA runtime wheel's `bin`, nvml.dll; AMD HIP SDK: amdhip64_6.dll; Intel: ze_loader.dll, OpenCL.dll).
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
WINDOWS = sys.platform == "win32"
|
|
12
|
+
|
|
13
|
+
#: the CUDA runtime, after the one the environment's wheel carries (`runtime._environment_runtime_libs`)
|
|
14
|
+
CUDA_RUNTIME = ["cudart64_12.dll", "cudart64_110.dll"] if WINDOWS else ["libcudart.so", "libcudart.so.12", "libcudart.so.11.0"]
|
|
15
|
+
#: the CUDA runtime file inside the nvidia-cuda-runtime wheel, and the wheel's directory that holds it
|
|
16
|
+
CUDA_RUNTIME_IN_WHEEL = ("bin", "cudart64_12.dll") if WINDOWS else ("lib", "libcudart.so.12")
|
|
17
|
+
#: the CUDA driver API
|
|
18
|
+
CUDA_DRIVER = ["nvcuda.dll"] if WINDOWS else ["libcuda.so.1", "libcuda.so"]
|
|
19
|
+
#: NVIDIA's management library
|
|
20
|
+
NVML = ["nvml.dll"] if WINDOWS else ["libnvidia-ml.so.1", "libnvidia-ml.so"]
|
|
21
|
+
#: the HIP runtime
|
|
22
|
+
HIP_RUNTIME = ["amdhip64_6.dll", "amdhip64.dll"] if WINDOWS else ["libamdhip64.so", "libamdhip64.so.5"]
|
|
23
|
+
#: the Level Zero loader
|
|
24
|
+
LEVEL_ZERO = ["ze_loader.dll"] if WINDOWS else ["libze_loader.so.1", "libze_loader.so"]
|
|
25
|
+
#: the OpenCL ICD loader
|
|
26
|
+
OPENCL = ["OpenCL.dll"] if WINDOWS else ["libOpenCL.so.1", "libOpenCL.so"]
|
|
@@ -39,23 +39,26 @@ def _environment_runtime_libs(package: str, names) -> list:
|
|
|
39
39
|
return []
|
|
40
40
|
import os
|
|
41
41
|
root = list(spec.submodule_search_locations)[0]
|
|
42
|
+
from nbxtensor.backend.libnames import CUDA_RUNTIME_IN_WHEEL, WINDOWS
|
|
42
43
|
out = []
|
|
43
44
|
for n in names:
|
|
44
|
-
cand = os.path.join(root,
|
|
45
|
+
cand = os.path.join(root, CUDA_RUNTIME_IN_WHEEL[0], n)
|
|
45
46
|
if os.path.exists(cand):
|
|
46
47
|
out.append(cand)
|
|
48
|
+
if WINDOWS: # the DLL's own directory searched for what it loads
|
|
49
|
+
os.add_dll_directory(os.path.dirname(cand))
|
|
47
50
|
return out
|
|
48
51
|
|
|
49
52
|
|
|
50
53
|
# Runtime API mapping per backend
|
|
54
|
+
from nbxtensor.backend import libnames as _LIB # noqa: E402 the libraries as this system names them
|
|
51
55
|
_GPU_BACKENDS = {
|
|
52
56
|
"cuda": {
|
|
53
|
-
"rt_libs": _environment_runtime_libs("nvidia.cuda_runtime", [
|
|
54
|
-
+ ["libcudart.so", "libcudart.so.12", "libcudart.so.11.0"],
|
|
57
|
+
"rt_libs": _environment_runtime_libs("nvidia.cuda_runtime", [_LIB.CUDA_RUNTIME_IN_WHEEL[1]]) + _LIB.CUDA_RUNTIME,
|
|
55
58
|
# the driver API's library: the virtual memory primitives of the expandable pool (`memory.vmm`, R16)
|
|
56
|
-
"driver_libs":
|
|
59
|
+
"driver_libs": _LIB.CUDA_DRIVER,
|
|
57
60
|
# the management library: what the driver attributes to THIS process on a device (`backend.process_memory`)
|
|
58
|
-
"management_libs":
|
|
61
|
+
"management_libs": _LIB.NVML,
|
|
59
62
|
"pci_bus_id": "cudaDeviceGetPCIBusId",
|
|
60
63
|
"malloc": "cudaMalloc", "free": "cudaFree",
|
|
61
64
|
"memcpy": "cudaMemcpy", "memset": "cudaMemset",
|
|
@@ -100,7 +103,7 @@ _GPU_BACKENDS = {
|
|
|
100
103
|
"device_enable_peer_access": "cudaDeviceEnablePeerAccess",
|
|
101
104
|
},
|
|
102
105
|
"hip": {
|
|
103
|
-
"rt_libs":
|
|
106
|
+
"rt_libs": _LIB.HIP_RUNTIME,
|
|
104
107
|
# the same three facts as cuda's, declared ABSENT: the expandable pool speaks the CUDA driver's VMM calls only
|
|
105
108
|
# (`memory.vmm`; HIP's hipMemCreate family is not wired), so a HIP device keeps its driver segments; and no
|
|
106
109
|
# per-process accounting is read on ROCm (`backend.process_memory` answers None, the runtime's growth is not
|
|
@@ -11,7 +11,8 @@ import time
|
|
|
11
11
|
from concurrent.futures import ThreadPoolExecutor
|
|
12
12
|
from typing import Dict, List, Optional, Sequence
|
|
13
13
|
|
|
14
|
-
__all__ = ["PIECE", "WITNESS_BYTES", "START_BYTES", "mount_of", "pieces", "trial", "choose", "measure", "workers_for"
|
|
14
|
+
__all__ = ["PIECE", "WITNESS_BYTES", "START_BYTES", "mount_of", "pieces", "trial", "choose", "measure", "workers_for",
|
|
15
|
+
"can_bypass_the_cache"]
|
|
15
16
|
|
|
16
17
|
PIECE = 16 << 20 # the loaders' read piece
|
|
17
18
|
|
|
@@ -63,14 +64,21 @@ def pieces(files, max_bytes: int):
|
|
|
63
64
|
return out, total
|
|
64
65
|
|
|
65
66
|
|
|
67
|
+
def can_bypass_the_cache() -> bool:
|
|
68
|
+
"""Whether this system lets a measure read past its page cache (macOS F_NOCACHE + msync, Linux posix_fadvise);
|
|
69
|
+
Windows offers neither through Python, and a rate read from the cache is not the storage's."""
|
|
70
|
+
return sys.platform == "darwin" or hasattr(os, "posix_fadvise")
|
|
71
|
+
|
|
72
|
+
|
|
66
73
|
def trial(pieces, workers: int) -> float:
|
|
67
74
|
"""Bytes per second reading `pieces` with `workers` threads, the cache bypassed."""
|
|
75
|
+
from nbxtensor.io.safetensors import _read_at
|
|
68
76
|
for path in {p for p, _, _ in pieces}:
|
|
69
77
|
_evict(path, os.path.getsize(path))
|
|
70
78
|
fds = {}
|
|
71
79
|
for path, _, _ in pieces:
|
|
72
80
|
if path not in fds:
|
|
73
|
-
fd = os.open(path, os.O_RDONLY)
|
|
81
|
+
fd = os.open(path, os.O_RDONLY | getattr(os, "O_BINARY", 0))
|
|
74
82
|
_no_cache(fd)
|
|
75
83
|
fds[path] = fd
|
|
76
84
|
bufs = [bytearray(PIECE) for _ in range(workers)]
|
|
@@ -80,7 +88,7 @@ def trial(pieces, workers: int) -> float:
|
|
|
80
88
|
buf = memoryview(bufs[i % workers])[:n]
|
|
81
89
|
got = 0
|
|
82
90
|
while got < n:
|
|
83
|
-
got +=
|
|
91
|
+
got += _read_at(fds[path], buf[got:], off + got)
|
|
84
92
|
return n
|
|
85
93
|
|
|
86
94
|
t = time.perf_counter()
|
|
@@ -146,6 +154,9 @@ def workers_for(directory, witness_dir=None, max_workers: Optional[int] = None,
|
|
|
146
154
|
up to everything the files hold. When no size gives a stable measure, refused by name: never a silent None, never
|
|
147
155
|
a default."""
|
|
148
156
|
from pathlib import Path
|
|
157
|
+
if not can_bypass_the_cache():
|
|
158
|
+
raise RuntimeError(f"ZERO FALLBACK: no uncached read-rate measure on this system ({sys.platform}: no way to "
|
|
159
|
+
f"read past the page cache) — no worker count is assumed")
|
|
149
160
|
root = Path(directory)
|
|
150
161
|
max_workers = max_workers or os.cpu_count() or 1
|
|
151
162
|
files = [str(p) for p in sorted(root.glob(pattern), key=lambda p: -p.stat().st_size)[:4]]
|
|
@@ -11,6 +11,7 @@ from __future__ import annotations
|
|
|
11
11
|
|
|
12
12
|
import ctypes
|
|
13
13
|
import math
|
|
14
|
+
import mmap
|
|
14
15
|
import os
|
|
15
16
|
from typing import Optional
|
|
16
17
|
|
|
@@ -23,7 +24,7 @@ from nbxtensor.dtype.convert import bf16_bits_to_f16, f32_to_bf16_bits
|
|
|
23
24
|
from nbxtensor.shape import contiguous_strides
|
|
24
25
|
from nbxtensor.memory.memory_pool import ComponentArena, HostPinnedArena
|
|
25
26
|
|
|
26
|
-
PAGE = os.sysconf(
|
|
27
|
+
PAGE = mmap.PAGESIZE # os.sysconf does not exist on Windows (its import stopped every plan there)
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
def spans(n: int, unit: int, align: int, workers: int):
|
|
@@ -36,6 +37,38 @@ def spans(n: int, unit: int, align: int, workers: int):
|
|
|
36
37
|
return [(a, min(a + step, n)) for a in range(0, n, step)]
|
|
37
38
|
|
|
38
39
|
|
|
40
|
+
def _read_at(fd: int, view: memoryview, offset: int) -> int:
|
|
41
|
+
"""Read into `view` from the file's byte `offset`, at that offset and never through a shared file position (the
|
|
42
|
+
workers read one file at once): `os.preadv` where the system has it (Linux, macOS); on Windows, which has neither
|
|
43
|
+
preadv nor pread, `ReadFile` with an OVERLAPPED offset on the descriptor's handle — a positioned read. Returns the
|
|
44
|
+
bytes read (0 at the end of the file)."""
|
|
45
|
+
if hasattr(os, "preadv"):
|
|
46
|
+
return os.preadv(fd, [view], offset)
|
|
47
|
+
if hasattr(os, "pread"):
|
|
48
|
+
data = os.pread(fd, len(view), offset)
|
|
49
|
+
view[:len(data)] = data
|
|
50
|
+
return len(data)
|
|
51
|
+
import msvcrt
|
|
52
|
+
from ctypes import wintypes
|
|
53
|
+
|
|
54
|
+
class _Overlapped(ctypes.Structure):
|
|
55
|
+
_fields_ = [("Internal", ctypes.c_void_p), ("InternalHigh", ctypes.c_void_p), ("Offset", wintypes.DWORD),
|
|
56
|
+
("OffsetHigh", wintypes.DWORD), ("hEvent", wintypes.HANDLE)]
|
|
57
|
+
|
|
58
|
+
n = min(len(view), 0x7FFFFFFF) # one ReadFile reads at most a DWORD's worth
|
|
59
|
+
ov = _Overlapped(0, 0, offset & 0xFFFFFFFF, offset >> 32, None)
|
|
60
|
+
got = wintypes.DWORD(0)
|
|
61
|
+
buf = (ctypes.c_char * n).from_buffer(view)
|
|
62
|
+
ok = ctypes.windll.kernel32.ReadFile(wintypes.HANDLE(msvcrt.get_osfhandle(fd)), buf, n, ctypes.byref(got),
|
|
63
|
+
ctypes.byref(ov))
|
|
64
|
+
if not ok:
|
|
65
|
+
err = ctypes.windll.kernel32.GetLastError()
|
|
66
|
+
if err == 38: # ERROR_HANDLE_EOF: a read at or past the end
|
|
67
|
+
return 0
|
|
68
|
+
raise OSError(err, f"ReadFile at offset {offset} of fd {fd}")
|
|
69
|
+
return int(got.value)
|
|
70
|
+
|
|
71
|
+
|
|
39
72
|
def read_bytes(fd: int, offset: int, nbytes: int, io) -> np.ndarray:
|
|
40
73
|
"""nbytes of the file at offset, read by the loader's workers into one buffer (page-aligned
|
|
41
74
|
spans; `preadv` may return short, so each span reads until it is full)."""
|
|
@@ -45,7 +78,7 @@ def read_bytes(fd: int, offset: int, nbytes: int, io) -> np.ndarray:
|
|
|
45
78
|
def _one(span):
|
|
46
79
|
a, b = span
|
|
47
80
|
while a < b:
|
|
48
|
-
got =
|
|
81
|
+
got = _read_at(fd, view[a:b], offset + a)
|
|
49
82
|
if got <= 0:
|
|
50
83
|
raise RuntimeError(f"weight read: {nbytes} bytes at offset {offset} of fd {fd} ended "
|
|
51
84
|
f"{b - a} bytes short (file truncated?)")
|
|
@@ -444,13 +444,13 @@ def _backend_content_hash(backend) -> str:
|
|
|
444
444
|
h = hashlib.sha256()
|
|
445
445
|
for name in getattr(type(backend), "CODEGEN_ENV", ()) or ():
|
|
446
446
|
h.update(f"{name}={name in os.environ}:{os.environ.get(name, '')}".encode())
|
|
447
|
-
files = sorted(f for f in pkg.rglob("*") if f.is_file() and f.suffix in (".py", ".so", ".dylib")
|
|
447
|
+
files = sorted(f for f in pkg.rglob("*") if f.is_file() and f.suffix in (".py", ".so", ".dylib", ".pyd", ".dll")
|
|
448
448
|
and "__pycache__" not in f.parts) if pkg.is_dir() else []
|
|
449
449
|
plugin = getattr(mod, "PLUGIN_LIBRARY", None)
|
|
450
450
|
if plugin is not None and Path(plugin).is_file() and Path(plugin) not in files:
|
|
451
451
|
files.append(Path(plugin))
|
|
452
452
|
for f in files:
|
|
453
|
-
h.update(
|
|
453
|
+
h.update((f.relative_to(pkg).as_posix() if pkg in f.parents else f.name).encode()) # "/" on every OS
|
|
454
454
|
h.update(hashlib.sha256(f.read_bytes()).digest())
|
|
455
455
|
return f"content-{h.hexdigest()[:16]}"
|
|
456
456
|
|
|
@@ -1115,6 +1115,20 @@ def _explain_miss(kernel_qual: str, key: tuple, memory_gb: Optional[int]) -> str
|
|
|
1115
1115
|
return f" (the application's explanation of the miss failed: {type(exc).__name__}: {exc})."
|
|
1116
1116
|
|
|
1117
1117
|
|
|
1118
|
+
def _not_served_because(raw: Dict[str, Any], here: Optional[int]) -> str:
|
|
1119
|
+
"""Why an entry the directory holds for this key is not served here: proven under another code generator than the
|
|
1120
|
+
running one (for this card's memory class), or on another memory class (register 56). The Mac's new-user run on the
|
|
1121
|
+
published Metal wheels (2026-11-07): every Apple entry carried the dev environment's generator and the line said
|
|
1122
|
+
"certified for 18 GB, this card is 18 GB, not served" — a memory class that matched, the cause unnamed."""
|
|
1123
|
+
covered = sorted(covered_memory_gbs(raw))
|
|
1124
|
+
gens, gen = sorted(proof_backends(raw)), running_generator()
|
|
1125
|
+
if here is not None and here in covered and gen is not None and gen not in gens:
|
|
1126
|
+
return (f"certified for this card's {here} GB under {', '.join(gens) or 'no named generator'}, and this machine "
|
|
1127
|
+
f"runs {gen}: not served — re-proven under it by `neurobrix autotune certify --reprove-generator`")
|
|
1128
|
+
return (f"certified for {', '.join(f'{c} GB' for c in covered) or 'no known memory class'}, this card is "
|
|
1129
|
+
f"{f'{here} GB' if here is not None else 'of unknown memory'}, not served (register 56)")
|
|
1130
|
+
|
|
1131
|
+
|
|
1118
1132
|
def refuse_missing(kernel_qual: str, tuner, key: tuple) -> None:
|
|
1119
1133
|
"""The certified-only answer to a miss: raised before any bench, naming the key, the profile,
|
|
1120
1134
|
why a directory entry (if any) is not served, and what the census says."""
|
|
@@ -1129,9 +1143,7 @@ def refuse_missing(kernel_qual: str, tuner, key: tuple) -> None:
|
|
|
1129
1143
|
try:
|
|
1130
1144
|
raw = lookup(kernel_qual, tuner, key, ignore_switch=True, any_class=True)
|
|
1131
1145
|
if raw is not None:
|
|
1132
|
-
|
|
1133
|
-
why = (f"; the directory certifies it for {', '.join(f'{c} GB' for c in covered) or 'no known memory class'} "
|
|
1134
|
-
f"and this card is {f'{here} GB' if here is not None else 'of unknown memory'} (register 56)")
|
|
1146
|
+
why = f"; the directory holds it: {_not_served_because(raw, here)}"
|
|
1135
1147
|
except Exception as exc: # noqa: BLE001 — the reason failed to compute: said, the refusal stands
|
|
1136
1148
|
why = f"; (could not read what the directory holds for it: {exc})"
|
|
1137
1149
|
raise KeyNotCertified(
|
|
@@ -1159,10 +1171,8 @@ def announce_missing(kernel_qual: str, tuner, key: tuple) -> None:
|
|
|
1159
1171
|
try:
|
|
1160
1172
|
raw = lookup(kernel_qual, tuner, key, ignore_switch=True, any_class=True)
|
|
1161
1173
|
if raw is not None:
|
|
1162
|
-
covered = sorted(covered_memory_gbs(raw))
|
|
1163
1174
|
here = executing_memory_gb(list((getattr(tuner, "nargs", None) or {}).values()) or None)
|
|
1164
|
-
why =
|
|
1165
|
-
f"this card is {f'{here} GB' if here is not None else 'of unknown memory'}, not served (register 56)")
|
|
1175
|
+
why = f" — {_not_served_because(raw, here)}"
|
|
1166
1176
|
except Exception as exc: # the reason failed to compute: say that, never an empty reason
|
|
1167
1177
|
why = f" — (could not read what the directory holds for it: {exc})"
|
|
1168
1178
|
print(f"[autotune] no certified setting for {kernel_short(kernel_qual)} {output_dtype(tuner, key)} "
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""A certified setting the directory holds but does not serve says why: proven under another code generator than the
|
|
2
|
+
running one, or on another memory class. The Mac's new-user run on the published Metal wheels (2026-11-07): every Apple
|
|
3
|
+
entry was proven under the development environment's generator, none was served, and the line said "certified for
|
|
4
|
+
18 GB, this card is 18 GB, not served (register 56)" — the memory class matched and the cause was not named.
|
|
5
|
+
|
|
6
|
+
What this test would do if the code were wrong: a generator mismatch reported as a memory class (red), a memory-class
|
|
7
|
+
miss reported as a generator (red)."""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from nbxtensor.ops import autotune_certified as C
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _entry(gen_version: str, memory_mb: int):
|
|
14
|
+
return {"proof": {"backend": {"triton": gen_version, "name": "metal"},
|
|
15
|
+
"machine": {"device": {"memory_mb": memory_mb}}}}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_a_generator_mismatch_on_the_right_memory_class_names_the_generators(monkeypatch):
|
|
19
|
+
monkeypatch.setattr(C, "running_generator", lambda: "triton 3.8.0+git4a15f415.nbx1 metal")
|
|
20
|
+
raw = _entry("3.8.0+git4a15f415", 18432)
|
|
21
|
+
gens = sorted(C.proof_backends(raw))
|
|
22
|
+
why = C._not_served_because(raw, 18)
|
|
23
|
+
assert why.startswith("certified for this card's 18 GB under "), why
|
|
24
|
+
assert gens[0] in why and "triton 3.8.0+git4a15f415.nbx1 metal" in why and "--reprove-generator" in why, why
|
|
25
|
+
assert "register 56" not in why
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_another_memory_class_is_said_as_such(monkeypatch):
|
|
29
|
+
raw = _entry("3.8.0", 32768)
|
|
30
|
+
monkeypatch.setattr(C, "running_generator", lambda: sorted(C.proof_backends(raw))[0])
|
|
31
|
+
why = C._not_served_because(raw, 16)
|
|
32
|
+
assert "certified for 32 GB, this card is 16 GB, not served (register 56)" == why, why
|
|
@@ -94,7 +94,7 @@ def test_doctor_on_a_mac_without_triton_names_the_command(monkeypatch, capsys):
|
|
|
94
94
|
from nbxtensor.backend import metal_backend
|
|
95
95
|
monkeypatch.setattr(metal_backend, "is_apple_silicon", lambda: True)
|
|
96
96
|
monkeypatch.setattr(metal_backend, "triton_metal_available", lambda: False)
|
|
97
|
-
assert main_mod.main(["doctor"]) ==
|
|
97
|
+
assert main_mod.main(["doctor"]) == 1 # nothing can run yet: said by the exit status too (the Mac, 04:21)
|
|
98
98
|
assert capsys.readouterr().out.strip() == (
|
|
99
99
|
"Apple GPU found; Triton for Metal not installed — run: python -m nbxtensor install-metal")
|
|
100
100
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|