Compare commits

...
849 Commits
Author SHA1 Message Date
wozeparrotandGitHub 9b14e8c3cd feat: tag 0.10.3 (#10310) 2025-05-14 15:45:13 -07:00
George HotzandGitHub 18f532d110 small changes from O(1) multi [pr] (#10309) 2025-05-14 15:34:07 -07:00
wozeparrotandGitHub 9bbc2bc2a7 hotfix: filter_too_much (#10308) 2025-05-14 15:31:51 -07:00
George HotzandGitHub fc8ef63194 multi doesn't need tuple arg anymore [pr] (#10307) 2025-05-14 15:16:40 -07:00
geohot 7a3d4de59a hotfix: add GRAPH_ONE_KERNEL=1 to UsbGPU openpilot test 2025-05-14 14:50:37 -07:00
wozeparrotandGitHub 2df2ec6640 feat: unpin hypothesis (#10306) 2025-05-14 14:26:28 -07:00
b52452d69f Remote multi (graph) (#9902)
* Remote multi (graph)

* Remote multi (graph transfers)

---------

Co-authored-by: George Hotz <[email protected]>
2025-05-14 10:54:23 -07:00
George HotzandGitHub 42e70193c9 multi: instead of real, just copy (#10289)
* multi: instead of real, just copy

* fix test

* remove real
2025-05-14 10:36:55 -07:00
qazalandGitHub 043efc6ec4 do not require self for track_rewrites [pr] (#10302) 2025-05-14 18:23:32 +03:00
uuuvnandGitHub dd816d0237 All MultiGraphRunners can graph transfers (#10301) 2025-05-14 17:23:02 +03:00
nimlgenandGitHub e00679dc92 am_smi: fix layout with sleep mode (#10300) 2025-05-14 15:44:42 +03:00
chenyuandGitHub fbaa26247a randn_like in minrf (#10298)
tested that it trains to similar loss
2025-05-14 07:59:50 -04:00
nimlgenandGitHub 0788659d08 usbgpu: fast cold boot (#10260)
* usbgpu: fast cold boot

* cleaner

* assert

* xx

* compat

* fix

* fix
2025-05-14 14:58:55 +03:00
qazalandGitHub d342f7688d remove some skips in test_schedule + use assertRaisesRegex [pr] (#10296) 2025-05-14 14:54:07 +03:00
qazalandGitHub 40f4ce3390 enable AMD CI for TestRandomness.test_multinomial [pr] (#10295) 2025-05-14 14:32:22 +03:00
nimlgenandGitHub 792853b9e2 usbgpu: enable cache for compute queue (#10294) 2025-05-14 13:05:36 +03:00
nimlgenandGitHub 1218fc2230 usbgpu: enable cache for 64bit addresses (#10293) 2025-05-14 12:37:39 +03:00
qazalandGitHub 1770e00c41 only CAPTURE_PROCESS_REPLAY=1 + add filterwarnings back [pr] (#10292) 2025-05-14 11:58:42 +03:00
qazalandGitHub 1c97338be5 enable process replay assert for schedule [pr] (#10280)
* enable process replay assert for schedule

* start at unique+1
2025-05-14 11:10:47 +03:00
George HotzandGitHub f1130ab3d3 openpilot benchmark test (#10290)
* openpilot benchmark test

* that
2025-05-13 22:49:28 -07:00
uuuvnandGitHub f726f79a9e Remote multi (transfer) (#10285) 2025-05-13 18:26:32 -07:00
uuuvnandGitHub 7bc4864bc4 Make dev a property of Allocator (#10286)
* Make `dev` a property of `Allocator`

(this is a prereq refactor for #10285)

At least `BufferXfer.copy` accesses it assuming it's always present,
currently most devices just add this property on their own repeating
the same code over and over again.

This is also a bit footguny, see `RemoteAllocator` that named this
property `device` instead of `dev`, i could obviously just change that
in one place but doing it globally seems like a better solution (and it
reduces code duplication too).

`MallocAllocator` is a bit special, but passing `None` works just fine.

* typing

* ignore type instead of cast
2025-05-13 17:01:01 -07:00
George HotzandGitHub ec46f658d7 openpilot llvm test [pr] (#10288) 2025-05-13 16:51:41 -07:00
uuuvnandGitHub 453b268342 Factor out remote connection and cache it (#10282)
Should be a small speed improvement but the main reason this is needed
is to have a defined ordering of RemoteRequests within one host so that
transfers won't required doing something like:
```python
src_dev.batch_submit()
dest_dev.q(Transfer(dest, src_dev.session, src))
dest_dev.batch_submit()
```
for correctness.
2025-05-13 15:02:06 -07:00
uuuvnandGitHub ddff9857b8 Remote properties is a dataclass (#10283)
Not strictly required for anything but soon there will be like 4 new
properties and having it be a huge json just seems like a bad taste.

It also seems right to not have a separate endpoint for this, just
`GetProperties` request that returns a repr of this similar to how
requests are sent in `BatchRequest`.

This will also make a switch to anything other than http much simpler
if it will be required for any reason, like just a tcp stream of
`BatchRequest`s
2025-05-13 11:56:58 -07:00
uuuvnandGitHub ba87eca0f1 Remote multi (basic) (#10269)
* Basic remote multi support

Simplest thing to be able to use remote with multiple gpus, very slow
because no transfers (copyin copyout for cross-device copies)

* tests
2025-05-13 09:52:47 -07:00
George HotzandGitHub 5f64bbc63d improve multi tests + add support for fixedvars [pr] (#10281)
* improve multi tests + add support for fixedvars [pr]

* add support for fixedvars
2025-05-13 09:27:00 -07:00
chenyuandGitHub 8a906cb124 Tensor.randn_like (#10276) 2025-05-13 11:53:59 -04:00
nimlgenandGitHub eab71d70ba usbgpu: rescan pci bus every run (#10279)
* usbgpu: rescan pci bus every run

* ff
2025-05-13 18:31:42 +03:00
chenyuandGitHub c4988bc07b only run test_u32_to_f16 if it supports fp16 (#10277)
* only run test_u32_to_f16 if it supports fp16

* cleanup
2025-05-13 11:16:14 -04:00
nimlgenandGitHub 9924c7d0e4 usbgpu: rebar (#10275)
* usbgpu: rebar

* cache back

* revert this

* fix

* ugh

* tt
2025-05-13 17:25:51 +03:00
uuuvnandGitHub 1900c3c68a Metal multi in ci is fine actually (#10274)
Useful for testing remote multi stuff
2025-05-13 10:07:35 -04:00
nimlgenandGitHub 6f42bf8b54 usbgpu: 10 steps in benchmark to hit cache (#10273) 2025-05-13 17:06:50 +03:00
ad5cb2717d FUSE_ARANGE=1 in bert bench (#10263)
still fails, something multi related maybe

Co-authored-by: qazal <[email protected]>
2025-05-13 09:12:19 -04:00
qazalandGitHub a2d6b0afe0 fix FUSE pushing through SHRINK (#10271) 2025-05-13 11:38:53 +03:00
geohotstanandGitHub 1c4ab6b991 ONNX add tests against ORT (#10270)
* start

* clean up

* indicate file location too
2025-05-13 04:03:52 -04:00
nimlgenandGitHub bb31cc4582 usbgpu: check hash in patcher (#10266) 2025-05-12 21:08:53 +03:00
uuuvnandGitHub 94907d02c8 Move session to RemoteRequest (#10264)
This is a prereq refactor for cloud multi which will make it possible to
use multiple devices from cloud host instead of just one.

I will do that via changing a session to be a `tuple[token, dev_idx]`

Previously the session was in cookies, this is a problem because a single
http request can contain many RemoteRequests with potentially different
devices.

The alternatives are either:

\- sending commands for different devices in separate http requests (slow)

\- only adding an idx in RemoteRequest in basically the same way i added
session here, keeping session a cookie and concat in server. This is how
i've done it previously and it looks just strictly worse than having it
all be in the same place.
2025-05-12 10:06:09 -07:00
Sieds LyklesandGitHub 02208565de add check (#10257) 2025-05-12 11:03:01 -04:00
nimlgenandGitHub 08ab184dfd usbgpu: copyin over 100mb/s (#10259)
* usbgpu: over 100mb/s

* align

* h
2025-05-12 16:52:43 +03:00
4c7c139102 Use cmod/cdiv in sym_infer (#10258)
* Use cmod/cdiv in sym_infer

* test

---------

Co-authored-by: chenyu <[email protected]>
2025-05-12 09:07:28 -04:00
chenyuandGitHub 0015b3921f sleep more in CI Remove amdgpu (#10261)
see if this is less flaky
2025-05-12 08:13:44 -04:00
qazalandGitHub 95c6a736a9 fix FUSE_ARANGE=1 for bert (#10255) 2025-05-12 14:44:05 +03:00
Sieds LyklesandGitHub 7c4b381fbf Extra simplify valid test [pr] (#10256)
* add test

* Change the range

* add todo test
2025-05-12 07:32:03 -04:00
7eeb35ba6f fix AMD LLVM compile error for bf16 cifar (#10254)
* fix AMD LLVM compile error

* remove llvm_bf16_cast

---------

Co-authored-by: b1tg <[email protected]>
2025-05-12 01:57:07 -04:00
uuuvnandGitHub a0ed1ec1ae Faster remote server (#10235) 2025-05-11 19:15:05 -07:00
41f5ece877 add nsw flag (#10249)
Co-authored-by: b1tg <[email protected]>
2025-05-11 19:14:32 -07:00
geohot 8864ff894b hotfix: that repeat_kv belongs outside the if 2025-05-11 18:43:01 -07:00
George HotzandGitHub 98c84a711d min rectified flow example [pr] (#10252)
* work on minrf example

* more

* jit sample

* t is tensor not const

* fixes

* more convs

* fix dropout

* don't print

* 504

* big patch

* onehot

* touch

* use embeddings

* dumb uses final layer

* act

* non fl

* match

* tp

* 3

* of

* ppsz

* normal

* add adln

* no t

* weird transformer

* weird transformer

* contig

* actual speed fix

* dumb

* cb

* 0

* t is 0

* mort-t

* args

* dumb days are over

* readable

* contig

* no more t mask

* mask_t

* init to zero

* clean

* steps

* work

* tt

* t

* solid
2025-05-11 18:36:44 -07:00
chenyuandGitHub 70c797b107 train bert tests (#10248)
added a working bert tiny test, and a failed bert FUSE_ARANGE test
2025-05-11 08:42:08 -04:00
b2df4cb696 add support for amdgpu-flat-work-group-size to AMD LLVM IR (#10246)
* add support for amdgpu-flat-work-group-size to AMD LLVM IR

* don't spam llvm init

---------

Co-authored-by: qazal <[email protected]>
2025-05-10 19:11:10 -07:00
qazalandGitHub 9210280811 add v_fmac_f16 vop3 instruction to remu (#10247)
* fmac vop3

* from the box
2025-05-10 23:48:25 +03:00
George HotzandGitHub 697259a8a1 amd_comgr_action_info_set_options was deprecated [pr] (#10245)
* amd_comgr_action_info_set_options was deprecated [pr]

* more standard
2025-05-10 11:59:04 -07:00
2e0990c4e9 even spacing in viz nodes (#10168)
* even spacing in viz nodes

* precise dy value

* dominant-baseline text-after-edge

* add STROKE_WIDTH constant, delete dominant_baseline attr

---------

Co-authored-by: qazal <[email protected]>
2025-05-10 10:35:10 +03:00
chenyuandGitHub d0e9b74f40 minor div_and_mod_folding cleanup [pr] (#10243)
remove type ignore and one walrus
2025-05-09 22:42:01 -04:00
Adam Van YmerenandGitHub a28ca0680f update dead link (#10242) 2025-05-09 19:59:52 -04:00
nimlgenandGitHub 2145bce3f9 usbgpu: copyin size is 16k (#10240)
* usbgpu: copyin size is 16k

* ush
2025-05-09 22:12:54 +03:00
74e40aafa0 use cdiv in div and mod folding (#10216)
* use cdiv

* use cdiv and cmod there as well

* Add tests

---------

Co-authored-by: chenyu <[email protected]>
2025-05-09 12:37:24 -04:00
Sieds LyklesandGitHub 8da9c070ca take gcd out of trunc div (#10238) 2025-05-09 12:08:10 -04:00
qazalandGitHub e2292f6663 TRACEMETA>=2 displays UOp metadata in VIZ (#10237) 2025-05-09 17:42:00 +03:00
qazalandGitHub d5686f33a9 delete KernelContext dataclass [pr] (#10236) 2025-05-09 17:36:21 +03:00
qazalandGitHub 467daf8d4c remap UOp metadata in graph_rewrite_map [pr] (#10234)
* remap metadata in graph_rewrite_map [pr]

* fix

* merge loops

* UOp.metadata returns Metadata|None

* shorter
2025-05-09 17:20:53 +03:00
nimlgenandGitHub 4c75b124b6 usb: copy into mv is faster (#10233)
* usb: copy into mv is faster

* missing

* bytes
2025-05-09 14:53:36 +03:00
nimlgenandGitHub d08ce62553 hcq: do not reread signal in wait (#10232) 2025-05-09 14:38:36 +03:00
nimlgenandGitHub 0464a31000 usbgpu: no overrun check needed (#10231) 2025-05-09 14:20:24 +03:00
nimlgenandGitHub 116390083f nvme speed write example (#10230) 2025-05-09 14:20:01 +03:00
chenyuandGitHub 9846435c2e fix test_div_numerator_negative (#10229)
the simplification was wrong with negative const_factor
2025-05-09 06:19:59 -04:00
chenyuandGitHub cba508c8c3 update uop symbolic tests (#10228)
clean up TODOs and update tests
2025-05-09 01:55:53 -04:00
chenyuandGitHub 56def6c319 better bound for mod negative number (#10227) 2025-05-09 01:19:47 -04:00
chenyuandGitHub 99f6d89dfb tighter idiv bound for symbolic denominator (#10226) 2025-05-08 22:38:56 -04:00
uuuvnandGitHub 82a6160ff7 Detect metal paravirtualization bug via device name instead of CI (#10225) 2025-05-08 19:31:47 -07:00
XingyuandGitHub a21369d039 Enhance tensor random functions with dtype support (#10214)
* Enhance tensor random functions with dtype support
- Updated `aten.uniform_` and `aten.normal_` to include dtype parameter in backend.py
- Added unit tests for uniform and normal tensor generation with specific dtypes in test.py

* Refactor test name for clarity
- Renamed `test_normal_dtype` to `test_normal` in `extra/torch_backend/test.py`
- Aims to improve readability and better reflect the test's purpose
2025-05-08 20:48:07 -04:00
qazalandGitHub b6904bbf83 Revert "split grouper into insert and finalize stages [pr] (#10222)" (#10224)
This reverts commit 2594e4db15.
2025-05-09 03:02:38 +03:00
qazalandGitHub 2594e4db15 split grouper into insert and finalize stages [pr] (#10222) 2025-05-09 02:36:22 +03:00
George HotzandGitHub 0b7e3e86d0 single device copy [pr] (#10221)
* single device copy [pr]

* simpler
2025-05-08 15:23:22 -07:00
qazalandGitHub 1d0f239df7 use Tensor.train() in schedule test + typo [pr] (#10220) 2025-05-08 23:46:42 +03:00
qazalandGitHub ff2aa6d0b2 buffer in create_kernel is optional [pr] (#10218)
* buffer in create_kernel is optional [pr]

* pylint
2025-05-08 22:35:55 +03:00
qazalandGitHub 40560e77c2 minor grouper + viz fixup [pr] (#10217)
* minor grouper + viz fixup [pr]

* gitignore mypy_cache

* reorder create_kernels

* replace with realized

* use tensor_map + viz before spec

* lint

* add that back
2025-05-08 21:39:44 +03:00
George HotzandGitHub 0411b09763 small changes from new multi [pr] (#10213) 2025-05-08 07:04:27 -07:00
a0580e8d3c Cleanup in div_and_mod_folding [pr] (#10178)
* Refactor binary var simplification

* Simplify the congruence logic

---------

Co-authored-by: George Hotz <[email protected]>
2025-05-08 06:25:32 -07:00
nimlgenandGitHub 267ba9b592 usbgpu: better names in copy speed benchmark (#10212) 2025-05-08 16:12:37 +03:00
hoovedandGitHub 7b4f05fd00 Add test for correctness of Infinity in WebGPU (#10201)
* use function for infinity instead of uniform

* test infinity math locally

* test infinity math in CI

* make pytest available to MacOS (WebGPU)

* revert to master except failing webgpu test
2025-05-08 05:20:05 -07:00
nimlgenandGitHub e24fe1c746 usbgpu: pci cache (#10207) 2025-05-08 14:31:01 +03:00
nimlgenandGitHub 7d6ed1b1e9 hotfix: mac ci (#10210)
* fixed?

* cmnt
2025-05-08 14:13:23 +03:00
nimlgenandGitHub ba52fce4b2 usbgpu: benchmark in ci (#10208)
* usbgpu: benchmark

* usbgpu: benchmark
2025-05-08 12:02:04 +03:00
qazalandGitHub d0e3449992 remove view_supported_devices, check allocator instead [pr] (#10209) 2025-05-08 11:45:02 +03:00
nimlgenandGitHub 5a7f6b4d8e am: fix launch on rdna4 (#10206) 2025-05-08 09:46:12 +03:00
George HotzandGitHub 8d4c563c01 all COPY can be clone (#10205)
* match old behavior

* simple

* it means the naive thing before the multi

* fix
2025-05-07 20:31:39 -07:00
hoovedandGitHub 8e76c40aea Refactor test: Enable generality in testing UOp alu expressions (#10200)
* use function for infinity instead of uniform

* test infinity math locally

* test infinity math in CI

* make pytest available to MacOS (WebGPU)

* revert to master except failing webgpu test

* isolate test refactor
2025-05-07 19:39:44 -07:00
George HotzandGitHub 83efc5d5bb lil changes from multi [pr] (#10202) 2025-05-07 14:42:30 -07:00
Rory ClearandGitHub 9f2931ae67 Fix yolo load failing silently (#10046)
* wait for js before loading model

* use f32

* revert html changes, try both cameras and remove f16 req

* clean
2025-05-07 11:46:09 -07:00
uuuvnandGitHub 10c9ede6b7 Cloud graph (#9876) 2025-05-07 11:41:41 -07:00
Sieds LyklesandGitHub 2891892834 Fold constant variable (#10196)
* Add rule

* add test and comment

* merge rule
2025-05-07 11:39:44 -07:00
Sieds LyklesandGitHub 8386527bb9 Take neg out of idiv (#10164)
* Add rules

* Fix tests

* Move rules lower to prevent recursion
2025-05-07 11:39:08 -07:00
qazalandGitHub e6c80a9e40 hotfix: early kwargs.pop('err') (#10197)
* hotfix: early kwargs.pop('err')

* err, no container
2025-05-07 23:53:26 +08:00
qazalandGitHub 3bc72f02d9 better error message for linearizer failures in viz [pr] (#10195) 2025-05-07 23:11:44 +08:00
09544d4556 Add rule and test (#10189)
Co-authored-by: chenyu <[email protected]>
2025-05-07 10:15:55 -04:00
nimlgenandGitHub c603b86d69 usbgpu: move queues to controller (#10194) 2025-05-07 16:41:16 +03:00
nimlgenandGitHub 0fbe494c6b usb: cache writes into 0xa000 (#10191)
* usb: cache writes into 0xa000

* mock

* match parent spec

* ugh
2025-05-07 16:03:35 +03:00
nimlgenandGitHub b8fb0f11ff hcq: parametrize signal allocation size (#10192) 2025-05-07 15:50:43 +03:00
nimlgenandGitHub 685d5c46df usbgpu: send pci write in batches (#10190)
* usbgpu: send pci write in batches

* mock
2025-05-07 14:41:56 +03:00
qazalandGitHub 3a32fa228c refactor merge_views matcher [pr] (#10188) 2025-05-07 19:22:06 +08:00
qazalandGitHub 94e07725a6 only reorder expand if it can fuse with input (#10186)
* failing test

* only reorder expand if it can fuse with input

* (16,) is reshaped to (4, 4)
2025-05-07 18:14:31 +08:00
qazalandGitHub 4ea3e373aa decode lds ops in remu (#10184) 2025-05-07 16:44:18 +08:00
uuuvnandGitHub dba073e5c0 Less messy broken graph on paravirtualized metal workaround (#10182)
* Less messy broken graph on paravirtualized metal workaround

GitHub CI macOS runners use paravirtualized metal which is broken with
graph (some comments say that ICB in particular is broken but in my
testing it was fine sometimes, but other times hitting an assert inside
metal's code related to resouces, so not sure).

> Assertion failed: (resource != nil), function -[IOGPUMetalResource initWithResource:], file IOGPUMetalResource.m, line 458.

This can be reproduced locally with any virtualization software (like utm)
that can create macOS VMs with apple's own virtualization framework.

* unused import
2025-05-06 20:41:02 +03:00
nimlgenandGitHub 59c03e8904 usbgpu: tiny changes in setup pci bars to match spec (#10181)
* usbgpu: tiny changes in setup pci bars to match spec

* unused
2025-05-06 20:39:03 +03:00
Ignacio SicaandGitHub 74c25bdc8b add support for ds_load_u8 in remu (#10180)
* add support for ds_load_u8 in remu

* add test for ds_load_u8
2025-05-06 20:31:00 +03:00
nimlgenandGitHub 10f115fdb0 usbgpu: USB_RESCAN_BUS envvar (#10177) 2025-05-06 17:09:36 +03:00
nimlgenandGitHub 781fd8c1eb usbgpu: some tlp error info (#10176)
* usbgpu: some tlp error info

* oops
2025-05-06 17:01:10 +03:00
nimlgenandGitHub aea1f77225 amd: uppercase amd_iface vals (#10175) 2025-05-06 15:12:50 +03:00
nimlgenandGitHub 34d55857cf usbgpu: more devs in scan_pci (#10171) 2025-05-06 11:55:34 +03:00
nimlgenandGitHub 37a7a99adb metal: fix graph when unrelated input buffers are not metal buffers (#10170)
* metal: fix graph when unrelated input buffers are not metal buffers

* tinier test
2025-05-06 11:37:16 +03:00
George HotzandGitHub 603c03bef2 fix tests for rewrite [pr] (#10167)
* fix tests for rewrite [pr]

* cleaner

* delete linearize_uop

* clean up the rest
2025-05-05 19:19:49 -07:00
wozeparrotandGitHub 10437904cd refactor: ops_cloud -> ops_remote [pr] (#10166) 2025-05-05 15:59:51 -07:00
uuuvnandGitHub b4dfb3ba78 A bit less convoluted jit capability detection (#9923)
Required for cloud multi stuff to know if graph supports transfers and
if graph is on the same host (multi-host graphs are not supported)
2025-05-05 09:16:18 -07:00
Sieds LyklesandGitHub 338f33efae Fast mod (#10055)
* Enable fast mod

* Add test
2025-05-05 09:15:43 -07:00
Kevin BuhlerandGitHub 363481e2fb correct mispelled words (#10165) 2025-05-05 08:12:41 -07:00
nimlgenandGitHub 98f4a831c8 am: do not alloc cwsr buffer (#10163) 2025-05-05 15:40:23 +03:00
qazalandGitHub ed552e99f6 cleaner llvmir masked load render [pr] (#10161) 2025-05-05 15:22:01 +08:00
qazalandGitHub 62e86bc5ec insert Ops.FUSE for arange (#10140)
* insert Ops.FUSE for arange

* reshape does not collapse

* do not fuse reshapes

* add children

* fixups

* work

* add Ops.WHERE support to z3

* fix fuse for cast

* diff

* ugh

* don't need this anymore

* contiguous

* add always_contiguous

* there too
2025-05-05 08:32:12 +03:00
qazalandGitHub cf626e23cb rename to ALWAYS_CONTIGUOUS [pr] (#10160) 2025-05-05 08:14:56 +03:00
George HotzandGitHub b68f036551 default on OSX is llvm 19 (#10159) 2025-05-04 18:13:50 -07:00
geohot e07d8b147a hotfix: don't OOM in the osx unit test 2025-05-04 17:53:55 -07:00
George HotzandGitHub 19cda7eb3a bitcast isn't needed for llvm pointers (#10158)
* bitcast isn't needed for llvm pointers

* downgrade to llvm 19

* Revert "downgrade to llvm 19"

This reverts commit 3777801b4b.

* fix llvm 20 bug

* Revert "fix llvm 20 bug"

This reverts commit edc1e053fa.
2025-05-04 17:30:45 -07:00
George HotzandGitHub a0240d8c2b lil work on llvm speed (#10157)
* lil work on llvm speed

* llvm failing test

* 1e-4

* simpler failing test

* once is fine

* gpt suggests this syntax change

* bump that debug
2025-05-04 16:37:26 -07:00
George HotzandGitHub 36ccaa88a6 move merge views [pr] (#10156)
* move merge views [pr]

* move flow to __init__ [pr]
2025-05-04 14:41:47 -07:00
George HotzandGitHub 5f3f162606 cache rewrites for renderer [pr] (#10155)
* add caching to rewrites for renderer [pr]

* remove that

* update ebs
2025-05-04 13:45:15 -07:00
George HotzandGitHub fe0724eebf prebuild all rewrites [pr] (#10154)
* prebuild all rewrites [pr]

* fix that

* tests pass with linearizer
2025-05-04 13:01:18 -07:00
geohot 2b055cb59c hotfix: add BLOCKFINAL op 2025-05-04 12:26:29 -07:00
George HotzandGitHub c64fb31bb7 simple reduce w/o devectorize [pr] (#10153)
* simple reduce w/o devectorize [pr]

* useful upgrades

* refactor to horizontal

* or_broadcasted
2025-05-04 08:42:02 -07:00
b38be2588f Graph support for LLVM (#10029)
* Graph support for LLVM

* Always inline functions

* Specify renderer class only once

* Improve formatting

* Fix indexing

* Rollback parameter name change

* Force CI rerun

---------

Co-authored-by: George Hotz <[email protected]>
2025-05-04 06:52:55 -07:00
848c7783a4 Sign check in div const div pattern (#10150)
* Add rule

* Relax the condition

* Add test

---------

Co-authored-by: chenyu <[email protected]>
2025-05-03 18:04:34 -04:00
nimlgenandGitHub cda72c1de6 amd: print full trace when AMD_IFACE is set (#10149) 2025-05-03 22:46:04 +03:00
George HotzandGitHub 7c33924a50 don't use real_size for mem_bytes [pr] (#10147) 2025-05-03 09:41:21 -04:00
qazalandGitHub 42cbf7aed4 more viz cleanups + notes [pr] (#10145) 2025-05-03 15:57:56 +08:00
qazalandGitHub d8cc1fd2f8 viz minor fixups (#10143)
* properly scroll sub rewrites into view

* fix resizer for right sidebar
2025-05-03 03:50:14 +03:00
qazalandGitHub 230a369708 remove some IGNORE_OOB [pr] (#10142)
* remove some IGNORE_OOB

* remove fuzz_schedule stuff

* test with global

* add for amd ci
2025-05-03 01:16:14 +03:00
qazalandGitHub 1ed5d733bd disable TRACK_MATCH_STATS for type_verify (#10141) 2025-05-02 20:59:19 +03:00
nimlgenandGitHub 993f0a0e87 am: a bit faster alloc (#10138)
* am: a bit faster allocs

* am: faster allocs
2025-05-02 16:03:42 +03:00
nimlgenandGitHub 81410befc2 am: remove sleep from wait_reg (#10139)
* am: remove sleep from wait_reg

* fst

* ooops
2025-05-02 15:46:29 +03:00
nimlgenandGitHub 45bf7c5b81 am: add allocation bench (#10135)
* init allocation bench

* sorryg

* betetr
2025-05-02 13:51:07 +03:00
nimlgenandGitHub 6a845c2de2 amd: fix sigs on xcc path (#10137) 2025-05-02 13:50:56 +03:00
nimlgenandGitHub bdd4dd9238 am: do not expect aligned size in valloc (#10136) 2025-05-02 12:19:59 +03:00
Ignacio SicaandGitHub 8f79492c75 fix test_tensor_cores_codegen for ptx renderer (#10119) 2025-05-01 21:52:36 -03:00
30bd6a619f usb gpu (#8766)
* start gpu

* progress

* fixes

* read correct

* libusb

* libusb works

* support asm24

* hmm

* one access file

* fix extra

* start AMBar

* works on am

* back to usb

* patch fw

* full fast write into a bar

* ugh, minus one gpus, next please

* mute libusb for now

* usb for asm24

* 63

* hmm

* ops

* rescan

* and gpu shoudl be there

* enumerate them?

* usbgpu bus 4, 100% reliable (draft)

* lil

* works

* comments

* add DEBUG

* cleaner

* simplest

* Revert "simplest"

This reverts commit 1d00354c16.

* Revert "cleaner"

This reverts commit c5662de956.

* assert we find gpu

* that's simpler

* this back

* simpler?

* correcT

* work

* nonsense

* works with more checks

* this works

* the 6s in the right place

* reliable now

* fix after reboot

* set config

* 1s timeouts

* close to fw loading

* streams

* usbhub works

* endpoints

* fix

* want to test tiny10

* move to tiny 10

* fix gpu

* ugly speed

* smth

* mostly broken, but signals and dmas

* do not reset gpu every time

* changes to run kernels

* ugh, not working

* t10

* pg and sc files

* some prog

* um?

* somehow it works

* patched for 24

* some tries

* minimal

* moving

* back to working

* so sloooooow

* move to controller

* usb.py rewrite

* rework

* cleaner 1

* cleaner 2

* cleaner 3

* new abstractions

* aft merge

* init controller

* cleaner 4

* cleaner 5

* patcher + tiny changes

* ignore that

* cleaner 6

* after rebase

* cleaner 7

* bring it back

* start linter war

* linter 2

* autogen was missing

* fix autogen

* typing

* better?

* mypy

* extra/legacy rename and cleaner

* shuffle

* better printing

* tiny changes and tests

---------

Co-authored-by: George Hotz <[email protected]>
2025-05-01 18:03:47 +03:00
nimlgenandGitHub 7573c0ef4e amd,nv: use .cpu_view() in bind (#10131) 2025-05-01 17:46:12 +03:00
nimlgenandGitHub 16e5376ae8 line limit 12800 for usb (#10130) 2025-05-01 16:57:44 +03:00
qazalandGitHub 0c59c6b8c7 remove replace from Tensor assign [pr] (#10127)
* remove replace from Tensor assign

* assign is contiguous

* allow chaining view

* only assert axis
2025-05-01 19:37:55 +08:00
nimlgenandGitHub 9caceda79a amd: comgr is not required (#10128) 2025-05-01 13:41:44 +03:00
nimlgenandGitHub c3d2e4a6e1 amd: use sdma to copy program (#10126)
* amd: use sdma to copy program

* rm

* ensure prog is copies

* match nv style
2025-05-01 13:04:22 +03:00
nimlgenandGitHub 09f5be9bcb amd: finalize device in case of failures (#10124) 2025-05-01 10:41:15 +03:00
George HotzandGitHub ef011ff5f9 flip Ops.COPY order [pr] (#10122)
* flip Ops.COPY order [pr]

* fix copy and support multi device copy in _device
2025-05-01 00:26:24 -04:00
chenyuandGitHub 145e51247a split CAST and BITCAST in PYTHON [pr] (#10123)
CAST only needs truncate and does not require dtype fmt. added bfloat16 tests can run locally
2025-04-30 23:27:35 -04:00
Ignacio SicaandGitHub bf5fb97498 fix AMD_LLVM bf16 tc for gfx1100 (#10102)
* fix amd_llvm bf16 tc

* cleanup pattern
2025-04-30 20:06:38 -03:00
George HotzandGitHub dd0070daab Revert "flip Ops.COPY order [pr] (#10120)" (#10121)
This reverts commit 984f09ac74.
2025-04-30 17:25:21 -04:00
George HotzandGitHub 984f09ac74 flip Ops.COPY order [pr] (#10120) 2025-04-30 16:50:18 -04:00
chenyuandGitHub 17d4d258ea simple symbolic slice in llama [pr] (#10112)
support slice that has step None and stop > start
2025-04-30 14:36:35 -04:00
nimlgenandGitHub b583ece8f3 amd: replace AMD_DRIVERLESS with AMD_IFACE (#10116)
* amd: replace AMD_DRIVERLESS with AMD_IFACE

* docs

* print direct err for amd_iface

* print for all
2025-04-30 20:22:02 +03:00
nimlgenandGitHub 0e1beaf44f nv: align copies + better test (#10118) 2025-04-30 20:09:53 +03:00
Ignacio SicaandGitHub 2941537250 cast is noop if src has dtypes.void (#10110) 2025-04-30 13:55:41 -03:00
nimlgenandGitHub fcdda4fc09 am: move boot memory to vram start (#10115) 2025-04-30 19:12:19 +03:00
nimlgenandGitHub 844d5577d8 hcq: make copy_bufs and kernargs_size params configurable per device (#10114) 2025-04-30 18:43:50 +03:00
nimlgenandGitHub 2ec3b722e2 nv: fix copies larger than 4g (#10117) 2025-04-30 18:43:17 +03:00
George HotzandGitHub d81acbeef6 multi: move shrink after copy (#10109)
* multi: move shrink after copy

* passing now
2025-04-30 10:29:51 -04:00
qazalandGitHub 67bd8489ad grouper cleanups [pr] (#10113) 2025-04-30 18:54:47 +08:00
nimlgenandGitHub b4c9a3d8f4 hcq: use mmio iface in copies (#10111)
* hcq: use mmio iface in copies

* linter

* fix_am

* am
2025-04-30 11:05:13 +03:00
nimlgenandGitHub 5c7d004da5 hcq: refactor int ptrs to hcqbuffers (#10105)
* hcq: refactor int ptrs to hcqbuffers

* more refactors

* linter

* use in allocator

* test fiz

* fx

* ops

* final?

* simpler

* keep this for now
2025-04-30 00:12:18 +03:00
chenyuandGitHub 573bbb9746 Revert "remove TransformerBlock contiguous in llama (#10104)" (#10108)
This reverts commit b8d07dcc54.
2025-04-29 15:28:38 -04:00
chenyuandGitHub 4a04098389 fix llama3 with nf4 quantize (#10107)
also int8 outputs is wrong
2025-04-29 15:14:36 -04:00
George HotzandGitHub 9c1b80499f names for graph rewrites + null device supports exp and friends (#10106) 2025-04-29 14:28:20 -04:00
chenyuandGitHub b8d07dcc54 remove TransformerBlock contiguous in llama (#10104) 2025-04-29 14:15:39 -04:00
Ignacio SicaandGitHub 9d5677c12c fix ptx linearizer bug 2 [pr] (#9967)
* check for local buffer

* hotfix

* add test_tensor_cores_emulation run for ptx
2025-04-29 14:30:07 -03:00
qazalandGitHub a59d18da21 hack for VIZ=1 with examples/llama (#10103)
* hack for VIZ=1 with examples/llama

* move it alongside BEAM=0
2025-04-29 23:42:17 +08:00
qazalandGitHub 93bf8764f2 do not open devices in lowering (#10101)
* do not open devices in lowering [pr]

* ctx=opts

* ctx

* fuzz test
2025-04-29 23:18:16 +08:00
George HotzandGitHub c3ff308abb range has only one src now [pr] (#10100)
* range has only one op now

* fix z3 checker

* ci fix

* needs shell

* try pip ensure update

* that ensurepip is useless

* upgrade pip before cache

* windows happy?
2025-04-29 10:31:05 -04:00
geohot 427471550a hotfix: amd tflops to 74 and some external_benchmark_sdxl_softmax stuff 2025-04-29 09:02:27 -04:00
Ignacio SicaandGitHub 58cf8cd493 add support for "shared_mem" for LLVM (#10093)
* init llvm shared

* add test_tensor_cores_emulation run for llvm
2025-04-29 08:56:36 -04:00
qazalandGitHub ad7546c931 assert in test_indexing_two_bind instead of silent fail (#10099)
* assert in test_indexing_two_bind instead of silent fail

* debuggable

* skip test_simple_train
2025-04-29 20:23:25 +08:00
cee220a1ab always expand ssa on wheres (#9697)
Co-authored-by: qazal <[email protected]>
2025-04-29 20:08:41 +08:00
qazalandGitHub 3b67f56c02 kernelize some llama realizes (#10098) 2025-04-29 18:39:56 +08:00
qazalandGitHub cbf7347cd6 display viz rewrites with tabbing if they are subrewrites (#10097)
* display viz rewrites with tabbing if they are subrewrites

* update viz api
2025-04-29 17:57:21 +08:00
George HotzandGitHub 73c2f6602f test sdxl softmax (#10096) 2025-04-28 21:55:50 -04:00
George HotzandGitHub eaceafecae do fusion locally (#10095)
* do fusion locally

* oops, that's the right way

* explicit delete closure
2025-04-28 20:45:37 -04:00
chenyuandGitHub 3eba3d6ee9 don't pass model in convert_from_huggingface and convert_from_gguf (#10094)
it only needs n_layers
2025-04-28 20:11:19 -04:00
George HotzandGitHub a2d0684fc1 test_attention_simple_view (#10092)
* test_attention_simple_view

* correct comment
2025-04-28 20:01:22 -04:00
Ignacio SicaandGitHub bda116d773 fix use_tensor_cores propagation (#10048)
* propagate use_tensor_cores

* add use_tensor_core to arg in test and search

* bugfix

* get TC val from ContextVar in search

* revert minor space change

* add tc emulation test to ci and benchmark

* revert

* revert whitespace change

* remove test for ptx

* add comment and remove llvm test run
2025-04-28 19:30:50 -03:00
George HotzandGitHub d32f5e9f3a improve rendering of shapes in viz + investigate symbolic [pr] (#10091) 2025-04-28 16:44:09 -04:00
Sieds LyklesandGitHub dbb7aee02e Split constant in div with negative x (#10088)
* add rule

* change test

* lower complexity limit

* remove offset in fold_unrolled_divs

* remove import

* add one more condition
2025-04-28 16:24:14 -04:00
chenyuandGitHub 610ee79b22 cherry pick mlperf5.0 branch to master (#10089) 2025-04-28 15:36:56 -04:00
chenyuandGitHub 459a223202 simpler Literal annotation in code_for_workitem [pr] (#10087) 2025-04-28 14:59:25 -04:00
nimlgenandGitHub dcd9a633c3 am: load minimum fw (#10083)
* am: load minimum psp parts

* try thos

* remove me & pfp
2025-04-28 21:28:05 +03:00
George HotzandGitHub ecff82a698 fixing single kernel softmax: resolve (#10086)
* fixing single kernel softmax: resolve

* add failing lin test
2025-04-28 13:46:20 -04:00
geohot 4c242b0483 hotfix: tests all pass on metal local 2025-04-28 12:09:00 -04:00
690dac79b5 don't modify the ranges on reduce rewrite (#10062)
* bug in div range folding

* simpler

* oh, this is right for indexing, but the div mod folding needs to be fixed

* reenable

* Passing test_complexity_w_unroll2 (#10068)

* Passing

* remove non_folded_divs

* Add check for negative tern in div folding

* Add test

* bump that limit

* fix casted

---------

Co-authored-by: Sieds Lykles <[email protected]>
2025-04-28 12:01:19 -04:00
quortusandGitHub 5130759605 Make sure clang always inline batched functions (#10037) 2025-04-28 10:48:24 -04:00
George HotzandGitHub c4a50f9d89 fix full shape in kernel.py [pr] (#10085)
* fix full shape in kernel.py

* fix that heuristic

* full shape in shapetracker is fast

* fix process replay [pr]

* simpler

* this

* i'm just going to ignore that one
2025-04-28 09:32:58 -04:00
qazalandGitHub ac37510f60 remu: only write v_cmp result if exec is set (#10084) 2025-04-28 20:31:52 +08:00
qazalandGitHub d6b436a815 remu bugfix with -0.0 negation (#10082) 2025-04-28 15:46:42 +08:00
nimlgenandGitHub 15e4302784 am: optimize zeroing out boot structs (#10081) 2025-04-28 10:15:32 +03:00
nimlgenandGitHub 68e5ab8552 am: fix typo in fw loading (#10080) 2025-04-28 09:45:00 +03:00
chenyuandGitHub e996584685 olmoe in mac benchmark (#10077) 2025-04-27 21:07:02 -04:00
George HotzandGitHub 732e172961 don't require contiguous after fuse (#10074) 2025-04-27 13:17:22 -04:00
qazalandGitHub 1aed04ec12 cpu is ground truth in VALIDATE_WITH_CPU=1 [pr] (#10067) 2025-04-28 01:14:21 +08:00
George HotzandGitHub 129bddde74 lin failure from SINGLE_KERNEL_SOFTMAX (#10073)
* lin failure from SINGLE_KERNEL_SOFTMAX

* fix lin issue

* more pure diff
2025-04-27 13:02:10 -04:00
geohot b341296304 hotfix: save sdxl ram 2025-04-27 12:09:45 -04:00
George HotzandGitHub 68c5f7ba80 load fast in sdxl (#10072)
* load fast in sdxl

* back to that with the ret

* no context
2025-04-27 11:58:51 -04:00
George HotzandGitHub 768eb94c3e disable debug for load_state_dict [pr] (#10070) 2025-04-27 11:11:56 -04:00
geohot 4b8ef6ce78 hotfix: sdxl corealize 2025-04-27 10:41:46 -04:00
George HotzandGitHub b6d2effaf5 assign is contiguous (#10066)
* assign is contiguous

* disable process replay for SDXL
2025-04-27 08:40:33 -04:00
George HotzandGitHub 1253819151 make beautiful indexing use a Variable (#10063)
* make beautiful indexing use a Variable

* stunning test

* better color

* training is broken

* fix tests

* fix variable indexing

* fix test

* no contiguous

* revert that

* revert that too

* indexing two bind

* skip for webgpu

* make not slow
2025-04-27 08:22:38 -04:00
Rory ClearandGitHub a13a43c4fe yolo 416 to 640 res (#10047) 2025-04-26 20:45:58 -04:00
chenyuandGitHub 4c1ce1a299 don't simplify if div folding resulted in negative numerator (#10064)
* don't simplify if div folding resulted in negative numerator

* test
2025-04-26 17:01:18 -04:00
George HotzandGitHub 1805403821 fix rand arange folding (#10060)
* test rand range

* --amend

* fix rand arange folding

* reduce_rangeless fix
2025-04-26 12:24:05 -04:00
qazalandGitHub d13c100981 don't sort dims in verify_sink_dims [pr] (#10059)
* don't sort dims in verify_sink_dims [pr]

* 1 can exist with n

* put process_replay warn last

* assert shape is the same

* bring that back
2025-04-26 23:24:30 +08:00
George HotzandGitHub c80fe6d5fc handle some fancier reduces (#10057)
* reduce_unparented

* handle fancier reduces

* fold more

* bugfix
2025-04-26 11:20:15 -04:00
nimlgenandGitHub e08270c1ba nv: fix program init for no-args kernels (#10058) 2025-04-26 18:08:53 +03:00
George HotzandGitHub 11113c9d07 reduce_unparented (#10056) 2025-04-26 09:48:16 -04:00
George HotzandGitHub ea5dddc537 reduce collapse generic (#10045)
* reduce collapse generic

* new arange folder

* new range folding

* correct with sym

* all tests pass

* indexing ops passes

* failing tests

* fix tests, remove unused

* revert that

* torch indexing is fast

* skip on webgpu

* touchups

* comments
2025-04-26 09:13:24 -04:00
quortusandGitHub 5cdc96409e Update outdated renderer.render calls (#10044) 2025-04-26 07:35:19 -04:00
nimlgenandGitHub e055b9422f am: fix mmap failures (#10054) 2025-04-26 14:21:28 +03:00
qazalandGitHub e1d2b64e92 remu new instructions (#10050)
* remu new instructions

* test_ds_store_half

* test_v_mul_f16
2025-04-26 02:04:12 +03:00
qazalandGitHub bba5d0a3e4 remu refactors (#10028)
* remu refactors

* scc is sgpr 253

* remove that

* rename to vcc_lo

* run cargo test in CI

* llvm-mc

* meh

* work

* work_group work 1

* seeded_lanes is dumb

* better than seeded_lanes

* does not need to be address

* 128 sgpr per wave

* scc is sgpr, we don't know which one

* null_src once more

* derive clone, wave init is cleaner

* init comes first
2025-04-26 04:31:10 +08:00
nimlgenandGitHub 0fc85a2b0a hcqfuzz: init (#10049)
* hcqfuzz: init

* fix fuzz

* linter

* graph

* taht test

* update readme
2025-04-25 23:19:21 +03:00
qazalandGitHub b30050e287 fix amdgpu_disassemble on mac [pr] (#10042) 2025-04-25 15:23:11 +08:00
George HotzandGitHub a197aa4ef3 upat reduce syntax [pr] (#10040)
* upat reduce syntax [pr]

* switch z3 to graph_rewrite
2025-04-24 22:05:28 -04:00
Ignacio SicaandGitHub 76a86735c0 hotfix amd bf16 is supported case (#10039)
* hotfix amd and amd_llvm

* bf16 not supported in ci

* hotfix amd_llvm is not a device

* remove default

* dont gate on ci and amd_llvm

* minor cleanup

* skip bf16 tc test for amd_llvm
2025-04-24 21:29:27 -03:00
Ignacio SicaandGitHub b4f823acbe fix helper_tc_allclose (#9606)
* fix helper_tc_allclose

* cleanup

* hotfix

* cleanup

* cleanup

* check real buffer and add cast for bf16

* cleanup

* fix padded for ops_python

* avoid assert on amd emulated tc

* swap dimensions

* revert, should have nothing to do with padded

* revert fix, should not go in this pr

* remove skip
2025-04-24 18:36:40 -03:00
3a189fa561 More yolo processing in tinygrad (#9928)
* more tg less np

* update webgpu html for new compile

* resize boxes

* remove text

* add back note

* fix indentation

* fix indentation

* remove magic num

* remove now unused funcs

* back to numpy nms

* no loop

* fix iou suppression

* update test

* dont suppress other classes

* add working scale

* fix expected value, rounded up 0.24 was being counted

* add postprocess bool for onnx test

* fix indents

* clean

* clean

* fix indent

* remove print

* fix indent

* remove unused import

* remove hardcoded 0.25

* space

* spacing

* clean label_predictions func

* remove single item lists

* space

* use postprocess output in test

* space

* clean

* clean

* remove redundant threshold

* remove redundant threshold

* clean

* rename var

* move loop into func

* unhardcode iou_threshold

* remove unused values

* clean

* add note

* clean

* keep const

* move back funcs

---------

Co-authored-by: George Hotz <[email protected]>
2025-04-24 16:21:46 -04:00
chenyuandGitHub 74c6cf8be3 lint mlperf model_train (#10038) 2025-04-24 16:19:44 -04:00
Ignacio SicaandGitHub 51ca19d061 set test_tensor_cores_padded_amd to expectedFailure (#10036)
* init

* add expected failure to correctly track progres

* hotfix

* skip for amd_llvm as well

* add skip

* add pr number

* move comment to amd test

* change reason
2025-04-24 17:11:40 -03:00
914d89fa0b fix tensor cores for gfx1201 (#9838)
* fix tensor cores for gfx1201

* fix typo

* fix python wmma

* AMDLLVMRenderer with arch + AMDLLVM tensor_cores

* fix ci

* clean up

* more tensor cores for RDNA4

* fix half/half, bfloat16/float, bfloat16/bfloat16 for amd_llvm

---------

Co-authored-by: nimlgen <[email protected]>
Co-authored-by: George Hotz <[email protected]>
2025-04-24 14:57:41 -04:00
779aa1e2e9 Enable image tests on cloud if clouddev supports image (#9903)
Co-authored-by: George Hotz <[email protected]>
2025-04-24 14:30:12 -04:00
uuuvnandGitHub 29a12b19ea Add macos CLOUD tests (#10033)
A lot more work is required to enable all of them and move into osxtests
matrix, for now i created a separate runner for them (copied from WebGPU)

Will add test/test_graph.py to those tests in #9876
2025-04-24 14:14:13 -04:00
Nishant RajadhyakshaandGitHub 55942a8d8e [Bounty] moved index_tensor off cpu in torch_backend (#9916)
* moved index tensor off cpu in torch_backend

* added support for None based indexing

* fix_to_pass_tests

* fix segfault tests
2025-04-24 14:12:37 -04:00
Ignacio SicaandGitHub 373ca59b7f use is_dtype_supported to check dtype support in tc tests (#10035) 2025-04-24 14:59:14 -03:00
Ignacio SicaandGitHub 93a1e9eeb9 improve bf16 case for is_dtype_supported [pr] (#10034)
* fix is_dtype_supported for bf16

* hotfix

* add llvm and amd_llvm

* gate on machine

* separate gpu vs cpu cases

* add arm case
2025-04-24 14:03:57 -03:00
uuuvnandGitHub 754d789f51 Fix and enable jit tests on CLOUD (#10031) 2025-04-24 18:39:31 +03:00
qazalandGitHub 0b482fb824 add RDNA3 parser to remu (#10025)
* llvm ref

* work

* all of them

* salu

* cleaner

* start

* vector ops

* done

* replace SMEM

* vopd

* sop1

* SOPC

* null stays null_src

* sopp

* SOPK

* sop2

* vop1

* vop2

* remove allow(dead_code)

* vopc
2025-04-24 21:34:07 +08:00
uuuvnandGitHub 0d903c9495 Print clouddev instead of cloudev's renderer (#10023)
This is kind of a bug because currently with DEBUG>=1 it will say that
remote has device and then an array of renderer props instead of a real
device name which doesn't make sense:

```
127.0.0.1 - - [24/Apr/2025 16:50:44] "GET /properties HTTP/1.1" 200 -
remote has device ['tinygrad.renderer.cstyle', 'MetalRenderer', []]
opened device CLOUD from pid:20210
```

Now it will actually print the name of device behind cloud:

```
127.0.0.1 - - [24/Apr/2025 16:56:29] "GET /properties HTTP/1.1" 200 -
remote has device METAL
opened device CLOUD from pid:20315
```
2025-04-24 09:32:08 -04:00
George HotzandGitHub aec75f51ef fixup some slow CI tests [pr] (#10027)
* fixup some slow CI tests [pr]

* shrink test index
2025-04-24 09:20:49 -04:00
qazalandGitHub c990aac2b1 skip flaky test_transcribe_file1_OOB (#10026) 2025-04-24 21:09:43 +08:00
George HotzandGitHub 4e2ccfddc6 ci refactor to split AMD/NVIDIA [pr] (#10024)
* ci refactor to split AMD [pr]

* split

* split amd tests

* explicit 0
2025-04-24 08:59:54 -04:00
uuuvnandGitHub 0c68e44d6f Cloud properties (#10021) 2025-04-24 08:17:01 -04:00
geohot db00d88415 hotfix: handle bad z3 install like z3 import fail 2025-04-24 08:09:40 -04:00
e75be6eafc [bounty] [pr] index validation with z3 (#9981)
* index validation with z3

* Change comment

* toposort -> toposort()

---------

Co-authored-by: George Hotz <[email protected]>
2025-04-24 08:06:08 -04:00
9e49721c47 CPUGraph support for clang (#10014)
Co-authored-by: George Hotz <[email protected]>
2025-04-24 07:52:35 -04:00
Park JunandGitHub c3ad7b2a84 create randperm and support pytorch backend (#10019) 2025-04-24 07:29:02 -04:00
Matthew DaiterandGitHub b545338e59 isin_Tensor_out added (#10018) 2025-04-24 07:26:51 -04:00
chenyuandGitHub a25abf55e3 retinanet only call postprocess_detections with RUNMLPERF (#10017)
during setup only need to compile `_eval_step().numpy()`
2025-04-23 20:45:38 -04:00
nimlgenandGitHub 7f53e80db9 hotfix: amd mmio on mi300 (#10016)
* hotfix: amd mmio on mi300

* fix

* ops
2025-04-24 01:08:18 +03:00
nimlgenandGitHub 1c5e353249 am: use mmio iface (#10012)
* am: use mmio iface

* linters

* fixes

* fixes + cleanups

* mute

* mypy

* style
2025-04-24 00:27:04 +03:00
chenyuandGitHub 65faa1d94b explicit device in mlperf scripts (#10015) 2025-04-23 17:11:52 -04:00
chenyuandGitHub a3f938dbee remove retinanet INITMLPERF from beam script (#10011)
it only controls logging, loading real data or not is solely controlled by RUNMLPERF
2025-04-23 14:32:54 -04:00
nimlgenandGitHub cc52b9c528 am: add entry() to PT (#10010) 2025-04-23 20:45:52 +03:00
nimlgenandGitHub c952cb965e amd: use mmio iface (#9997)
* amd: use mmio iface

* mypy

* rename
2025-04-23 20:13:00 +03:00
Francis LataandGitHub 5542aeb0e4 RetinaNet MLPerf flag updates (#10009)
* add RUNMLPERF and update INITMLPERF usage

* update scripts to use RUNMLPERF
2025-04-23 13:00:34 -04:00
George HotzandGitHub de0504276b pop 0 is slow [pr] (#10007) 2025-04-23 17:00:59 +01:00
chenyuandGitHub d3a8d5c128 print postprocess_detections time in retinanet eval (#10005)
`BS=96 BASEDIR="/raid/datasets/openimages" MODEL=retinanet python examples/mlperf/model_eval.py`

```
...
loaded dataset             @  8.64s
loaded initial data        @ 12.57s
******  619.97 ms to enqueue, 46042.13 ms to realize ( 116.22 ms fetching, 45399.58 ms postprocess_detections).     0.09 examples/sec.  0.83 TFLOPS  @ 59.23s
******  147.49 ms to enqueue, 37362.16 ms to realize ( 146.96 ms fetching, 36618.84 ms postprocess_detections).     0.11 examples/sec.  1.03 TFLOPS  @ 96.74s
******  152.85 ms to enqueue, 37244.08 ms to realize ( 120.67 ms fetching, 36235.19 ms postprocess_detections).     0.11 examples/sec.  1.04 TFLOPS  @ 134.14s
******  146.39 ms to enqueue, 37279.85 ms to realize (  65.07 ms fetching, 36233.56 ms postprocess_detections).     0.11 examples/sec.  1.04 TFLOPS  @ 171.56s
******  152.41 ms to enqueue, 37264.04 ms to realize ( 127.08 ms fetching, 36196.10 ms postprocess_detections).     0.11 examples/sec.  1.04 TFLOPS  @ 208.98s
******  151.29 ms to enqueue, 36868.08 ms to realize ( 142.73 ms fetching, 36153.07 ms postprocess_detections).     0.11 examples/sec.  1.05 TFLOPS  @ 246.00s
******  136.41 ms to enqueue, 37325.04 ms to realize (  90.29 ms fetching, 36573.38 ms postprocess_detections).     0.11 examples/sec.  1.04 TFLOPS  @ 283.46s
```
2025-04-23 11:39:56 -04:00
George HotzandGitHub 2ed3acd767 toposort is a function [pr] (#10004) 2025-04-23 16:25:03 +01:00
uuuvnandGitHub 0730ff0e50 Skip test that requires lru if device's allocator isn't lru (#10003) 2025-04-23 16:12:56 +01:00
George HotzandGitHub 954cb06957 deepwalk without recursion [pr] (#10002)
* deepwalk without recursion [pr]

* comment and remove that test
2025-04-23 15:57:50 +01:00
uuuvnandGitHub 9de73ccc22 Skip test that requires python 3.12 on older versions (#10001)
`out.cast(it.dtype.fmt).tolist()` fails with `ValueError: memoryview: destination format must be a native single character format prefixed with an optional '@'`
2025-04-23 10:09:26 -04:00
George HotzandGitHub 71ecc7fa1a use a pattern matcher for upcast [pr] (#10000) 2025-04-23 14:24:23 +01:00
George HotzandGitHub cc1087d2ec move simplify into views_to_indexed_uops (#9999)
* move simplify into views_to_indexed_uops

* cache that
2025-04-23 13:50:27 +01:00
chenyuandGitHub c39128133c retinanet green scripts (#9996)
also removed realize in data_get and used empty for fake data. slightly bigger lr. https://wandb.ai/chenyuxyz/MLPerf-RetinaNet/runs/8skid0e8?nw=nwuserchenyuxyz
2025-04-23 08:28:03 -04:00
George HotzandGitHub a4a5f2d54a faster block order [pr] (#9998)
* faster block reorder [pr]

* ahh, that's even faster
2025-04-23 13:11:30 +01:00
chenyuandGitHub 61bfd23881 update mlperf-logging version (#9995) 2025-04-22 19:32:39 -04:00
dbbd755cba FP8s truncate (#9937)
* truncate fp8

* fix

* maybe like that?

* fix linters

* ruff

* move from extra and add ml_types to tests

* minor changes

* str to dtypes and nan support

---------

Co-authored-by: pkotzbach <[email protected]>
2025-04-22 19:12:49 -04:00
qazalandGitHub 58180caad3 schedule linearize small cleanups [pr] (#9994) 2025-04-23 05:42:29 +08:00
qazalandGitHub f4ec57baff new schedule linearizer enqueues KERNEL UOps [pr] (#9993)
* new schedule linearizer enqueues kernels [pr]

* no defaultdict

* diff

* minor
2025-04-23 05:17:58 +08:00
geohot d1f6701eb7 hotfix: lower amd threshold + improve block reorder test 2025-04-22 20:44:29 +01:00
nimlgenandGitHub db51133537 rename HWInterface -> FileIOInterface (#9989)
* rename HWInterface -> FileIOInterface

* ugh
2025-04-22 22:18:57 +03:00
George HotzandGitHub c1539b0319 putting add first orders loads as expected (#9991) 2025-04-22 20:12:05 +01:00
nimlgenandGitHub bd580d8ea4 hcq: use mmio interface in nv (#9986)
* hcq: start mmio interface

* allow double cast

* revert

* faster?

* simpler, not needed more now

* dd

* types

* fix
2025-04-22 21:58:12 +03:00
George HotzandGitHub feee6986c9 faster block reorder (#9990)
* faster block reorder [pr]

* that shouldn't change order

* key just in sorted

* ind
2025-04-22 19:18:57 +01:00
qazalandGitHub 6cb2d18c03 refactor schedule linearize to defaultdict [pr] (#9984)
* refactor schedule linearize to defaultdict [pr]

* skip that

* don't need .get
2025-04-23 00:00:23 +08:00
chenyuandGitHub 9e5e371999 make DISABLE_COMPILER_CACHE a ContextVar [pr] (#9983) 2025-04-22 10:32:54 -04:00
qazalandGitHub bbc324f5dc remove CAST_AFTER_EXPAND (#9980) 2025-04-22 21:06:11 +08:00
George HotzandGitHub c519b553db non recursive toposort is 2x+ faster (#9979)
* non recursive toposort is 2x+ faster

* don't change the order
2025-04-22 13:59:38 +01:00
qazalandGitHub 0d9014d021 place create_ast last, type_verify in the end (once) [pr] (#9977) 2025-04-22 20:15:23 +08:00
chenyuandGitHub fb89d9a584 retinanet eval combine output on GPUS[0] (#9966)
eval 35 sec -> 20 sec. it was spending 13 seconds assembling output tensor on CPU backend. GPUS[0] seems to have enough memory, otherwise we can lower EVAL_BS
2025-04-22 07:43:51 -04:00
qazalandGitHub 7b55846e08 prep STORE UOp creation for multi output [pr] (#9975)
* prep STORE UOp creation for multi output [pr]

* test_multioutput_ast
2025-04-22 19:34:52 +08:00
George HotzandGitHub e358e0a0c6 move metadata set to tensor [pr] (#9976)
* move metadata set to tensor [pr]

* only track that in tensor.py
2025-04-22 12:30:35 +01:00
qazalandGitHub f6271515fe refactor UOp.st [pr] (#9973) 2025-04-22 18:46:56 +08:00
George HotzandGitHub f5dc70c624 microbenchmarks + micro speed ups (#9972)
* microbenchmarks

* forgot the ubenchs

* clean up type verify
2025-04-22 11:30:46 +01:00
qazalandGitHub 1cf4e24ca5 fix kernelize usage with pm_gradient (#9953)
* fix kernelize usage with pm_gradient

* remove that
2025-04-22 17:26:05 +08:00
32bbff942c amd: add nbio 7.2.0 for some rdna2 (#9964)
* - Updated of #9700 which fixes #9665 but for the Steam Deck which was erroring on NBIO 7.2.0

* unrelated change

---------

Co-authored-by: nimlgen <[email protected]>
2025-04-22 12:10:48 +03:00
Ignacio SicaandGitHub 0e79aee706 use_tensor_cores bugfix (#9969) 2025-04-21 22:58:17 -03:00
chenyuandGitHub 5294c32279 dev scripts for retinanet (#9968)
also BASE_DIR -> BASEDIR for consistency, and move wandb up a bit for more accurate timing
2025-04-21 17:54:56 -04:00
nimlgenandGitHub 4340197132 am: download fw from web (#9956)
* am: download fw from web

* tested

* link works

* default to web

* this is default

* not used
2025-04-21 23:26:33 +03:00
nimlgenandGitHub 7244ca863c am: fix double read of sdma fw (#9965) 2025-04-21 23:04:34 +03:00
uuuvnandGitHub b35f94b6ec Don't hardcode default CLOUDDEV (#9935) 2025-04-21 18:46:55 +01:00
Francis LataandGitHub defa1e77f6 get the proper dataset count (#9962) 2025-04-21 12:11:37 -04:00
qazalandGitHub 36ed3c3253 fix kernelize with VIEW children (#9961) 2025-04-21 23:38:46 +08:00
uuuvnandGitHub 757533cbe6 Less verbose cloud multiprocessing start (#9960)
The set name before starting part used to be required for #9935 when
CLOUDDEV was a global variable, now just readability improvement
2025-04-21 16:19:54 +01:00
Francis LataandGitHub d7e247f329 RetinaNet INITMLPERF support (#9950)
* fixes to make fake data work

* fix eval beam

* fix merge issue
2025-04-21 10:32:05 -04:00
014f870733 rm (#9959)
Co-authored-by: KamilisJonkus <[email protected]>
2025-04-21 15:23:45 +01:00
chenyuandGitHub f68c7041c4 doc fix is_floating_point dtype.float -> dtypes.float (#9958) 2025-04-21 09:23:59 -04:00
akhuntsariaandGitHub 2d423e6737 fix assertion message for supported device in export_model (#9957) 2025-04-21 09:23:44 -04:00
ttomsaandGitHub 783a191925 rm mul from _masked_setitem (#9951) 2025-04-21 06:41:50 -04:00
nimlgenandGitHub 46469f00a2 am: tiny changes in psp load (#9952) 2025-04-21 11:52:02 +03:00
qazalandGitHub 0bee225a58 Tensor.kernelize docs (#9946)
* Tensor.kernelize docs

* syntax

* test_kernelize_bw

* Tensor.kernelize docstring

* pruning

* tiny details

* details 2

* becomes_map terminology

* more changes to becomes
2025-04-21 16:34:03 +08:00
Francis LataandGitHub ea4cb2c715 small cleanups (#9947) 2025-04-20 20:33:20 -04:00
qazalandGitHub e8910540f6 Kernelize can be called multiple times on a Tensor (#9949)
* Kernelize can be called multiple times on a Tensor

* add (failing) test_kernelize_bw
2025-04-21 06:28:47 +08:00
qazalandGitHub 1d90be2cff match kernelize API in process replay (#9948) 2025-04-21 05:23:41 +08:00
qazalandGitHub 343a5eb588 dedup assigns in grouper VIZ name function [pr] (#9942) 2025-04-20 21:42:25 +08:00
qazalandGitHub e20ef7196a Tensor.kernelize (#9845)
* add kernelize

* remove that

* kernelize returns self

* update abstractions2.py

* kernelize in test_schedule

* temp: assert BUFFER_VIEW's existence

* ASSIGN must have a buffer or subbuffer target

* assert and shrink

* fix

* padded setitem

* var

* toposort once

* extra

* base_buffer

* end with BUFFER_VIEW

* setitem for disk

* test_setitem_becomes_subbuffer

* mul slice test

* torch backend fix 1

* non-deterministic

* keep subbuffer
2025-04-20 20:53:49 +08:00
qazalandGitHub dd16087f62 fold double ASSIGN to same target (#9941) 2025-04-20 19:06:38 +08:00
qazalandGitHub 9a9aba4cd5 setitem tests (some failing) from kernelize (#9940) 2025-04-20 18:47:55 +08:00
chenyuandGitHub 6c30948df6 hand_coded_optimizations returns list[Opt] [pr] (#9938)
new api looks like `k.apply_opts(hand_coded_optimizations(k))`
2025-04-19 20:26:59 -04:00
chenyuandGitHub 720f20865b remove required_optimizations (#9848) 2025-04-19 16:51:16 -04:00
qazalandGitHub 218e01833d update scheduler section for abstractions2.py [pr] (#9927) 2025-04-19 12:09:14 +03:00
chenyuandGitHub 3fdba48fc7 update bert green and README (#9934)
submission candidate
2025-04-18 21:21:28 -04:00
George HotzandGitHub b359125ebf rewrite the linearizer (#9885)
* random speedups [pr]

* speeding up linearizer

* test_gemm passes

* progress

* test_gemm passes

* working

* simpler

* blockstart unneeded

* simpler

* bugfix

* work

* don't compare

* faster

* progress

* cleanups

* work

* cleanups

* working

* reorder

* name is dumb

* fix tests

* lin2 works

* clean ctx

* mostly bottom up

* passes

* same speed now

* new lin is faster

* dedup

* lines and tuples

* track that

* lin

* revert that

* tests should pass

* merge siblings

* cleaner expression

* only lin2

* finally, some speed

* simpler

* fix unmergables with blockends
2025-04-18 22:35:40 +01:00
Ignacio SicaandGitHub 023b1c28a2 test_tensor_cores_padded refactor (#9724)
* set pad t 3 for amd padded tc test

* change pad for amd regardless CI

* test tc padded uops and correctness separately

* add test_tensor_cores_padded_uops test to ci

* remove redundant chack for amd device

* cleanup
2025-04-18 17:05:54 -03:00
Ignacio SicaandGitHub afff82ba0f fix ptx linearizer bug [pr] (#9926)
* fix ptx bug

* align 16

* revert align because it breaks pr

* smallest diff that fixes ptx bug
2025-04-18 13:48:43 -03:00
chenyuandGitHub 617b45748f fuse embedding for bert on red (#9925)
also updated BEAM param and use AMD driver for actual run. 535ms step
2025-04-18 07:20:25 -04:00
qazalandGitHub b58decac0c fix diamond assigns before mapping tensors UOps to assigns (#9855)
* keep tensor_map until diamond assign fixup

* ctx
2025-04-18 14:17:43 +03:00
qazalandGitHub a37d921917 get name from SINK in process replay (#9924)
* get name from SINK in process replay

* space
2025-04-18 13:51:11 +03:00
George HotzandGitHub aa98aff4cd don't use ops name, just keep sink (#9922)
* don't use ops name, just keep sink

* fix test

* endif sink
2025-04-18 08:59:18 +01:00
geohot 8919370c76 hotfix: fix test_save_all_dtypes on METAL 2025-04-18 08:42:31 +01:00
qazalandGitHub 16dfe0a902 upstream remu (#9921) 2025-04-18 01:57:36 +03:00
qazalandGitHub d287afe3b1 remove shapeless const check in full_shape [pr] (#9911)
* remove shapeless const check in full_shape [pr]

* those can go too
2025-04-18 00:00:26 +03:00
chenyuandGitHub fe6a482f1d pin hypothesis version to 6.131.0 (#9920)
6.131.1 seems to cause timeout in CI
2025-04-17 16:34:10 -04:00
chenyuandGitHub f5256e0020 Kernel.apply_opts [pr] (#9917)
* Kernel.apply_opts [pr]

updated all `for opt in`. also updated a few test_liinearizer tests to not implcitly depend on hand_coded_optimization

* not you yet
2025-04-17 08:00:56 -04:00
chenyuandGitHub e2ed673c94 FUSE_ARANGE_UINT to not fuse uint (#9915)
hack to bypass rand, can FUSE_ARANGE on green for 6ms per step
2025-04-16 18:49:38 -04:00
qazalandGitHub 497daa658a hotfix: edge-labels go above the overlay (#9910) 2025-04-16 23:38:12 +08:00
qazalandGitHub e8e43c6dad ensure edge labels are always on top (#9908) 2025-04-16 21:08:06 +08:00
qazalandGitHub 5265f25088 add counter for incoming edges in viz (#9907) 2025-04-16 20:14:14 +08:00
Eitan TurokandGitHub 2c7c205bc5 Fix dtype comparisons in vectorized transcendental + tests (#9794)
* init test

* cleanup

* init

* update

* fix

* fix python runtime for vectorized code

* awesome helper

* update

* update

* cleanup

* more cleaning

* cleanup more

* fix tests

* more cleaning

* cleanup more

* fix

* even cleaner

* failing tests is sad

* cleanup

* better name

* make tests pass

* remove vec from python runtime

* remove vec from eval_uop

* remove expected failues

* better name
2025-04-16 08:06:12 -04:00
qazalandGitHub 929e5a9905 do not construct GrouperContext [pr] (#9906) 2025-04-16 18:26:31 +08:00
XingyuandGitHub 047c8fd70d Add amax support to Tensor operations in Torch Backend (#9905)
* Add amax support to Tensor operations
- Implemented amax function in backend.py for tensor max operations.
- Added unit tests for amax in test.py to ensure correct functionality.

* Fix formatting in amax output function
- Adjusted spacing in the amax output lambda function in backend.py
- Improved code readability for better maintenance
2025-04-16 10:35:50 +01:00
uuuvnandGitHub d7f623dac2 Use Buffer in cloud server instead of opaques (#9875)
Not-quite-required but makes cloud graph a *lot* cleaner because unlike
raw compiled programs `GraphRunner` takes `Buffer`s like other runners.

Otherwise either of: adding a new option to not free on `__del__`,
(ab)using `external_ptr` to prevent free, or making something like a
`FakeBuffer` is required.
2025-04-16 10:17:32 +01:00
qazalandGitHub 05334e0f3f construct children from UOp.toposort [pr] (#9882)
* construct children from UOp.toposort [pr]

* only for bases
2025-04-16 16:55:59 +08:00
geohotstanandGitHub 4e8f25109a Revert "ONNX add output shape validation (#9720)" (#9904)
This reverts commit ac713e04db.
2025-04-16 03:15:56 -04:00
chenyuandGitHub e8024c8281 faster bert global_norm (#9901)
tinyamd 2% faster.  also updated beam params that's 2-3% faster.

update mlperf doc and steps too
2025-04-15 18:24:44 -04:00
Sieds LyklesandGitHub 91ccf1c343 Off by one error in start_pos (#9792)
Variable upper bound is inclusive
2025-04-15 15:07:13 -04:00
5849c43382 FP8s part 1 (#9887)
* fp8s part 1

* prettier

* fixes

* fixes

* remove stuff that should be in next pr

* revert

* add creation

---------

Co-authored-by: pkotzbach <[email protected]>
2025-04-15 11:20:02 -04:00
Francis LataandGitHub 31483050c0 add eval_freq flag (#9894) 2025-04-15 06:42:40 -04:00
nimlgenandGitHub 83ae83d871 compare amd and am to cpu as well (#9896) 2025-04-15 13:32:18 +03:00
nimlgenandGitHub 23a95dd84d script to compare amd and am kerns (#9889)
* script to compare amd and am kerns

* tool

* is it used???
2025-04-15 00:11:22 +03:00
chenyuandGitHub ce454793e6 support specifying dtype for Tensor.linear (#9886) 2025-04-14 13:55:11 -04:00
e8a0aee88d add arch to AMDLLVMRenderer (#9884)
* add arch to AMDLLVMRenderer

* __reduce__ to match others

---------

Co-authored-by: nimlgen <[email protected]>
2025-04-14 19:59:22 +03:00
George HotzandGitHub 44e4934167 fast pattern matcher [pr] (#9737)
* FastPatternMatcher

* works without that

* fix test pickle

* strict len

* compile match function

* dynamic compile

* fast

* faster

* compile

* track

* a lot faster

* clean up

* dup or

* faster and simpler

* fast match doesn't support store

* plane

* minor refactor

* real speed

* don't imply return None

* upat

* fix test

* heard you wanted more speed

* no generator

* split cf

* early fixup

* fxn fixup

* reconstruct_function

* Revert "reconstruct_function"

This reverts commit 37dac010ab.

* simpler stuff

* too big

* upat compile error

* cleanups

* don't cache that

* cleanups

* 10 -> 15
2025-04-14 15:24:41 +01:00
chenyuandGitHub 43d3a75d6c increase bert max train_steps (#9883) 2025-04-14 08:53:44 -04:00
qazalandGitHub bf099520a4 add names to grouper rewrites + cleanups [pr] (#9881)
* add names to grouper rewrites + cleanups [pr]

* assign_targets
2025-04-14 19:47:36 +08:00
George HotzandGitHub ca8aaadd00 clean up some patterns [pr] (#9880)
* clean up some patterns [pr]

* cleanest

* move that into upat_interpret
2025-04-14 11:33:22 +01:00
George HotzandGitHub 355739fc94 switch to universal match [pr] (#9879)
* switch to universal match [pr]

* 10 -> 15
2025-04-14 09:15:37 +01:00
Nishant RajadhyakshaandGitHub 32ed128598 fixing transformer training bug (#9877) 2025-04-13 19:34:20 -04:00
George HotzandGitHub bd5939514d clean up a few patterns [pr] (#9873) 2025-04-13 20:19:37 +01:00
Alexey ZaytsevandGitHub 78a6af3da7 Use $CUDA_PATH/include for CUDA headers (#9858) 2025-04-13 16:20:19 +01:00
chenyuandGitHub e2a40fb523 update bert mi300x script (#9872)
2 runs failed to converge in 10 back to back runs, increase total train steps and some beam params (2% faster step)
2025-04-13 10:07:36 -04:00
qazalandGitHub e201bc3e93 process replay kernel asts in toposort order [pr] (#9869)
* process replay kernel asts in toposort order [pr]

* use HEAD replay
2025-04-13 17:20:34 +08:00
qazalandGitHub 7191f88551 add asserts for KERNEL op ast [pr] (#9868) 2025-04-13 16:50:18 +08:00
qazalandGitHub 5ee9c343e6 add device to NullRenderer [pr] (#9867) 2025-04-13 13:17:16 +08:00
Francis LataandGitHub 2793cca9a6 RetinaNet MLPerf (#8385)
* add support for a custom BASEDIR for openimages download

* make export step faster

* add focal loss

* update model_eval with new dataloader

* generate_anchors in tinygrad

* update initializers for model

* small cleanup

* revert isin enhancements

* recursively go through backbone layers to freeze them

* add optimizer

* minor cleanup

* start dataloader work with input images

* add first transform for train set

* reuse existing prepare_target

* continue with dataloader implementation

* add dataloader

* separate out KiTS19 dataset test cases

* create mock data samples for test

* add dataloader + test

* cleanup dataloader test and revert shm path

* trim dataloader related code needed from ref

* got dataloader with normalize working

* update image to be float32

* add back normalization and negate it in test

* clean up reference dataset implementation + ruff changes

* add validation set test

* add proper training loop over the training dataset

* add LambdaLR support

* add LR scheduler and the start of training step

* get forward call to model work and setup multi-GPU

* already passed device

* return matches from dataloader

* hotfix for dataloader typo causing some hang

* start some work on classification loss

* update focal loss to support masking

* add missing test and cleanup focal loss

* cleanup unit tests

* remove masking support for sigmoid_focal_loss

* make ClassificationHead loss work

* cleanups + fix dataloader tests

* remove sigmoid when computing loss

* make anchors use Tensors

* simplify anchors batching

* revert anchors to use np

* implement regression loss

* fix regression loss

* cleanup losses

* move BoxCoder to MLPerf helpers

* revert helper changes

* fixes after helper refactor cleanup

* add tests for l1_loss

* start re-enabling training step

* minor cleanup

* add pycocotools to testing dependencies

* make training work

* adjust regression loss to mask after L1 loss is calculated

* reduce img and lbl sizes by half for KiTS19 dataset tests

* Revert "reduce img and lbl sizes by half for KiTS19 dataset tests"

This reverts commit d115b0c664.

* temporarily disable openimages dataset tests to debug CI

* enable openimages dataset test and create samples once

* temporarily disable openimages validation set test

* reenable test and add some debugging to the test

* add boto3 testing dependencies

* add pandas to testing dependencies

* This reverts commit 467704fec6.

* reenable test

* move sample creation to setup

* realize boxcoder's encoding

* add wandb

* fix wandb resuming feature

* move anchors as part of dataloader

* fix dtype for anchor inside dataloader and fix horizontal flip transformation

* add support for BENCHMARK

* set seed

* debug dataset test failuire

* Revert "debug dataset test failuire"

This reverts commit 1b2f9d7f50.

* fix dataloader script

* do not realize when sharding model weights

* setup openimages samples differently

* create the necessary samples per test case

* enable lr scheduler and fix benchmark timing

* add jit to the training loop

* add checkpointing and training resume capabilities

* refactor on training loop and start the work on val looop

* add debug logging for dataloader test

* debug test

* assert boxes again

* update validation dataloader and more cleanups

* fix validation test case

* add multi device support to retinanet eval

* fix issue with realized on dataloader

* remove optional disk tensors in dataloader

* remove verbose debugging on datasets test

* put back parallel testing and remove img_ids Tensor from dataloader

* cleanup train and validation dataloader

* return validation targets in dataloader

* cleanup boxes and labels in dataloader

* fix img_ids repeating its values

* remove unnecessary targets from validation dataloader

* add validation loop to training script

* adjust LR to be the ratio of the batch size

* minor cleanups

* remove frozen layers from optimizer's params

* hyperparameter adjustments and cleanups

* model init, hyperparam, and data preprocessing updates

* no need to return loaded keys for resnet

* fix train script

* update loss calculation for regresionhead and some cleanups

* add JIT reset support

* add nan check during training

* Revert "add nan check during training"

This reverts commit ddf1f0d5dd.

* Revert "Revert "add nan check during training""

This reverts commit b7b2943197.

* some typing cleanups

* update seeding on dataloader and the start of training script

* undo changse

* undo more changes

* more typing fixes

* minor cleanups

* update dataloader seed

* hotfix: log metric and move target metric check outside of CKPT

* check for CKPT when target metric is reached before saving

* add TRAIN_BEAM and EVAL_BEAM

* minor cleanup

* update hyperparams and add support for EVAL_BS

* add green coloring to metric reached statement

* initial work to support f16

* update model initializers to be monkeypatched

* update layers to support float32 weight loading + float16 training

* don't return loss that's scaled

* run eval on benchmark beam

* move BEAM to their respective steps

* update layers to be compatible with fp16

* end BENCHMARK after first eval

* cleanups and adjust learning rate for fp16

* remove duplicated files from test

* revert losses changes

* Revert "revert losses changes"

This reverts commit aebccf93ac.

* go back to old LR

* cast batchnorm to float32

* set new loss scaler default value for float16

* remove LambdaLRScheduler

* remove runner and use dataloader on eval

* fix retinanet eval with new dataloader

* remove unused import

* revert lr_scheduler updates

* use BS=96 with new learning rate

* rename module initializers

* more cleanups on training loop

* remove contig from optim.step

* simplify sum when computing loss
2025-04-12 22:11:51 -04:00
nimlgenandGitHub 23b67f532c amd: minor comments and readme updates (#9865) 2025-04-12 23:24:05 +03:00
nimlgenandGitHub 7c466c24f7 am_smi: refactor to support arches (#9864)
* am_smi: refactor to support arches

* shorter
2025-04-12 20:37:01 +03:00
nimlgenandGitHub a9430b4118 am: fix metrics table for smu14_0_2 (#9863) 2025-04-12 19:07:22 +03:00
Alexey ZaytsevandGitHub 3bce5ad2b4 clang should not emit the .comment section (#9859)
This section gets included in the finanl image, and we get a lot of garbage with DEBUG=7
2025-04-12 10:59:11 +08:00
Alexey ZaytsevandGitHub 7dda6aae7d Skip CLOUD in external_test_example (#9857)
Closes #9814
2025-04-12 10:17:44 +08:00
nimlgenandGitHub 7919bb4f8a amd: do not use log2 (#9852) 2025-04-11 19:53:06 +03:00
nimlgenandGitHub ada0f67d3d am: fix speed of ring copies (#9854) 2025-04-11 17:28:06 +03:00
chenyuandGitHub 4aab16ca6a bert script cleanup and assert nan loss (#9851) 2025-04-11 05:41:49 -04:00
qazalandGitHub ad677f8e55 create_ast cleanups from kernelize [pr] (#9849) 2025-04-11 16:10:21 +08:00
qazalandGitHub cbc5e7ed45 unbind variables when creating ScheduleItems [pr] (#9846) 2025-04-11 15:23:53 +08:00
chenyuandGitHub 6896197978 relax ATOL for TC half tests more (#9847) 2025-04-11 03:20:22 -04:00
George HotzandGitHub dd52951dd0 fix single kernel softmax with cast (#9842)
* fix single kernel softmax with cast

* tolerate none

* 3e-4

* skip on dtype
2025-04-11 12:12:02 +08:00
chenyuandGitHub 8c6299bced move hand_coded_optimizations to heuristic.py [pr] (#9844)
* move hand_coded_optimizations to heuristic.py [pr]

also folded all long lines

* make a copy and rename self -> k

* fix test
2025-04-10 23:40:16 -04:00
chenyuandGitHub e0ec8be37d use CPU for test_schedule_ring (#9843)
* use CPU for test_schedule_ring

* why pre-commit is good
2025-04-10 23:20:53 -04:00
qazalandGitHub 7045920786 give _apply_map_to_tensors substitutes name [pr] (#9840) 2025-04-11 10:38:57 +08:00
qazalandGitHub 40ef2f2857 add ast fixup stage to tensor_map [pr] (#9839) 2025-04-11 09:24:01 +08:00
qazalandGitHub fbc6aa53d4 script for local process_replay + fix viz name [pr] (#9837) 2025-04-11 00:39:18 +08:00
b1tgandGitHub a35b475d18 fix am driver for gfx1201 (#9836) 2025-04-10 19:33:02 +03:00
qazalandGitHub 16956b79de canonicalize Device.DEFAULT (#9835) 2025-04-10 23:02:11 +08:00
George HotzandGitHub f666dd14eb fix get reduce contraction with test (#9834) 2025-04-10 22:24:21 +08:00
geohot c3fa470852 hotfix: remove tracebacklimit, it persists if you catch the exception and made webgpu flaky 2025-04-10 20:29:25 +08:00
chenyuandGitHub 7fa5f29582 add test_embedding to test_softmax_fusion (#9832) 2025-04-10 08:25:34 -04:00
chenyuandGitHub 995d20673a increase bert TRAIN_STEPS for mi300x (#9833)
got a few non converged ones so try to increase steps. we need >= 90% runs to converge
2025-04-10 08:25:09 -04:00
geohot 25e2a3cf5d hotfix: fix get_contraction_with_reduce 2025-04-10 20:18:19 +08:00
George HotzandGitHub 53f0b2aad7 fix infinite loop in flash attention (#9827)
* fix infinite loop in flash attention

* get_contraction_with_reduce

* skip that test

* SINGLE_KERNEL_SOFTMAX + fix multi

* default IGNORE_OOB

* print change
2025-04-10 20:06:44 +08:00
qazalandGitHub 16afe04f45 move process replay to grouper (#9830)
* simpler

* sched
2025-04-10 18:27:42 +08:00
chenyuandGitHub c8f47c1d07 not_support_multi_device helper (#9831)
unify the test helper to skip ci device that does not support multi
2025-04-10 05:25:29 -04:00
chenyuandGitHub 817746b30e add contiguous to EmbeddingBert output (#9829)
for some reason with random dropout it creates different ast on each device. And search embedding is slow. This workaround saved 6 minutes setup time on mi300x (25->19) and resulted in similar speed
2025-04-10 04:31:19 -04:00
qazalandGitHub fd4f06e623 kernelize prereqs [pr] (#9811)
* kernelize prereqs [pr]

* work

* tensor maps to assign

* unwrap st

* process replay

* grouper changes

* replay
2025-04-10 15:22:20 +08:00
chenyuandGitHub c462162db8 update benchmark bert scripts with BS and ACC_DTYPE (#9826)
BS=16, ACC_DTYPE=half for tinybox, BS=128, ACC_DTYPE=float for mi300x
2025-04-10 02:06:02 -04:00
qazalandGitHub 498a2bf738 add err handling tests to viz + cleanups (#9825)
* cleanup

* add err handling tests to viz + cleanups

* lint
2025-04-10 14:05:05 +08:00
chenyuandGitHub a0b72f066a don't free intermediate for bert mi300x (#9824) 2025-04-10 01:48:34 -04:00
chenyuandGitHub 566e389585 more relaxed ATOL for HALF=1 simple_matmul test (#9823)
it's a function of N so only updated in the test command
2025-04-10 00:46:16 -04:00
Francis LataandGitHub eb2e59db42 RetinaNet model type annotations and loss functions (#9822)
* add type annotations and loss functions for training

* combine sum of multiple dims inside loss functions
2025-04-10 00:31:37 -04:00
chenyuandGitHub 06a928b341 higher ATOL for half input TC test (#9821)
flaky
2025-04-09 23:57:25 -04:00
Francis LataandGitHub 7bb36d71b2 remove openimages iterate (#9820) 2025-04-09 22:54:12 -04:00
chenyuandGitHub 2e1002e179 EVAL_BS=96 and BEAM=3 for bert green (#9819)
19m -> 13m setup and same end to end time
2025-04-09 22:37:27 -04:00
uuuvnandGitHub 3ee317ffed Fix kfd autogen and verify it in ci (#9818)
Had to autogen newer uapi headers for #9746 (dmabuf export ioctl missing),
submitting just the fix without updating to newer headers as they are only
needed for infiniband stuff
2025-04-10 09:53:42 +08:00
nimlgenandGitHub d7330ea6ad amd: refactor sqtt into sep functions (#9816)
* amd: refactor sqtt into sep functions

* fix
2025-04-10 00:39:45 +03:00
nimlgenandGitHub 0ca98b9f20 amd: gfx9 use cache ctrls in acquire_mem (#9815) 2025-04-09 20:17:02 +03:00
George HotzandGitHub fce432d2e3 Ops.FUSE makes softmax a single kernel (#9808)
* KERNELIZE makes softmax a single kernel

* single kernel works

* softmax works

* broken

* correct

* skip that test

* kernelize tests

* rename to fuse

* better reduce_push_add_ones code

* correct now

* cleanups

* oops

* return None if we can't push ones

* rename + docs

* atol fixes group

* flash attention broken test
2025-04-09 22:56:28 +08:00
nimlgenandGitHub 1798ce7e52 amd: faster xcc sync (#9783)
* amd: faster xcc sync

* move to same cacheline

* comment

* keep it uncached + better poll timings

* revert this, should be fine

* fixed now?

* minor
2025-04-09 15:56:50 +03:00
qazalandGitHub 3bd992dc95 multi stage graph_rewrite_map (#9803)
* multistage graph_rewrite_map

* s/merge_map/input_map

* build up kernel_map from the tensor_map
2025-04-09 15:59:45 +08:00
chenyuandGitHub 57f4bc3fbb add numpy to setup linting (#9806)
this would have caught the mypy error in fp8 pr. keep ignore_missing_imports to true as we also import torch which is fat
2025-04-09 03:47:03 -04:00
George HotzandGitHub bf769fa5c5 label ranges with their number (#9805) 2025-04-09 14:31:18 +08:00
chenyuandGitHub c5db5b83b9 add SHOULD_USE_TC=1 check to simple_matmul (#9802)
* add SHOULD_USE_TC=1 check to simple_matmul

also zero centered the random input and update atol for tf32

* ATOL=2e-2 for HALF
2025-04-09 02:24:42 -04:00
qazalandGitHub f27dbc8c35 becomes_map cleanups [pr] (#9790)
* cleanup becomes_map [pr]

* source
2025-04-09 14:11:53 +08:00
qazalandGitHub 7d2349c827 track_rewrites in scheduler [pr] (#9801) 2025-04-09 12:48:14 +08:00
George HotzandGitHub bb18adb0d5 reduce with a mul chain (#9799)
* reduce with a mul chain

* inside is just 1
2025-04-09 12:42:32 +08:00
geohot 78caf55154 Revert "FP8 support on NVIDIA (#8631)"
This reverts commit 2c8e4ea865.
2025-04-09 12:27:41 +08:00
geohot d1505137ad Revert "move TestOpsFp8s skipTest (#9797)"
This reverts commit a3aaf92b21.
2025-04-09 12:27:40 +08:00
geohot 14928fecff Revert "fix TF32 tensor core dropped in tc_sm89 (#9798)"
This reverts commit 7c9a96824f.
2025-04-09 12:27:39 +08:00
qazalandGitHub 1ed4eae510 hotfix: don't add shape to SINK viz node (#9800) 2025-04-09 12:04:33 +08:00
chenyuandGitHub 7c9a96824f fix TF32 tensor core dropped in tc_sm89 (#9798)
also add `SHOULD_USE_TC=1` to verify TC is applied in simple_matmul
2025-04-08 23:20:50 -04:00
chenyuandGitHub a3aaf92b21 move TestOpsFp8s skipTest (#9797)
so get_available_devices is not called when running other tests
2025-04-08 22:44:07 -04:00
2c8e4ea865 FP8 support on NVIDIA (#8631)
* squashed fp8 commits

* tensorcore start

* minor changes

* pre-commit

* pylint

* Delete fp8mul.cu

* clean

* small bugfix

* fix test_dtype

* fix test_dtype_alu

* add EMULATE_CUDA_SM89

* fix ci

* fix test_linearizer

* fix test_linearizer

* fix swizzle

* add debug to simple_matmul

* fixed swizzle

* python emulator

* refactor python emulator

* setup fix

* numpy setup

* ml_dtypes only in emulate_cuda_sm89

* fix pylint

* fix tests

* fix mypy

* fix mypy

* fix ruff

* done python emulator

* add acc type

* tests

* mypy

* clean code

* add cuda tensor core tests to CI

* minor fix

* clean test_dtype.py

* clean cstyle.py

* clean test_ops.py

* fix test

* fix test

* whitespaces

* pylint

* pylint

* amd?

* amd?

* amd

* reduce lines

* mockgpu remove

* fix

* ruff

* ruff

* fix mypy

* ruff

* test only for cuda

* fixed formatting

* small fixes

* small fix

* least_upper_dtype if fp8s not supported

* log and reciprocal are supported for fp8s

* ops python fixes

* dtypes.fp8s use

* e4m3 + e5m2 result dtype test

* truncate linter fix

---------

Co-authored-by: pkotzbach <[email protected]>
Co-authored-by: George Hotz <[email protected]>
Co-authored-by: chenyu <[email protected]>
2025-04-08 21:54:04 -04:00
hoovedandGitHub 5d85765327 types for WebGPU runtime (#9791)
* add type annotations to ops_webgpu

* rerun CI

* add types to some _run params
2025-04-08 22:52:17 +03:00
chenyuandGitHub 4c8582a7ce pipe allow_test_size in _time_program (#9789)
* pipe allow_test_size in _time_program

it was dropped long time ago and BEAM_ESTIMATE is doing nothing

* revert BEAM_ESTIMATE
2025-04-08 09:07:40 -04:00
chenyuandGitHub 8fe83385ec add system json for mi300x mlperf (#9786)
* add system json for mi300x mlperf

```
python3 -m mlperf_logging.system_desc_checker examples/mlperf/training_submission_v5.0/tinycorp/systems/tinybox_8xMI300X.json training 4.1.0
INFO -   System description checker passed for tinybox 8xMI300X
```

also removed the rocm from tinybox_red since we are not using it

* update mlperf-logging version
2025-04-08 06:36:44 -04:00
chenyuandGitHub 4a807ee952 remove duplicated z3-solver in setup.py (#9787) 2025-04-08 06:12:58 -04:00
qazalandGitHub 21e872df44 remove consts from sched_sink [pr] (#9782) 2025-04-08 16:08:24 +08:00
qazalandGitHub f13e9cf2d9 move view_left to grouper.py + tiny reorders [pr] (#9780)
* move view_left to grouper.py [pr]

* reorder grouper

* test_schedule
2025-04-08 15:39:28 +08:00
chenyuandGitHub 7a28133b37 failed test for single softmax backward (#9778)
getting RecursionError with DONT_GROUP_REDUCES=1
2025-04-08 02:36:32 -04:00
George HotzandGitHub fefee5d3ab single kernel softmax (#9776)
* real single kernel softmax

* cleanup

* fix blockend insertion

* add to bert test
2025-04-08 12:35:48 +08:00
qazalandGitHub 9963bb51e0 grouper tests cleanups [pr] (#9777)
* grouper tests cleanups [pr]

* viz

* tuple

* whitespace
2025-04-08 12:33:11 +08:00
chenyuandGitHub 4cc7422769 use AM driver in bert mlperf (#9775)
we should commit to use AM. it's 7ms slower python time now
2025-04-07 23:40:27 -04:00
geohot db22094d35 hotfix: update softmax fusion test 2025-04-08 11:23:19 +08:00
Francis LataandGitHub f8fe15e64e move BoxCoder to mlperf helpers (#9773) 2025-04-07 20:27:06 -04:00
Eitan TurokandGitHub bb7922b95f Vectorize Transcendental Regression Tests (#9753)
* init test

* cleanup
2025-04-08 01:27:39 +08:00
chenyuandGitHub 7c4a739fe4 full script for bert mi300x (#9772) 2025-04-07 11:41:31 -04:00
07d1aefaf4 fast idiv (#9755)
* fast idiv with tests and fuzzer

* Add todo comment

* Add env variable to toggle fast_idiv

* Move env check

* Add fuzz fast_idiv to ci

---------

Co-authored-by: chenyu <[email protected]>
2025-04-07 08:32:24 -04:00
nimlgenandGitHub fa888ee077 minor test cleanups (#9770)
* fix test_graph on max

* pcie5
2025-04-07 15:29:12 +03:00
chenyuandGitHub 3069ebfad1 use BERT_LAYERS=2 in bert init (#9769)
save 5 minut scheduling in setup so we can fit more search
2025-04-07 07:46:37 -04:00
qazalandGitHub 891322fd51 split into grouper.py (#9768)
* split into grouper.py

* update tests

* reorder
2025-04-07 18:40:59 +08:00
qazalandGitHub 219b8c9e8b return becomes_map in scheduler [pr] (#9766)
* add a graph_rewrite pass for creating asts [pr]

* disk

* benchmark

* return becomes_map in scheduler

* reorder schedule.py into grouper and linearizer [pr]

* comments
2025-04-07 17:36:23 +08:00
qazalandGitHub 6306dea6e2 add a graph_rewrite pass for creating asts [pr] (#9765)
* add a graph_rewrite pass for creating asts [pr]

* disk

* benchmark
2025-04-07 16:32:11 +08:00
qazalandGitHub 07eea567d4 reorder tensor_map and grouper parts [pr] (#9764) 2025-04-07 15:36:13 +08:00
qazalandGitHub 8ddb1357c0 fix UPat.location after pickle (#9763)
* fix UPat.location after pickle [pr]

* named upat test
2025-04-07 15:16:42 +08:00
qazalandGitHub 4cd27aa0e6 hotfix: viz recenter and unlimited zoom (#9760)
* hotfix: viz recenter and unlimited zoom

* add shapes to the ast graph

* not for COPY
2025-04-07 14:38:03 +08:00
chenyuandGitHub d0dace4306 update doc for permute to 3d tensor (#9758)
easier to see if it's permuted to or permuted from
2025-04-07 00:38:05 -04:00
chenyuandGitHub b190d85ad7 benchmark script bert softmax (#9759) 2025-04-07 00:31:18 -04:00
Ignacio SicaandGitHub 58785181a8 AMD bf16xf32 TC (#9717)
* dont test bf16 for emulated amd tc

* skip bf16 tc test in ci

* skip bf16 for AMD in test_tensor_cores_codegen

* add simple bf16 gemm test to benchmark
2025-04-07 11:41:04 +08:00
chenyuandGitHub 43e4565148 weighted linear in external_benchmark_bert_matmuls (#9757)
include the linear to get qkv, and permute so that stride matches with the real run
2025-04-06 23:35:42 -04:00
George HotzandGitHub 28e06d2d44 minor cleanups from patternmatcher [pr] (#9756) 2025-04-07 11:28:14 +08:00
qazalandGitHub 1ce4912770 viz profiler ui (#9664)
* localhost:8000/prof

* selector + table

* add pid

* on null selection reset filters

* table sort

* charset=utf-8

* clear the rest

* sort by duration

* render table

* format

* nothing in copy thread

* keep starts

* sort back

* less javascript

* diff

* works on firefox
2025-04-07 00:30:17 +08:00
chenyuandGitHub 8a585dc5c1 benchmark script for matmuls in bert (#9752)
2 main matmuls in the bert layers. getting these to be fast makes bert fast
2025-04-06 19:34:25 +08:00
qazalandGitHub 139999c6d7 map viz files + query params cleanup [pr] (#9754)
* map viz files + query params cleanup [pr]

* .width + fix
2025-04-06 16:20:00 +08:00
Francis LataandGitHub 71b8890dd6 use validation dataloader inside retinanet eval (#9747) 2025-04-05 16:46:55 -04:00
nimlgenandGitHub 5f7c79676f jit: prune independent copies (#9749)
* jit: prune independent copies

* linter

* check kernel cnt
2025-04-05 20:50:28 +03:00
nimlgenandGitHub c2573b247c jit: rename optimize_weights -> replan_buffers_memory_layout (#9751) 2025-04-05 20:35:15 +03:00
uuuvnandGitHub 493fb315b1 fix RDNA2 support (#9700)
linux amdgpu_discovery.c:amdgpu_discovery_set_ip_blocks is a ton of
switch cases with sometimes weird choices like replacing nbio 3.X with
2.3 while nbio 2.5 is somehow nbio 7.0. `import_module` currently just
tries to replace revision and minor with zeroes if there is no exact
match, but that's not enough to cover all that weirdness
2025-04-05 18:42:47 +03:00
chenyuandGitHub 5a04f4d4ba revert bert hparams for green and red (#9744)
did more runs and it's not really better and not worth the change. only useful for BS=1024
2025-04-05 07:38:01 -04:00
chenyuandGitHub 407ca54382 symbolic fold double where (#9436)
* symbolic fold double where

a.where(b.where(c, d), d) -> (a & b).where(c, d). a pattern in optimizer

* test case
2025-04-05 05:12:17 -04:00
9c2fc695b5 cond.logical_not().where(a,b) -> cond.where(b,a) (#9741)
* Add rule for negation in where, simplifies arange patterns

* 0 becomes 0.0 again

* Only if cond is bool

* ne is never None

* Add a test

---------

Co-authored-by: chenyu <[email protected]>
2025-04-04 19:13:32 -04:00
Sieds LyklesandGitHub e9a3ac02a5 Remove ne from arange pattern (#9743) 2025-04-04 18:31:13 -04:00
nimlgenandGitHub 86c55414d7 ops_amd: simplify gfx version (#9742)
* ops_amd: simplify gfx version

* fix

* all vesrsion compact style

* mypy

* revert this

* rename back to target
2025-04-04 22:18:11 +03:00
qazalandGitHub 16d6aa15f1 record unittest name in process replay (#9731)
* record unittest name in process replay

* getitem

* filename + (optional) name

* del

* get_test_method

* not solved

* try with linecache

* test: print_loc

* format

* without linecache

* checkout master
2025-04-05 01:39:48 +08:00
qazalandGitHub 354db961c6 viz refactor to prep for profiler [pr] (#9739) 2025-04-04 17:13:14 +08:00
chenyuandGitHub fe998798fb linearizer failure test for OUT OF BOUNDS ACCESS (#9738) 2025-04-04 03:48:43 -04:00
George HotzandGitHub 8b5a523743 fix minimum length in pattern matcher (#9736) 2025-04-04 14:57:01 +08:00
chenyuandGitHub 640ff681c3 rename bert script to 8xMI300X (#9734)
and adds a script for single MI300X
2025-04-03 23:36:24 -04:00
George HotzandGitHub b719aa1fb0 only check once for divisible fold lengths (#9732) 2025-04-04 11:27:34 +08:00
George HotzandGitHub 926b0bcc57 cache folded upcast [pr] (#9733) 2025-04-04 11:23:19 +08:00
George HotzandGitHub 8206c7281e move const multiply after REDUCE (#9730) 2025-04-04 11:07:46 +08:00
chenyuandGitHub 6b3480ec70 update mi300x bert haparams (#9716)
* update mi300x bert haparams

borrowed from previous submission that also did BS=1024

* update
2025-04-03 22:30:00 -04:00
George HotzandGitHub cac8bcf8b5 use Ops.REDUCE (#9721)
* decrease bert python time [pr]

* order copies

* Revert "order copies"

This reverts commit 3f62c8693b.

* rewrite count

* Ops.REDUCE

* acc first in the add chain

* Fix tensor core acc

* arange patterns look good

* fix multireduce gate

* reduce rewrite rule

* bump that to 15 minutes

* multiwmma isn't fusing

* gep through wmma is gep pushing

* bump that timeout too, it's all env setup

* add failing test
2025-04-04 10:14:34 +08:00
nimlgenandGitHub 949459fdd6 jit: fix deallocate on unallocated buffers in free_intermediates (#9699) 2025-04-03 18:32:51 +03:00
qazalandGitHub 52a8ecb15e record unittest location in process replay [pr] (#9727) 2025-04-03 20:50:09 +08:00
geohotstanandGitHub ac713e04db ONNX add output shape validation (#9720)
* add output shape validation and remove support for sequence_type

* nit better err msg

* add sequence_type back

* improve err msg

* Revert "improve err msg"

This reverts commit dc9eaea4bb.

* Revert "add sequence_type back"

This reverts commit 288170b2d9.

* do explicit shape equality

* small nit
2025-04-03 05:44:53 -04:00
chenyuandGitHub 7dadbf3697 insert float() in bert acc (#9726)
sum of bool by default uses default_float for acc. So without float, it might overflow with a large BS and default_float=HALF.

fixed clsf_accuracy to not be inf in mi300x bert
2025-04-03 05:44:09 -04:00
chenyuandGitHub 79145e3d40 cleanup truncate_bf16 [pr] (#9725)
use torch bfloat16 for groundtruth in test. also a TODO for discrepancy
2025-04-03 05:43:49 -04:00
Ignacio SicaandGitHub bc2d86195e increase test tolerance (#9719) 2025-04-03 15:24:09 +08:00
chenyuandGitHub 1d25844d44 Revert "disable CI red llama 3 4 gpu beam (#9690)" (#9709)
This reverts commit 6a5eacba8b.
2025-04-03 02:34:39 -04:00
George HotzandGitHub 49dafe6d43 add gc tests [pr] (#9718)
* add gc tests [pr]

* del

* more gc tests

* add NullGraph
2025-04-03 14:08:32 +08:00
Ignacio SicaandGitHub bc91fffc5d fix gated store with index in python backend (#9703)
* add default gate in index

* assert store

* add TestRendererFailures

- move test_gated_store_with_alu to new TestRenderFailures class for
tests that fail on multiple renderers
- add test_renderer_failures.py run on python CI

* add test for gated index in 2d

* test TestRenderFailures
2025-04-03 12:48:28 +08:00
qazalandGitHub f2bd65ccfc delete Ops.EMPTY and Tensor._metaop (#9715)
* delete Ops.EMPTY and Tensor._metaop [pr]

* test_creation

* arg=

* abstractions2
2025-04-03 12:29:02 +08:00
George HotzandGitHub 5c7b549eab use functools.cache instead of lru_cache(None) [pr] (#9714)
* use functools.cache instead of lru_cache(None) [pr]

* more cache
2025-04-03 11:47:13 +08:00
qazalandGitHub bbd13191f4 cleanup tensor BIND + remove outdated comments in tensor.py [pr] (#9712)
* cleanup tensor BIND + remove outdated comments in tensor.py [pr]

* from_blob whitespace

* assert
2025-04-03 11:21:53 +08:00
geohotstanandGitHub e1d7e47cca fix ONNX IsInf unintended dtype promotion (#9711)
* add IsInf

* add corresponding test

* that float16 is kinda silly
2025-04-02 22:46:15 -04:00
qazalandGitHub 11ae254dc5 construct BUFFER UOps directly when device in known [pr] (#9710)
* construct BUFFER UOps directly when device in known [pr]

* diff
2025-04-03 10:41:44 +08:00
George HotzandGitHub 1714fc3ba4 start work on speed [pr] (#9707)
* fix get_location

* fix get_location try 2

* clean up split_load_store [pr]

* SHR fixup [pr]
2025-04-03 10:39:01 +08:00
geohot 0f1ffc2050 hotfix: cat tests 2048 instead of 256 2025-04-03 10:37:56 +08:00
uuuvnandGitHub 5bd485c027 Fix double SDMA_OP_FENCE (#9705)
Introduced in #9585, probably when i incorrectly resolved merge conflict
while rebasing an old, mi300x-only branch. Seems to be the source of
multi gpu beam llama hangs
2025-04-03 09:43:37 +08:00
chenyuandGitHub a6fec2f5ae dev_run for bert on mi300x (#9706) 2025-04-02 21:12:55 -04:00
nimlgenandGitHub d96b4983ac amd: support rdna4 in runtime again (#9702) 2025-04-03 01:19:23 +07:00
Ignacio SicaandGitHub 2d6d8b7355 add bf16 mfma support (#9695)
* add bf16 mfma support

* skip tc if emulated_amd and dtypes is bf16

* hotfix
2025-04-02 21:44:49 +08:00
nimlgenandGitHub a6733f519f dsp: make relro sections contiguous (#9701) 2025-04-02 18:02:16 +07:00
George HotzandGitHub ea5caefef0 gep should look at count, not vcount (#9698)
* gep should look at count, not vcount

* gep in order is a rule

* min change

* gep on void
2025-04-02 18:10:57 +08:00
George HotzandGitHub f72a87fd0e add proper support for Ops.IGNORE to remove store masks (#9692)
* add proper support for Ops.IGNORE to remove store masks

* remove useless NHWC

* revert that
2025-04-02 16:38:01 +08:00
chenyuandGitHub 3b8d923692 remove skip LLVM in test_div_int (#9686) 2025-04-02 04:15:00 -04:00
chenyuandGitHub bc3bfcbad4 update install gpuocelot (#9693)
`-DCMAKE_POLICY_VERSION_MINIMUM=3.5`
2025-04-02 04:10:34 -04:00
e78e8722dc Revert "LDS noop and spec (#9669)" (#9691)
This reverts commit 870b545ace.

Co-authored-by: Ignacio Sica <[email protected]>
2025-04-02 15:31:32 +08:00
George HotzandGitHub 4514fd91c1 more stuff from DSP (#9689)
* more good stuff from dsp branch

* test pkl imagenet
2025-04-02 15:27:48 +08:00
chenyuandGitHub 6a5eacba8b disable CI red llama 3 4 gpu beam (#9690)
device hangs and ci would fail
2025-04-02 03:19:09 -04:00
Ignacio SicaandGitHub 876a8be97a Debug env var breakdown (#9663)
* add debug level breakdown

* hotfix

* Update env_vars.md
2025-04-02 14:34:07 +08:00
George HotzandGitHub 6f812d3f2f fixes from the dsp branch + 12500 lines (#9683)
* fixes from the dsp branch

* more changes

* those are gep pushing
2025-04-02 13:07:17 +08:00
chenyuandGitHub c20f112e9f example test use z3 to verify valid simplification (#9684) 2025-04-02 01:05:52 -04:00
chenyuandGitHub bca0c85193 skip CI CPU test_data_parallel_resnet_train_step (#9685)
flaky
2025-04-02 01:04:54 -04:00
qazalandGitHub bb94f13e58 add RECORD_TRACEBACKS=1 option to process replay (#9679)
* add RECORD_TRACEBACKS=1 option to process replay

* stack
2025-04-02 11:58:27 +08:00
chenyuandGitHub 3acc1b928a minor div_and_mod_folding cleanup [pr] (#9681)
it's not wrong because the dtype is never used, but `x.const_like` is more readable
2025-04-01 23:51:36 -04:00
chenyuandGitHub c672716b38 improve vmin/vmax for IDIV (#9678) 2025-04-01 23:16:01 -04:00
chenyuandGitHub 8dd88ad476 don't div_and_mod_folding for negative numerator with remainder (#9674)
can be wrong in C div since it truncates towards zero
2025-04-01 16:26:23 -04:00
chenyuandGitHub 0e34f9082e helper functions for cstyle div mod [pr] (#9673) 2025-04-01 08:06:56 -04:00
qazalandGitHub eee0dcc37a merge viz back into one file (#9672)
* merge viz back into one file

* work

* rename lib to js directory

* fix diff

* less indenting

* memory graph is back

* viz_sz.py
2025-04-01 19:52:02 +08:00
Ignacio SicaandGitHub 870b545ace LDS noop and spec (#9669)
* init lds noop and lds_0 spec

* refactor lds helper test

* fix typo

* test all lds at the same time

* change comment

* comment

* start test_lds_full

* test_lds_tc

* add tc spec
2025-04-01 18:44:55 +08:00
uuuvnandGitHub 609a006242 AMDComputeQueue.wreg (#9628)
* AMDComputeQueue.wreg

Used to be part of #9428, i think it's much more readable than repeating
the ~same pm4 things over and over again, especially with separate .encode

* fix indentation
2025-04-01 17:01:33 +07:00
qazalandGitHub fa373e15a3 hotfix: NULL=1 Buffer does not have _buf (#9661) 2025-04-01 17:43:55 +08:00
nimlgenandGitHub 3e2f42c2e8 autogen: remove am headers from extra (#9666) 2025-04-01 14:45:30 +07:00
Ignacio SicaandGitHub cfad139189 bump assembly debug to 7 (#9662) 2025-04-01 11:51:33 +08:00
Ignacio SicaandGitHub ac533e89a2 remove duplicated ast print (#9660) 2025-04-01 10:29:24 +08:00
Ignacio SicaandGitHub 846ef84cda move uops print to debug >= 6 (#9659) 2025-04-01 10:29:09 +08:00
d9af4cfc1b AMD_LLVM: tensor cores support (#9613)
* tensor cores support

* test tesor cores codegen

* use rewrite rules

---------

Co-authored-by: b1tg <[email protected]>
2025-04-01 09:56:27 +08:00
qazalandGitHub 1658eb4e63 always fit fresh viz graph into view [pr] (#9657) 2025-04-01 09:34:26 +08:00
a1ee4d587f Fix test_ops for tiny backend (#9302)
* fix some tests in test_ops for torch backend(171 failing)

* fix more tests (135 failures)

* fix tests (126 failing)

* handle transposed convs (109 tests failing)

* fix slice

* fix lshift & rshift and more tests (87 tests failing)

* revert accidental change

* remove unnecessary changes (82 failures)

* fix backward for avg_pool2d (78 failures)

* fix backward for avg_pool2d (78 failures)

* fix replication backpass

* fix reflection pad back pass (71 failures)

* cummax with indicies, aten.mv and move out methods (67 failures)

* extract avg_pool2d and avg_pool3d to separate functions (62 failures)

* revert changes for cat_out

* rewrite avg_pool and pad without repetition

* remove duplicates from decomps

* slice rewrite and add slice_backward (59 failures)

* add dtype fixup from https://github.com/tinygrad/tinygrad/pull/9297

* fix linter error and remove Tensor.pad (48 failures)

* add select_backward and index_put (40 failures)

* fix some more tests (36 failures)

* fix more tests (12 failures)

* some cleanups and fix couple more tests (10 failures)

* cleaner way to write upsample

* some more upsample cleanups

* use lambda for upsample

* add autowrapper for upsample forward

* cumsum and max_dim without aten functions

* revert _log_softmax

* fix more tests (1 failure)

* make linter happy

* move import to appropriate func

* make linter happy

* add codes for noqa

* some more refactors

* remove comment

* remove dependency on aten function for conv backward

* some more refactors

* add returns

* revert a change from merge

* some cleanups

* remove whitespace

* remove ruff change

* revert upsample

* add masked_fill_.Tensor and scatter.src_out

* add todo

* fix test_biased_conv2d

* fix test_var_one_in_axis & test_std_one_in_axis but break test_biased_conv2d :(

* revert torch_debug

* revert torch_debug

* skip test_gather_failure for the tiny backend

* make padding registration more consise

* add nonzero

* remove scatter_add since we already have the out

* fix scatter

* remove some repetition

* make upsample backward registrations more concise

* remove select.int

* use Tensor.cumsum

* realize conv2d outputs before backward to fix test_biased_conv2d

* add a todo for realize(1 failure)

* add new_empty and new_empty_strided

* make test_pad_circular_mode forward only and remove redundant stuff

* fix linter errors

* remove expect failure

* just tb

* slice is a view_op

* contiguous only when lazydata.is_realized

* fix backward for test_pad_circular_mode

* revert torch.nn.functional.pad override

* add transpose.int and make constant_pad_nd contiguous

* slice_backwards has no kwargs

---------

Co-authored-by: chenyu <[email protected]>
2025-03-31 21:13:09 -04:00
qazalandGitHub a0b4465412 bring GroupOp.Meta back (#9656) 2025-04-01 01:02:29 +08:00
Ignacio SicaandGitHub f277f407f2 remove smem_prefix_for_cast for amd (#9651) 2025-03-31 23:03:35 +08:00
chenyuandGitHub f7cb2e8da3 bert dev_beam for mi300x box (#9648)
* bert dev_beam for mi300x box

* terminate BENCHMARK properly
2025-03-31 08:35:51 -04:00
qazalandGitHub 5171b098e5 merge_double_reduce without asserts [pr] (#9650) 2025-03-31 19:17:05 +08:00
Ignacio SicaandGitHub 1444069c09 Uppercase K for dimension and lowercase k for kernel in linearizer tc helper test (#9649) 2025-03-31 19:05:36 +08:00
Ignacio SicaandGitHub baa67fd124 Uppercase N and M (standalone syntax change) (#9647) 2025-03-31 18:45:30 +08:00
chenyuandGitHub aca0f1befb print idx when OUT OF BOUNDS ACCESS (#9646)
in some cases (if there's a where in idx) the vmin/vmax might not be tight
2025-03-31 06:12:44 -04:00
Priyank PatelandGitHub e2d9322d21 torch backend: partial fix for strided related test fails (#9642)
* partial fix for strided related test fails

* cleanup

* fix lint
2025-03-31 05:45:18 -04:00
qazalandGitHub 76c1b1edf6 viz kernel list cleanup (#9643) 2025-03-31 15:53:39 +08:00
George HotzandGitHub e4c545b396 linearizer fix from dsp branch (#9641)
* linearizer fix from dsp branch

* revert that
2025-03-31 14:26:39 +08:00
George HotzandGitHub ec405b919f Revert "Revert "do not block gc in UOp.toposort (#9623)" (#9624)" (#9639)
This reverts commit 7ef02d0e1c.
2025-03-31 14:03:38 +08:00
George HotzandGitHub 49b1c46d16 good changes from the dsp branch (#9638) 2025-03-31 13:02:53 +08:00
qazalandGitHub 9d67d3a2f3 simpler viz codeblocks (#9636)
* simpler viz codeblocks

* err
2025-03-31 11:48:35 +08:00
chenyuandGitHub 60eb0c4ed7 exclude slow tests on PYTHON (#9634) 2025-03-30 22:55:05 -04:00
chenyuandGitHub 5012ba3f04 cumalu touchup [pr] (#9632) 2025-03-30 22:43:11 -04:00
chenyuandGitHub d8d7ac1bb1 fix bert free_intermediates (#9633)
fix when only run eval `TRAIN=0 BERT_SIZE=tiny examples/mlperf/training_submission_v5.0/tinycorp/benchmarks/bert/implementations/tinybox_green/dev_beam.sh`
2025-03-30 22:42:52 -04:00
qazalandGitHub ff984c807d hotfix: less lines for viz helpers (#9631) 2025-03-31 10:10:34 +08:00
qazalandGitHub c206a7ae6d refactor viz state updates (#9630)
* refactor viz state updates

* onclick
2025-03-31 09:54:54 +08:00
6652003839 Add cumprod to Tensor (#9629)
* probably how cumprod should look like

* update _cumalu to work with MUL

* shorter

* cumprod testing

* clean

* more cleanup

* add cumprod to torch backend.

* make it look like cumsum

* mypy fix

---------

Co-authored-by: chenyu <[email protected]>
2025-03-30 21:49:18 -04:00
d52e91db7b ONNX ops clean ups (#9622)
* combine work from remove numpy and onnx ops tests

* clippy

---------

Co-authored-by: chenyu <[email protected]>
2025-03-30 21:39:22 -04:00
uuuvnandGitHub 962c0f65f8 Fix generate_am (#9626)
This should be a comment
2025-03-31 01:15:44 +08:00
uuuvnandGitHub 2a4247b8c2 RDNA 3.5 support (#9627) 2025-03-31 01:15:20 +08:00
a08b07b4da Bump onnx==1.17.0 (#9618)
* bump

* remove resize tf_crop_and_resize

---------

Co-authored-by: chenyu <[email protected]>
2025-03-30 03:21:51 -04:00
qazalandGitHub 7ef02d0e1c Revert "do not block gc in UOp.toposort (#9623)" (#9624)
This reverts commit f1a35bbb54.
2025-03-30 12:57:06 +08:00
qazalandGitHub f1a35bbb54 do not block gc in UOp.toposort (#9623) 2025-03-30 11:54:17 +08:00
nimlgenandGitHub 54e1e59b44 am: rdna 4 support (#9621)
* hm

* fix

* return this

* fine

* g

* ruff

* fix
2025-03-29 23:16:27 +07:00
nimlgenandGitHub 118bd1cbed hotfix: amd imports (#9620) 2025-03-29 20:19:53 +07:00
uuuvnandGitHub 5908b89f71 MI300X support (WIP) (#9585) 2025-03-29 19:46:42 +08:00
geohot 77f0d09ecf hotfix: HIP supports parallel BEAM search 2025-03-29 11:49:53 +08:00
chenyuandGitHub 162f286a0e add a few Tensor method to doc (#9614)
* add a few Tensor method to doc

* clone
2025-03-28 13:47:16 -04:00
uuuvnandGitHub dd9aae02c3 Refactor ops_amd.py (MI300X prereq) (#9428) 2025-03-29 00:17:20 +07:00
uuuvnandGitHub 3e1168ff5e am: module import in common (#9615) 2025-03-28 21:29:34 +07:00
nimlgenandGitHub a8ff85369e cpugraph for dsp (#9601)
* cpugraph init

* fixes

* no cpu for now

* mypy

* fix
2025-03-28 19:06:31 +07:00
nimlgenandGitHub fa0ebbd237 jit: optimize before pickle (#9611)
* jit: optimize before pickle

* optimize weights

* fix

* mypy

* mypy2
2025-03-28 19:06:09 +07:00
George HotzandGitHub 392a311312 Revert "add copy button in VIZ code-block (#9605)" (#9610)
This reverts commit d1e8598c81.
2025-03-28 17:05:44 +08:00
Harsh NatuskarandGitHub d1e8598c81 add copy button in VIZ code-block (#9605)
* works

* only second block has copy

* better function

* better

* ...

* smol function

* update copy-btn css

* updates
2025-03-28 16:52:21 +08:00
qazalandGitHub b4ea45b4a6 fix viz recenter + worker cleanup (#9607) 2025-03-28 15:24:53 +08:00
Andrew FureyandGitHub 50dee4a7b3 add test for checking const gradients (#9598) 2025-03-27 15:17:37 -04:00
chenyuandGitHub 5358b0904b update uop_given_valid if a node becomes const (#9604)
* update uop_given_valid if a node becomes const

* cleanup
2025-03-27 14:57:46 -04:00
chenyuandGitHub a187dfd3df bert BEAM_UOPS_MAX 3000->4000 (#9603)
more stable for the final step time

green 410ms (master) -> 397ms (BEAM=4) -> 392ms (this)
red 561ms (master) -> 550ms (this)
2025-03-27 11:58:47 -04:00
qazalandGitHub 088a677e25 rescale to fit viz graph [pr] (#9599)
* zoom to fit the graph in viz [pr]

* always on screen fit graph

* space key recenters
2025-03-27 23:33:51 +08:00
nimlgenandGitHub 3737821b9e prepare for clang graph (#9600)
* prepare for clang graph

* emu

* ops

* ops2

* better type

* fix
2025-03-27 20:09:37 +07:00
qazalandGitHub bf94924d5a fix viz with nested graph_rewrite (#9595) 2025-03-27 13:14:28 +08:00
qazalandGitHub c011751b41 statically define viz arrow heads (#9594) 2025-03-27 12:22:04 +08:00
qazalandGitHub 0877497bad hotfix: use captured uops in viz render [pr] (#9593)
* hotfix: use captured uops in viz render [pr]

* better error
2025-03-27 11:52:12 +08:00
qazalandGitHub e5ff7b23d7 refactor to @track_matches + add failing test_nested_rewrite (#9592)
* test_nested_rewrite

* refactor to track_matches

* positional arg
2025-03-27 11:11:56 +08:00
chenyuandGitHub 62888614f6 lower bert eval bs to 24 (#9590)
oom during eval
2025-03-26 21:25:23 -04:00
nimlgenandGitHub dc9da1d917 memplan into one buffer (#9526)
* new memplanner

* new should works

* fix

* VALIDATE_MEMORY_PLANNER

* hm?

* ugh

* fix alignment

* fix2

* rm

* tiny fixes

* test

* comments and fixes

* fix2

* liiiinetr

* t

* fix
2025-03-27 01:46:50 +07:00
qazalandGitHub 8b717c345c cache viz worker at launch (#9589) 2025-03-27 01:10:02 +08:00
George HotzandGitHub d62ced8981 symbolic -> symbolic_flat (#9588) 2025-03-26 23:34:43 +08:00
George HotzandGitHub 8aaa5e1ec5 generate the individual indexes (#9587) 2025-03-26 22:32:06 +08:00
George HotzandGitHub 5c6cd884e3 multiple simplifies is faster [pr] (#9586)
* multiple simplifies is faster [pr]

* cleanup

* cleanup
2025-03-26 21:42:52 +08:00
George HotzandGitHub 1e6e75e39a little changes from dsp branch (#9582)
* little changes from dsp branch

* not that one

* need the where

* Revert "need the where"

This reverts commit 140f89c878.
2025-03-26 20:01:21 +08:00
nimlgenandGitHub e88a640ca5 fix _access_resources for offset buffers (#9580)
* fix _access_resources for offset buffers

* test
2025-03-26 18:42:43 +07:00
AndreyandGitHub 7b865ed03d use tuple in isinstance for type checking (#9583) 2025-03-26 19:36:48 +08:00
George HotzandGitHub 9115ce8860 linearizer fixups from DSP branch (#9581) 2025-03-26 18:28:15 +08:00
qazalandGitHub e799df537e prep viz UI cleanup for grid scales (#9579)
* less ways to make a button

* move collapse out

* work

* do not create extra resizers

* better

* ul

* safari
2025-03-26 17:48:15 +08:00
nimlgenandGitHub ccbcdca473 add memplanner tests (#9577) 2025-03-26 10:59:39 +07:00
qazalandGitHub c03dadfcb9 add TORCHVIZ=1 to beautiful_mnist_torch (#9576) 2025-03-26 11:17:08 +08:00
qazalandGitHub 93bcb974c5 select torch device in examples/beautiful_mnist_torch.py (#9575) 2025-03-26 11:01:25 +08:00
uuuvnandGitHub 2c32126fc8 am: AMRegister refactor (#9572) 2025-03-26 00:52:40 +07:00
chenyuandGitHub cddd750d68 add a failed test case for jit/nojit rand [pr] (#9574)
currently adding jit produced different rand values
2025-03-25 13:32:44 -04:00
nimlgenandGitHub 4cf2b68ca8 am_smi: fix init for newer versions (#9559) 2025-03-25 23:48:05 +07:00
qazalandGitHub a6a5c0aec5 add NULL=1 backend (#9573)
* add NULL=1 backend

* NullAllocator

* line

* metadata should still work

* it shouldn't have memory usage

* Revert "it shouldn't have memory usage"

This reverts commit a9080fdd43.

* back

* null flops
2025-03-25 22:20:52 +08:00
qazalandGitHub b60d9976b4 better yaxis formatting in viz memory graph (#9570)
* better bytes format

* pluralize

* 1 less line
2025-03-25 16:50:22 +08:00
qazalandGitHub faf3b5b245 display kernel metadata in memory viz (#9569)
* display kernel metadata in memory viz

* fix that
2025-03-25 13:14:54 +08:00
qazalandGitHub 52301fe68e move Buffer refcount increment out of schedule.py (#9564)
* move Buffer refcount increment out of schedule.py

* add TestGC.test_assign_refcount

* refcount refers to Ops.BUFFER UOps
2025-03-25 12:08:27 +08:00
qazalandGitHub 262f5a2bd3 hotfix: replace link in viz/readme (#9568) 2025-03-25 10:24:49 +08:00
chenyuandGitHub 6427272bf6 minor update to rand [pr] (#9566) 2025-03-24 18:49:50 -04:00
chenyuandGitHub b0e070e737 remove MOCKGPU workaround in rand (#9565)
also `requires_grad_` to save a line
2025-03-24 17:49:45 -04:00
qazalandGitHub d7c754ce49 failing test for UOp buffer ref count (#9563)
* failing test for UOp buffer ref count

* lint
2025-03-25 00:10:48 +08:00
f90001e1a6 amd llvm render (no_comgr prereq) (#9543)
* amd llvm render

* skip test_div_rounding_mode

---------

Co-authored-by: b1tg <[email protected]>
2025-03-24 22:50:51 +08:00
Priyank PatelandGitHub 4f5e03bd60 better fix inplace detach (#9557) 2025-03-24 22:50:28 +08:00
qazalandGitHub 1c40873962 show buffer info in memory viz (#9562) 2025-03-24 22:12:30 +08:00
qazalandGitHub efaee75656 start viz of memory usage (#9561)
* start viz of memory usage

* polygons/bars + use d3
2025-03-24 19:05:35 +08:00
qazalandGitHub 1cfe6d02fe refactor uop_to_json to return a dict [pr] (#9560) 2025-03-24 16:38:17 +08:00
nimlgenandGitHub edf9e1bf8d am: move out soc21 to a sep module (#9551)
* am: soc module is not part of am

* am: soc module is not part of am
2025-03-24 14:17:42 +07:00
George HotzandGitHub 74d98eafb8 add onnx frontend stub [pr] (#9558) 2025-03-24 12:24:34 +08:00
geohot de7d6cec3a hotfix: DEBUG 5 prints the ast 2025-03-24 11:43:11 +08:00
chenyuandGitHub ba41076e94 update embedding test to not use dtypes.long [pr] (#9556) 2025-03-23 21:33:38 -04:00
chenyuandGitHub c965f4c20b update bert config (#9555)
BEAM 4->5 for green, 2% faster
use AMD driver instead of AM for red, 5% faster
2025-03-23 16:14:41 -04:00
chenyuandGitHub d734e24c01 minor WEBGPU_PATH cleanup [pr] (#9552)
also mypy recognizes `sys.platform == 'win32'` but does not recognizes it if wrapped inside a helper...
2025-03-23 09:10:02 -04:00
Ahmed HarmoucheandGitHub 7ce7fe0574 Refactor webgpu_dawn lib finding (#9547)
* Refactor webgpu_dawn lib finding

* Fix ruff
2025-03-23 08:23:29 -04:00
uuuvnandGitHub c631c72f22 HCQ: Increment timeline signal before submitting (#9550)
`AMDComputeQueue.__del__` frees `hw_page` which is safe because
`AMDAllocator._free` does `self.dev.synchronize()` which is supposed
to wait for execution of IB to finish, however that doesn't happen if
AMDComputeQueue is dropped right after submit before timeline signal is
incremented, which it is in most places leading to a race if .bind() is
also used (required for multi-xcc because bug in mec fw treats all
PACKET3_PRED_EXECs outside IBs as if they had EXEC_COUNT of zero).
2025-03-23 18:30:38 +07:00
nimlgenandGitHub d5667419af am: move out pte creation logic (#9548)
* am: move out pte creation logic

* emu

* ops
2025-03-23 18:29:10 +07:00
geohotstanandGitHub 309afa20b7 add Tensor.max_unpool2d (#9518)
* why does max_unpool2d feel slower than out.gradient ...

* slightly cleaner

* what happened to ruff

* need to think about this some more

* slightly faster now?

* clean up, 1 more failing edge case

* ok good

* working TINY_BACKEND

* nit doc wording

* retry CI
2025-03-22 12:11:33 -04:00
quortusandGitHub bdd44d4255 Fix DSP transcendentals (#9542) 2025-03-22 11:08:18 +08:00
Ignacio SicaandGitHub eddafb84e5 Bugfix for TC=3 (#9464)
* wrong but uses less shared

* for size 8 tc1 with devectorize in 0 loads into local before wmma and works

* improvements over tc1 devectorize

* fix tc=3

* works for handcoded tc opts

* clean bugfix tc=3

* fix

* revert changes
2025-03-21 16:43:42 -07:00
chenyuandGitHub 6da78164f9 assert Kernel ast.op to be Ops.SINK [pr] (#9539)
rest of the code assumes self.ast is defined anyway
2025-03-21 18:09:44 -04:00
chenyuandGitHub c33679c47b increase size in test_multinomial_counterexample (#9540)
should be less flaky
2025-03-21 17:46:52 -04:00
Francis LataandGitHub 1a1087e3a0 cleanups on losses and dataset tests (#9538) 2025-03-21 17:03:18 -04:00
Francis LataandGitHub 8cbe4009fc RetinaNet losses (#9536)
* add sigmoid_focal_loss and l1_loss

* update ref implementation comment
2025-03-21 15:52:54 -04:00
e6389184c5 update comment for retinanet dataloader implementations (#9534)
Co-authored-by: chenyu <[email protected]>
2025-03-21 15:07:45 -04:00
chenyuandGitHub ee3d313b34 Revert "update ruff to 0.11.2 (#9531)" (#9535)
This reverts commit d8d65e2747.
2025-03-21 14:52:25 -04:00
chenyuandGitHub b46b8ee15e add a flag to log when beam surpassed max limit [pr] (#9533) 2025-03-21 13:37:02 -04:00
Francis LataandGitHub eb95825eea RetinaNet dataloader (#9442)
* retinanet dataloader

* remove batch_size from generate_anchors

* refactor kits19 dataset tests

* add tests for dataloader

* fix testing setup and cleanups

* remove unused import
2025-03-21 13:36:41 -04:00
58206fa8a9 add amd llvm compiler (#9519)
Co-authored-by: b1tg <[email protected]>
Co-authored-by: chenyu <[email protected]>
2025-03-21 23:13:27 +08:00
chenyuandGitHub d8d65e2747 update ruff to 0.11.2 (#9531)
0.11.2 fixed the false alert from 0.11.1. also pinned the version in setup for now to prevent broken CI from ruff upgrade
2025-03-21 10:32:59 -04:00
qazalandGitHub ee3ed73ed1 add reorder_view matcher to scheduler [pr] (#9528) 2025-03-21 17:46:20 +08:00
George HotzandGitHub 8e555c586c switch quantization to unsigned/unsigned + add Ops.REDUCE (#9527)
* switch quantization to unsigned/unsigned + add Ops.REDUCE

* tests

* nhwc + replay pkl
2025-03-21 17:02:37 +08:00
nimlgenandGitHub a35b0a88bf am: just rename and reorder ip init funcs (#9504) 2025-03-21 15:57:32 +08:00
nimlgenandGitHub 8a131ab271 am: allow allocations as small as a page (#9523)
* am: fix allocs

* bettermsg

* comment

* next time
2025-03-21 15:53:32 +08:00
Sieds LyklesandGitHub 3ad3ac4d1e Change dtypes.int to dtypes.ints (#9517) 2025-03-20 17:24:26 -04:00
chenyuandGitHub b9fab9b914 pin ruff to 0.11.0 in CI (#9520)
0.11.1 had a bug https://github.com/astral-sh/ruff/issues/16874 that breaks ci
2025-03-20 13:12:50 -04:00
3c5161b4cb add validation of the bounds of Ops.INDEX (#9503)
* add validation of the bounds of Ops.INDEX

* do mask properly

* more validation

* correct

* fix gated

* add CAST support to vmin/vmax

* fix ptx and image

* ptx no diff

* upat.index also stays

---------

Co-authored-by: qazal <[email protected]>
2025-03-20 12:15:55 +08:00
qazalandGitHub 0b20f91ce7 remove move_mask from the devectorizer (#9511)
* remove move_mask from the devectorizer

* add (wrong) ptx

* reason

* enable index addition in PTX, we won't have the INDEX anyways

* space
2025-03-20 11:53:12 +08:00
qazalandGitHub 9302738263 hotfix: more consistent wgsl.py spacing + cleanups [pr] (#9515)
* hotfix: more consistent wgsl.py spacing + cleanups [pr]

* free things up
2025-03-20 11:07:15 +08:00
68053d0510 dsp stuff / sniff ioctls from snpe (#9490)
* sniff ioctls from snpe

* dump input buffers

* snpe logs from dsp

* NHWC support

* knum 3

* this run?

* revert those

---------

Co-authored-by: Comma Device <[email protected]>
2025-03-20 10:38:23 +08:00
qazalandGitHub 2223b93338 add UPat.or_casted [pr] (#9513) 2025-03-20 10:08:32 +08:00
qazalandGitHub 1839e8c9b3 place masks in INDEX for TestGatedStoreRewrite [pr] (#9512) 2025-03-20 09:46:53 +08:00
bd731a8624 AMDCompiler refactor (no_comgr prereq) (#9497)
* add amdgpu_disassemble to helpers

* refactor hip compiler

---------

Co-authored-by: b1tg <[email protected]>
2025-03-20 09:44:07 +08:00
geohotstanandGitHub 8c0d0a122c Add return_indices to max_pool (#9506)
* wow argmax is so good

* 1 less line

* clean up and better variable names

* is this torch thing right...?

* add more tests

* slap a TODO on it

* clean ups

* prettier looking code and fix ceil mode test

* add return types and some docs

* ok that was a bad example since indices == value, just no example
2025-03-19 15:25:37 -04:00
chenyuandGitHub 189f62d44f add rounding to tqdm unit scale (#9507)
fixed `AssertionError: ' 1.00/10.0  1000it/s]' != ' 1.00/10.0  1.00kit/s]'`
2025-03-19 12:08:46 -04:00
nimlgenandGitHub a5c971ff3a am: prereqs for rdna4 1/n (#9495)
* am: ip_ver rename for acc

* am: refactor this

* fix version

* ugh
2025-03-19 17:14:57 +08:00
Francis LamandGitHub 1e5d9ad8f7 extra/gemm/max_matmul: start of custom kernels for GEMM (#6926)
* extra/gemm/max_matmul: start of custom kernels for GEMM

* add an unoptimized FP16/FP16 MMA example

* add slow 3-stage fp16 acc example

* add correct 3-stage pipeline with unswizzled/flat smem input (slow)

* add acc fp16 example with 3 stages and swizzle (no bank conflicts)

* add max version of NV fp16_fp16_fp16

* fix up comments and removed unused code in max variations

* add start of no_xor example

* fix to account for UOps to Ops
2025-03-19 15:04:57 +08:00
geohot 865f23dd7b olmoe memory usage cleanups 2025-03-19 12:28:18 +08:00
2c87a22cf2 fix prg size calculation when there are adjacent mapped ranges (#9498)
Co-authored-by: b1tg <[email protected]>
2025-03-19 11:55:03 +08:00
1d71436e6a use libllvm19 in ci (#9494)
Co-authored-by: b1tg <[email protected]>
2025-03-19 11:53:32 +08:00
a95b489a55 nanoGPT train works with tiny torch backend (#9283)
* train_shakespeare_char.py works

* move aten.where.self_out to tiny_backend_out

* fix memory leak

* corealize in the backward_hook

* Update backend.py

---------

Co-authored-by: George Hotz <[email protected]>
2025-03-19 11:51:02 +08:00
chenyuandGitHub f8976dd2eb enable more webgpu tests (#9502)
OSX has larger buffer number limit, and it supports fp16 now
2025-03-18 23:03:54 -04:00
qazalandGitHub ae688e4103 simple failing test for scheduling parallel reduce [pr] (#9501)
* simple failing test for scheduling parallel reduce [pr]

* atol
2025-03-19 10:52:13 +08:00
e4dad99145 nn.state docs cleanup (#8332)
* doc cleanup

* extension cleanup

* manual definition

* bring back accept_filename for gguf_load

---------

Co-authored-by: George Hotz <[email protected]>
Co-authored-by: chenyu <[email protected]>
2025-03-18 17:16:40 -04:00
chenyuandGitHub 1ea4876dfa olmoe touchups (#9499)
GlobalCounters.reset() and only validate if temperature is 0
2025-03-18 15:25:45 -04:00
geohotstanandGitHub f7506c6c25 JIT OLMoE (#9396)
* jit the forward

* might timeout, idk just send it

* this is dumb

* naive bitonic lol

* idk if this is correct, but that squeeze before is definitly not

* vectorized bitonic sort, but still slow

* yay 1 layer is correct

* alright its pretty good

* good enough

* rerun CI

* nit improve comment
2025-03-18 14:49:02 -04:00
Ignacio SicaandGitHub 5c56cac0a0 MI300 mfma support (#9417)
* add f16/f32 mfma support for MI300

- add 16x16 mfma shape support for f16 with f32 acc
- add ops_python mfma emulation
- add arch to AMDRenderer

* minor cleanup

* minor cleanup

* add mfma emulation task to ci

* add back todo

* hotfix: comment

* add tc=3 job to ci
2025-03-18 14:33:30 -03:00
hoovedandGitHub 5500887eed improve reproducibility of WebGPU CI puppeteer test (#9496)
* try to make CI test fail with slow JS import

* prevent race between model import and reference

* revert artificial delay in JS module import
2025-03-18 09:27:38 -04:00
qazalandGitHub cde4fd3be3 do not view_left assign + elementwise sources always have a shape [pr] (#9491) 2025-03-18 17:42:51 +08:00
George HotzandGitHub 117b7a16ef VALIDATE_WITH_CPU [pr] (#9488)
* VALIDATE_WITH_CPU [pr]

* fix test
2025-03-18 15:15:04 +08:00
qazalandGitHub 935cd01f56 simple failing test for graph_rewrite children [pr] (#9489)
* simple failing test for graph_rewrite children [pr]

* lint

* update too
2025-03-18 13:07:21 +08:00
George HotzandGitHub d20494e6d7 move buffer logic to Buffer [pr] (#9487)
* move buffer logic to Buffer [pr]

* pass shape into as_typed_buffer

* pass shape into as_typed_buffer

* work

* cleaner

* fix tests
2025-03-18 11:21:21 +08:00
qazalandGitHub 3be228182f unbind Tensor variables last [pr] (#9486)
* reorder do_realize [pr]

* move merge_views

* unbind all variables at the end [pr]
2025-03-18 09:52:01 +08:00
qazalandGitHub b44f9c409a reorder do_realize [pr] (#9485)
* reorder do_realize [pr]

* move merge_views
2025-03-18 09:30:10 +08:00
nimlgenandGitHub a82c9332d3 am: rename soc21 to soc (#9482) 2025-03-18 08:54:26 +08:00
qazalandGitHub b100fc0b20 split the rule that uses context in scheduler simplifier [pr] (#9484)
* split the rule that uses context in scheduler simplifier [pr]

* add
2025-03-18 08:12:26 +08:00
Anish UmaleandGitHub 5e58f4b65b Tiny backend test_ops fix part 3 (#9483)
* extract straightforward things from https://github.com/tinygrad/tinygrad/pull/9302

* pass dtype and device for ones_like
2025-03-17 18:01:51 -04:00
9fcef4d009 add masked_select to tensor.py (#9468)
* add masked_select to tensor.py

* fix tests

---------

Co-authored-by: George Hotz <[email protected]>
2025-03-17 16:05:36 -04:00
chenyuandGitHub 4f8eac59ea failed test case for threefry (#9469)
* failed test case for threefry

not sure if it's always like this, but increment before _threefry_random_bits is incorrect. the counts should start with random numbers generated so far.

use jax to generate 20 + 20 + 10 random numbers, the first 20 + 20 matches and the last 10 are different. just moving increment after _threefry_random_bits matches the number but jit test failes

* workaround

* why is this different?

* revert those

* and that
2025-03-17 14:52:10 -04:00
6dd8e5ba7c refactor llvm compiler (#9403)
* refactor LLVMCompiler

* new interface

* automatic configuration

---------

Co-authored-by: b1tg <[email protected]>
Co-authored-by: George Hotz <[email protected]>
2025-03-18 00:13:49 +08:00
53d6f1e1bb Add bitonic cat sort (#9422)
* poc

* repeated values fail, sigh

* is this being timed out?

* fix up down names

* bitonic v2, does this run?

* bitonic v3, faster

* bitonic v3.1, faster

* bitonic v3.1.1, same speed unlucky

* support dim and indices

* bitonic v3.2, simpler code, TODO repeated indices

* bruv gimme green for once cmon

* cat (stack) implementation, slow but maybe one day when cat is fast meow

* revert to v3.2

* bitonic v4, who let the cats out edition

* clean up variable names

* figured out repeated indices :D

* ruff check --fix

* use sort for topk

* add Tensor.sort everywhere

* fix docs and add some types

* slightly better variable names

* am I doing torch inplace correctly?

* delegate sort to values_stable

* add a contig, faster first sort

* maybe don't test_inplace

---------

Co-authored-by: chenyu <[email protected]>
2025-03-17 12:01:23 -04:00
chenyuandGitHub f53be010d7 lower bert learning rate (#9481)
slightly better. first sub 3hr run https://wandb.ai/chenyuxyz/MLPerf-BERT/runs/0or96ink/overview
2025-03-17 10:49:56 -04:00
qazalandGitHub e03c0aacf2 more explicit DONT_PUSH_VIEWS [pr] (#9479)
* more explicit DONT_PUSH_VIEWS [pr]

* update tests to not handcode ast

* lint

* test_recursive_swizzle and test_simple_store_reshape
2025-03-17 20:43:21 +08:00
qazalandGitHub 3b00a778ba fix view_left for unsafe pad ops [pr] (#9478) 2025-03-17 19:02:02 +08:00
qazalandGitHub 813f713edc merge_views for buffer ops + create valids last (#9472)
* merge_views for buffer ops + create valids last

* view.arg

* pass
2025-03-17 17:15:44 +08:00
qazalandGitHub bd1f71c1e2 simple failing test for extra ops in VALID [pr] (#9474)
* simple failing test for extra valids [pr]

* this has DEBUG=4
2025-03-17 17:02:40 +08:00
qazalandGitHub e26caf4c3a hotfix: skip test_mean_half_precision_underflow on amd ci (#9476)
The global size is very large (781250 gidx) and the emulated version takes more than 1
minute to execute the kernel.
2025-03-17 16:47:48 +08:00
George HotzandGitHub 824c5f41ac dsp work try 3 (#9475)
* dsp work try 3

* padding
2025-03-17 16:42:12 +08:00
George HotzandGitHub 242daa4f9a ptrcat (#9473) 2025-03-17 16:06:37 +08:00
George HotzandGitHub 52ae9af4dd Fast DSP for MobileNetV2 (try 2) (#9467)
* Fast DSP for MobileNetV2 (try 2)

* enable fast path on uchar

* fix tests
2025-03-17 15:10:36 +08:00
George HotzandGitHub 15ee742afa add get_children_map to uop (#9470)
* add get_children_map to uop

* update_children

* fix new children
2025-03-17 14:36:13 +08:00
chenyuandGitHub d2cfbd8a4d bert lower learning rate and total steps (#9466)
closer to the other submission with BS=240. converged with 10% less epochs
2025-03-16 17:21:20 -04:00
George HotzandGitHub 09e7708b49 minimum change for rdna4 [pr] (#9455) 2025-03-16 13:39:24 +08:00
qazalandGitHub be2161652b reorder into swizzler + ast_fixup [pr] (#9456) 2025-03-15 09:00:14 +01:00
George HotzandGitHub cb7a7f69c7 quantization preprocessor from DSP, should be universal (#9437)
* quantization preprocessor from DSP, should be universal

* touchups

* fix tests
2025-03-15 07:49:37 +08:00
chenyuandGitHub ca5064a5b6 remove Kernel.float4_axis [pr] (#9448) 2025-03-14 17:54:32 -04:00
chenyuandGitHub 0e591baf43 redo simple_matmul change (#9450)
numpy does not support bfloat16
2025-03-14 17:53:52 -04:00
chenyuandGitHub b0f63d3c04 Revert "simple_matmul.py uses np to generate random (#9438)" (#9449)
This reverts commit 14018050c1.
2025-03-14 17:14:22 -04:00
Ignacio SicaandGitHub 14018050c1 simple_matmul.py uses np to generate random (#9438)
* np generates randoms

* hotfix: use generator for int dtype

* float32 as default dtype for float generator

* use np.float32 instead of stirng

* add dtype= to integers generator

* change import _to_np_dtype source
2025-03-14 17:36:50 -03:00
qazalandGitHub 2a50e6440d filter sink by DONT_PUSH_VIEWS + remove extra base [pr] (#9446) 2025-03-14 21:27:46 +01:00
qazalandGitHub 3af7a08a06 ast_fixup in one graph_rewrite pass [pr] (#9444) 2025-03-14 20:14:31 +01:00
nimlgenandGitHub bd4ae5ac53 am: hotfix: import modules (#9443)
* am: hotfix: import modules

* hmm
2025-03-15 03:10:18 +08:00
nimlgenandGitHub 77a8430616 am: use smu based on discovery (#9441) 2025-03-15 02:10:45 +08:00
uuuvnandGitHub 5ff90cb261 am: less magic values (#9440) 2025-03-15 02:10:35 +08:00
Ignacio SicaandGitHub 459d0cd14f add arch to AMDRenderer and HIPRenderer (#9431) 2025-03-13 13:06:27 -03:00
nimlgenandGitHub 357e364ab8 am: turn off unord dispatch (#9433) 2025-03-13 23:59:28 +08:00
chenyuandGitHub 99b0287e4e add GROUP and GROUPTOP to test_arange (#9432)
it does not grow quadratically, but it's not 0 ops now
2025-03-13 11:28:38 -04:00
qazalandGitHub 90ffa9bd45 swizzle without buffer ops try 2 [pr] (#9427)
* add DONT_PUSH_VIEWS to matchers

* swizzle without buffer ops try 2 [pr]

* swizzle reduceop

* simple failing test

* fix failing test

* s/on/for
2025-03-13 10:00:40 +01:00
qazalandGitHub 4df2b6347d hotfix: bump tinybox red training CI timeout to 30 minutes (#9426) 2025-03-13 09:31:44 +01:00
geohot 931436204c hotfix: 12000 lines, for AMD stuff 2025-03-13 10:48:14 +08:00
George HotzandGitHub bfc68d1953 add gep rules to simplify (#9419)
* add gep rules to simplify

* ws

* flipped direction
2025-03-13 09:46:25 +08:00
0bed9b6cd2 benchmark huggingface onnx models (#8493)
* add ability to ORT=1

* test_vs_ort

* useless f

* actually have benchmark take in modelproto for more flexibility in huggingface stuff

* ok runs

* good

* oops fix benchmark_onnx __main__

* 224 as default

* add ORT=1 option to huggingface_onnx

* use Tensor to get_input

* add abilty to do single onnx model testing

* better names

* merge properly...

* copy in onnx_helpers

* better

* decent script

* need to add debug tool first

* new limit usage

* why did narrowing_error come back..

* pretty decent

* revert validate change

* more ops bug fixes

* revert unnecessary changes

* fix InstanceNorm too

* remove op from O4

* minimize diff

* address old feedback

* unsure of this, just revert

* remove that assert

* working attention

* to_python_const Attention

* cant init from np constant so just do this

* final

* fix bug in attention

* attention clean ups

* add hard TODOs and REPOPATH and TRUNCATE envvar

* fix input_ids default value

* final

* fix scatter

* cleaner _prepare_quantize

* use new attention and tempfile for huggingface script

* more stats

* update

* remove outdated code

* big refactor to something usable by CI

* booooooom

* clean up

* update to using yaml as env var input

* add dry run

* try

* valid pad

* use argparser and fix gather bug

* ignore all yaml

* tiny bit more polish

* woah ignoring all yaml was not right

* typo

* decouple huggingface_onnx_run debug run with huggingface_onnx_download

* bug fix for downloading single model

* WOOOO ok much better

* oops argparse 'required' is an invalid argument for positionals

* oops argparse 'required' is an invalid argument for positionals

* add assert

* fix types

---------

Co-authored-by: chenyu <[email protected]>
2025-03-12 20:13:12 -04:00
chenyuandGitHub 4992958dae update bert beam params (#9423)
BEAM_MIN_PROGRESS=5 for setup speed
2025-03-12 13:00:41 -04:00
qazalandGitHub 12978f0d05 reorder contiguous/assign ast rules [pr] (#9420)
* apply setitem ShapeTracker when creating store [pr]

* comments + early contiguous remove

* better

* linter
2025-03-12 12:13:27 +01:00
George HotzandGitHub 5f6d5b057d expand index isn't grouping by access size (#9418)
* expand index isn't grouping by access size

* split_load_store

* scalar vec

* +correct_load_store

* vectorized and

* correct_load_store always

* simplify before divides
2025-03-12 17:24:10 +08:00
George HotzandGitHub 815ad0b7a8 support load/store grouping in DEVECTORIZE=0 (#9409) 2025-03-12 11:34:37 +08:00
Priyank PatelandGitHub 4714c4f9ad torch backend multigpu - add devices and tests (#9414)
* add multi-device support and tests

* simplify
2025-03-12 11:33:11 +08:00
chenyuandGitHub 22fc0a2e36 bert sum acc in half (#9412)
also BS=96
2025-03-11 23:03:15 -04:00
nimlgenandGitHub f995b465b8 am: set doorbell offsets to nb (#9413) 2025-03-12 10:35:47 +08:00
qazalandGitHub 95e0f069be hotfix: gitignore *.log [pr] (#9410) 2025-03-11 21:39:19 +01:00
nimlgenandGitHub 78ebade125 Merge pull request #9408 from nimlgen/hcq_progress_during_wait
hcq: reset timer on progress in singal.wait
2025-03-11 19:40:23 +08:00
George HotzandGitHub e174c6c3bc new devectorizer (#9331)
* new devectorizer

* lidx

* test linearizer passes

* fix images

* fix unfoldable image load

* delete unused

* improve fix_unfoldable_image_load

* working for image

* fixup types

* fixup transcendental

* cast_vec

* cleaner transcendental

* skip failing test

* err, flip that

* not devec

* sqrt
2025-03-11 18:47:56 +08:00
qazalandGitHub 69fac5fe89 Merge pull request #9407 from tinygrad/no_const_after_sym
no const/view in schedule sink after sym [pr]
2025-03-11 12:24:09 +02:00
nimlgen 4d09ea4c06 hcq: reset timer on progress in singal.wait 2025-03-11 10:02:14 +00:00
qazal fa69fd3afc no const/view in schedule sink after sym [pr] 2025-03-11 10:58:38 +01:00
George HotzandGitHub 68f062c8be cast_vec on transcendental (#9406) 2025-03-11 17:30:46 +08:00
e85001b6ee SQTT profiling (#9278)
* sqtt

* docs

* multi-device

* ProfileSQTTEvent

* exec update

* 256mb default

* don't let people hang their gpus

* bitfields from autogen

* asic info from mesa

* more bitfields from autogen

* SQTT_ITRACE_SE_MASK

---------

Co-authored-by: George Hotz <[email protected]>
2025-03-11 13:19:56 +08:00
George HotzandGitHub 2780e2027e devectorize prereqs [pr] (#9404) 2025-03-11 12:33:29 +08:00
beed00eabe fix torch backend memory leak (#9395)
* fix leak, realize everything on torch optim step

* only realize a subset

---------

Co-authored-by: George Hotz <[email protected]>
2025-03-11 10:48:20 +08:00
chenyuandGitHub 01e8b60911 acc_dtype -> dtype (#9402)
matched numpy and torch
2025-03-10 16:05:30 -04:00
qazalandGitHub 59dfb234eb replace hardcoded ast with tensors in TestSwizzle [pr] (#9401) 2025-03-10 19:33:57 +01:00
796c3bbb23 torch: support in-place operations on views (#9371)
* add torch inplace tests

* first set of tests passing

* wrap all inplace funcs, add more tests

* fixes and wrap more functions

* fix all uint8 tests to avoid slow tests

* fix the one test

* another test, another fix

* and one more, works for ddp now

* something on contiguous, cleanup

---------

Co-authored-by: qazal <[email protected]>
2025-03-10 23:29:00 +08:00
qazalandGitHub 2afc7759a7 sink in kernel op [pr] (#9397)
* sink in kernel op [pr]

* metadata
2025-03-10 13:13:42 +01:00
George HotzandGitHub 25847080f0 olmoe (from stream, wip) (#9390)
* olmoest working (but not)

* it's correct

* compare ropes

* old code wasn't wrong

* default device

* no metal

* fix permute

* working

* more minimal
2025-03-10 13:46:33 +08:00
geohotstanandGitHub 1d64c12f2b add Topk to tensor (#9343)
* terrible but somewhat working impl

* linux behaves differently than macos?

* slightly better impl

* small clean up; haven't figured this out yet

* better

* torch has different behavior on linux and macos for duplicated values

* add sum docs

* fix test

* add torch return_type test

* add an exception test

* wrap_fxn instead, and move op lower in order

* better repeated values test

* rerun ci
2025-03-09 20:01:42 -04:00
qazalandGitHub a1f41fadf6 test_schedule cleanups + add DONT_GROUP_REDUCES [pr] (#9392)
* test_schedule cleanups + add DONT_GROUP_REDUCES [pr]

* replace with test_swizzle_reduceop

* delete duplicate tests

* test_allow_push_permutes

* one kernel tests
2025-03-09 15:01:08 +01:00
wozeparrotandGitHub b6fe5ab4dd fix: correct gfx10 ctl stack size (#9384) 2025-03-09 13:03:20 +08:00
qazalandGitHub 456697d0be always create kernels for assign/contiguous/copy [pr] (#9388) 2025-03-08 15:32:06 +01:00
qazalandGitHub 286b480f82 do not replace assign with the offset buffer [pr] (#9387) 2025-03-08 11:57:44 +01:00
qazalandGitHub ecfccdea8e remove views from the kernel graph minimum diff (#9385)
* remove views from the kernel graph

* notes
2025-03-08 10:14:42 +01:00
qazalandGitHub 0d2762c010 prep refactor for adding buffer ops last [pr] (#9383)
* prep refactor for adding buffer ops last [pr]

* freeze buffers

* add swizzle_reduceop

* shape for reduceop_view_right

* simpler elementwise_view_right

* add shapetracker to const

* only const

* from process replay
2025-03-08 08:00:14 +01:00
bde0347618 amd: support relocatable elf (#9380)
Co-authored-by: b1tg <[email protected]>
2025-03-08 02:21:49 +08:00
nimlgenandGitHub 243078dda9 am: optimize tlb usage (#9049)
* am: optimize tlb usage

* fxies

* comments

* tiny
2025-03-07 19:37:29 +03:00
qazalandGitHub 46720294d6 reorder ScheduleItem creation [pr] (#9379) 2025-03-07 17:20:53 +01:00
qazalandGitHub dc89dae994 remove unmasked valid after swizzles (#9377) 2025-03-07 16:43:16 +01:00
geohotstanandGitHub 088d86691b fix onnx gather and onnx auto_pad VALID mode (#9375)
* fix gather and auto_pad

* long -> int64
2025-03-07 10:27:23 -05:00
qazalandGitHub 3565c08df5 refactor to kernel ast fixup [pr] (#9376) 2025-03-07 15:47:38 +01:00
304afe0d55 tinychat in browser, Part 3: browser app (#9276)
* load llama3-1B to WEBGPU device

* include compile script for loading llama3 to WEBGPU

* parametrize max_context in build_transformer fxn

* jit_model with two different args sets

* compile for webgpu, split weights

* load model weight parts in browser

* export all tensors from initialized transformer

* run transformer inference in browser

* enable tiktoken with llama bpe in browser

* count total tokens on client with tiktoken.js

* full client-side chat streaming, eliminate server

* revert change that enabled jitting with 2 argsets

* llama without Variable or cache_kv, for webgpu

* have client use mask tokens / whole context

* cleanup staged weights

* add tiktoken.js build script, README

* export CLANG for Q6_k to float32 decompression

* fix and test exported CLANG code for Q6_k to fp32

* revert changes to jit and export_model

* isolate clang export

* test Q6_K to float32 decompression in browser

* gguf_load now also returns t_infos and data_start

* prepare llama-1B Q6_K gguf chunks for browser

* cache and decompress quantized llama in browser

* enable separate deployment of large files

* fix kv cache and symbolic with llama wgpu

* eliminate browser lag during decompression

* hash metadata and weight chunks

* delete obsolete indexeddb cache to free disk

* add progress bar, track model download/decompress

* refactor progress callback

* skip buffer hash verification for speed

* Display progress for entire loading scope

* Report page load errors to user

* actually display errors

* skip prompt tokens already seen by model

* skip prefilling with last assistant message tokens

* on page load tell user if webgpu not enabled

* push deployed URL root to window.history

* make note of bug sources with TODO items

* isolate bug in CLANG with BEAM=2

* remove clang_bug.py from diff

* decompress q6k to f32 on webgpu instead of clang

* remove unused code

* inter-weight decomp with larger wgpu kernels

* parallelize decompression submissions

* refactor dequantize scheduling

* add progress bar back

* fix bug

* temp fix for loading GGUF Q6_K to fp16 not fp32

* fix rendering of exported CLANG

* remove weight casts, sketch js functions for clang

* get symbolic vars from jit_cache for model export

* include symbolic vars in exported CLANG

* render js for clang transformer

* toggle clang/webgpu deployment; refactor decomp

* compile and render clang Q6_K->fp16 and int8 quant

* fix rendered clang for abs(fp16), to work in wasm

* simplify clang js wrapping

* run compiled clang in worker

* prepare llama weights in workers, q6k to int8/fp16

* tinychat on clang in browser, f32/int8 weights

* move wasm inference to (now flexible) worker

* don't load redundant embeddings

* modest wasm perf gain with compile flags

* set default backend, enable backend choice/backup

* render symbolic vars in exported WEBGPU

* quantize webgpu llama to int8/f32

* improve UX arising from rendered WEBGPU

* clean up webgpu launch

* new weights split: smaller chunks, tinygrad quant.

* switch webgpu inference to int8 quant

* remove unneeded clang decompression

* eliminate unneeded kv cache transfer to wasm

* use 1 worker for simplified clang decompression

* display launch errors

* refactor: stream load weight chunks to WebGPU

* show loading chunk completion

* quantize embeddings to int8

* test float16 as input for quantization

* webgpu: use f16 source, int8 embed, eliminate q6k

* simplify split weights prep: all from state_dict

* revert change to nn.state.gguf_load

* remove unneeded decompression from webgpu client

* remove unneeded code

* decrease dl chunks from 47 to 16 MiB

* improve stability of webgpu loading on mobile

* autodetect mobile, improve load stability

* refactor: progress closure

* refactor: one unified progress bar

* remove unneeded code

* revert changes to tinygrad core library

* enforce ios18.3 nerfed max buf size

* BEAM=3 webgpu

* cache integrity, mobile save throttling

* improve mobile UX - no autozoom on prompt box

* clang: int8 from f16, remove q6k

* reduce concurrent dls on mobile to 2 for stability

* refactor: wasm backend with stream loading

* prevent race between wasm load and indexedb save

* split wasm kernels into separate modules

* js wrapper for multiple wasm module inference

* revert multi-module wasm to single module

* make mobile wasm load more stable/fast

* refactor: copy weights into wasm without crashes

* fix bug in download queue; increase mobile dls

* refactor exported clang wrapper, split weights

* remove unnecessary code

* greatly improve int8 quant quality with rounding

* eliminate mobile throttling

* increase webgpu context to 4096 tokens

* export webgpu js functions

* enable separate hosted weights for mobile/pc

* enable prompt-thread switching during generation

* stop generation when max_context is reached

* show progress bar for prefill

* tell user if webgpu fails, while wasm loads

* make loading messages more concise

* update font

* revert changes to tinychat python app launch

* cleanup quantization, add scale_dtype param

* cleanup kv cache code

* cleanup compile code

* link tok_embeddings with output in webgpu export

* refactor: export_model webgpu: symbolic vars

* refactor: export_model weight loading

* forgot to commit export_model.py

* change CLANG to CPU

* deal with pylint incorrectly failing tests

* simplify f-strings for older CI python version

* fix pre-python3.12 parser errors

* [Int32Array] not Int32Array

* cleanup webgpu compile after refactor export_model

* refactor WASM export into export_model

* merge WebGPU/WASM compile scripts

* simplify max_contexts for local deployment

* fix parser issues and whitespace

* deduplicate variable defs for non-wasm clang export

* cleanup code

* cleanup compile scripts

* simplify wasm inference wrapping

* simplify webgpu symbolic vars export

* refactor: unify export of symbolic variables

* simplify WASM export

* simplify clang/wasm export

* update README and build scripts

* separate files for browser/python apps

* restore original python tinychat app files

* browser and python tinychats share assets

* minor cleanup

* isolate app layer diff

* add .gitignore for generated files

* validate CPU/WEBGPU models in python

* prevent infinite generation if validation fails

* check if exported weight files are unique

---------

Co-authored-by: George Hotz <[email protected]>
2025-03-07 15:07:33 +08:00
hoovedandGitHub 136cf7b8b1 hotfix: load >2 GiB from disk on macOS (#9361)
* enable loading >2 GiB buffer from disk on macOS

* handle None case raised by mypy

* add test

* revert fix to repro bug in CI

* tell CI to run a unit test for macOS

* reapply fix
2025-03-07 14:51:58 +08:00
Friedrich Carl EichenrothandGitHub dbdefbbe54 Typed methods in tensor.py (#9356)
* types for tensor.py

* x

* more

* remove some casts

* more typing

* fix linting issues

* -1 line

* add last type

* cast 🤙🤙
2025-03-05 20:34:18 -05:00
nimlgenandGitHub 77f7ddf62a gfx10 correct ctl stack size (#9365) 2025-03-05 23:04:16 +03:00
nimlgenandGitHub c8a74b11ed am: resize bar error msg (#9366) 2025-03-05 23:02:04 +03:00
nimlgenandGitHub 9bd13de44c lower test_gemv_4096_16384 to 750 for red (#9367) 2025-03-05 22:44:48 +03:00
uuuvnandGitHub b75f307234 amd: autogen ip bases (#9360) 2025-03-05 22:30:38 +03:00
chenyuandGitHub 2cb2fce8d9 lower test_gemm_8192 amd_tflops to 65 (#9364) 2025-03-05 14:06:11 -05:00
b3ac60ce53 Fix test_ops for tiny backend part 2 (#9358)
* extact functions from https://github.com/tinygrad/tinygrad/pull/9302

* revert gather and add aten.elu_backward

* address review

---------

Co-authored-by: chenyu <[email protected]>
2025-03-05 13:38:40 -05:00
uuuvnandGitHub c6d76770e4 Increase timeout on macos tests (#9362)
Process replay timeouts: https://github.com/tinygrad/tinygrad/actions/runs/13682213444/job/38257133289?pr=9360
2025-03-05 13:04:16 -05:00
nimlgenandGitHub cd9d74f7ea use am in training benchmarks (#9357)
* am in training benchmarks

* fix

* not needed anymore
2025-03-05 19:13:47 +03:00
chenyuandGitHub 2af129c078 bert corealize multiple outputs (#9359)
1% faster step
2025-03-05 10:58:37 -05:00
nimlgenandGitHub d550583657 am: flush hdp (#9354)
* am: fix hdp

* and flush it
2025-03-05 16:31:59 +03:00
Priyank PatelandGitHub f048256341 fix TORCH_DEBUG=1 sigsegv (#9352) 2025-03-05 12:24:53 +03:00
chenyuandGitHub ad72269f08 bert put eval copy and getting lr in jit (#9350) 2025-03-04 20:57:03 -05:00
geohot 7576a1da23 hotfix: line count to 11500, lines for SQTT and AMDLLVM 2025-03-05 09:21:18 +08:00
chenyuandGitHub 9eb45eb629 add a flag to skip bert train (#9349) 2025-03-04 17:13:00 -05:00
nimlgenandGitHub 14c88abf27 add some options to allreduce bench (#9348) 2025-03-04 23:46:36 +03:00
nimlgenandGitHub 993ef42bd5 am: hdp cg (#9346) 2025-03-04 20:44:09 +03:00
chenyuandGitHub e301f21f63 CI ubuntu-20.04 -> ubuntu-22.04 (#9345)
20.04 is removed now
2025-03-04 11:39:12 -05:00
01f7a4fadc tinychat in browser, Part 2: model export (#9274)
* load llama3-1B to WEBGPU device

* include compile script for loading llama3 to WEBGPU

* parametrize max_context in build_transformer fxn

* jit_model with two different args sets

* compile for webgpu, split weights

* load model weight parts in browser

* export all tensors from initialized transformer

* run transformer inference in browser

* enable tiktoken with llama bpe in browser

* count total tokens on client with tiktoken.js

* full client-side chat streaming, eliminate server

* revert change that enabled jitting with 2 argsets

* llama without Variable or cache_kv, for webgpu

* have client use mask tokens / whole context

* cleanup staged weights

* add tiktoken.js build script, README

* export CLANG for Q6_k to float32 decompression

* fix and test exported CLANG code for Q6_k to fp32

* revert changes to jit and export_model

* isolate clang export

* test Q6_K to float32 decompression in browser

* gguf_load now also returns t_infos and data_start

* prepare llama-1B Q6_K gguf chunks for browser

* cache and decompress quantized llama in browser

* enable separate deployment of large files

* fix kv cache and symbolic with llama wgpu

* eliminate browser lag during decompression

* hash metadata and weight chunks

* delete obsolete indexeddb cache to free disk

* add progress bar, track model download/decompress

* refactor progress callback

* skip buffer hash verification for speed

* Display progress for entire loading scope

* Report page load errors to user

* actually display errors

* skip prompt tokens already seen by model

* skip prefilling with last assistant message tokens

* on page load tell user if webgpu not enabled

* push deployed URL root to window.history

* make note of bug sources with TODO items

* isolate bug in CLANG with BEAM=2

* remove clang_bug.py from diff

* decompress q6k to f32 on webgpu instead of clang

* remove unused code

* inter-weight decomp with larger wgpu kernels

* parallelize decompression submissions

* refactor dequantize scheduling

* add progress bar back

* fix bug

* temp fix for loading GGUF Q6_K to fp16 not fp32

* fix rendering of exported CLANG

* remove weight casts, sketch js functions for clang

* get symbolic vars from jit_cache for model export

* include symbolic vars in exported CLANG

* render js for clang transformer

* toggle clang/webgpu deployment; refactor decomp

* compile and render clang Q6_K->fp16 and int8 quant

* fix rendered clang for abs(fp16), to work in wasm

* simplify clang js wrapping

* run compiled clang in worker

* prepare llama weights in workers, q6k to int8/fp16

* tinychat on clang in browser, f32/int8 weights

* move wasm inference to (now flexible) worker

* don't load redundant embeddings

* modest wasm perf gain with compile flags

* set default backend, enable backend choice/backup

* render symbolic vars in exported WEBGPU

* quantize webgpu llama to int8/f32

* improve UX arising from rendered WEBGPU

* clean up webgpu launch

* new weights split: smaller chunks, tinygrad quant.

* switch webgpu inference to int8 quant

* remove unneeded clang decompression

* eliminate unneeded kv cache transfer to wasm

* use 1 worker for simplified clang decompression

* display launch errors

* refactor: stream load weight chunks to WebGPU

* show loading chunk completion

* quantize embeddings to int8

* test float16 as input for quantization

* webgpu: use f16 source, int8 embed, eliminate q6k

* simplify split weights prep: all from state_dict

* revert change to nn.state.gguf_load

* remove unneeded decompression from webgpu client

* remove unneeded code

* decrease dl chunks from 47 to 16 MiB

* improve stability of webgpu loading on mobile

* autodetect mobile, improve load stability

* refactor: progress closure

* refactor: one unified progress bar

* remove unneeded code

* revert changes to tinygrad core library

* enforce ios18.3 nerfed max buf size

* BEAM=3 webgpu

* cache integrity, mobile save throttling

* improve mobile UX - no autozoom on prompt box

* clang: int8 from f16, remove q6k

* reduce concurrent dls on mobile to 2 for stability

* refactor: wasm backend with stream loading

* prevent race between wasm load and indexedb save

* split wasm kernels into separate modules

* js wrapper for multiple wasm module inference

* revert multi-module wasm to single module

* make mobile wasm load more stable/fast

* refactor: copy weights into wasm without crashes

* fix bug in download queue; increase mobile dls

* refactor exported clang wrapper, split weights

* remove unnecessary code

* greatly improve int8 quant quality with rounding

* eliminate mobile throttling

* increase webgpu context to 4096 tokens

* export webgpu js functions

* enable separate hosted weights for mobile/pc

* enable prompt-thread switching during generation

* stop generation when max_context is reached

* show progress bar for prefill

* tell user if webgpu fails, while wasm loads

* make loading messages more concise

* update font

* revert changes to tinychat python app launch

* cleanup quantization, add scale_dtype param

* cleanup kv cache code

* cleanup compile code

* link tok_embeddings with output in webgpu export

* refactor: export_model webgpu: symbolic vars

* refactor: export_model weight loading

* forgot to commit export_model.py

* change CLANG to CPU

* deal with pylint incorrectly failing tests

* simplify f-strings for older CI python version

* fix pre-python3.12 parser errors

* [Int32Array] not Int32Array

* cleanup webgpu compile after refactor export_model

* refactor WASM export into export_model

* merge WebGPU/WASM compile scripts

* simplify max_contexts for local deployment

* fix parser issues and whitespace

* deduplicate variable defs for non-wasm clang export

* cleanup code

* cleanup compile scripts

* simplify wasm inference wrapping

* simplify webgpu symbolic vars export

* refactor: unify export of symbolic variables

* simplify WASM export

* simplify clang/wasm export

* update README and build scripts

* separate files for browser/python apps

* restore original python tinychat app files

* browser and python tinychats share assets

* minor cleanup

* isolate compile/export model

---------

Co-authored-by: George Hotz <[email protected]>
2025-03-04 15:53:30 +08:00
94db8426cb Add consistent typing for python 3.10 in tensor.py (#9326)
* add consistent typing for python 3.10 in tensor.py

* pull

* Tensor.copysign (#9329)

* fast amd gemm (#9318)

* 50 TFLOP AMD gemm

* add lds tiling

* register tiling

* flip locals

* work

* comment

* remove those

* fix Tensor.view with a tuple arg (#9330)

* reorder binops (#9328)

* reorder binops

* test improvements + fix string tests

* ugh, okay this

* Make const moving not depend on the order (#9245)

Since floats are not being flipped anymore this should help with const
folding for floats

* use empty for test instead of rand (#9332)

* linter

---------

Co-authored-by: chenyu <[email protected]>
Co-authored-by: George Hotz <[email protected]>
Co-authored-by: Sieds Lykles <[email protected]>
2025-03-03 16:00:17 -05:00
chenyuandGitHub 019417743c ruff torch backend (#9341) 2025-03-03 15:15:23 -05:00
nimlgenandGitHub f9e4c638f1 torch_hook fixes (#9334) 2025-03-03 23:07:30 +03:00
chenyuandGitHub 40619a4bbc separate workflow for TINY_BACKEND=1 mnist (#9339)
* separate workflow for TINY_BACKEND=1 mnist

* rebalance
2025-03-03 13:05:24 -05:00
Anish UmaleandGitHub bafa40fe12 Tiny backend test_ops fix part1 (#9338)
* extract name methods from https://github.com/tinygrad/tinygrad/pull/9302

* t.grad.numpy() -> t.grad.cpu().numpy()

* revert TORCH_DEBUG change

* revert dtype change in aten.sum
2025-03-03 12:36:51 -05:00
George HotzandGitHub 0d4ba7dd87 import tinygrad.frontend.torch (#9337)
* import tinygrad.frontend.torch

* type ignore
2025-03-04 00:15:29 +08:00
Friedrich Carl EichenrothandGitHub b4028e48ae Torch Backend Refinement (#9327)
* fix some torch tests

* fixup

* small change

* fixup

* fix test

* use default function

* add todo

* bunch of small changes

* fix tests

* more tests

* fix

* fix

* test fix

* simplify
2025-03-03 10:24:02 -05:00
qazalandGitHub 23084fd850 merge merge_views and remove_movement_ops [pr] (#9333)
* merge merge_views and remove_movement_ops [pr]

* fix that assert
2025-03-03 12:38:59 +01:00
George HotzandGitHub ece0a0f305 use empty for test instead of rand (#9332) 2025-03-03 16:19:06 +08:00
Sieds LyklesandGitHub 27e899aea5 Make const moving not depend on the order (#9245)
Since floats are not being flipped anymore this should help with const
folding for floats
2025-03-03 16:09:27 +08:00
George HotzandGitHub 2cc4cb74f0 reorder binops (#9328)
* reorder binops

* test improvements + fix string tests

* ugh, okay this
2025-03-03 14:58:18 +08:00
chenyuandGitHub 146eb73790 fix Tensor.view with a tuple arg (#9330) 2025-03-02 23:35:23 -05:00
George HotzandGitHub a73d8717f3 fast amd gemm (#9318)
* 50 TFLOP AMD gemm

* add lds tiling

* register tiling

* flip locals

* work

* comment

* remove those
2025-03-03 12:01:14 +08:00
chenyuandGitHub ba4b8c2c23 Tensor.copysign (#9329) 2025-03-02 21:33:49 -05:00
Friedrich Carl EichenrothandGitHub 06ef9cc9f4 aten leaky_relu, div.out_mode, clamp_max, clamp_min, copysign (#9323)
* fix some torch tests

* fixup

* small change

* fixup

* fix test

* use default function

* add todo
2025-03-02 19:12:16 -05:00
Friedrich Carl EichenrothandGitHub ac9c96dae1 add tensor.py typing (#9325) 2025-03-02 16:24:39 -05:00
George HotzandGitHub cd03458ab3 fix barrier + comgr asm + mini viz fix (#9322)
* fix barrier + comgr asm + mini viz fix

* delete peephole
2025-03-02 23:35:00 +08:00
nimlgenandGitHub 8cae00833c flaky test in ci (#9321) 2025-03-02 16:27:22 +03:00
nimlgenandGitHub 91c421fb7d adaptive am_smi (#9319) 2025-03-02 15:45:07 +03:00
Ali LadjevardiandGitHub 00028e87bb Failing test for not realizing intermediate expand in multi-GPU (#9320) 2025-03-02 12:54:48 +01:00
geohot ba97fd0b9c hotfix: add test/external/external_benchmark_disk_raw 2025-03-02 02:32:15 +00:00
chenyuandGitHub cc2bbb0bf1 Tensor.isfinite (#9316) 2025-03-01 19:58:56 -05:00
d9ec05cea6 Test Onnx quantization behavior (#9301)
* add DynamicDequantizeLinear and corresponding tests

* wow qlinearops are round away from zero

* this passes locally...

* again

* try

* try separate test

* round to even again

* also add QLinearMul

---------

Co-authored-by: chenyu <[email protected]>
2025-03-01 19:21:58 -05:00
uuuvnandGitHub a8a6e22cbd Do not "oob"-write zero to regCOMPUTE_THREAD_TRACE_ENABLE every exec (#9314)
```python
self.pkt3(amd_gpu.PACKET3_SET_SH_REG, gfxreg(amd_gpu.regCOMPUTE_RESTART_X), 0, 0, 0, 0)
```

Will write zero to regCOMPUTE_RESTART_{X,Y,Z} and regCOMPUTE_THREAD_TRACE_ENABLE because of:

```python
regCOMPUTE_RESTART_X = 0x1bbb
regCOMPUTE_RESTART_Y = 0x1bbc
regCOMPUTE_RESTART_Z = 0x1bbd
regCOMPUTE_THREAD_TRACE_ENABLE = 0x1bbe
```

There is also a similar "oob"-write to regCOMPUTE_PIPELINESTAT_ENABLE and regCOMPUTE_PERFCOUNT_ENABLE in:

```python
self.pkt3(amd_gpu.PACKET3_SET_SH_REG, gfxreg(amd_gpu.regCOMPUTE_START_X), 0, 0, 0, *local_size, 0, 0)
```

But it doesn't seem to be strictly required for SQTT, so i left it alone
2025-03-01 17:07:58 +03:00
Priyank PatelandGitHub f4148ac46a torch fix casting and add ops for sd vae(s) (#9297)
* torch fix copy casting and add upsample op

* update cast and add test

* fix lint

* add pad for sdxl vae to work
2025-03-01 08:49:10 -05:00
qazalandGitHub 845814f396 revert buffer_view change (#9311)
* Revert "BUFFER_VIEW is a node in the kernel graph + delete ViewOp (#9298)"

This reverts commit 3210b656b6.

* Revert "substitute ast from kernel op [pr] (#9293)"

This reverts commit 5a9c788ae6.
2025-03-01 11:00:12 +01:00
nimlgenandGitHub 80b8756150 add npy as_buffer (#9309)
* npy -> dev copies faster

* rv and cpout
2025-03-01 12:34:29 +03:00
chenyuandGitHub fe0f860209 update test_ops for tensors from torch (#9308)
a few detach().numpy() -> detach().cpu().numpy()
2025-02-28 15:57:25 -05:00
chenyuandGitHub 38d7aae3b7 onnx fmod (#9307) 2025-02-28 14:09:22 -05:00
chenyuandGitHub 7c7db78feb support float mod (#9306)
also added spec check on Ops.MOD to be ints only
2025-02-28 13:33:58 -05:00
chenyuandGitHub 90808e2dd0 div rounding_mode (#9304) 2025-02-28 11:38:25 -05:00
chenyuandGitHub 3ae66e59a3 least_upper_float is at least default_float (#9303)
* least_upper_float is at least default_float

en route for div rounding mode. dtype of true int division would change from int32 to default_float, which matches torch too.

* fix bert acc
2025-02-28 10:41:56 -05:00
qazalandGitHub 3210b656b6 BUFFER_VIEW is a node in the kernel graph + delete ViewOp (#9298) 2025-02-28 12:15:04 +02:00
qazalandGitHub 5a9c788ae6 substitute ast from kernel op [pr] (#9293)
* substitute ast from kernel op [pr]

* add buffer_map

* without tensor_map + complete in_degree/children graph

* count groups + append assigns

* first
2025-02-28 11:44:48 +02:00
nimlgenandGitHub 052722a7bc torch hook: address comments (#9295)
* torch hook: address comments

* failed test
2025-02-28 11:51:52 +03:00
d657d5f754 [Bounty] Vectorize Transcendental (#9058)
* init

* cast everythig right

* more casting

* install pillow in test

* quick tests

* simplify

* quick tests

* delete test

* tests

* fix import error

* add vec to ldexp3k

* vec for bitcast

* some helper tests

* high level tests

* clean tests

* change tolerance so cuda passes

* ruff passes

* remove tests for transcendental helpers

* ruff passes

* make exponent in power vectorized

* fix pow test

* add newline

* add vec dtype to ilogb2k

* comment + clean up

* ruff

---------

Co-authored-by: chenyu <[email protected]>
Co-authored-by: George Hotz <[email protected]>
2025-02-28 15:47:25 +08:00
Priyank PatelandGitHub 8ae215dd3d torch backend fix manual seed warning (#9292) 2025-02-28 13:45:32 +08:00
George HotzandGitHub 5aa80cb602 add CUSTOMI for inline custom (#9291) 2025-02-28 11:11:30 +08:00
geohot ac40316692 hotfix: group cpu functions in torch backend 2025-02-28 10:39:00 +08:00
George HotzandGitHub b32595dbbc torch examples (#9290)
* torch, fix examples/mnist

* fix vae torch example

* where out
2025-02-28 10:16:06 +08:00
ZwX1616andGitHub c977781b3c no numpy change if no NPY (#9281)
* skip np change check if no NPY

* use any
2025-02-28 09:32:35 +08:00
hoovedandGitHub 3b9950241e tinychat in browser, Part 1: llama (#9273)
* load llama3-1B to WEBGPU device

* include compile script for loading llama3 to WEBGPU

* parametrize max_context in build_transformer fxn

* jit_model with two different args sets

* compile for webgpu, split weights

* load model weight parts in browser

* export all tensors from initialized transformer

* run transformer inference in browser

* enable tiktoken with llama bpe in browser

* count total tokens on client with tiktoken.js

* full client-side chat streaming, eliminate server

* revert change that enabled jitting with 2 argsets

* llama without Variable or cache_kv, for webgpu

* have client use mask tokens / whole context

* cleanup staged weights

* add tiktoken.js build script, README

* export CLANG for Q6_k to float32 decompression

* fix and test exported CLANG code for Q6_k to fp32

* revert changes to jit and export_model

* isolate clang export

* test Q6_K to float32 decompression in browser

* gguf_load now also returns t_infos and data_start

* prepare llama-1B Q6_K gguf chunks for browser

* cache and decompress quantized llama in browser

* enable separate deployment of large files

* fix kv cache and symbolic with llama wgpu

* eliminate browser lag during decompression

* hash metadata and weight chunks

* delete obsolete indexeddb cache to free disk

* add progress bar, track model download/decompress

* refactor progress callback

* skip buffer hash verification for speed

* Display progress for entire loading scope

* Report page load errors to user

* actually display errors

* skip prompt tokens already seen by model

* skip prefilling with last assistant message tokens

* on page load tell user if webgpu not enabled

* push deployed URL root to window.history

* make note of bug sources with TODO items

* isolate bug in CLANG with BEAM=2

* remove clang_bug.py from diff

* decompress q6k to f32 on webgpu instead of clang

* remove unused code

* inter-weight decomp with larger wgpu kernels

* parallelize decompression submissions

* refactor dequantize scheduling

* add progress bar back

* fix bug

* temp fix for loading GGUF Q6_K to fp16 not fp32

* fix rendering of exported CLANG

* remove weight casts, sketch js functions for clang

* get symbolic vars from jit_cache for model export

* include symbolic vars in exported CLANG

* render js for clang transformer

* toggle clang/webgpu deployment; refactor decomp

* compile and render clang Q6_K->fp16 and int8 quant

* fix rendered clang for abs(fp16), to work in wasm

* simplify clang js wrapping

* run compiled clang in worker

* prepare llama weights in workers, q6k to int8/fp16

* tinychat on clang in browser, f32/int8 weights

* move wasm inference to (now flexible) worker

* don't load redundant embeddings

* modest wasm perf gain with compile flags

* set default backend, enable backend choice/backup

* render symbolic vars in exported WEBGPU

* quantize webgpu llama to int8/f32

* improve UX arising from rendered WEBGPU

* clean up webgpu launch

* new weights split: smaller chunks, tinygrad quant.

* switch webgpu inference to int8 quant

* remove unneeded clang decompression

* eliminate unneeded kv cache transfer to wasm

* use 1 worker for simplified clang decompression

* display launch errors

* refactor: stream load weight chunks to WebGPU

* show loading chunk completion

* quantize embeddings to int8

* test float16 as input for quantization

* webgpu: use f16 source, int8 embed, eliminate q6k

* simplify split weights prep: all from state_dict

* revert change to nn.state.gguf_load

* remove unneeded decompression from webgpu client

* remove unneeded code

* decrease dl chunks from 47 to 16 MiB

* improve stability of webgpu loading on mobile

* autodetect mobile, improve load stability

* refactor: progress closure

* refactor: one unified progress bar

* remove unneeded code

* revert changes to tinygrad core library

* enforce ios18.3 nerfed max buf size

* BEAM=3 webgpu

* cache integrity, mobile save throttling

* improve mobile UX - no autozoom on prompt box

* clang: int8 from f16, remove q6k

* reduce concurrent dls on mobile to 2 for stability

* refactor: wasm backend with stream loading

* prevent race between wasm load and indexedb save

* split wasm kernels into separate modules

* js wrapper for multiple wasm module inference

* revert multi-module wasm to single module

* make mobile wasm load more stable/fast

* refactor: copy weights into wasm without crashes

* fix bug in download queue; increase mobile dls

* refactor exported clang wrapper, split weights

* remove unnecessary code

* greatly improve int8 quant quality with rounding

* eliminate mobile throttling

* increase webgpu context to 4096 tokens

* export webgpu js functions

* enable separate hosted weights for mobile/pc

* enable prompt-thread switching during generation

* stop generation when max_context is reached

* show progress bar for prefill

* tell user if webgpu fails, while wasm loads

* make loading messages more concise

* update font

* revert changes to tinychat python app launch

* cleanup quantization, add scale_dtype param

* cleanup kv cache code

* cleanup compile code

* link tok_embeddings with output in webgpu export

* refactor: export_model webgpu: symbolic vars

* refactor: export_model weight loading

* forgot to commit export_model.py

* change CLANG to CPU

* deal with pylint incorrectly failing tests

* simplify f-strings for older CI python version

* fix pre-python3.12 parser errors

* [Int32Array] not Int32Array

* cleanup webgpu compile after refactor export_model

* refactor WASM export into export_model

* merge WebGPU/WASM compile scripts

* simplify max_contexts for local deployment

* fix parser issues and whitespace

* deduplicate variable defs for non-wasm clang export

* cleanup code

* cleanup compile scripts

* simplify wasm inference wrapping

* simplify webgpu symbolic vars export

* refactor: unify export of symbolic variables

* simplify WASM export

* simplify clang/wasm export

* update README and build scripts

* separate files for browser/python apps

* restore original python tinychat app files

* browser and python tinychats share assets

* minor cleanup

* isolate diffs to llama files

* minor cleanup

* set default scale_dtype

* set default scale_dtype for NF4 quantization

* make quantization of tok_embeds optional

* match output with tok_embeds if not quantizing

* minor change
2025-02-27 15:57:37 -05:00
chenyuandGitHub 184030168d fix aten.reflection_pad2d (#9289)
tested the torch doc example
2025-02-27 15:53:46 -05:00
chenyuandGitHub 0de6585df0 fix aten.normal_ arg (#9288)
should be mean and std.
2025-02-27 15:36:25 -05:00
chenyuandGitHub 8ee2b460ee Tensor.var_mean (#9287) 2025-02-27 15:15:31 -05:00
qazalandGitHub cdf66cc67f test: recompute expanded CAST (#9286)
* those views should merge

* diff cleanup

* gpu

* put it behind CAST_AFTER_EXPAND
2025-02-27 19:22:17 +01:00
nimlgenandGitHub 43e60914f3 init torch hooking (#9284)
* smth

* mv

* prof wk

* revert and move

* fix

* nvprof

* fix and no print much
2025-02-27 19:36:55 +03:00
George HotzandGitHub 387ea41e99 increase speed of torch mnist: use gradient api (#9282) 2025-02-27 11:57:41 +08:00
a0764f0dc0 (bounty) Make mnist training run with torch backend (#9233)
* yml changes

* torch backend remove meta decomps and add test

* torch backend bump timeout for tests

---------

Co-authored-by: George Hotz <[email protected]>
2025-02-27 11:32:25 +08:00
geohot 67ba073c55 hotfix: test accuracy in beautiful_mnist_torch 2025-02-27 11:18:59 +08:00
George HotzandGitHub 9088125a6a a lil more torch (#9280) 2025-02-27 11:12:20 +08:00
George HotzandGitHub b6a14911c8 start torch.compile support (#9279) 2025-02-27 10:29:51 +08:00
chenyuandGitHub 4342300eff lower test_gemm_8192 amd to 70 (#9277)
flaky
2025-02-26 16:32:08 -05:00
nimlgenandGitHub c4c29c8acc nv: parse elf attrs (#9275)
* better

* hm

* hm

* fixed
2025-02-26 23:21:57 +03:00
chenyuandGitHub 6350725e2d simpler leaky_relu (#9271)
rendered as `*(data0+alu0) = ((val0<0.0f)?(0.01f*val0):val0);` instead of two wheres.

possible to update rewrite rules too
2025-02-26 13:43:48 -05:00
Francis LataandGitHub 86b737a120 leakyrelu to leaky_relu (#9270) 2025-02-26 13:22:08 -05:00
chenyuandGitHub cd822bbe11 hotfix torch_grad.detach().cpu().numpy() in test_ops (#9268) 2025-02-26 12:27:35 -05:00
chenyuandGitHub 49ca90df75 update test_ops backward tests (#9267)
instead of `(out+1).square().mean().backward()`, use forward.sum().gradient to get closer to the gradients
2025-02-26 12:09:24 -05:00
chenyuandGitHub aaf0a8069f xor -> bitwise_xor (#9264) 2025-02-26 10:21:14 -05:00
George HotzandGitHub 2158dc4849 full fix for as_strided in torch backend (#9257)
* fixes from chargpt for torch backend

* shrink support

* add stride support

* comment cleanup

* a few more

* work

* import the stream hack

* llvm multi auto
2025-02-26 22:34:05 +08:00
qazalandGitHub f60f997bf7 viz ui fixes [pr] (#9261) 2025-02-26 14:52:18 +01:00
qazalandGitHub bfd1e55bda show zoom to fit button in VIZ if graph isn't in view [pr] (#9258)
* show zoom to fit button in VIZ if graph isn't in view [pr]

* select #render
2025-02-26 14:20:39 +01:00
qazalandGitHub f70bad42ce minor becomes_map cleanup + comments [pr] (#9256)
* substitute assign source for KERNEL + comments [pr]

* minor becomes_map cleanup + comments [pr]
2025-02-26 12:36:27 +01:00
George HotzandGitHub 7780393460 rig up torch's testing framework [pr] (#9254)
* rig up torch's testing framework [pr]

* support more movement ops

* dec on expand

* fix tests

* work

* fix tests

* a few more

* decomps + opt hook

* installed pytest
2025-02-26 18:46:22 +08:00
qazalandGitHub b3755370ae substitute assign source for KERNEL + comments [pr] (#9255) 2025-02-26 11:44:29 +01:00
qazalandGitHub 941559098b do not lockup VIZ when rendering big graphs [pr] (#8795)
* new viz renderer

* aesthetics

* progress message

* pruning + timeout at 2s
2025-02-26 09:15:26 +01:00
qazalandGitHub e162aa862d is_realized only if buffer is allocated (#9253)
* is_realized only if the buffer is allocated

* fix the image check too

* assert test_lil_model after ExecItems run
2025-02-26 08:58:08 +01:00
George HotzandGitHub b603af373e run some tests from torch [pr] (#9252)
* run some tests from torch [pr]

* yml

* wrap_out

* clean up for the new people

* a lil more
2025-02-26 15:42:22 +08:00
George HotzandGitHub 3f4eb9006a test for device mismatch [pr] (#9250)
* test for device mismatch [pr]

* fix bert
2025-02-26 13:06:33 +08:00
9c4d9d9f10 Acc first (#9232)
* put acc in front of the add chain

* handle the other case

* Make loop collapse more generic

* Remove mulacc_unrolled

* Actually remove it

---------

Co-authored-by: George Hotz <[email protected]>
Co-authored-by: chenyu <[email protected]>
2025-02-25 22:10:15 -05:00
chenyuandGitHub 979e84f30e RESET_STEP in bert setup and beam (#9248)
running dev_beam migh OOM without it but runs fine in real run.
2025-02-25 19:15:10 -05:00
nimlgenandGitHub 2676c9d46e dsp: raise exec errors as RuntimeError for beam (#9246) 2025-02-25 19:22:35 +03:00
nimlgenandGitHub 70db8c3003 hcq: dyn alloc signals (#9238)
* hcq: dyn alloc signals

* types and uniqueue devs

* typing

* mypy

* mypy one more time

* test

* make fds to not intersect in mockgpu between drivers
2025-02-25 17:22:24 +03:00
chenyuandGitHub 6610ad58ab hotfix bert no shard with only one device (#9243)
`LLVM=1 BERT_SIZE="tiny" DEFAULT_FLOAT=HALF BENCHMARK=5 MODEL="bert" python3 examples/mlperf/model_train.py` runs for me with this. it should not failed with single device shard though
2025-02-25 09:05:11 -05:00
qazalandGitHub bba9c22f53 implement the new subbuffer spec for DISK [pr] (#9241) 2025-02-25 13:36:23 +01:00
qazalandGitHub 48dfed064a remove const/var from the kernel graph [pr] (#9240) 2025-02-25 12:21:55 +01:00
nimlgenandGitHub b4c3780df0 hotfix: interop example (#9237)
* hotfix: interop example

* rm this

* fix

* fix ci mps

* atol rtol

* no uaf
2025-02-25 10:32:00 +03:00
chenyuandGitHub 8c7be428e5 update bert BS to 78 (#9236)
fits 78 now. about 215 tflops on green
2025-02-24 22:47:35 -05:00
990c240b82 Stable pow gradient (#9226)
* Stable gradient

* More efficient

* Fix and test for +-inf

* cleaner

* skip webgpu test

---------

Co-authored-by: chenyu <[email protected]>
2025-02-24 20:54:26 -05:00
chenyuandGitHub 731d14e718 hotfix bump testmetal2 timeout-minutes to 20 (#9235)
setup is taking too long
2025-02-24 20:23:56 -05:00
cbfe95d306 bring cast before view back (#9230)
* bring cast before view back

* tune it to only trigger on expands

---------

Co-authored-by: chenyu <[email protected]>
2025-02-25 01:50:39 +02:00
chenyuandGitHub 90c3ed17c5 move cast to before softmax in attention (#9213)
* move cast to before softmax in attention

saved some memory because exp (which is used for backward) are done in half. training bert seems fine and can fit BS=78 now (from 66)

* test
2025-02-24 17:24:59 -05:00
f0b24d230c add test_onnx_ops.py (#8569)
* boom

* fix webgpu

* use exact variable names in test so that AI can read easier

* add tag for specific test name like test a specific dtype

* fix ruff

* astype everything

* dtype in array creation

* just arange

* is 67% considered fixed?

* move test up

* small cleanups

* share function

* add qgemm as well

* add qgemm too

* make sure qgemm comes out as int

* take out qgemm for now

* fixed test

* add correct qgemm

* addressing feedback here too, early naive fix for now

* simplify bias and c to be minimalistic enough to test correctness

* refactored qlinearops

* maybe these asserts aren't the best..

* fix test

* updated tests to cover new ops

* try to add to CI

* move test_onnx_ops into testextra/

* more attention tests

* qlinear_add atol=1

* attention still not fullllllly correct

* it is what it is

---------

Co-authored-by: chenyu <[email protected]>
2025-02-24 16:15:22 -05:00
56288243e6 metal PyTorch interop (#9229)
* add from_blob support to mps cuda

* objc_id

* metal pytorch interop

* fix comments

---------

Co-authored-by: George Hotz <[email protected]>
2025-02-24 22:36:08 +03:00
qazalandGitHub 687d157906 delete cast early folding from ops [pr] (#9228) 2025-02-24 19:00:51 +01:00
c9493e41a6 reorder expand (#9051)
* reorder expand

* symbolic ops needs resolve here

* s/arg/st + whitespace

* viz

---------

Co-authored-by: qazal <[email protected]>
2025-02-24 13:55:47 +01:00
qazalandGitHub 14aa2395d0 allow VIEW(BUFFER) in Tensor UOps [pr] (#9210)
* allow VIEW(BUFFER) in Tensor UOps [pr]

* still reshapes

* update becomes_map tests

* bring copy folder to the scheduler

* lint

* only sgd left

* optimizer assign

* 13 kernels

* rename to test_reorder_expand + assert VIEW
2025-02-24 13:06:15 +01:00
1d06d61b16 from_blob for cuda (#9223)
* from_blob for cuda

* maybe docs?

* minor docs

* example

* waiting 9224

---------

Co-authored-by: George Hotz <[email protected]>
2025-02-24 14:02:06 +03:00
George HotzandGitHub fc32ff80d6 torch and numpy dtype interop [pr] (#9224)
* torch and numpy dtype interop [pr]

* less lines

* order
2025-02-24 18:26:49 +08:00
geohot 24615db5f5 hotfix: torch cuda interop example 2025-02-24 09:02:48 +00:00
geohot fd731e740a hotfix: add note on backend2.py 2025-02-24 11:23:03 +08:00
albanDandGitHub f2dd9c1562 simplify c++ code (#9221) 2025-02-24 11:04:41 +08:00
qazalandGitHub d12efc95d4 support custom name function in viz [pr] (#9219)
* support custom name function in viz [pr]

* title case

* assert name count in test_track_rewrites_name_fxn
2025-02-24 03:03:25 +02:00
chenyuandGitHub b3ae664d5d fix gradient of pow(t, int) (#9217)
semi revert some pow logic back to tensor. added direct gradient check because the backward in test_ops passed by luck
2025-02-23 17:42:09 -05:00
qazalandGitHub 12b5b83821 set TRACK_MATCH_STATS=0 for real_strides [pr] (#9216) 2025-02-23 23:26:31 +02:00
qazalandGitHub 9db0ec46a7 simpler buf_uop [pr] (#9215)
* simpler buf_uop [pr]

* assert after realize it's buffer
2025-02-23 19:23:14 +01:00
qazalandGitHub 898aafe6fd move split_reduceop to scheduler + enable it for multi (#9214)
* move split_reduceop to scheduler + enable it for multi

* merge r and _reduceop
2025-02-23 17:30:04 +01:00
ShikChenandGitHub 05e3202fba remove unused memsize_to_str and minor cleanups [pr] (#9211)
* fix edge cases in memsize_to_str()

Inputs <= 1 now return "0.00 B" for 0 and "1.00 B" for 1, avoiding an
IndexError. Also, memsize_to_str(1000) now returns "1.00 KB" instead of
"1000.00 B".

Replaced the list comprehension with a next(...) generator for conciseness
and efficiency.

* simplify code using idiomatic python

- Remove the unused `memsize_to_str()` function in helpers.
- Use a tuple for checking multiple string prefixes/suffixes.
- Avoid unnecessary list construction by using iterables directly.
- Check None in @diskcache to ensure proper caching of falsy values.

* revert generators back to list comprehension

Sometimes building list first could be faster. Keep it as is.
2025-02-23 09:58:37 -05:00
qazalandGitHub 81a71ae0f6 hotfix: skip test_exclude_const_metadata (#9208) 2025-02-22 23:26:04 +02:00
chenyuandGitHub e0adb1fc76 really run test_ops with TINY_BACKEND in ci (#9206)
was failing with `line 1: pytest: command not found`
2025-02-22 15:51:24 -05:00
qazalandGitHub e6d20c47e3 simpler becomes_map update [pr] (#9201)
* simpler becomes_map update

* err, no metadata for device

* simpler tensor metadata mapping + tests [pr]

* remove kernel metadata

* don't map nones

* pruning

* linter
2025-02-22 20:50:58 +01:00
qazalandGitHub 4578c3e8fd simpler tensor metadata mapping + tests [pr] (#9203)
* simpler tensor metadata mapping + tests [pr]

* remove kernel metadata

* don't map nones
2025-02-22 20:18:46 +01:00
qazalandGitHub b711c6343a no early return + allow childless const/bind/var in kernel graph [pr] (#9202) 2025-02-22 19:28:22 +01:00
George HotzandGitHub 97bc723538 torch backend works for ResNet-18 (#9200)
* torch backend progress, a few more functions

* resnet works

* pillow

* tv
2025-02-22 22:16:23 +08:00
George HotzandGitHub f92820d30d torch backend tests (#9198)
* torch backend tests

* pythonpath

* install ninja
2025-02-22 16:01:49 +08:00
George HotzandGitHub 4e6665bda5 different way to write torch backend (#9197)
* different way to write torch backend

* both backends

* more work

* simpler code

* more work

* test both

* imply unwrap/wrap

* FORWARD_ONLY=1 TINY_BACKEND=1 python3 test/test_ops.py TestOps.test_add works

* ready to start making test_ops work in torch backend

* backward pass, TINY_BACKEND=1 python3 test/test_ops.py TestOps.test_add works

* FORWARD_ONLY=1 TINY_BACKEND=1 python3 test/test_ops.py TestOps.test_simple_conv2d works

* matmul backward is broken with as_strided
2025-02-22 14:42:26 +08:00
nimlgenandGitHub 041b6d5678 am: load fw in batches (#9185)
* am: load fw in batches

* am: 1mb less fw copies

* mypy

* list
2025-02-21 23:21:31 +03:00
qazalandGitHub 1db4341e9f move viz graph to lib/graph [pr] (#9196)
* move viz graph to lib/graph [pr]

* add package

* share with program
2025-02-21 21:04:07 +01:00
geohotstanandGitHub 6587c7879b simple fixes to onnx (#9195)
* uncontroversial changes

* cleaner _prepare_quantize
2025-02-21 13:10:06 -05:00
Simon RandGitHub 2318d7ac51 Add missing tinygrad.runtime.autogen.am to packages (#9194) 2025-02-21 15:38:24 +02:00
qazalandGitHub 8bb80b6e5e reorder AST matchers + comments [pr] (#9193) 2025-02-21 14:31:15 +01:00
qazalandGitHub 2eab8021fb remove inputs+outputs attributes from ScheduleItem [pr] (#9192)
* remove inputs/outputs from ScheduleItem

* fix test_linearizer

* fix test_conv_shapetracker

* fix test_schedule + lint

* test_image_dtype + multitensor + search
2025-02-21 13:48:11 +01:00
George HotzandGitHub e87be0131e torch backend start (#9191)
* start torch backend

* progress

* ugh, you need cpp crap

* 1+1 works

* 1+1 works

* becoming a real backend

* ready to merge?
2025-02-21 16:57:28 +08:00
453 changed files with 1356046 additions and 249159 deletions
+13 -11
View File
@@ -44,6 +44,9 @@ runs:
uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python-version }}
- name: Upgrade pip
shell: bash
run: python -m pip install --upgrade pip
# **** Caching packages ****
# TODO: key should include input.deps, but it can't since it can't contain commas
@@ -121,9 +124,8 @@ runs:
echo -e 'Package: *\nPin: release o=repo.radeon.com\nPin-Priority: 600' | sudo tee /etc/apt/preferences.d/rocm-pin-600
sudo apt update || true
sudo apt install --no-install-recommends --allow-unauthenticated -y hsa-rocr comgr hsa-rocr-dev liburing-dev libc6-dev
curl -s https://api.github.com/repos/Qazalin/remu/releases/latest | \
jq -r '.assets[] | select(.name == "libremu.so").browser_download_url' | \
sudo xargs curl -L -o /usr/local/lib/libremu.so
cargo build --release --manifest-path ./extra/remu/Cargo.toml
sudo ln -sf ${{ github.workspace }}/extra/remu/target/release/libremu.so /usr/local/lib/libremu.so
sudo tee --append /etc/ld.so.conf.d/rocm.conf <<'EOF'
/opt/rocm/lib
/opt/rocm/lib64
@@ -137,9 +139,7 @@ runs:
curl -s -H "Authorization: token $GH_TOKEN" curl -s https://api.github.com/repos/nimlgen/amdcomgr_dylib/releases/latest | \
jq -r '.assets[] | select(.name == "libamd_comgr.dylib").browser_download_url' | \
sudo xargs curl -L -o /usr/local/lib/libamd_comgr.dylib
curl -s -H "Authorization: token $GH_TOKEN" curl -s https://api.github.com/repos/Qazalin/remu/releases/latest | \
jq -r '.assets[] | select(.name == "libremu.dylib").browser_download_url' | \
sudo xargs curl -L -o /usr/local/lib/libremu.dylib
cargo build --release --manifest-path ./extra/remu/Cargo.toml
# **** CUDA ****
@@ -175,7 +175,7 @@ runs:
git checkout b16039dc940dc6bc4ea0a98380495769ff35ed99
mkdir build
cd build
cmake .. -Wno-dev -G Ninja -DOCELOT_BUILD_TOOLS=OFF -DCMAKE_BUILD_ALWAYS=0 -DBUILD_TESTS_CUDA=OFF
cmake .. -Wno-dev -G Ninja -DOCELOT_BUILD_TOOLS=OFF -DCMAKE_BUILD_ALWAYS=0 -DBUILD_TESTS_CUDA=OFF -DCMAKE_POLICY_VERSION_MINIMUM=3.5
ninja
- name: Install gpuocelot
if: inputs.cuda == 'true'
@@ -202,8 +202,8 @@ runs:
if: inputs.webgpu == 'true' && runner.os == 'macOS'
shell: bash
run: |
sudo mkdir -p /usr/local/lib
sudo curl -L https://github.com/wpmed92/pydawn/releases/download/v0.1.6/libwebgpu_dawn.dylib -o /usr/local/lib/libwebgpu_dawn.dylib
brew tap wpmed92/dawn
brew install dawn
# **** LLVM ****
@@ -212,11 +212,13 @@ runs:
shell: bash
run: |
echo 'Acquire::http::Pipeline-Depth "5";' | sudo tee -a /etc/apt/apt.conf.d/99parallel
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc
echo "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-19 main" | sudo tee /etc/apt/sources.list.d/llvm.list
sudo apt update -y || true
sudo apt install -y --no-install-recommends llvm-dev
sudo apt install -y --no-install-recommends libllvm19 clang-19 lld-19
- name: Install LLVM (macOS)
if: inputs.llvm == 'true' && runner.os == 'macOS'
shell: bash
run: |
brew install llvm
brew install llvm@19
+47 -28
View File
@@ -24,6 +24,9 @@ on:
jobs:
testmacbenchmark:
name: Mac Benchmark
env:
# since sudo is required for usbgpu on macos, move the cache to a new location, as some of the files are owned by root
PYTHONPYCACHEPREFIX: /tmp/tiny_python_pycache
runs-on: [self-hosted, macOS]
timeout-minutes: 20
defaults:
@@ -54,24 +57,25 @@ jobs:
run: JIT=1 python3.11 examples/stable_diffusion.py --seed 0 --noshow --timing | tee sd_no_fp16.txt
- name: Run Stable Diffusion v2
run: JIT=1 python3.11 examples/sdv2.py --fp16 --seed 0 --noshow --timing | tee sdv2.txt
# process replay can't capture this, the graph is too large
- name: Run SDXL
run: JIT=1 python3.11 examples/sdxl.py --seed 0 --noshow --timing | tee sdxl.txt
run: CAPTURE_PROCESS_REPLAY=0 JIT=1 python3.11 examples/sdxl.py --seed 0 --noshow --timing | tee sdxl.txt
- name: Run model inference benchmark
run: METAL=1 python3.11 test/external/external_model_benchmark.py
- name: Test speed vs torch
run: BIG=2 MPS=1 python3.11 test/test_speed_v_torch.py | tee torch_speed.txt
- name: Test tensor cores
run: METAL=1 python3.11 test/test_linearizer.py TestLinearizer.test_tensor_cores TestLinearizer.test_tensor_cores_padded
run: METAL=1 python3.11 test/test_linearizer.py TestLinearizer.test_tensor_cores TestLinearizer.test_tensor_cores_emulation TestLinearizer.test_tensor_cores_padded TestLinearizer.test_tensor_cores_padded_uops
- name: Test AMX tensor cores
run: |
DEBUG=2 CPU=1 AMX=1 python3.11 test/test_linearizer.py TestLinearizer.test_tensor_cores TestLinearizer.test_tensor_cores_padded
DEBUG=2 LLVM=1 AMX=1 python3.11 test/test_linearizer.py TestLinearizer.test_tensor_cores TestLinearizer.test_tensor_cores_padded
DEBUG=2 CPU=1 AMX=1 python3.11 test/test_linearizer.py TestLinearizer.test_tensor_cores TestLinearizer.test_tensor_cores_emulation TestLinearizer.test_tensor_cores_padded TestLinearizer.test_tensor_cores_padded_uops
DEBUG=2 LLVM=1 AMX=1 python3.11 test/test_linearizer.py TestLinearizer.test_tensor_cores TestLinearizer.test_tensor_cores_emulation TestLinearizer.test_tensor_cores_padded TestLinearizer.test_tensor_cores_padded_uops
- name: Run Tensor Core GEMM (float)
run: DEBUG=2 python3.11 extra/gemm/simple_matmul.py | tee matmul.txt
run: DEBUG=2 SHOULD_USE_TC=1 python3.11 extra/gemm/simple_matmul.py | tee matmul.txt
- name: Run Tensor Core GEMM (half)
run: DEBUG=2 HALF=1 python3.11 extra/gemm/simple_matmul.py | tee matmul_half.txt
run: DEBUG=2 SHOULD_USE_TC=1 HALF=1 python3.11 extra/gemm/simple_matmul.py | tee matmul_half.txt
- name: Run Tensor Core GEMM (bfloat16)
run: DEBUG=2 BFLOAT16=1 python3.11 extra/gemm/simple_matmul.py | tee matmul_bfloat16.txt
run: DEBUG=2 SHOULD_USE_TC=1 BFLOAT16=1 python3.11 extra/gemm/simple_matmul.py | tee matmul_bfloat16.txt
- name: Fuzz Padded Tensor Core GEMM
run: METAL=1 M_START=6 M_STOP=10 M_STEP=1 N_START=6 N_STOP=10 N_STEP=1 K_START=6 K_STOP=24 K_STEP=1 TC_OPT=2 DEBUG=2 python3.11 ./extra/gemm/fuzz_matmul.py
- name: Run LLaMA
@@ -84,6 +88,10 @@ jobs:
run: |
python3.11 examples/llama.py --gen 1 --prompt "Hello." --count 10 --temperature 0 --timing --quantize int8 | tee llama_int8.txt
python3.11 examples/llama.py --gen 1 --prompt "Hello." --count 10 --temperature 0 --timing --quantize nf4 | tee llama_nf4.txt
- name: Run quantized LLaMA3
run: |
python3.11 examples/llama3.py --size 8B --temperature 0 --benchmark --quantize int8 | tee llama3_int8.txt
python3.11 examples/llama3.py --size 8B --temperature 0 --benchmark --quantize nf4 | tee llama3_nf4.txt
#- name: Run LLaMA 7B on 4 (virtual) GPUs
# run: python3.11 examples/llama.py --gen 1 --size 7B --shard 4 --prompt "Hello." --count 10 --temperature 0 --timing | tee llama_four_gpu.txt
- name: Run GPT2
@@ -94,6 +102,8 @@ jobs:
run: HALF=1 python3.11 examples/gpt2.py --count 10 --temperature 0 --timing | tee gpt2_half.txt
- name: Run GPT2 w HALF/BEAM
run: HALF=1 JITBEAM=2 IGNORE_BEAM_CACHE=1 python3.11 examples/gpt2.py --count 10 --temperature 0 --timing | tee gpt2_half_beam.txt
- name: Run OLMoE
run: python3.11 examples/olmoe.py
- name: Train MNIST
run: time PYTHONPATH=. TARGET_EVAL_ACC_PCT=96.0 python3.11 examples/beautiful_mnist.py | tee beautiful_mnist.txt
- name: Run 10 CIFAR training steps
@@ -104,6 +114,14 @@ jobs:
# run: STEPS=10 DEFAULT_FLOAT=BFLOAT16 python3.11 examples/hlb_cifar10.py | tee train_cifar_bf16.txt
- name: Run 10 CIFAR training steps w winograd
run: JIT=1 WINO=1 STEPS=10 python3.11 examples/hlb_cifar10.py | tee train_cifar_wino.txt
- name: UsbGPU boot time
run: sudo -E PYTHONPATH=. DEBUG=2 AM_RESET=1 AMD=1 AMD_IFACE=USB time python3.11 test/test_tiny.py TestTiny.test_plus
- name: UsbGPU tiny tests
run: sudo -E PYTHONPATH=. AMD=1 AMD_IFACE=USB python3.11 test/test_tiny.py
- name: UsbGPU copy speeds
run: sudo -E PYTHONPATH=. AMD=1 AMD_IFACE=USB python3.11 test/external/external_test_usb_asm24.py TestDevCopySpeeds
- name: UsbGPU openpilot test
run: sudo -E PYTHONPATH=. AMD=1 AMD_IFACE=USB AMD_LLVM=1 NOLOCALS=0 IMAGE=0 GRAPH_ONE_KERNEL=1 python3.11 examples/openpilot/compile3.py https://github.com/commaai/openpilot/raw/9118973ed03c1ae1d40cf69a29507ec2cc78efd7/selfdrive/modeld/models/supercombo.onnx
- uses: actions/upload-artifact@v4
with:
name: Speed (Mac)
@@ -115,6 +133,8 @@ jobs:
llama_beam.txt
llama_int8.txt
llama_nf4.txt
llama3_int8.txt
llama3_nf4.txt
llama_four_gpu.txt
gpt2_unjitted.txt
gpt2_jitted.txt
@@ -174,17 +194,17 @@ jobs:
run: NV=1 python test/external/external_benchmark_multitensor_allreduce.py
- name: Test tensor cores
run: |
NV=1 ALLOW_TF32=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores TestLinearizer.test_tensor_cores_padded
PTX=1 ALLOW_TF32=1 NV=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores TestLinearizer.test_tensor_cores_padded
NV=1 ALLOW_TF32=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores TestLinearizer.test_tensor_cores_emulation TestLinearizer.test_tensor_cores_padded TestLinearizer.test_tensor_cores_padded_uops
PTX=1 ALLOW_TF32=1 NV=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores TestLinearizer.test_tensor_cores_emulation TestLinearizer.test_tensor_cores_padded TestLinearizer.test_tensor_cores_padded_uops
- name: Run Tensor Core GEMM (CUDA)
run: |
CUDA=1 HALF=1 DEBUG=2 python3 extra/gemm/simple_matmul.py | tee matmul.txt
CUDA=1 BFLOAT16=1 DEBUG=2 python3 extra/gemm/simple_matmul.py | tee matmul_bfloat16.txt
CUDA=1 ALLOW_TF32=1 DEBUG=2 python3 extra/gemm/simple_matmul.py | tee matmul_tf32.txt
CUDA=1 SHOULD_USE_TC=1 HALF=1 DEBUG=2 python3 extra/gemm/simple_matmul.py | tee matmul.txt
CUDA=1 SHOULD_USE_TC=1 BFLOAT16=1 DEBUG=2 python3 extra/gemm/simple_matmul.py | tee matmul_bfloat16.txt
CUDA=1 SHOULD_USE_TC=1 ALLOW_TF32=1 DEBUG=2 ATOL=2e-2 python3 extra/gemm/simple_matmul.py | tee matmul_tf32.txt
- name: Run Tensor Core GEMM (PTX)
run: NV=1 PTX=1 HALF=1 DEBUG=2 python3 extra/gemm/simple_matmul.py | tee matmul_ptx.txt
run: NV=1 PTX=1 SHOULD_USE_TC=1 HALF=1 DEBUG=2 python3 extra/gemm/simple_matmul.py | tee matmul_ptx.txt
- name: Run Tensor Core GEMM (NV)
run: NV=1 HALF=1 DEBUG=2 python3 extra/gemm/simple_matmul.py | tee matmul_nv.txt
run: NV=1 SHOULD_USE_TC=1 HALF=1 DEBUG=2 python3 extra/gemm/simple_matmul.py | tee matmul_nv.txt
- name: Test NV=1
run: DEBUG=2 NV=1 python -m pytest -rA test/test_tiny.py
- name: Test CUDA=1
@@ -192,7 +212,7 @@ jobs:
- name: Run Stable Diffusion
run: NV=1 python3 examples/stable_diffusion.py --fp16 --seed 0 --noshow --timing | tee sd.txt
- name: Run SDXL
run: NV=1 CAPTURE_PROCESS_REPLAY=0 python3 examples/sdxl.py --seed 0 --noshow --timing | tee sdxl.txt
run: CAPTURE_PROCESS_REPLAY=0 NV=1 CAPTURE_PROCESS_REPLAY=0 python3 examples/sdxl.py --seed 0 --noshow --timing | tee sdxl.txt
- name: Run LLaMA
run: |
NV=1 JIT=0 python3 examples/llama.py --gen 1 --prompt "Hello." --count 10 --temperature 0 --timing | tee llama_unjitted.txt
@@ -303,7 +323,7 @@ jobs:
run: NV=1 CAPTURE_PROCESS_REPLAY=0 DEFAULT_FLOAT=HALF BENCHMARK=10 BS=1536 GPUS=6 MODEL=resnet python3 examples/mlperf/model_train.py | tee train_resnet.txt
- name: Run 10 MLPerf Bert training steps (6 gpu)
# TODO: remove BERT_LAYERS once scheduler is fast
run: NV=1 CAPTURE_PROCESS_REPLAY=0 DEFAULT_FLOAT=HALF BENCHMARK=10 BS=66 GPUS=6 BERT_LAYERS=2 MODEL=bert python3 examples/mlperf/model_train.py | tee train_bert.txt
run: NV=1 CAPTURE_PROCESS_REPLAY=0 DEFAULT_FLOAT=HALF BENCHMARK=10 BS=66 GPUS=6 BERT_LAYERS=2 FUSE_ARANGE=1 FUSE_ARANGE_UINT=0 MODEL=bert python3 examples/mlperf/model_train.py | tee train_bert.txt
- uses: actions/upload-artifact@v4
with:
name: Speed (NVIDIA Training)
@@ -369,9 +389,12 @@ jobs:
- name: Test speed vs theoretical
run: AMD=1 IGNORE_BEAM_CACHE=1 BEAM_DEBUG=1 DEBUG=1 python -m pytest -rA test/external/speed_v_theoretical.py --durations=20
- name: Test tensor cores
run: AMD=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores TestLinearizer.test_tensor_cores_padded
run: |
AMD=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores TestLinearizer.test_tensor_cores_emulation TestLinearizer.test_tensor_cores_padded_amd TestLinearizer.test_tensor_cores_padded_uops
AMD=1 AMD_LLVM=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores TestLinearizer.test_tensor_cores_emulation TestLinearizer.test_tensor_cores_padded_amd TestLinearizer.test_tensor_cores_padded_uops
AMD=1 SHOULD_USE_TC=1 BFLOAT16=1 DEBUG=2 python3 extra/gemm/simple_matmul.py
- name: Run Tensor Core GEMM (AMD)
run: AMD=1 HALF=1 DEBUG=2 python3 extra/gemm/simple_matmul.py | tee matmul_amd.txt
run: AMD=1 SHOULD_USE_TC=1 HALF=1 DEBUG=2 ATOL=2e-2 python3 extra/gemm/simple_matmul.py | tee matmul_amd.txt
- name: Test AMD=1
run: DEBUG=2 AMD=1 python -m pytest -rA test/test_tiny.py
- name: Test HIP=1
@@ -380,7 +403,7 @@ jobs:
#- name: Fuzz Padded Tensor Core GEMM
# run: HSA=1 M_START=12 M_STOP=20 M_STEP=1 N_START=12 N_STOP=20 N_STEP=1 K_START=28 K_STOP=36 K_STEP=1 HALF=1 TC_OPT=2 DEBUG=2 python3 ./extra/gemm/fuzz_matmul.py
- name: Remove amdgpu
run: sleep 5 && sudo rmmod amdgpu # sleep a bit to let the driver unload the prev pid.
run: sleep 10 && sudo rmmod amdgpu # sleep a bit to let the driver unload the prev pid.
- name: Test AM cold start time
run: time AMD=1 AM_RESET=1 python3 test/test_tiny.py TestTiny.test_plus
- name: Test AM warm start time
@@ -388,7 +411,7 @@ jobs:
- name: Run Stable Diffusion
run: AMD=1 python3 examples/stable_diffusion.py --fp16 --seed 0 --noshow --timing | tee sd.txt
- name: Run SDXL
run: AMD=1 python3 examples/sdxl.py --seed 0 --noshow --timing | tee sdxl.txt
run: CAPTURE_PROCESS_REPLAY=0 AMD=1 python3 examples/sdxl.py --seed 0 --noshow --timing | tee sdxl.txt
- name: Run LLaMA 7B
run: |
AMD=1 JIT=0 python3 examples/llama.py --gen 1 --prompt "Hello." --count 10 --temperature 0 --timing | tee llama_unjitted.txt
@@ -447,7 +470,7 @@ jobs:
testmoreamdbenchmark:
name: tinybox red Training Benchmark
runs-on: [self-hosted, Linux, tinybox]
timeout-minutes: 20
timeout-minutes: 30
defaults:
run:
shell: bash -o pipefail {0}
@@ -455,8 +478,8 @@ jobs:
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Insert amdgpu
run: sudo modprobe amdgpu
- name: Remove amdgpu
run: sudo rmmod amdgpu || true
- name: Symlink models and datasets
run: |
mkdir -p weights
@@ -474,10 +497,6 @@ jobs:
rm -f /tmp/staging.db /tmp/staging.db-shm /tmp/staging.db-wal
- name: reset process replay
run: test/external/process_replay/reset.py
- name: setup perflevel
run: |
examples/mlperf/training_submission_v4.1/tinycorp/benchmarks/bert/implementations/tinybox_red/setup.sh
rocm-smi
- name: Train MNIST
run: time PYTHONPATH=. AMD=1 TARGET_EVAL_ACC_PCT=96.0 python3 examples/beautiful_mnist.py | tee beautiful_mnist.txt
- name: Run 10 CIFAR training steps
@@ -500,7 +519,7 @@ jobs:
run: AMD=1 CAPTURE_PROCESS_REPLAY=0 DEFAULT_FLOAT=HALF BENCHMARK=10 BS=1536 GPUS=6 MODEL=resnet python3 examples/mlperf/model_train.py | tee train_resnet.txt
- name: Run 10 MLPerf Bert training steps (6 gpu)
# TODO: remove BERT_LAYERS once scheduler is fast
run: AMD=1 CAPTURE_PROCESS_REPLAY=0 DEFAULT_FLOAT=HALF BENCHMARK=10 BS=66 GPUS=6 BERT_LAYERS=2 MODEL=bert python3 examples/mlperf/model_train.py | tee train_bert.txt
run: AMD=1 CAPTURE_PROCESS_REPLAY=0 DEFAULT_FLOAT=HALF BENCHMARK=10 BS=66 GPUS=6 BERT_LAYERS=2 FUSE_ARANGE=1 FUSE_ARANGE_UINT=0 MODEL=bert python3 examples/mlperf/model_train.py | tee train_bert.txt
- uses: actions/upload-artifact@v4
with:
name: Speed (AMD Training)
+277 -48
View File
@@ -29,9 +29,9 @@ jobs:
- name: External Benchmark Schedule
run: PYTHONPATH="." python3 test/external/external_benchmark_schedule.py
- name: Speed Test
run: LLVM=1 LLVMOPT=1 python3 test/test_speed_v_torch.py
run: LLVM=1 python3 test/test_speed_v_torch.py
- name: Speed Test (BEAM=2)
run: BEAM=2 LLVM=1 LLVMOPT=1 python3 test/test_speed_v_torch.py
run: BEAM=2 LLVM=1 python3 test/test_speed_v_torch.py
docs:
name: Docs
@@ -88,7 +88,7 @@ jobs:
autogen:
name: Autogen
runs-on: ubuntu-22.04
timeout-minutes: 10
timeout-minutes: 15
steps:
- name: Checkout Code
uses: actions/checkout@v4
@@ -116,14 +116,20 @@ jobs:
- name: Verify AMD autogen
run: |
cp tinygrad/runtime/autogen/hsa.py /tmp/hsa.py.bak
cp tinygrad/runtime/autogen/kfd.py /tmp/kfd.py.bak
cp tinygrad/runtime/autogen/comgr.py /tmp/comgr.py.bak
cp tinygrad/runtime/autogen/amd_gpu.py /tmp/amd_gpu.py.bak
cp tinygrad/runtime/autogen/sqtt.py /tmp/sqtt.py.bak
./autogen_stubs.sh hsa
./autogen_stubs.sh kfd
./autogen_stubs.sh comgr
./autogen_stubs.sh amd
./autogen_stubs.sh sqtt
diff /tmp/hsa.py.bak tinygrad/runtime/autogen/hsa.py
diff /tmp/kfd.py.bak tinygrad/runtime/autogen/kfd.py
diff /tmp/comgr.py.bak tinygrad/runtime/autogen/comgr.py
diff /tmp/amd_gpu.py.bak tinygrad/runtime/autogen/amd_gpu.py
diff /tmp/sqtt.py.bak tinygrad/runtime/autogen/sqtt.py
- name: Verify Linux autogen
run: |
cp tinygrad/runtime/autogen/libc.py /tmp/libc.py.bak
@@ -143,10 +149,75 @@ jobs:
./autogen_stubs.sh llvm
diff /tmp/llvm.py.bak tinygrad/runtime/autogen/llvm.py
torchbackend:
name: Torch Backend Tests
runs-on: ubuntu-latest
timeout-minutes: 15
env:
IGNORE_OOB: 0
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup Environment
uses: ./.github/actions/setup-tinygrad
with:
key: torch-backend-pillow-torchvision-et-pt
deps: testing_minimal
pydeps: "pillow torchvision expecttest"
llvm: 'true'
- name: Install ninja
run: |
sudo apt update || true
sudo apt install -y --no-install-recommends ninja-build
- name: Lint with ruff
run: |
pip3 install --upgrade --force-reinstall ruff==0.11.0
python3 -m ruff check extra/torch_backend/backend.py
- name: Test one op
run: PYTHONPATH=. FORWARD_ONLY=1 TINY_BACKEND=1 python3 test/test_ops.py TestOps.test_add
- name: Test ResNet-18
run: PYTHONPATH=. DEBUG=2 python3 extra/torch_backend/example.py
- name: My (custom) tests
run: PYTHONPATH=. python3 extra/torch_backend/test.py
- name: Test one op in torch tests
run: PYTHONPATH=. DEBUG=2 python3 extra/torch_backend/torch_tests.py TestTinyBackendPRIVATEUSE1.test_unary_log_tiny_float32
- name: Test Ops with TINY_BACKEND
run: PYTHONPATH=. LLVM=1 LLVMOPT=0 TINY_BACKEND=1 python3 -m pytest -n auto test/test_ops.py --durations=20
- name: Test in-place operations on views
run: PYTHONPATH=. TORCH_DEBUG=1 python3 extra/torch_backend/test_inplace.py
- name: Test multi-gpu
run: PYTHONPATH=. LLVM=1 GPUS=4 TORCH_DEBUG=1 python3 extra/torch_backend/test_multigpu.py
torchbackendmore:
name: Torch Backend Tests More
runs-on: ubuntu-latest
timeout-minutes: 15
env:
IGNORE_OOB: 0
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup Environment
uses: ./.github/actions/setup-tinygrad
with:
key: torch-backend-pillow-torchvision-et-pt
deps: testing_minimal
llvm: 'true'
- name: Install ninja
run: |
sudo apt update || true
sudo apt install -y --no-install-recommends ninja-build
- name: Test beautiful_mnist in torch with TINY_BACKEND
run: SPLIT_REDUCEOP=0 FUSE_ARANGE=1 PYTHONPATH=. LLVM=1 TARGET_EVAL_ACC_PCT=96.0 TINY_BACKEND=1 python3 examples/other_mnist/beautiful_mnist_torch.py
- name: Test some torch tests (expect failure)
run: PYTHONPATH=. python3 -m pytest extra/torch_backend/torch_tests.py -v --tb=no || true
tc:
name: Tensor Core tests
runs-on: ubuntu-latest
timeout-minutes: 10
env:
IGNORE_OOB: 0
steps:
- name: Checkout Code
uses: actions/checkout@v4
@@ -162,7 +233,8 @@ jobs:
- name: Test emulated METAL tensor cores
run: |
DEBUG=2 EMULATE_METAL=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_ops.py TestOps.test_big_gemm
PYTHONPATH=. DEBUG=2 EMULATE_METAL=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores TestLinearizer.test_tensor_cores_padded
PYTHONPATH=. DEBUG=2 EMULATE_METAL=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores
PYTHONPATH=. DEBUG=2 EMULATE_METAL=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores_padded TestLinearizer.test_tensor_cores_padded_uops
- name: Test emulated AMX tensor cores
run: PYTHONPATH=. DEBUG=2 AMX=1 EMULATE_AMX=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_ops.py TestOps.test_gemm
- name: Test emulated AMD tensor cores
@@ -171,13 +243,28 @@ jobs:
PYTHONPATH=. DEBUG=2 EMULATE_AMD=1 FORWARD_ONLY=1 PYTHON=1 N=64 HALF=1 ACC_HALF=0 python3 ./extra/gemm/simple_matmul.py
PYTHONPATH=. DEBUG=2 EMULATE_AMD=1 FORWARD_ONLY=1 PYTHON=1 N=16 HALF=1 ACC_HALF=1 python3 ./extra/gemm/simple_matmul.py
PYTHONPATH=. DEBUG=2 EMULATE_AMD=1 FORWARD_ONLY=1 PYTHON=1 N=64 HALF=1 ACC_HALF=1 python3 ./extra/gemm/simple_matmul.py
PYTHONPATH=. DEBUG=2 EMULATE_AMD=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores TestLinearizer.test_tensor_cores_padded
PYTHONPATH=. DEBUG=2 EMULATE_AMD=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores
PYTHONPATH=. DEBUG=2 EMULATE_AMD=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores_padded_amd TestLinearizer.test_tensor_cores_padded_uops
- name: Test emulated AMD MFMA tensor cores
run: |
PYTHONPATH=. DEBUG=2 EMULATE_AMD_MFMA=1 FORWARD_ONLY=1 PYTHON=1 N=64 HALF=1 ACC_HALF=0 python3 ./extra/gemm/simple_matmul.py
PYTHONPATH=. DEBUG=2 EMULATE_AMD_MFMA=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores
PYTHONPATH=. DEBUG=2 EMULATE_AMD_MFMA=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores_padded TestLinearizer.test_tensor_cores_padded_uops
- name: Test emulated AMD RDNA4 tensor cores
run: |
PYTHONPATH=. DEBUG=2 EMULATE_AMD_RDNA4=1 FORWARD_ONLY=1 PYTHON=1 N=16 HALF=1 ACC_HALF=0 python3 ./extra/gemm/simple_matmul.py
PYTHONPATH=. DEBUG=2 EMULATE_AMD_RDNA4=1 FORWARD_ONLY=1 PYTHON=1 N=64 HALF=1 ACC_HALF=0 python3 ./extra/gemm/simple_matmul.py
PYTHONPATH=. DEBUG=2 EMULATE_AMD_RDNA4=1 FORWARD_ONLY=1 PYTHON=1 N=16 HALF=1 ACC_HALF=1 python3 ./extra/gemm/simple_matmul.py
PYTHONPATH=. DEBUG=2 EMULATE_AMD_RDNA4=1 FORWARD_ONLY=1 PYTHON=1 N=64 HALF=1 ACC_HALF=1 python3 ./extra/gemm/simple_matmul.py
PYTHONPATH=. DEBUG=2 EMULATE_AMD_RDNA4=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores
PYTHONPATH=. DEBUG=2 EMULATE_AMD_RDNA4=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores_padded TestLinearizer.test_tensor_cores_padded_uops
- name: Test emulated CUDA tensor cores
run: |
DEBUG=2 EMULATE_CUDA=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_ops.py TestOps.test_gemm_fp16
DEBUG=2 EMULATE_CUDA=1 ALLOW_TF32=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_ops.py TestOps.test_gemm
DEBUG=2 EMULATE_CUDA_SM75=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_ops.py TestOps.test_gemm_fp16
PYTHONPATH="." DEBUG=2 EMULATE_CUDA=1 ALLOW_TF32=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores TestLinearizer.test_tensor_cores_padded
PYTHONPATH="." DEBUG=2 EMULATE_CUDA=1 ALLOW_TF32=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores
PYTHONPATH="." DEBUG=2 EMULATE_CUDA=1 ALLOW_TF32=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_linearizer.py TestLinearizer.test_tensor_cores_padded TestLinearizer.test_tensor_cores_padded_uops
- name: Test emulated INTEL OpenCL tensor cores
run: DEBUG=2 EMULATE_INTEL=1 FORWARD_ONLY=1 PYTHON=1 HALF=1 N=64 python3 ./extra/gemm/simple_matmul.py
- name: Full test tensor cores
@@ -189,11 +276,12 @@ jobs:
PYTHONPATH=. DEBUG=2 AMX=1 EMULATE_AMX=1 FORWARD_ONLY=1 PYTHON=1 python3 ./test/test_linearizer.py TestLinearizer.test_tensor_cores
- name: Test tensor cores (TC=3)
run: |
TC=3 DEBUG=3 EMULATE_METAL=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_ops.py TestOps.test_gemm
TC=3 PYTHONPATH=. DEBUG=3 EMULATE_AMD=1 PYTHON=1 N=16 HALF=1 ACC_HALF=0 python3 ./extra/gemm/simple_matmul.py
TC=3 DEBUG=3 EMULATE_CUDA=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_ops.py TestOps.test_gemm_fp16
TC=3 PYTHONPATH=. DEBUG=3 EMULATE_INTEL=1 PYTHON=1 N=16 HALF=1 python3 ./extra/gemm/simple_matmul.py
TC=3 PYTHONPATH=. DEBUG=3 AMX=1 EMULATE_AMX=1 FORWARD_ONLY=1 PYTHON=1 python3 test/test_ops.py TestOps.test_gemm
PYTHONPATH=. DEBUG=2 PYTHON=1 EMULATE_METAL=1 python3 ./test/test_linearizer.py TestLinearizer.test_tensor_cores_emulation
PYTHONPATH=. DEBUG=2 PYTHON=1 EMULATE_AMD=1 python3 ./test/test_linearizer.py TestLinearizer.test_tensor_cores_emulation
PYTHONPATH=. DEBUG=2 PYTHON=1 EMULATE_AMD_MFMA=1 python3 ./test/test_linearizer.py TestLinearizer.test_tensor_cores_emulation
PYTHONPATH=. DEBUG=2 PYTHON=1 EMULATE_CUDA=1 python3 ./test/test_linearizer.py TestLinearizer.test_tensor_cores_emulation
PYTHONPATH=. DEBUG=2 PYTHON=1 EMULATE_INTEL=1 python3 ./test/test_linearizer.py TestLinearizer.test_tensor_cores_emulation
PYTHONPATH=. DEBUG=2 PYTHON=1 EMULATE_AMX=1 AMX=1 python3 ./test/test_linearizer.py TestLinearizer.test_tensor_cores_emulation
- name: Test device flop counts
run: |
PYTHONPATH=. DEBUG=2 EMULATE_METAL=1 PYTHON=1 python3 ./test/test_uops_stats.py TestUOpsStatsMatmulHalf
@@ -206,6 +294,8 @@ jobs:
name: Python Backend
runs-on: ubuntu-latest
timeout-minutes: 10
env:
IGNORE_OOB: 0
steps:
- name: Checkout Code
uses: actions/checkout@v4
@@ -217,13 +307,15 @@ jobs:
- name: Test dtype with Python emulator
run: DEBUG=1 PYTHONPATH=. PYTHON=1 python3 -m pytest -n=auto test/test_dtype.py test/test_dtype_alu.py
- name: Test ops with Python emulator
run: DEBUG=2 PYTHON=1 python3 -m pytest -n=auto test/test_ops.py -k "not (test_split or test_simple_cumsum or test_cumsum or test_einsum or test_dot or test_dot_1d or test_big_gemm or test_broadcastdot or test_multidot or test_var_axis or test_std_axis or test_broadcast_full or test_broadcast_partial or test_simple_conv3d or test_dilated_conv_transpose2d or test_simple_conv_transpose3d or test_large_input_conv2d or test_max_pool2d or test_max_pool2d_simple or test_max_pool2d_bigger_stride or test_avg_pool2d or test_cat or test_scaled_product_attention or test_scaled_product_attention_causal or test_slice_fancy_indexing_dim_inject_none or test_slice_fancy_indexing_list_indices or test_slice_fancy_indexing_no_dim_collapse or test_slice_fancy_indexing_tuple_indices or test_slice_fancy_indexing_list_with_tensors or test_slice_fancy_indexing_dim_collapse_int or test_interpolate_bilinear or test_interpolate_bilinear_corners_aligned or test_scaled_dot_product_attention or test_cummax)" --durations=20
run: DEBUG=2 PYTHON=1 python3 -m pytest -n=auto test/test_ops.py -k "not (test_split or test_simple_cumsum or test_cumsum or test_einsum or test_dot or test_dot_1d or test_big_gemm or test_broadcastdot or test_multidot or test_var_axis or test_std_axis or test_broadcast_full or test_broadcast_partial or test_simple_conv3d or test_dilated_conv_transpose2d or test_simple_conv_transpose3d or test_large_input_conv2d or test_max_pool2d or test_max_pool2d_simple or test_max_pool2d_bigger_stride or test_avg_pool2d or test_cat or test_scaled_product_attention or test_scaled_product_attention_causal or test_slice_fancy_indexing_dim_inject_none or test_slice_fancy_indexing_list_indices or test_slice_fancy_indexing_no_dim_collapse or test_slice_fancy_indexing_tuple_indices or test_slice_fancy_indexing_list_with_tensors or test_slice_fancy_indexing_dim_collapse_int or test_interpolate_bilinear or test_interpolate_bilinear_corners_aligned or test_scaled_dot_product_attention or test_cummax or test_simple_cummax or test_logcumsumexp or test_sort or test_cumprod)" --durations=20
- name: Test uops with Python emulator
run: PYTHON=1 python3 -m pytest test/test_uops.py --durations=20
- name: Test symbolic with Python emulator
run: PYTHONPATH=. PYTHON=1 python3 test/test_symbolic_ops.py
- name: test_linearizer_failures with Python emulator
run: PYTHONPATH=. PYTHON=1 python3 -m pytest -rA test/test_linearizer_failures.py::TestLinearizerFailures::test_failure_1
- name: test_renderer_failures with Python emulator
run: PYTHONPATH=. PYTHON=1 python3 -m pytest -rA test/test_renderer_failures.py::TestRendererFailures
linter:
name: Linters
@@ -244,8 +336,9 @@ jobs:
run: python -m pylint --disable=all -e W0311 -e C0303 --jobs=0 --indent-string=' ' --recursive=y .
- name: Lint with ruff
run: |
pip3 install --upgrade --force-reinstall ruff
pip3 install --upgrade --force-reinstall ruff==0.11.0
python3 -m ruff check .
python3 -m ruff check examples/mlperf/model_train.py --ignore E501
- name: Lint tinygrad with pylint
run: python -m pylint tinygrad/
- name: Run mypy
@@ -268,8 +361,15 @@ jobs:
run: awk '/```python/{flag=1;next}/```/{flag=0}flag' README.md > README.py && PYTHONPATH=. python README.py
- name: Run unit tests
run: PYTHONPATH="." python -m pytest -n=auto test/unit/
- name: Repo line count < 11300 lines
run: MAX_LINE_COUNT=11300 python sz.py
- name: Run targetted tests on NULL backend
run: PYTHONPATH="." NULL=1 python3 test/test_multitensor.py TestMultiTensor.test_data_parallel_resnet_train_step
# TODO: support fake weights
#- name: Run LLaMA 7B on 4 fake devices
# run: NULL=1 python3 examples/llama.py --gen 1 --size 7B --shard 4 --prompt "Hello." --count 3 --temperature 0 --timing
- name: Run GC tests
run: PYTHONPATH="." python test/external/external_uop_gc.py
- name: Repo line count < 13000 lines
run: MAX_LINE_COUNT=13000 python sz.py
fuzzing:
name: Fuzzing
@@ -285,6 +385,8 @@ jobs:
deps: testing_minimal
- name: Fuzz Test symbolic
run: python test/external/fuzz_symbolic.py
- name: Fuzz Test fast idiv
run: python test/external/fuzz_fast_idiv.py
- name: Fuzz Test shapetracker
run: |
PYTHONPATH="." python test/external/fuzz_shapetracker.py
@@ -292,8 +394,10 @@ jobs:
testgpuimage:
name: 'GPU IMAGE Tests'
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
timeout-minutes: 10
env:
IGNORE_OOB: 0
steps:
- name: Checkout Code
uses: actions/checkout@v4
@@ -316,8 +420,10 @@ jobs:
testopenpilot:
name: 'openpilot Compile Tests'
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
timeout-minutes: 10
env:
IGNORE_OOB: 0
steps:
- name: Checkout Code
uses: actions/checkout@v4
@@ -327,13 +433,16 @@ jobs:
key: openpilot-compile
deps: testing
opencl: 'true'
llvm: 'true'
- name: Test openpilot model kernel count and gate usage
run: |
PYTHONPATH="." ALLOWED_KERNEL_COUNT=209 ALLOWED_READ_IMAGE=2105 ALLOWED_GATED_READ_IMAGE=29 FLOAT16=0 GPU=1 IMAGE=2 python examples/openpilot/compile3.py https://github.com/commaai/openpilot/raw/v0.9.4/selfdrive/modeld/models/supercombo.onnx
PYTHONPATH="." ALLOWED_KERNEL_COUNT=209 ALLOWED_READ_IMAGE=2138 ALLOWED_GATED_READ_IMAGE=29 FLOAT16=0 GPU=1 IMAGE=2 python examples/openpilot/compile3.py https://github.com/commaai/openpilot/raw/v0.9.4/selfdrive/modeld/models/supercombo.onnx
- name: Test openpilot alt model correctness (float32)
run: PYTHONPATH="." FLOAT16=0 DEBUGCL=1 GPU=1 IMAGE=2 python examples/openpilot/compile3.py https://github.com/commaai/openpilot/raw/3799fe46b3a629e491d4b8498b8ae83e4c88c304/selfdrive/modeld/models/supercombo.onnx
- name: Test openpilot fastvits model correctness (float32)
run: PYTHONPATH="." FLOAT16=0 DEBUGCL=1 GPU=1 IMAGE=2 python examples/openpilot/compile3.py https://github.com/commaai/openpilot/raw/9118973ed03c1ae1d40cf69a29507ec2cc78efd7/selfdrive/modeld/models/supercombo.onnx
- name: Test openpilot LLVM compile
run: PYTHONPATH="." LLVM=1 LLVMOPT=1 JIT=2 BEAM=0 IMAGE=0 python examples/openpilot/compile3.py https://github.com/commaai/openpilot/raw/9118973ed03c1ae1d40cf69a29507ec2cc78efd7/selfdrive/modeld/models/supercombo.onnx
- name: Run process replay tests
uses: ./.github/actions/process-replay
@@ -341,6 +450,8 @@ jobs:
name: 'ONNX+Optimization Tests'
runs-on: ubuntu-22.04
timeout-minutes: 20
env:
IGNORE_OOB: 0
steps:
- name: Checkout Code
@@ -359,11 +470,15 @@ jobs:
run: CPU=1 python -m pytest -n=auto test/external/external_test_onnx_backend.py --durations=20
- name: Test ONNX (LLVM)
run: LLVM=1 python -m pytest -n=auto test/external/external_test_onnx_backend.py --durations=20
- name: Run CLOUD=1 Test
- name: Test Additional ONNX Ops (CPU)
run: CPU=1 PYTHONPATH=. python3 test/external/external_test_onnx_ops.py
- name: Test Quantize ONNX
run: CPU=1 PYTHONPATH=. python3 test/test_quantize_onnx.py
- name: Run REMOTE=1 Test
run: |
CLOUDDEV=CPU CLOUD=1 python3 test/test_tiny.py
CLOUDDEV=GPU CLOUD=1 python3 test/test_tiny.py
CLOUDDEV=GPU IMAGE=2 CLOUD=1 python3 test/test_tiny.py
REMOTEDEV=CPU REMOTE=1 python3 -m pytest test/test_tiny.py test/test_jit.py test/test_multitensor.py
REMOTEDEV=GPU REMOTE=1 python3 -m pytest test/test_tiny.py test/test_image_dtype.py test/test_jit.py
REMOTEDEV=GPU IMAGE=2 REMOTE=1 python3 -m pytest test/test_tiny.py test/test_image_dtype.py
- name: Test Optimization Helpers
run: PYTHONPATH="." DEBUG=1 python3 extra/optimization/test_helpers.py
- name: Test Action Space
@@ -381,6 +496,8 @@ jobs:
name: Models (llvm+cpu+gpu)
runs-on: ubuntu-22.04
timeout-minutes: 10
env:
IGNORE_OOB: 0
steps:
- name: Checkout Code
uses: actions/checkout@v4
@@ -403,7 +520,9 @@ jobs:
testdsp:
name: Linux (DSP)
runs-on: ubuntu-24.04
timeout-minutes: 10
timeout-minutes: 15
env:
IGNORE_OOB: 0
steps:
- name: Checkout Code
uses: actions/checkout@v4
@@ -412,7 +531,7 @@ jobs:
with:
key: dsp-minimal
deps: testing_minimal
pydeps: "onnx==1.16.0 onnxruntime"
pydeps: "onnx==1.17.0 onnxruntime pillow"
llvm: "true"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
@@ -427,10 +546,14 @@ jobs:
cache-to: type=gha,mode=min
- name: Run test_tiny on DSP
run: DEBUG=2 DSP=1 python test/test_tiny.py
- name: Test transcendentals
run: CC=clang-19 PYTHONPATH="." DEBUG=2 DSP=1 python test/test_transcendental.py TestTranscendentalVectorized
- name: Test quantize onnx
run: PYTHONPATH="." DEBUG=2 DSP=1 python3 test/test_quantize_onnx.py
- name: Test LLVM=1 DEVECTORIZE=0
run: LLVM=1 DEVECTORIZE=0 python3 -m pytest -n auto test/test_tiny.py test/test_ops.py -k "not test_avg_pool3d_failure"
- name: Test LLVM=1 DEVECTORIZE=0 for model
run: PYTHONPATH="." LLVM=1 DEVECTORIZE=0 python3 test/models/test_efficientnet.py
- name: Test CPU=1 DEVECTORIZE=0
run: CPU=1 DEVECTORIZE=0 python3 -m pytest -n auto test/test_tiny.py test/test_ops.py -k "not test_avg_pool3d_failure"
@@ -460,11 +583,50 @@ jobs:
- name: Run process replay tests
uses: ./.github/actions/process-replay
tests:
testamd:
strategy:
fail-fast: false
matrix:
backend: [llvm, cpu, gpu, ptx, amd, nv] #, triton]
backend: [amd, amdllvm]
name: Linux (${{ matrix.backend }})
runs-on: ubuntu-22.04
timeout-minutes: 20
env:
IGNORE_OOB: 0
AMD: 1
MOCKGPU: 1
FORWARD_ONLY: 1
AMD_LLVM: ${{ matrix.backend == 'amdllvm' && '1' || matrix.backend != 'amdllvm' && '0' }}
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup Environment
uses: ./.github/actions/setup-tinygrad
with:
key: ${{ matrix.backend }}-minimal
deps: testing_minimal
amd: 'true'
llvm: ${{ matrix.backend == 'amdllvm' && 'true' }}
- name: Check Device.DEFAULT and print some source
run: |
PYTHONPATH=${{ github.workspace }} python3 -c "from tinygrad import Device; assert Device.DEFAULT in ['AMD'], Device.DEFAULT"
DEBUG=5 PYTHONPATH=${{ github.workspace }} FORWARD_ONLY=1 python3 test/test_ops.py TestOps.test_add
- name: Run LLVM test
if: matrix.backend=='amdllvm'
run: PYTHONPATH="." python test/test_amd_llvm.py
- name: Run pytest (amd)
run: python -m pytest -n=auto test/test_ops.py test/test_dtype.py test/test_dtype_alu.py test/test_linearizer.py test/test_randomness.py test/imported/test_indexing.py test/test_hcq.py test/external/external_test_am.py --durations=20
- name: Run TRANSCENDENTAL math
run: TRANSCENDENTAL=2 python -m pytest -n=auto test/test_ops.py::TestOps::test_sin test/test_ops.py::TestOps::test_cos test/test_ops.py::TestOps::test_tan test/test_ops.py::TestOps::test_exp test/test_ops.py::TestOps::test_log --durations=20
- name: Run process replay tests
uses: ./.github/actions/process-replay
testnvidia:
strategy:
fail-fast: false
matrix:
backend: [ptx, nv]
name: Linux (${{ matrix.backend }})
runs-on: ubuntu-22.04
@@ -477,25 +639,49 @@ jobs:
uses: ./.github/actions/setup-tinygrad
with:
key: ${{ matrix.backend }}-minimal
deps: testing_minimal${{matrix.backend=='ptx'&&',cuda'||matrix.backend=='triton'&&',triton'||''}}
opencl: ${{ matrix.backend == 'gpu' && 'true' }}
amd: ${{ matrix.backend == 'amd' && 'true' }}
cuda: ${{ (matrix.backend == 'ptx' || matrix.backend == 'triton' || matrix.backend == 'nv') && 'true' }}
deps: testing_minimal
cuda: 'true'
- name: Set env
run: printf "${{ matrix.backend == 'llvm' && 'LLVM=1' || matrix.backend == 'cpu' && 'CPU=1' || matrix.backend == 'gpu' && 'GPU=1' || matrix.backend == 'PTX' && 'FORWARD_ONLY=1\nJIT=1\nOPT=2\nCUDA=1\nPTX=1\nMOCKGPU=1' || matrix.backend == 'triton' && 'FORWARD_ONLY=1\nJIT=1\nOPT=2\nNV=1\nMOCKGPU=1\nTRITON=1\nTRITON_PTXAS_PATH=/usr/bin/ptxas' || matrix.backend == 'amd' && 'AMD=1\nMOCKGPU=1\nFORWARD_ONLY=1' || matrix.backend == 'nv' && 'NV=1\nMOCKGPU=1\nFORWARD_ONLY=1' }}" >> $GITHUB_ENV
run: printf "${{ matrix.backend == 'PTX' && 'FORWARD_ONLY=1\nJIT=1\nOPT=2\nCUDA=1\nPTX=1\nMOCKGPU=1' || matrix.backend == 'nv' && 'NV=1\nMOCKGPU=1\nFORWARD_ONLY=1' }}" >> $GITHUB_ENV
- name: Check Device.DEFAULT and print some source
run: |
PYTHONPATH=${{ github.workspace }} python3 -c "from tinygrad import Device; assert Device.DEFAULT in ['LLVM','CPU','CUDA','GPU','AMD','NV'], Device.DEFAULT"
PYTHONPATH=${{ github.workspace }} python3 -c "from tinygrad import Device; assert Device.DEFAULT in ['CUDA','NV'], Device.DEFAULT"
DEBUG=5 PYTHONPATH=${{ github.workspace }} FORWARD_ONLY=1 python3 test/test_ops.py TestOps.test_add
- name: Run pytest (not cuda or amd)
if: matrix.backend!='ptx' && matrix.backend!='triton' && matrix.backend != 'amd' && matrix.backend != 'nv'
run: python -m pytest -n=auto test/ --ignore=test/models --ignore=test/unit --durations=20
- name: Run pytest (cuda)
if: matrix.backend=='ptx'||matrix.backend=='triton'||matrix.backend=='nv'
run: python -m pytest -n=auto test/ --ignore=test/models --ignore=test/unit --ignore test/test_gc.py --durations=20
- name: Run pytest (amd)
if: matrix.backend=='amd'
run: python -m pytest -n=auto test/test_ops.py test/test_dtype.py test/test_dtype_alu.py test/test_linearizer.py test/test_randomness.py test/imported/test_indexing.py test/test_hcq.py test/external/external_test_am.py --durations=20
- name: Run process replay tests
uses: ./.github/actions/process-replay
tests:
strategy:
fail-fast: false
matrix:
backend: [llvm, cpu, gpu]
name: Linux (${{ matrix.backend }})
runs-on: ubuntu-22.04
timeout-minutes: 20
env:
IGNORE_OOB: 0
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup Environment
uses: ./.github/actions/setup-tinygrad
with:
key: ${{ matrix.backend }}-minimal
deps: testing_minimal
opencl: ${{ matrix.backend == 'gpu' && 'true' }}
llvm: ${{ matrix.backend == 'llvm' && 'true' }}
- name: Set env
run: printf "${{ matrix.backend == 'llvm' && 'LLVM=1' || matrix.backend == 'cpu' && 'CPU=1' || matrix.backend == 'gpu' && 'GPU=1' }}" >> $GITHUB_ENV
- name: Check Device.DEFAULT and print some source
run: |
PYTHONPATH=${{ github.workspace }} python3 -c "from tinygrad import Device; assert Device.DEFAULT in ['LLVM','CPU','GPU'], Device.DEFAULT"
DEBUG=5 PYTHONPATH=${{ github.workspace }} FORWARD_ONLY=1 python3 test/test_ops.py TestOps.test_add
- name: Run pytest (not cuda)
run: python -m pytest -n=auto test/ --ignore=test/models --ignore=test/unit --durations=20
- name: Run TRANSCENDENTAL math
run: TRANSCENDENTAL=2 python -m pytest -n=auto test/test_ops.py::TestOps::test_sin test/test_ops.py::TestOps::test_cos test/test_ops.py::TestOps::test_tan test/test_ops.py::TestOps::test_exp test/test_ops.py::TestOps::test_log --durations=20
- name: Run process replay tests
@@ -506,7 +692,9 @@ jobs:
testmetal2:
name: MacOS (unit)
runs-on: macos-14
timeout-minutes: 10
timeout-minutes: 20
env:
IGNORE_OOB: 0
steps:
- name: Checkout Code
@@ -519,12 +707,13 @@ jobs:
python-version: '3.11'
amd: 'true'
cuda: 'true'
llvm: 'true'
- name: Run real world test
run: JIT=2 METAL=1 python -m pytest -n=auto test/models/test_real_world.py --durations=20
run: METAL=1 python -m pytest -n=auto test/models/test_real_world.py --durations=20
- name: Test models (Metal)
run: JIT=2 METAL=1 python -m pytest -n=auto test/models --durations=20
run: METAL=1 python -m pytest test/models -v --durations=20
- name: Run ONNX
run: JIT=2 METAL=1 python -m pytest -n=auto test/external/external_test_onnx_backend.py --durations=20
run: METAL=1 python -m pytest -n=auto test/external/external_test_onnx_backend.py --durations=20
- name: Test tensor core ops (fake)
run: TC=2 METAL=1 DEBUG=3 python test/test_ops.py TestOps.test_gemm
- name: Test tensor core ops (real)
@@ -535,8 +724,6 @@ jobs:
run: PYTHONPATH="." METAL=1 IGNORE_BEAM_CACHE=1 python3 -m pytest extra/optimization/test_beam_search.py
- name: Fuzz Test linearizer
run: PYTHONPATH="." METAL=1 DEPTH=4 FUZZ_N=50 FUZZ_MAX_SIZE=1000000 python test/external/fuzz_linearizer.py
# - name: Fuzz Test models schedule
# run: FUZZ_SCHEDULE=1 FUZZ_SCHEDULE_MAX_PATHS=5 python -m pytest test/models/test_train.py test/models/test_end2end.py
- name: Run TRANSCENDENTAL math
run: TRANSCENDENTAL=2 python -m pytest -n=auto test/test_ops.py::TestOps::test_sin test/test_ops.py::TestOps::test_cos test/test_ops.py::TestOps::test_tan test/test_ops.py::TestOps::test_exp test/test_ops.py::TestOps::test_log --durations=20
- name: Run pytest (amd)
@@ -546,6 +733,14 @@ jobs:
FORWARD_ONLY: 1
run: |
python3 -m pytest -n=auto test/test_hcq.py test/test_tiny.py --durations=20
- name: Run pytest (amd with llvm backend)
env:
MOCKGPU: 1
AMD: 1
AMD_LLVM: 1
FORWARD_ONLY: 1
run: |
python -m pytest -n=auto test/test_hcq.py test/test_tiny.py test/test_amd_llvm.py --durations=20
- name: Run pytest (ptx)
env:
MOCKGPU: 1
@@ -568,7 +763,10 @@ jobs:
uses: ./.github/actions/setup-tinygrad
with:
key: osx-webgpu
deps: testing_minimal
webgpu: 'true'
- name: Test infinity math in WGSL
run: WEBGPU=1 python -m pytest -n=auto test/test_renderer_failures.py::TestWGSLFailures::test_multiply_infinity --durations=20
- name: Build WEBGPU Efficientnet
run: WEBGPU=1 WEBGPU_BACKEND="WGPUBackendType_Metal" python3 -m examples.compile_efficientnet
- name: Clean npm cache
@@ -578,6 +776,30 @@ jobs:
- name: Run WEBGPU Efficientnet
run: node test/web/test_webgpu.js
osxremote:
name: MacOS (remote)
runs-on: macos-15
timeout-minutes: 10
env:
REMOTE: 1
REMOTEDEV: METAL
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup Environment
uses: ./.github/actions/setup-tinygrad
with:
key: macos-remote
deps: testing_minimal
- name: Check Device.DEFAULT and print some source
run: |
python -c "from tinygrad import Device; assert Device.DEFAULT == 'REMOTE', Device.DEFAULT"
python -c "from tinygrad import Device; assert Device.default.properties.real_device == 'METAL', Device.default.properties.real_device"
DEBUG=4 python3 test/test_tiny.py TestTiny.test_plus
- name: Run REMOTE=1 Test
run: |
python3 -m pytest test/test_tiny.py test/test_jit.py test/test_multitensor.py
osxtests:
strategy:
fail-fast: false
@@ -585,7 +807,9 @@ jobs:
backend: [metal, llvm, cpu]
name: MacOS (${{ matrix.backend }})
runs-on: macos-15
timeout-minutes: 10
timeout-minutes: 20
env:
IGNORE_OOB: 0
steps:
- name: Checkout Code
uses: actions/checkout@v4
@@ -596,7 +820,7 @@ jobs:
deps: testing_minimal
llvm: ${{ matrix.backend == 'llvm' && 'true' }}
- name: Set env
run: printf "${{ matrix.backend == 'llvm' && 'LLVM=1' || matrix.backend == 'cpu' && 'CPU=1' || matrix.backend == 'metal' && 'METAL=1\nJIT=2'}}" >> $GITHUB_ENV
run: printf "${{ matrix.backend == 'llvm' && 'LLVM=1' || matrix.backend == 'cpu' && 'CPU=1' || matrix.backend == 'metal' && 'METAL=1'}}" >> $GITHUB_ENV
- name: Check Device.DEFAULT and print some source
run: |
python -c "from tinygrad import Device; assert Device.DEFAULT == '${{ matrix.backend }}'.upper(), Device.DEFAULT"
@@ -605,6 +829,9 @@ jobs:
run: python3 -m pytest -n=auto test/ --ignore=test/models --ignore=test/unit --durations=20
- name: Run process replay tests
uses: ./.github/actions/process-replay
- name: Run macOS-specific unit test
if: matrix.backend == 'cpu'
run: python3 -m pytest test/unit/test_disk_tensor.py::TestDiskTensor::test_copy_to_cpu_not_truncated
# ****** Windows Tests ******
@@ -616,7 +843,9 @@ jobs:
name: Windows (${{ matrix.backend }})
runs-on: windows-latest
timeout-minutes: 10
timeout-minutes: 15
env:
IGNORE_OOB: 0
steps:
- name: Checkout Code
uses: actions/checkout@v4
+6 -1
View File
@@ -10,6 +10,7 @@ notebooks
*.so
*.txt
build
!examples/tinychat/assets/cdn.jsdelivr.net/npm/[email protected]/build/
/dist
*.egg-info
/env
@@ -33,6 +34,8 @@ extra/datasets/open-images-v6-mlperf
extra/datasets/kits/
extra/datasets/COCO/
extra/datasets/audio*
extra/huggingface_onnx/models/*
extra/huggingface_onnx/*.yaml
extra/weights
venv
examples/**/net.*[js,json]
@@ -55,5 +58,7 @@ weights
comgr_*
*.pkl
site/
master_schedule.py
profile_stats
*.log
target
.mypy_cache
+208 -28
View File
@@ -35,7 +35,7 @@ def _try_dlopen_$name():
for candidate in PATHS_TO_TRY:
try: return ctypes.CDLL(candidate)
except OSError: pass
raise RuntimeError("library $name not found")
return None
EOF
}
@@ -78,11 +78,11 @@ generate_kfd() {
clang2py /usr/include/linux/kfd_ioctl.h -o $BASE/kfd.py -k cdefstum
fixup $BASE/kfd.py
sed -i "s\import ctypes\import ctypes, os\g" $BASE/kfd.py
sed -i "s\import fcntl, functools\import functools" $BASE/kfd.py
sed -i "s\import ctypes,os\a from tinygrad.runtime.support import HWInterface\g" $BASE/kfd.py
sed -i "s\def _do_ioctl(__idir, __base, __nr, __user_struct, __fd, **kwargs):\def _do_ioctl(__idir, __base, __nr, __user_struct, __fd:HWInterface, **kwargs):\g" $BASE/kfd.py
sed -i "s\fcntl.ioctl(__fd, (__idir<<30)\__fd.ioctl((__idir<<30)\g" $BASE/kfd.py
sed -i "s/import ctypes/import ctypes, os/g" $BASE/kfd.py
sed -i "s/import fcntl, functools/import functools/g" $BASE/kfd.py
sed -i "/import functools/a from tinygrad.runtime.support.hcq import FileIOInterface" $BASE/kfd.py
sed -i "s/def _do_ioctl(__idir, __base, __nr, __user_struct, __fd, \*\*kwargs):/def _do_ioctl(__idir, __base, __nr, __user_struct, __fd:FileIOInterface, \*\*kwargs):/g" $BASE/kfd.py
sed -i "s/fcntl.ioctl(__fd, (__idir<<30)/__fd.ioctl((__idir<<30)/g" $BASE/kfd.py
python3 -c "import tinygrad.runtime.autogen.kfd"
}
@@ -171,6 +171,7 @@ generate_amd() {
extra/hip_gpu_driver/sdma_v6_0_0_pkt_open.h \
extra/hip_gpu_driver/gc_11_0_0_offset.h \
extra/hip_gpu_driver/gc_10_3_0_offset.h \
extra/hip_gpu_driver/sienna_cichlid_ip_offset.h \
--clang-args="-I/opt/rocm/include -x c++" \
-o $BASE/amd_gpu.py
@@ -286,83 +287,260 @@ generate_vfio() {
fixup $BASE/vfio.py
sed -i "s\import ctypes\import ctypes, os\g" $BASE/vfio.py
sed -i "s\import fcntl, functools\import functools" $BASE/vfio.py
sed -i "s\import ctypes,os\a from tinygrad.runtime.support import HWInterface\g" $BASE/vfio.py
sed -i "s\import ctypes,os\a from tinygrad.runtime.support import FileIOInterface\g" $BASE/vfio.py
sed -i "s\fcntl.ioctl(__fd, (__idir<<30)\return __fd.ioctl((__idir<<30)\g" $BASE/vfio.py
}
generate_am() {
AMKERN_COMMIT_HASH=ceb12c04e2b5b53ec0779362831f5ee40c4921e4
AMKERN_SRC=/tmp/ROCK-Kernel-Driver-$AMKERN_COMMIT_HASH
if [ ! -d "$AMKERN_SRC" ]; then
git clone https://github.com/ROCm/ROCK-Kernel-Driver $AMKERN_SRC --depth 1
fi
AMKERN_AMD=$AMKERN_SRC/drivers/gpu/drm/amd/
AMKERN_INC=$AMKERN_AMD/include/
clang2py -k cdefstum \
extra/amdpci/headers/v11_structs.h \
extra/amdpci/headers/v12_structs.h \
extra/amdpci/headers/amdgpu_vm.h \
extra/amdpci/headers/discovery.h \
extra/amdpci/headers/amdgpu_ucode.h \
extra/amdpci/headers/soc21_enum.h \
extra/amdpci/headers/psp_gfx_if.h \
extra/amdpci/headers/amdgpu_psp.h \
extra/amdpci/headers/amdgpu_irq.h \
extra/amdpci/headers/amdgpu_doorbell.h \
extra/amdpci/headers/soc15_ih_clientid.h \
$AMKERN_INC/soc15_ih_clientid.h \
--clang-args="-include stdint.h" \
-o $BASE/am/am.py
fixup $BASE/am/am.py
sed -i "s\(int64_t)\ \g" $BASE/am/am.py
sed -i "s\AMDGPU_PTE_MTYPE_VG10(2)\AMDGPU_PTE_MTYPE_VG10(0, 2)\g" $BASE/am/am.py # incorrect parsing (TODO: remove when clang2py is gone).
clang2py -k cdefstum \
extra/amdpci/headers/mp_13_0_0_offset.h \
extra/amdpci/headers/mp_13_0_0_sh_mask.h \
$AMKERN_AMD/amdkfd/kfd_pm4_headers_ai.h \
$AMKERN_AMD/amdgpu/soc15d.h \
-o $BASE/am/pm4_soc15.py
fixup $BASE/am/pm4_soc15.py
clang2py -k cdefstum \
$AMKERN_AMD/amdkfd/kfd_pm4_headers_ai.h \
$AMKERN_AMD/amdgpu/nvd.h \
-o $BASE/am/pm4_nv.py
fixup $BASE/am/pm4_nv.py
clang2py -k cdefstum \
$AMKERN_INC/vega10_enum.h \
-o $BASE/am/vega10.py
fixup $BASE/am/vega10.py
clang2py -k cdefstum \
$AMKERN_INC/navi10_enum.h \
-o $BASE/am/navi10.py
fixup $BASE/am/navi10.py
clang2py -k cdefstum \
$AMKERN_INC/soc21_enum.h \
-o $BASE/am/soc21.py
fixup $BASE/am/soc21.py
clang2py -k cdefstum \
$AMKERN_INC/soc24_enum.h \
-o $BASE/am/soc24.py
fixup $BASE/am/soc24.py
clang2py -k cdefstum \
$AMKERN_INC/asic_reg/mp/mp_13_0_0_offset.h \
$AMKERN_INC/asic_reg/mp/mp_13_0_0_sh_mask.h \
-o $BASE/am/mp_13_0_0.py
fixup $BASE/am/mp_13_0_0.py
# 14_0_3 reuses 14_0_2
clang2py -k cdefstum \
extra/amdpci/headers/mp_11_0_offset.h \
extra/amdpci/headers/mp_11_0_sh_mask.h \
$AMKERN_INC/asic_reg/mp/mp_14_0_2_offset.h \
$AMKERN_INC/asic_reg/mp/mp_14_0_2_sh_mask.h \
-o $BASE/am/mp_14_0_3.py
fixup $BASE/am/mp_14_0_3.py
clang2py -k cdefstum \
$AMKERN_INC/asic_reg/mp/mp_11_0_offset.h \
$AMKERN_INC/asic_reg/mp/mp_11_0_sh_mask.h \
-o $BASE/am/mp_11_0.py
fixup $BASE/am/mp_11_0.py
clang2py -k cdefstum \
extra/amdpci/headers/gc_11_0_0_offset.h \
extra/amdpci/headers/gc_11_0_0_sh_mask.h \
$AMKERN_INC/asic_reg/gc/gc_9_4_3_offset.h \
$AMKERN_INC/asic_reg/gc/gc_9_4_3_sh_mask.h \
extra/amdpci/overlay/gc_9_4_3.h \
-o $BASE/am/gc_9_4_3.py
fixup $BASE/am/gc_9_4_3.py
clang2py -k cdefstum \
$AMKERN_INC/asic_reg/gc/gc_10_3_0_offset.h \
$AMKERN_INC/asic_reg/gc/gc_10_3_0_sh_mask.h \
-o $BASE/am/gc_10_3_0.py
fixup $BASE/am/gc_10_3_0.py
clang2py -k cdefstum \
$AMKERN_INC/asic_reg/gc/gc_11_0_0_offset.h \
$AMKERN_INC/asic_reg/gc/gc_11_0_0_sh_mask.h \
-o $BASE/am/gc_11_0_0.py
fixup $BASE/am/gc_11_0_0.py
clang2py -k cdefstum \
extra/amdpci/headers/mmhub_3_0_0_offset.h \
extra/amdpci/headers/mmhub_3_0_0_sh_mask.h \
$AMKERN_INC/asic_reg/gc/gc_12_0_0_offset.h \
$AMKERN_INC/asic_reg/gc/gc_12_0_0_sh_mask.h \
-o $BASE/am/gc_12_0_0.py
fixup $BASE/am/gc_12_0_0.py
clang2py -k cdefstum \
extra/hip_gpu_driver/sdma_registers.h \
$AMKERN_AMD/amdgpu/vega10_sdma_pkt_open.h \
--clang-args="-I/opt/rocm/include -x c++" \
-o $BASE/am/sdma_4_0_0.py
fixup $BASE/am/sdma_4_0_0.py
clang2py -k cdefstum \
extra/hip_gpu_driver/sdma_registers.h \
$AMKERN_AMD/amdgpu/navi10_sdma_pkt_open.h \
--clang-args="-I/opt/rocm/include -x c++" \
-o $BASE/am/sdma_5_0_0.py
fixup $BASE/am/sdma_5_0_0.py
clang2py -k cdefstum \
extra/hip_gpu_driver/sdma_registers.h \
$AMKERN_AMD/amdgpu/sdma_v6_0_0_pkt_open.h \
--clang-args="-I/opt/rocm/include -x c++" \
-o $BASE/am/sdma_6_0_0.py
fixup $BASE/am/sdma_6_0_0.py
clang2py -k cdefstum \
$AMKERN_INC/asic_reg/mmhub/mmhub_3_0_0_offset.h \
$AMKERN_INC/asic_reg/mmhub/mmhub_3_0_0_sh_mask.h \
-o $BASE/am/mmhub_3_0_0.py
fixup $BASE/am/mmhub_3_0_0.py
clang2py -k cdefstum \
extra/amdpci/headers/mmhub_3_0_2_offset.h \
extra/amdpci/headers/mmhub_3_0_2_sh_mask.h \
$AMKERN_INC/asic_reg/mmhub/mmhub_3_0_2_offset.h \
$AMKERN_INC/asic_reg/mmhub/mmhub_3_0_2_sh_mask.h \
-o $BASE/am/mmhub_3_0_2.py
fixup $BASE/am/mmhub_3_0_2.py
clang2py -k cdefstum \
extra/amdpci/headers/nbio_4_3_0_offset.h \
extra/amdpci/headers/nbio_4_3_0_sh_mask.h \
$AMKERN_INC/asic_reg/nbio/nbio_2_3_offset.h \
$AMKERN_INC/asic_reg/nbio/nbio_2_3_sh_mask.h \
-o $BASE/am/nbio_2_3_0.py
fixup $BASE/am/nbio_2_3_0.py
clang2py -k cdefstum \
$AMKERN_INC/asic_reg/nbio/nbio_7_2_0_offset.h \
$AMKERN_INC/asic_reg/nbio/nbio_7_2_0_sh_mask.h \
-o $BASE/am/nbio_7_2_0.py
fixup $BASE/am/nbio_7_2_0.py
clang2py -k cdefstum \
$AMKERN_INC/asic_reg/mmhub/mmhub_4_1_0_offset.h \
$AMKERN_INC/asic_reg/mmhub/mmhub_4_1_0_sh_mask.h \
-o $BASE/am/mmhub_4_1_0.py
fixup $BASE/am/mmhub_4_1_0.py
clang2py -k cdefstum \
$AMKERN_INC/asic_reg/nbio/nbio_4_3_0_offset.h \
$AMKERN_INC/asic_reg/nbio/nbio_4_3_0_sh_mask.h \
-o $BASE/am/nbio_4_3_0.py
fixup $BASE/am/nbio_4_3_0.py
clang2py -k cdefstum \
extra/amdpci/headers/osssys_6_0_0_offset.h \
extra/amdpci/headers/osssys_6_0_0_sh_mask.h \
$AMKERN_INC/asic_reg/nbif/nbif_6_3_1_offset.h \
$AMKERN_INC/asic_reg/nbif/nbif_6_3_1_sh_mask.h \
-o $BASE/am/nbif_6_3_1.py
fixup $BASE/am/nbif_6_3_1.py
clang2py -k cdefstum \
$AMKERN_INC/asic_reg/nbio/nbio_7_9_0_offset.h \
$AMKERN_INC/asic_reg/nbio/nbio_7_9_0_sh_mask.h \
-o $BASE/am/nbio_7_9_0.py
fixup $BASE/am/nbio_7_9_0.py
clang2py -k cdefstum \
$AMKERN_INC/asic_reg/nbio/nbio_7_11_0_offset.h \
$AMKERN_INC/asic_reg/nbio/nbio_7_11_0_sh_mask.h \
-o $BASE/am/nbio_7_11_0.py
fixup $BASE/am/nbio_7_11_0.py
clang2py -k cdefstum \
$AMKERN_INC/asic_reg/oss/osssys_6_0_0_offset.h \
$AMKERN_INC/asic_reg/oss/osssys_6_0_0_sh_mask.h \
-o $BASE/am/osssys_6_0_0.py
fixup $BASE/am/osssys_6_0_0.py
clang2py -k cdefstum \
extra/amdpci/headers/smu_v13_0_0_ppsmc.h \
extra/amdpci/headers/smu13_driver_if_v13_0_0.h \
$AMKERN_INC/asic_reg/oss/osssys_7_0_0_offset.h \
$AMKERN_INC/asic_reg/oss/osssys_7_0_0_sh_mask.h \
-o $BASE/am/osssys_7_0_0.py
fixup $BASE/am/osssys_7_0_0.py
clang2py -k cdefstum \
$AMKERN_AMD/pm/swsmu/inc/pmfw_if/smu_v13_0_0_ppsmc.h \
$AMKERN_AMD/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h \
extra/amdpci/headers/amdgpu_smu.h \
-o $BASE/am/smu_v13_0_0.py
fixup $BASE/am/smu_v13_0_0.py
clang2py -k cdefstum \
$AMKERN_AMD/pm/swsmu/inc/pmfw_if/smu_v14_0_0_pmfw.h \
$AMKERN_AMD/pm/swsmu/inc/pmfw_if/smu_v14_0_2_ppsmc.h \
$AMKERN_AMD/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0.h \
extra/amdpci/headers/amdgpu_smu.h \
--clang-args="-include stdint.h" \
-o $BASE/am/smu_v14_0_3.py
fixup $BASE/am/smu_v14_0_3.py
clang2py -k cdefstum \
$AMKERN_INC/asic_reg/hdp/hdp_6_0_0_offset.h \
$AMKERN_INC/asic_reg/hdp/hdp_6_0_0_sh_mask.h \
-o $BASE/am/hdp_6_0_0.py
fixup $BASE/am/hdp_6_0_0.py
clang2py -k cdefstum \
$AMKERN_INC/asic_reg/hdp/hdp_7_0_0_offset.h \
$AMKERN_INC/asic_reg/hdp/hdp_7_0_0_sh_mask.h \
-o $BASE/am/hdp_7_0_0.py
fixup $BASE/am/hdp_7_0_0.py
}
generate_sqtt() {
clang2py -k cdefstum \
extra/sqtt/sqtt.h \
-o $BASE/sqtt.py
fixup $BASE/sqtt.py
sed -i "s\import ctypes\import ctypes, os\g" $BASE/sqtt.py
python3 -c "import tinygrad.runtime.autogen.sqtt"
}
generate_webgpu() {
clang2py -l /usr/local/lib/libwebgpu_dawn.so extra/webgpu/webgpu.h -o $BASE/webgpu.py
clang2py extra/webgpu/webgpu.h -o $BASE/webgpu.py
fixup $BASE/webgpu.py
sed -i 's/import ctypes/import ctypes, ctypes.util/g' $BASE/webgpu.py
sed -i "s|ctypes.CDLL('/usr/local/lib/libwebgpu_dawn.so')|ctypes.CDLL(ctypes.util.find_library('webgpu_dawn'))|g" $BASE/webgpu.py
sed -i "s/FIXME_STUB/webgpu/g" "$BASE/webgpu.py"
sed -i "s/FunctionFactoryStub()/ctypes.CDLL(webgpu_support.WEBGPU_PATH)/g" "$BASE/webgpu.py"
sed -i "s/import ctypes/import ctypes, tinygrad.runtime.support.webgpu as webgpu_support/g" "$BASE/webgpu.py"
python3 -c "import tinygrad.runtime.autogen.webgpu"
}
generate_libusb() {
clang2py -k cdefstum \
/usr/include/libusb-1.0/libusb.h \
-o $BASE/libusb.py
fixup $BASE/libusb.py
sed -i "s\import ctypes\import ctypes, os\g" $BASE/libusb.py
sed -i "s/FIXME_STUB/libusb/g" "$BASE/libusb.py"
sed -i "s/libusb_le16_to_cpu = libusb_cpu_to_le16//g" "$BASE/libusb.py"
sed -i "s/FunctionFactoryStub()/None if (lib_path:=os.getenv('LIBUSB_PATH', ctypes.util.find_library('usb-1.0'))) is None else ctypes.CDLL(lib_path)/g" "$BASE/libusb.py"
python3 -c "import tinygrad.runtime.autogen.libusb"
}
if [ "$1" == "opencl" ]; then generate_opencl
elif [ "$1" == "hip" ]; then generate_hip
elif [ "$1" == "comgr" ]; then generate_comgr
@@ -373,6 +551,7 @@ elif [ "$1" == "kfd" ]; then generate_kfd
elif [ "$1" == "nv" ]; then generate_nv
elif [ "$1" == "amd" ]; then generate_amd
elif [ "$1" == "am" ]; then generate_am
elif [ "$1" == "sqtt" ]; then generate_sqtt
elif [ "$1" == "qcom" ]; then generate_qcom
elif [ "$1" == "io_uring" ]; then generate_io_uring
elif [ "$1" == "libc" ]; then generate_libc
@@ -382,6 +561,7 @@ elif [ "$1" == "adreno" ]; then generate_adreno
elif [ "$1" == "pci" ]; then generate_pci
elif [ "$1" == "vfio" ]; then generate_vfio
elif [ "$1" == "webgpu" ]; then generate_webgpu
elif [ "$1" == "libusb" ]; then generate_libusb
elif [ "$1" == "all" ]; then generate_opencl; generate_hip; generate_comgr; generate_cuda; generate_nvrtc; generate_hsa; generate_kfd; generate_nv; generate_amd; generate_io_uring; generate_libc; generate_am; generate_webgpu
else echo "usage: $0 <type>"
fi
+27 -10
View File
@@ -1,7 +1,7 @@
# tinygrad is a tensor library, and as a tensor library it has multiple parts
# 1. a "runtime". this allows buffer management, compilation, and running programs
# 2. a "Device" that uses the runtime but specifies compute in an abstract way for all
# 3. a "LazyBuffer" that fuses the compute into kernels, using memory only when needed
# 3. a "UOp" that fuses the compute into kernels, using memory only when needed
# 4. a "Tensor" that provides an easy to use frontend with autograd ".backward()"
@@ -74,30 +74,47 @@ fxn.exec([out, a, b])
assert out.as_buffer().cast('I')[0] == 5
print("******** third, the LazyBuffer ***********")
print("******** third, the UOp ***********")
from tinygrad.engine.realize import run_schedule
from tinygrad.engine.schedule import create_schedule_with_vars
from tinygrad.engine.grouper import get_becomes_map
# allocate some values + load in values
a = UOp.metaop(Ops.EMPTY, (1,), dtypes.int32, DEVICE)
b = UOp.metaop(Ops.EMPTY, (1,), dtypes.int32, DEVICE)
a = UOp.new_buffer(DEVICE, 1, dtypes.int32)
b = UOp.new_buffer(DEVICE, 1, dtypes.int32)
a.buffer.allocate().copyin(memoryview(bytearray(struct.pack("I", 2))))
b.buffer.allocate().copyin(memoryview(bytearray(struct.pack("I", 3))))
# describe the computation
out = a.alu(Ops.ADD, b)
out = a + b
s = UOp(Ops.SINK, dtypes.void, (out,))
# schedule the computation as a list of kernels
sched, _, becomes_map = create_schedule_with_vars(out.sink())
for si in sched: print(si.ast.op) # NOTE: the first two convert it to CPU
# NOTE: UOps are no longer mutable, the scheduler gives you a map to lookup which BUFFER the result was written to
out = becomes_map[out]
# group the computation into kernels
becomes_map = get_becomes_map(s)
# the compute maps to an assign
assign = becomes_map[a+b]
# the first source is the output buffer (data)
assert assign.src[0].op is Ops.BUFFER
# the second source is the kernel (compute)
assert assign.src[1].op is Ops.KERNEL
# schedule the kernel graph in a linear list
s = UOp(Ops.SINK, dtypes.void, (assign,))
sched, _, becomes_map = create_schedule_with_vars(s)
assert len(sched) == 1
# DEBUGGING: print the compute ast
print(sched[-1].ast)
# NOTE: sched[-1].ast is the same as st_0 above
# the output will be stored in a new buffer
out = becomes_map[assign]
assert out.op is Ops.BUFFER and not out.buffer.is_allocated()
print(out)
# run that schedule
run_schedule(sched)
+1 -1
View File
@@ -1,6 +1,6 @@
# AM Driver
AM driver is a userspace driver targeting AMD's 7900XTX. You only need tinygrad to send compute tasks to your GPU!
AM driver is a userspace driver targeting AMD's RDNA3/RDNA4. You only need tinygrad to send compute tasks to your GPU!
## How to run?
Make sure that amdgpu module is unloaded and just run tinygrad with `AMD=1`!
+1 -2
View File
@@ -115,9 +115,8 @@ HCQ-compatible devices use a global timeline signal for synchronizing all operat
```python
HWQueue().wait(your_device.timeline_signal, your_device.timeline_value - 1) \
.exec(...)
.signal(your_device.timeline_signal, your_device.timeline_value) \
.signal(your_device.timeline_signal, your_device.next_timeline()) \
.submit(your_device)
your_device.timeline_value += 1
# Optionally wait for execution
your_device.timeline_signal.wait(your_device.timeline_value - 1)
+109
View File
@@ -0,0 +1,109 @@
# Kernel Creation
Tinygrad lazily builds up a graph of Tensor operations. The Tensor graph includes a mix of:
- Buffer and Assignment Ops: `BUFFER`, `BUFFER_VIEW`, `COPY`, `ASSIGN`
- Movement Ops: `RESHAPE`, `EXPAND`, `PERMUTE`, `PAD`, `SHRINK`, `FLIP`
- Compute Ops: `ADD`, `MUL`, `REDUCE_AXIS`, ...
`Tensor.kernelize` creates the kernels and buffers needed to realize the output Tensor(s).
## Kernelize flow
Let's see how a multiply add Tensor graph becomes a fused elementwise kernel.
```py
# initialize 3 input buffers on the device
a = Tensor([1]).realize()
b = Tensor([2]).realize()
c = Tensor([3]).realize()
# create the Tensor graph
mul = a*b
out = mul+c
print(mul) # <Tensor <UOp METAL (1,) int (<Ops.MUL: 48>, None)> on METAL with grad None>
print(out) # <Tensor <UOp METAL (1,) int (<Ops.ADD: 52>, None)> on METAL with grad None>
out.kernelize()
print(mul) # <Tensor <UOp METAL (1,) int (<Ops.MUL: 48>, None)> on METAL with grad None>
print(out) # <Tensor <UOp METAL (1,) int (<Ops.ASSIGN: 66>, None)> on METAL with grad None>
```
The multiply Tensor stays the same because it is fused. The output Tensor's UOp becomes a new ASSIGN UOp:
```py
print(out.lazydata)
```
The first source is the output BUFFER:
```
UOp(Ops.BUFFER, dtypes.int, arg=1, src=(
UOp(Ops.DEVICE, dtypes.void, arg='METAL', src=()),
UOp(Ops.UNIQUE, dtypes.void, arg=6, src=()),))
```
And the second source is the KERNEL and its 4 buffer edges (output_buffer, a, b, c):
```
UOp(Ops.KERNEL, dtypes.void, arg=<Kernel 12 SINK(<Ops.STORE: 45>,) (__add__, __mul__)>, src=(
UOp(Ops.BUFFER, dtypes.int, arg=1, src=(
x1:=UOp(Ops.DEVICE, dtypes.void, arg='METAL', src=()),
UOp(Ops.UNIQUE, dtypes.void, arg=6, src=()),)),
UOp(Ops.BUFFER, dtypes.int, arg=1, src=(
x1,
UOp(Ops.UNIQUE, dtypes.void, arg=1, src=()),)),
UOp(Ops.BUFFER, dtypes.int, arg=1, src=(
x1,
UOp(Ops.UNIQUE, dtypes.void, arg=3, src=()),)),
UOp(Ops.BUFFER, dtypes.int, arg=1, src=(
x1,
UOp(Ops.UNIQUE, dtypes.void, arg=5, src=()),)),))
```
KERNEL describes the compute AST, metadata and memory dependencies.
BUFFER holds a reference to the device memory where the output will be stored.
Once a Tensor is kernelized, all children will LOAD its BUFFER, instead of fusing it:
```py
child = out+2
child.kernelize()
print(child.lazydata.src[1].arg.ast)
```
```
UOp(Ops.SINK, dtypes.void, arg=None, src=(
UOp(Ops.STORE, dtypes.void, arg=None, src=(
UOp(Ops.DEFINE_GLOBAL, dtypes.int.ptr(1), arg=0, src=()),
x2:=UOp(Ops.VIEW, dtypes.void, arg=ShapeTracker(views=(View(shape=(1,), strides=(0,), offset=0, mask=None, contiguous=True),)), src=()),
UOp(Ops.ADD, dtypes.int, arg=None, src=(
UOp(Ops.LOAD, dtypes.int, arg=None, src=(
UOp(Ops.DEFINE_GLOBAL, dtypes.int.ptr(1), arg=1, src=()),
x2,)),
UOp(Ops.CONST, dtypes.int, arg=2, src=(
x2,)),)),)),))
```
`Tensor.realize` will execute the kernels and write outputs to memory:
```py
Tensor.realize(out)
print(out) # <Tensor <UOp METAL (1,) int (<Ops.BUFFER: 23>, <buf real:True device:METAL size:1 dtype:dtypes.int offset:0>)> on METAL with grad None>
print(out.item()) # 5
```
<hr />
**Summary**
- The large Tensor graph is built from a mix of data, compute and movement Ops.
- `Tensor.kernelize` splits the Tensor graph into data (BUFFER), compute (KERNEL) and links dependencies with ASSIGN.
- `Tensor.realize` executes KERNELs on device and replaces the Tensor graph with just a BUFFER.
- Kernelize can be called multiple times on a Tensor. This allows for incrementally building the kernel fusion layout of a large Tensor graph, without having to call `realize` or `schedule`.
+15 -2
View File
@@ -30,7 +30,7 @@ These control the behavior of core tinygrad even when used as a library.
Variable | Possible Value(s) | Description
---|---|---
DEBUG | [1-6] | enable debugging output, with 4 you get operations, timings, speed, generated code and more
DEBUG | [1-7] | enable debugging output (operations, timings, speed, generated code and more)
GPU | [1] | enable the GPU (OpenCL) backend
CUDA | [1] | enable CUDA backend
AMD | [1] | enable AMD backend
@@ -49,4 +49,17 @@ VISIBLE_DEVICES | [list[int]]| restricts the NV/AMD devices that are availab
JIT | [0-2] | 0=disabled, 1=[jit enabled](quickstart.md#jit) (default), 2=jit enabled, but graphs are disabled
VIZ | [1] | 0=disabled, 1=[viz enabled](https://github.com/tinygrad/tinygrad/tree/master/tinygrad/viz)
ALLOW_TF32 | [1] | enable TensorFloat-32 tensor cores on Ampere or newer GPUs.
WEBGPU_BACKEND | [WGPUBackendType_Metal, ...] | Force select a backend for WebGPU (Metal, DirectX, OpenGL, Vulkan...)
WEBGPU_BACKEND | [WGPUBackendType_Metal, ...] | Force select a backend for WebGPU (Metal, DirectX, OpenGL, Vulkan...)
CUDA_PATH | str | Use `CUDA_PATH/include` for CUDA headers for CUDA and NV backends. If not set, TinyGrad will use `/usr/local/cuda/include`, `/usr/include` and `/opt/cuda/include`.
## Debug breakdown
Variable | Value | Description
---|---|---
DEBUG | >= 1 | Enables debugging and lists devices being used
DEBUG | >= 2 | Provides performance metrics for operations, including timing, memory usage, bandwidth for each kernel execution
DEBUG | >= 3 | Outputs buffers used for each kernel (shape, dtype and strides) and the applied optimizations at a kernel level
DEBUG | >= 4 | Outputs the generated kernel code
DEBUG | >= 5 | Displays the intermediate representation of the computation UOps (AST)
DEBUG | >= 6 | Displays the intermediate representation of the computation UOps in a linearized manner, detailing the operation sequence
DEBUG | >= 7 | Outputs the assembly code generated for the target hardware
+7
View File
@@ -29,5 +29,12 @@
::: tinygrad.nn.state.get_state_dict
::: tinygrad.nn.state.get_parameters
::: tinygrad.nn.state.load_state_dict
::: tinygrad.nn.state.tar_extract
options:
show_signature: false
separate_signature: false
::: tinygrad.nn.state.torch_load
options:
show_signature: false
separate_signature: false
::: tinygrad.nn.state.gguf_load
+2 -2
View File
@@ -110,7 +110,7 @@ class TinyNet:
def __call__(self, x):
x = self.l1(x)
x = x.leakyrelu()
x = x.leaky_relu()
x = self.l2(x)
return x
@@ -118,7 +118,7 @@ net = TinyNet()
```
We can see that the forward pass of our neural network is just the sequence of operations performed on the input tensor `x`.
We can also see that functional operations like `leakyrelu` are not defined as classes and instead are just methods we can just call.
We can also see that functional operations like `leaky_relu` are not defined as classes and instead are just methods we can just call.
Finally, we just initialize an instance of our neural network, and we are ready to start training it.
## Training
+60 -1
View File
@@ -5,7 +5,7 @@ tinygrad supports various runtimes, enabling your code to scale across a wide ra
| Runtime | Description | Requirements |
|---------|-------------|--------------|
| [NV](https://github.com/tinygrad/tinygrad/tree/master/tinygrad/runtime/ops_nv.py) | Provides acceleration for NVIDIA GPUs | Ampere/Ada series GPUs |
| [AMD](https://github.com/tinygrad/tinygrad/tree/master/tinygrad/runtime/ops_amd.py) | Provides acceleration for AMD GPUs | RDNA2/RDNA3 series GPUs |
| [AMD](https://github.com/tinygrad/tinygrad/tree/master/tinygrad/runtime/ops_amd.py) | Provides acceleration for AMD GPUs | RDNA2/RDNA3/RDNA4 series GPUs. You can select one of the interfaces for communication by setting `AMD_IFACE=(KFD|PCI)`. See [AMD interfaces](#amd-interfaces) for more details. |
| [QCOM](https://github.com/tinygrad/tinygrad/tree/master/tinygrad/runtime/ops_qcom.py) | Provides acceleration for QCOM GPUs | 6xx series GPUs |
| [METAL](https://github.com/tinygrad/tinygrad/tree/master/tinygrad/runtime/ops_metal.py) | Utilizes Metal for acceleration on Apple devices | M1+ Macs; Metal 3.0+ for `bfloat` support |
| [CUDA](https://github.com/tinygrad/tinygrad/tree/master/tinygrad/runtime/ops_cuda.py) | Utilizes CUDA for acceleration on NVIDIA GPUs | NVIDIA GPU with CUDA support |
@@ -13,3 +13,62 @@ tinygrad supports various runtimes, enabling your code to scale across a wide ra
| [CPU (C Code)](https://github.com/tinygrad/tinygrad/tree/master/tinygrad/runtime/ops_cpu.py) | Runs on CPU using the clang compiler | `clang` compiler in system `PATH` |
| [LLVM (LLVM IR)](https://github.com/tinygrad/tinygrad/tree/master/tinygrad/runtime/ops_llvm.py) | Runs on CPU using the LLVM compiler infrastructure | llvm libraries installed and findable |
| [WEBGPU](https://github.com/tinygrad/tinygrad/tree/master/tinygrad/runtime/ops_webgpu.py) | Runs on GPU using the Dawn WebGPU engine (used in Google Chrome) | Dawn library installed and findable. Download binaries [here](https://github.com/wpmed92/pydawn/releases/tag/v0.1.6). |
## Interoperability
tinygrad provides interoperability with OpenCL and PyTorch, allowing efficient tensor data sharing between frameworks through the `Tensor.from_blob` API. This enables zero-copy operations by working directly with external memory pointers.
**Important**: When using external memory pointers with tinygrad tensors, you must ensure these pointers remain valid throughout the entire lifetime of the tinygrad tensor to prevent memory corruption.
### `CUDA`/`METAL` PyTorch Interoperability
You can seamlessly work with CUDA/MPS tensors between PyTorch and tinygrad without data copying:
```python
from tinygrad.dtype import _from_torch_dtype
tensor1 = torch.tensor([1.0, 2.0, 3.0], device=torch.device("cuda"))
tiny_tensor1 = Tensor.from_blob(tensor1.data_ptr(), tensor1.shape, dtype=_from_torch_dtype(tensor1.dtype), device='CUDA')
# Before tinygrad calculations, mps needs to be synchronized to make sure data is valid.
if data.device.type == "mps": torch.mps.synchronize()
else: torch.cuda.synchronize()
x = (tiny_tensor1 + 1).realize()
```
### `QCOM` OpenCL Interoperability
tinygrad supports OpenCL interoperability on `QCOM` backend.
Buffer interop allows direct access to OpenCL memory buffers:
```python
# create raw opencl buffer.
cl_buf = cl.clCreateBuffer(cl_context, cl.CL_MEM_READ_WRITE, 0x100, None, status := ctypes.c_int32())
# extract pointers
cl_buf_desc_ptr = to_mv(ctypes.addressof(cl_buf), 8).cast('Q')[0]
rawbuf_ptr = to_mv(cl_buf_desc_ptr, 0x100).cast('Q')[20] # offset 0xA0 is a raw gpu pointer.
# create tiny tensor
tiny = Tensor.from_blob(rawbuf_ptr, (8, 8), dtype=dtypes.int, device='QCOM')
```
And the same for the images:
```python
# create cl image.
cl_img = cl.clCreateImage2D(cl_context, cl.CL_MEM_READ_WRITE, cl.cl_image_format(cl.CL_RGBA, cl.CL_FLOAT), w, h, 0, None, status := ctypes.c_int32())
# extract pointers
cl_buf_desc_ptr = to_mv(ctypes.addressof(cl_img), 8).cast('Q')[0]
rawbuf_ptr = to_mv(cl_buf_desc_ptr, 0x100).cast('Q')[20] # offset 0xA0 is a raw gpu pointer.
# create tiny tensor
tiny = Tensor.from_blob(rawbuf_ptr, (h*w*4,), dtype=dtypes.imagef((h,w)), device='QCOM')
```
## AMD Interfaces
AMD backend supports several interfaces for communicating with devices:
* `KFD`: uses the amdgpu driver
* `PCI`: uses the [AM driver](developer/am.md)
You can force an interface by setting `AMD_IFACE` to one of these values. In the case of `AMD_IFACE=PCI`, this may unbind your GPU from the amdgpu driver.
+2
View File
@@ -20,7 +20,9 @@
::: tinygrad.Tensor.manual_seed
::: tinygrad.Tensor.rand
::: tinygrad.Tensor.rand_like
::: tinygrad.Tensor.randn
::: tinygrad.Tensor.randn_like
::: tinygrad.Tensor.randint
::: tinygrad.Tensor.normal
::: tinygrad.Tensor.uniform
+7 -2
View File
@@ -22,6 +22,7 @@ Elementwise ops operate on a per element basis. They don't change the shape of t
::: tinygrad.Tensor.round
::: tinygrad.Tensor.isinf
::: tinygrad.Tensor.isnan
::: tinygrad.Tensor.isfinite
::: tinygrad.Tensor.lerp
::: tinygrad.Tensor.square
::: tinygrad.Tensor.clamp
@@ -52,7 +53,7 @@ Elementwise ops operate on a per element basis. They don't change the shape of t
::: tinygrad.Tensor.erf
::: tinygrad.Tensor.gelu
::: tinygrad.Tensor.quick_gelu
::: tinygrad.Tensor.leakyrelu
::: tinygrad.Tensor.leaky_relu
::: tinygrad.Tensor.mish
::: tinygrad.Tensor.softplus
::: tinygrad.Tensor.softsign
@@ -65,13 +66,17 @@ Elementwise ops operate on a per element basis. They don't change the shape of t
::: tinygrad.Tensor.div
::: tinygrad.Tensor.idiv
::: tinygrad.Tensor.mod
::: tinygrad.Tensor.xor
::: tinygrad.Tensor.bitwise_xor
::: tinygrad.Tensor.bitwise_and
::: tinygrad.Tensor.bitwise_or
::: tinygrad.Tensor.bitwise_not
::: tinygrad.Tensor.lshift
::: tinygrad.Tensor.rshift
::: tinygrad.Tensor.pow
::: tinygrad.Tensor.maximum
::: tinygrad.Tensor.minimum
::: tinygrad.Tensor.where
::: tinygrad.Tensor.copysign
## Casting Ops
+5
View File
@@ -9,6 +9,7 @@
::: tinygrad.Tensor.isclose
::: tinygrad.Tensor.mean
::: tinygrad.Tensor.var
::: tinygrad.Tensor.var_mean
::: tinygrad.Tensor.std
::: tinygrad.Tensor.std_mean
::: tinygrad.Tensor.softmax
@@ -22,6 +23,7 @@
::: tinygrad.Tensor.avg_pool2d
::: tinygrad.Tensor.max_pool2d
::: tinygrad.Tensor.max_unpool2d
::: tinygrad.Tensor.conv2d
::: tinygrad.Tensor.conv_transpose2d
::: tinygrad.Tensor.dot
@@ -34,6 +36,9 @@
::: tinygrad.Tensor.interpolate
::: tinygrad.Tensor.scatter
::: tinygrad.Tensor.scatter_reduce
::: tinygrad.Tensor.masked_select
::: tinygrad.Tensor.sort
::: tinygrad.Tensor.topk
## Neural Network (functional)
+1
View File
@@ -25,6 +25,7 @@
::: tinygrad.Tensor.replace
::: tinygrad.Tensor.assign
::: tinygrad.Tensor.detach
::: tinygrad.Tensor.clone
::: tinygrad.Tensor.to
::: tinygrad.Tensor.to_
::: tinygrad.Tensor.shard
+1 -1
View File
@@ -1,4 +1,4 @@
# model based off https://towardsdatascience.com/going-beyond-99-mnist-handwritten-digits-recognition-cfff96337392
# model based off https://medium.com/data-science/going-beyond-99-mnist-handwritten-digits-recognition-cfff96337392
from typing import List, Callable
from tinygrad import Tensor, TinyJit, nn, GlobalCounters
from tinygrad.helpers import getenv, colored, trange
+5 -5
View File
@@ -1,12 +1,12 @@
import sys, onnx, time
from tinygrad import TinyJit, Device, GlobalCounters, fetch, getenv
from extra.onnx import OnnxRunner
import sys, onnx, time, pickle
from tinygrad import TinyJit, GlobalCounters, fetch, getenv
from tinygrad.frontend.onnx import OnnxRunner
from extra.onnx_helpers import get_example_inputs, validate
def load_onnx_model(onnx_file):
onnx_model = onnx.load(onnx_file)
run_onnx = OnnxRunner(onnx_model)
run_onnx_jit = TinyJit(lambda **kwargs: next(iter(run_onnx({k:v.to(Device.DEFAULT) for k,v in kwargs.items()}).values())), prune=True)
run_onnx_jit = TinyJit(lambda **kwargs: next(iter(run_onnx({k:v.to(None) for k,v in kwargs.items()}).values())), prune=True, optimize=True)
return run_onnx_jit, run_onnx.graph_inputs
if __name__ == "__main__":
@@ -33,4 +33,4 @@ if __name__ == "__main__":
if getenv("ORT"):
validate(onnx_file, new_inputs, rtol=1e-3, atol=1e-3)
print("model validated")
print("model validated")
+2 -2
View File
@@ -34,8 +34,8 @@ if __name__ == "__main__":
part2 = nn.state.torch_load(fetch("https://huggingface.co/teknium/OpenHermes-2.5-Mistral-7B/resolve/main/pytorch_model-00002-of-00002.bin?download=true"))
with Timing("weights -> model: "):
nn.state.load_state_dict(model, fix_bf16(convert_from_huggingface(part1, model, 32, 8)), strict=False)
nn.state.load_state_dict(model, fix_bf16(convert_from_huggingface(part2, model, 32, 8)), strict=False)
nn.state.load_state_dict(model, fix_bf16(convert_from_huggingface(part1, 32, 32, 8)), strict=False)
nn.state.load_state_dict(model, fix_bf16(convert_from_huggingface(part2, 32, 32, 8)), strict=False)
if not os.path.isfile("/tmp/tokenizer.model"): create_fixed_tokenizer("/tmp/tokenizer.model")
spp = SentencePieceProcessor(model_file="/tmp/tokenizer.model")
+1 -1
View File
@@ -8,7 +8,7 @@ import numpy as np
import subprocess
import tensorflow as tf
import tf2onnx
from extra.onnx import OnnxRunner
from tinygrad.frontend.onnx import OnnxRunner
from tinygrad.tensor import Tensor
from extra.export_model import export_model_clang, compile_net, jit_model
+1 -1
View File
@@ -189,7 +189,7 @@ class GPT2:
tokens = Variable("tokens", 0, VOCAB_SIZE).bind(toks[0][start_pos])
else:
tokens = Tensor([x[start_pos:] for x in toks])
tok = self.model(tokens, Variable("start_pos", 1 if start_pos else 0, MAX_CONTEXT).bind(start_pos), temperature).tolist()
tok = self.model(tokens, Variable("start_pos", 1 if start_pos else 0, MAX_CONTEXT-1).bind(start_pos), temperature).tolist()
start_pos = len(toks[0])
for i,t in enumerate(tok): toks[i].append(t)
return [self.tokenizer.decode(x) for x in toks]
+2 -1
View File
@@ -3,6 +3,7 @@ from extra.mcts_search import mcts_search
from examples.mlperf.helpers import get_mlperf_bert_model
from tinygrad import Tensor, Device, dtypes, nn
from tinygrad.codegen.kernel import Kernel
from tinygrad.codegen.heuristic import hand_coded_optimizations
from tinygrad.ops import Ops, sym_infer
from tinygrad.device import Compiled
from tinygrad.engine.search import beam_search, bufs_from_lin
@@ -83,7 +84,7 @@ if __name__ == "__main__":
# always try hand coded opt
lin = Kernel(si.ast, opts=device.renderer)
lin.hand_coded_optimizations()
lin.apply_opts(hand_coded_optimizations(lin))
lins.append((lin, "HC"))
# maybe try tensor cores
+4 -2
View File
@@ -211,11 +211,13 @@ class LLaMa:
else:
weights = load(str(model_path))
if "model.embed_tokens.weight" in weights:
weights = convert_from_huggingface(weights, model, params["args"]["n_heads"], params["args"].get("n_kv_heads", params["args"]["n_heads"]))
weights = convert_from_huggingface(weights, params["args"]["n_layers"], params["args"]["n_heads"], params["args"].get("n_kv_heads", params["args"]["n_heads"]))
weights = fix_bf16(weights)
with Context(BEAM=0):
# prevent tracking model weights
# this is a part of a larger problem with BUFFER UOps and gc in TRACK_MATCH_STATS=2
with Context(BEAM=0, TRACK_MATCH_STATS=0):
# quantize
if quantize is not None:
weights = linear.quantize(weights, device)
+30 -15
View File
@@ -47,7 +47,7 @@ def concat_weights(models, device=None):
disk_tensors: List[Tensor] = [model[name] for model in models]
if len(disk_tensors) == 1 or len(disk_tensors[0].shape) == 1:
return disk_tensors[0].to(device=device)
axis = 1 if name.endswith(".attention.wo.weight") or name.endswith(".feed_forward.w2.weight") else 0
axis = 1 if name.endswith((".attention.wo.weight", ".feed_forward.w2.weight")) else 0
lazy_tensors = [data.to(device=device) for data in disk_tensors]
return lazy_tensors[0].cat(*lazy_tensors[1:], dim=axis)
return {name: convert(name) for name in {name: None for model in models for name in model}}
@@ -73,16 +73,17 @@ class Int8Linear:
self.scale = Tensor.ones(out_features, dtype=dtypes.half)
def __call__(self, x):
return x.dot(self.weight.cast(dtype=dtypes.half).T*self.scale)
return x.dot(self.weight.cast(self.scale.dtype).T*self.scale)
@staticmethod
def quantize(tensors, device):
def quantize(tensors, device, scale_dtype=dtypes.float16, quantize_embeds=False):
new_tensors = {}
for name,v in tensors.items():
if "feed_forward" in name or "attention.w" in name:
if "feed_forward" in name or "attention.w" in name or (quantize_embeds and "tok_embeddings.weight" in name):
assert "weight" in name, name
v = v.cast(scale_dtype)
scale = v.abs().max(axis=1) / 127.0
int8_weight = (v.T/scale).T.cast(dtype=dtypes.int8)
int8_weight = (v.T/scale).T.round().cast(dtype=dtypes.int8) # without round(), cast truncates -34.9 to -34
new_tensors[name] = int8_weight
new_tensors[name.replace('weight', 'scale')] = scale
if isinstance(device, tuple):
@@ -90,8 +91,20 @@ class Int8Linear:
new_tensors[name.replace('weight', 'scale')].shard_(device, axis=None)
else:
new_tensors[name] = v
if quantize_embeds: new_tensors.update({"output.weight": new_tensors["tok_embeddings.weight"], "output.scale": new_tensors["tok_embeddings.scale"]})
return new_tensors
class Int8Embedding:
def __init__(self, vocab_size:int, embed_size:int):
self.vocab_sz, self.embed_sz = vocab_size, embed_size
self.weight, self.scale = Tensor.ones(vocab_size, embed_size, dtype=dtypes.int8), Tensor.ones(vocab_size, dtype=dtypes.half)
def __call__(self, idx:Tensor) -> Tensor:
if not hasattr(self, 'arange'): self.arange = Tensor.arange(self.vocab_sz, requires_grad=False, device=self.weight.device).unsqueeze(-1)
big_shp = idx.shape+(self.vocab_sz, self.embed_sz)
arange, idx, vals = self.arange.expand(big_shp), idx.reshape(idx.shape+(1, 1)).expand(big_shp), (self.weight.cast(self.scale.dtype).T*self.scale).T
return (arange == idx).mul(vals).sum(-2, dtype=vals.dtype)
def NF4Linear(block_size):
_CODE = [
-1.0, -0.6961928009986877, -0.5250730514526367, -0.39491748809814453, -0.28444138169288635, -0.18477343022823334, -0.09105003625154495, 0.0,
@@ -113,7 +126,8 @@ def NF4Linear(block_size):
return x.linear(unscaled.reshape(self.out_features, self.in_features).T)
@staticmethod
def quantize(state_dict: dict[str, Tensor], device) -> dict[str, Tensor]:
def quantize(state_dict: dict[str, Tensor], device, scale_dtype=dtypes.float16, quantize_embeds=False) -> dict[str, Tensor]:
assert not quantize_embeds # TODO: support this?
new_state_dict = {}
for k, v in state_dict.items():
if "feed_forward" in k or "attention.w" in k:
@@ -121,7 +135,7 @@ def NF4Linear(block_size):
scale = (grouped.abs().max(axis=1, keepdim=True))
coded = ((grouped / scale).unsqueeze(-1) - CODE.to(v.device)).abs().argmin(axis=-1).cast(dtypes.uint8).flatten()
new_state_dict[k] = coded[::2] * 2 ** 4 + coded[1::2]
new_state_dict[k.replace(".weight", ".scale")] = scale.cast(dtypes.float16)
new_state_dict[k.replace(".weight", ".scale")] = scale.cast(scale_dtype)
if isinstance(device, tuple):
new_state_dict[k].shard_(device, axis=-1)
new_state_dict[k.replace('weight', 'scale')].shard_(device, axis=None)
@@ -144,13 +158,14 @@ MODEL_PARAMS = {
"files": 8
}
}
def build_transformer(model_path: Path, model_size="8B", quantize=None, device=None):
def build_transformer(model_path: Path, model_size="8B", quantize=None, scale_dtype=dtypes.float16, device=None, max_context=8192, load_weights=True):
# build model
if quantize == "int8": linear = Int8Linear
elif quantize == "nf4": linear = NF4Linear(64)
else: linear = nn.Linear
model = Transformer(**MODEL_PARAMS[model_size]["args"], linear=linear, max_context=8192, jit=True)
if quantize == "int8": linear, embedding, quantize_embeds = Int8Linear, Int8Embedding, True
elif quantize == "nf4": linear, embedding, quantize_embeds = NF4Linear(64), nn.Embedding, False
else: linear, embedding, quantize_embeds = nn.Linear, nn.Embedding, False
model = Transformer(**MODEL_PARAMS[model_size]["args"], linear=linear, embedding=embedding, max_context=max_context, jit=True)
if not load_weights: return model
# load weights
if model_path.is_dir():
if (model_path / "model.safetensors.index.json").exists(): weights = load(str(model_path / "model.safetensors.index.json"))
@@ -159,16 +174,16 @@ def build_transformer(model_path: Path, model_size="8B", quantize=None, device=N
else:
weights = load(str(model_path))
if "model.embed_tokens.weight" in weights:
weights = convert_from_huggingface(weights, model, MODEL_PARAMS[model_size]["args"]["n_heads"], MODEL_PARAMS[model_size]["args"]["n_kv_heads"])
weights = convert_from_huggingface(weights, MODEL_PARAMS[model_size]["args"]["n_layers"], MODEL_PARAMS[model_size]["args"]["n_heads"], MODEL_PARAMS[model_size]["args"]["n_kv_heads"])
elif "token_embd.weight" in weights:
weights = convert_from_gguf(weights, model)
weights = convert_from_gguf(weights, MODEL_PARAMS[model_size]["args"]["n_layers"])
weights = fix_bf16(weights)
with Context(BEAM=0):
# quantize
if quantize == "float16": weights = {k:v.cast(quantize).contiguous() for k,v in weights.items()}
elif quantize is not None:
weights = linear.quantize(weights, device)
weights = linear.quantize(weights, device, scale_dtype, quantize_embeds)
for _,v in weights.items(): v.realize()
# shard
+1 -1
View File
@@ -25,7 +25,7 @@ if __name__ == "__main__":
Tensor.training = True
optimizer = nn.optim.Adam(nn.state.get_parameters(model), lr=1e-4)
warmup_count = getenv("WARMUP", 3)
for i in range(warmup_count): # TODO: why does it take three and not two to stablize
for i in range(warmup_count): # TODO: why does it take three and not two to stabilize
GlobalCounters.reset()
X = Tensor.empty(4, 64, dtype=dtypes.int).reshape(B, T)
Y = Tensor.empty(4, 64, dtype=dtypes.int).reshape(B, T)
+157
View File
@@ -0,0 +1,157 @@
# much taken from https://github.com/cloneofsimo/minRF
from tinygrad import Tensor, nn, GlobalCounters, TinyJit
from tinygrad.helpers import getenv, trange
from extra.models.llama import Attention, FeedForward, precompute_freqs_cis
def modulate(x:Tensor, shift:Tensor, scale:Tensor) -> Tensor: return x * (1 + scale.unsqueeze(1)) + shift.unsqueeze(1)
# TODO: why doesn't the TimestepEmbedder from minRF work?
class TimestepEmbedder:
def __init__(self, hidden_size): self.mlp = [nn.Linear(1, hidden_size), Tensor.silu, nn.Linear(hidden_size, hidden_size)]
def __call__(self, t:Tensor): return t.reshape(-1, 1).sequential(self.mlp)
class TransformerBlock:
def __init__(self, dim, n_heads, norm_eps=1e-5):
self.attention = Attention(dim, n_heads)
self.feed_forward = FeedForward(dim, 4*dim)
self.attention_norm = nn.LayerNorm(dim, eps=norm_eps)
self.ffn_norm = nn.LayerNorm(dim, eps=norm_eps)
self.adaLN_modulation = nn.Linear(dim, 6 * dim, bias=True)
def __call__(self, x:Tensor, freqs_cis:Tensor, adaln_input:Tensor):
shift_msa, scale_msa, gate_msa, shift_mlp, scale_mlp, gate_mlp = self.adaLN_modulation(adaln_input.silu()).chunk(6, dim=1)
x = x + gate_msa.unsqueeze(1) * self.attention(modulate(self.attention_norm(x), shift_msa, scale_msa), 0, freqs_cis)
x = x + gate_mlp.unsqueeze(1) * self.feed_forward(modulate(self.ffn_norm(x), shift_mlp, scale_mlp))
return x.contiguous().contiguous_backward()
class FinalLayer:
def __init__(self, dim, patch_size, out_channels):
self.norm_final = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
self.linear = nn.Linear(dim, patch_size*patch_size*out_channels, bias=True)
self.adaLN_modulation = nn.Linear(dim, 2 * dim, bias=True)
# init weights/bias to 0
self.linear.weight.replace(self.linear.weight.zeros_like().contiguous())
self.linear.bias.replace(self.linear.bias.zeros_like().contiguous())
def __call__(self, x:Tensor, c:Tensor):
shift, scale = self.adaLN_modulation(c.silu()).chunk(2, dim=1)
x = modulate(self.norm_final(x), shift, scale)
return self.linear(x)
# channels=1, input_size=32, dim=64, n_layers=6, n_heads=4, num_classes=10
class DiT_Llama:
def __init__(self, in_channels=1, dim=64, n_layers=6, n_heads=4, num_classes=10, patch_size=2):
self.patch_size = patch_size
self.out_channels = in_channels
self.num_classes = num_classes
self.init_conv_seq = [
nn.Conv2d(in_channels, dim // 2, kernel_size=5, padding=2, stride=1), Tensor.silu, nn.GroupNorm(32, dim//2),
nn.Conv2d(dim //2, dim // 2, kernel_size=5, padding=2, stride=1), Tensor.silu, nn.GroupNorm(32, dim//2),
]
self.x_embedder = nn.Linear(self.patch_size * self.patch_size * dim // 2, dim, bias=True)
self.t_embedder = TimestepEmbedder(dim)
self.y_embedder = nn.Embedding(num_classes+1, dim)
self.final_layer = FinalLayer(dim, self.patch_size, self.out_channels)
self.freqs_cis = precompute_freqs_cis(dim // n_heads, 4096)
self.layers = [TransformerBlock(dim, n_heads) for _ in range(n_layers)]
def unpatchify(self, x:Tensor):
c, p = self.out_channels, self.patch_size
h = w = int(x.shape[1] ** 0.5)
x = x.reshape(shape=(x.shape[0], h, w, p, p, c))
x = x.rearrange("n h w p q c -> n c h p w q")
return x.reshape(shape=(x.shape[0], c, h * p, h * p))
def patchify(self, x:Tensor):
B, C, H, W = x.shape
x = x.reshape(B, C, H // self.patch_size, self.patch_size, W // self.patch_size, self.patch_size)
x = x.permute(0, 2, 4, 1, 3, 5).flatten(-3).flatten(1, 2)
return x # B <H*W ish> <C*patch_size*patch_size>
def __call__(self, x:Tensor, t:Tensor, y:Tensor) -> Tensor:
x = x.sequential(self.init_conv_seq)
x = self.patchify(x)
x = self.x_embedder(x)
adaln_input = self.t_embedder(t) + self.y_embedder(y)
adaln_input = adaln_input.contiguous()
for layer in self.layers:
x = layer(x, self.freqs_cis[:, :x.size(1)], adaln_input=adaln_input)
x = self.final_layer(x, adaln_input)
return self.unpatchify(x)
def rf(self, x:Tensor, cond:Tensor):
b = x.shape[0]
# self.ln is True
t = Tensor.randn((b,)).sigmoid()
texp = t.view([b, *([1] * len(x.shape[1:]))])
# conditional dropout
dropout_prob = 0.1
cond = (Tensor.rand(cond.shape[0]) < dropout_prob).where(cond.full_like(self.num_classes), cond)
# this is rectified flow
z1 = x.randn_like()
zt = (1 - texp) * x + texp * z1
vtheta = self(zt, t, cond)
# MSE loss
return ((z1 - x) - vtheta).square().mean()
def sample(self, z, cond, null_cond, sample_steps=50, cfg=2.0):
b = z.size(0)
dt = Tensor.full((b,)+(1,)*len(z.shape[1:]), fill_value=1.0/sample_steps).contiguous()
images = [z]
for i in range(sample_steps, 0, -1):
t = Tensor.full((b,), fill_value=i/sample_steps).contiguous()
vc = self(z, t, cond)
vu = self(z, t, null_cond)
vc = vu + cfg * (vc - vu)
z = z - dt * vc
z = z.contiguous()
images.append(z)
return images
def mviz(t:Tensor):
assert len(t.shape) == 4 and t.shape[1] == 1
ft = t.permute(1,2,0,3).reshape(32, -1)
assert ft.shape[-1]%32 == 0
print("")
for y in ((ft+1)/2).clamp(0,1).tolist():
ln = [f"\033[38;5;{232+int(x*23)}m██" for x in y]
print(''.join(ln) + "\033[0m")
if __name__ == "__main__":
X_train, Y_train, X_test, Y_test = nn.datasets.mnist()
X_train = X_train.pad((2,2,2,2))
X_train = ((X_train.float()/255)-0.5)/0.5
Y_train = Y_train.int()
model = DiT_Llama(patch_size=getenv("PATCH_SIZE", 2))
for r in nn.state.get_parameters(model): r.realize()
optimizer = nn.optim.Adam(nn.state.get_parameters(model), lr=5e-4)
@TinyJit
@Tensor.train()
def train_step():
if getenv("OVERFIT"): samples = Tensor.zeros(getenv("BS", 256), dtype='int')
else: samples = Tensor.randint(getenv("BS", 256), high=X_train.shape[0])
optimizer.zero_grad()
loss = model.rf(X_train[samples], Y_train[samples])
loss.backward()
optimizer.step()
return loss
@TinyJit
@Tensor.test()
def sample(z:Tensor, cond:Tensor) -> Tensor:
return model.sample(z, cond, Tensor.full_like(cond, 10), sample_steps=getenv("SAMPLE_STEPS", 20))[-1]
for steps in (t:=trange(getenv("STEPS", 5000))):
if steps%10 == 0: mviz(sample(Tensor.randn(3, 1, 32, 32), Tensor([5,0,4], dtype='int')))
GlobalCounters.reset()
loss = train_step()
t.set_description(f"loss: {loss.item():9.2f}")
+169
View File
@@ -348,6 +348,167 @@ def batch_load_unet3d(preprocessed_dataset_dir:Path, batch_size:int=6, val:bool=
# happens with BENCHMARK set
pass
### RetinaNet
def load_retinanet_data(base_dir:Path, val:bool, queue_in:Queue, queue_out:Queue,
imgs:Tensor, boxes:Tensor, labels:Tensor, matches:Tensor|None=None,
anchors:Tensor|None=None, seed:int|None=None):
from extra.datasets.openimages import image_load, random_horizontal_flip, resize
from examples.mlperf.helpers import box_iou, find_matches, generate_anchors
import torch
while (data:=queue_in.get()) is not None:
idx, img, tgt = data
img = image_load(base_dir, img["subset"], img["file_name"])
if val:
img = resize(img)[0]
else:
if seed is not None:
np.random.seed(seed)
random.seed(seed)
torch.manual_seed(seed)
img, tgt = random_horizontal_flip(img, tgt)
img, tgt, _ = resize(img, tgt=tgt)
match_quality_matrix = box_iou(tgt["boxes"], (anchor := np.concatenate(generate_anchors((800, 800)))))
match_idxs = find_matches(match_quality_matrix, allow_low_quality_matches=True)
clipped_match_idxs = np.clip(match_idxs, 0, None)
clipped_boxes, clipped_labels = tgt["boxes"][clipped_match_idxs], tgt["labels"][clipped_match_idxs]
boxes[idx].contiguous().realize().lazydata.base.realized.as_buffer(force_zero_copy=True)[:] = clipped_boxes.tobytes()
labels[idx].contiguous().realize().lazydata.base.realized.as_buffer(force_zero_copy=True)[:] = clipped_labels.tobytes()
matches[idx].contiguous().realize().lazydata.base.realized.as_buffer(force_zero_copy=True)[:] = match_idxs.tobytes()
anchors[idx].contiguous().realize().lazydata.base.realized.as_buffer(force_zero_copy=True)[:] = anchor.tobytes()
imgs[idx].contiguous().realize().lazydata.base.realized.as_buffer(force_zero_copy=True)[:] = img.tobytes()
queue_out.put(idx)
queue_out.put(None)
def batch_load_retinanet(dataset, val:bool, base_dir:Path, batch_size:int=32, shuffle:bool=True, seed:int|None=None):
def _enqueue_batch(bc):
from extra.datasets.openimages import prepare_target
for idx in range(bc * batch_size, (bc+1) * batch_size):
img = dataset.loadImgs(next(dataset_iter))[0]
ann = dataset.loadAnns(dataset.getAnnIds(img_id:=img["id"]))
tgt = prepare_target(ann, img_id, (img["height"], img["width"]))
if img_ids is not None:
img_ids[idx] = img_id
if img_sizes is not None:
img_sizes[idx] = tgt["image_size"]
queue_in.put((idx, img, tgt))
def _setup_shared_mem(shm_name:str, size:tuple[int, ...], dtype:dtypes) -> tuple[shared_memory.SharedMemory, Tensor]:
if os.path.exists(f"/dev/shm/{shm_name}"): os.unlink(f"/dev/shm/{shm_name}")
shm = shared_memory.SharedMemory(name=shm_name, create=True, size=prod(size))
shm_tensor = Tensor.empty(*size, dtype=dtype, device=f"disk:/dev/shm/{shm_name}")
return shm, shm_tensor
image_ids = sorted(dataset.imgs.keys())
batch_count = min(32, len(image_ids) // batch_size)
queue_in, queue_out = Queue(), Queue()
procs, data_out_count = [], [0] * batch_count
shm_imgs, imgs = _setup_shared_mem("retinanet_imgs", (batch_size * batch_count, 800, 800, 3), dtypes.uint8)
if val:
boxes, labels, matches, anchors = None, None, None, None
img_ids, img_sizes = [None] * (batch_size * batch_count), [None] * (batch_size * batch_count)
else:
img_ids, img_sizes = None, None
shm_boxes, boxes = _setup_shared_mem("retinanet_boxes", (batch_size * batch_count, 120087, 4), dtypes.float32)
shm_labels, labels = _setup_shared_mem("retinanet_labels", (batch_size * batch_count, 120087), dtypes.int64)
shm_matches, matches = _setup_shared_mem("retinanet_matches", (batch_size * batch_count, 120087), dtypes.int64)
shm_anchors, anchors = _setup_shared_mem("retinanet_anchors", (batch_size * batch_count, 120087, 4), dtypes.float64)
shutdown = False
class Cookie:
def __init__(self, bc):
self.bc = bc
def __del__(self):
if not shutdown:
try: _enqueue_batch(self.bc)
except StopIteration: pass
def shuffle_indices(indices, seed):
rng = random.Random(seed)
rng.shuffle(indices)
if shuffle: shuffle_indices(image_ids, seed=seed)
dataset_iter = iter(image_ids)
try:
for _ in range(cpu_count()):
proc = Process(
target=load_retinanet_data,
args=(base_dir, val, queue_in, queue_out, imgs, boxes, labels),
kwargs={"matches": matches, "anchors": anchors, "seed": seed}
)
proc.daemon = True
proc.start()
procs.append(proc)
for bc in range(batch_count):
_enqueue_batch(bc)
for _ in range(len(image_ids) // batch_size):
while True:
bc = queue_out.get() // batch_size
data_out_count[bc] += 1
if data_out_count[bc] == batch_size: break
data_out_count[bc] = 0
if val:
yield (imgs[bc * batch_size:(bc + 1) * batch_size],
img_ids[bc * batch_size:(bc + 1) * batch_size],
img_sizes[bc * batch_size:(bc + 1) * batch_size],
Cookie(bc))
else:
yield (imgs[bc * batch_size:(bc + 1) * batch_size],
boxes[bc * batch_size:(bc + 1) * batch_size],
labels[bc * batch_size:(bc + 1) * batch_size],
matches[bc * batch_size:(bc + 1) * batch_size],
anchors[bc * batch_size:(bc + 1) * batch_size],
Cookie(bc))
finally:
shutdown = True
for _ in procs: queue_in.put(None)
queue_in.close()
for _ in procs:
while queue_out.get() is not None: pass
queue_out.close()
# shutdown processes
for proc in procs: proc.join()
shm_imgs.close()
if not val:
shm_boxes.close()
shm_labels.close()
shm_matches.close()
shm_anchors.close()
try:
shm_imgs.unlink()
if not val:
shm_boxes.unlink()
shm_labels.unlink()
shm_matches.unlink()
shm_anchors.unlink()
except FileNotFoundError:
# happens with BENCHMARK set
pass
if __name__ == "__main__":
def load_unet3d(val):
assert not val, "validation set is not supported due to different sizes on inputs"
@@ -368,6 +529,14 @@ if __name__ == "__main__":
for x,y,c in batch_load_resnet(val=val):
pbar.update(x.shape[0])
def load_retinanet(val):
from extra.datasets.openimages import BASEDIR, download_dataset
from pycocotools.coco import COCO
dataset = COCO(download_dataset(base_dir:=getenv("BASEDIR", BASEDIR), "validation" if val else "train"))
with tqdm(total=len(dataset.imgs.keys())) as pbar:
for x in batch_load_retinanet(dataset, val, base_dir):
pbar.update(x[0].shape[0])
load_fn_name = f"load_{getenv('MODEL', 'resnet')}"
if load_fn_name in globals():
globals()[load_fn_name](getenv("VAL", 1))
+124
View File
@@ -1,6 +1,7 @@
from collections import OrderedDict
import unicodedata
from typing import Optional
import math
import numpy as np
from tinygrad.nn import state
from tinygrad.tensor import Tensor, dtypes
@@ -230,3 +231,126 @@ def get_fake_data_bert(BS:int):
"masked_lm_weights": Tensor.empty((BS, 76), dtype=dtypes.float32, device="CPU"),
"next_sentence_labels": Tensor.empty((BS, 1), dtype=dtypes.int32, device="CPU"),
}
def find_matches(match_quality_matrix:np.ndarray, high_threshold:float=0.5, low_threshold:float=0.4, allow_low_quality_matches:bool=False) -> np.ndarray:
BELOW_LOW_THRESHOLD, BETWEEN_THRESHOLDS = -1, -2
def _set_low_quality_matches_(matches:np.ndarray, all_matches:np.ndarray, match_quality_matrix:np.ndarray):
highest_quality_foreach_gt = np.max(match_quality_matrix, axis=1)
pred_inds_to_update = np.nonzero(match_quality_matrix == highest_quality_foreach_gt[:, None])[1]
matches[pred_inds_to_update] = all_matches[pred_inds_to_update]
assert low_threshold <= high_threshold
matched_vals, matches = match_quality_matrix.max(axis=0), match_quality_matrix.argmax(axis=0)
all_matches = np.copy(matches) if allow_low_quality_matches else None
below_low_threshold = matched_vals < low_threshold
between_thresholds = (matched_vals >= low_threshold) & (matched_vals < high_threshold)
matches[below_low_threshold] = BELOW_LOW_THRESHOLD
matches[between_thresholds] = BETWEEN_THRESHOLDS
if allow_low_quality_matches:
assert all_matches is not None
_set_low_quality_matches_(matches, all_matches, match_quality_matrix)
return matches
def box_iou(boxes1:np.ndarray, boxes2:np.ndarray) -> np.ndarray:
def _box_area(boxes:np.ndarray) -> np.ndarray: return (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1])
def _box_inter_union(boxes1:np.ndarray, boxes2:np.ndarray) -> tuple[np.ndarray, np.ndarray]:
area1, area2 = _box_area(boxes1), _box_area(boxes2)
lt, rb = np.maximum(boxes1[:, None, :2], boxes2[:, :2]), np.minimum(boxes1[:, None, 2:], boxes2[:, 2:])
wh = np.clip(rb - lt, a_min=0, a_max=None)
inter = wh[:, :, 0] * wh[:, :, 1]
union = area1[:, None] + area2 - inter
return inter, union
inter, union = _box_inter_union(boxes1, boxes2)
return inter / union
def generate_anchors(input_size:tuple[int, int], scales:Optional[tuple[Tensor, ...]]=None, aspect_ratios:Optional[tuple[Tensor, ...]]=None) -> list[np.ndarray]:
def _compute_grid_sizes(input_size:tuple[int, int]) -> np.ndarray:
return np.ceil(np.array(input_size)[None, :] / 2 ** np.arange(3, 8)[:, None])
scales = tuple((i, int(i * 2 ** (1/3)), int(i * 2 ** (2/3))) for i in 2 ** np.arange(5, 10)) if scales is None else scales
aspect_ratios = ((0.5, 1.0, 2.0),) * len(scales) if aspect_ratios is None else aspect_ratios
aspect_ratios = tuple(ar for ar in aspect_ratios)
grid_sizes = _compute_grid_sizes(input_size)
assert len(scales) == len(aspect_ratios) == len(grid_sizes), "scales, aspect_ratios, and grid_sizes must have the same length"
anchors = []
for s, ar, gs in zip(scales, aspect_ratios, grid_sizes):
s, ar = np.array(s), np.array(ar)
h_ratios = np.sqrt(ar)
w_ratios = 1 / h_ratios
ws = (w_ratios[:, None] * s[None, :]).reshape(-1)
hs = (h_ratios[:, None] * s[None, :]).reshape(-1)
base_anchors = (np.stack([-ws, -hs, ws, hs], axis=1) / 2).round()
stride_h, stride_w = input_size[0] // gs[0], input_size[1] // gs[1]
shifts_x, shifts_y = np.meshgrid(np.arange(gs[1]) * stride_w, np.arange(gs[0]) * stride_h)
shifts_x, shifts_y = shifts_x.reshape(-1), shifts_y.reshape(-1)
shifts = np.stack([shifts_x, shifts_y, shifts_x, shifts_y], axis=1, dtype=np.float32)
anchors.append((shifts[:, None] + base_anchors[None, :]).reshape(-1, 4))
return anchors
class BoxCoder(object):
def __init__(self, weights, bbox_xform_clip=math.log(1000. / 16), apply_to_remove=True):
self.weights = weights
self.bbox_xform_clip = bbox_xform_clip
self.apply_to_remove = apply_to_remove
def encode(self, reference_boxes, proposals):
TO_REMOVE = self.apply_to_remove # TODO remove
ex_widths = proposals[..., 2] - proposals[..., 0] + TO_REMOVE
ex_heights = proposals[..., 3] - proposals[..., 1] + TO_REMOVE
ex_ctr_x = proposals[..., 0] + 0.5 * ex_widths
ex_ctr_y = proposals[..., 1] + 0.5 * ex_heights
gt_widths = reference_boxes[..., 2] - reference_boxes[..., 0] + TO_REMOVE
gt_heights = reference_boxes[..., 3] - reference_boxes[..., 1] + TO_REMOVE
gt_ctr_x = reference_boxes[..., 0] + 0.5 * gt_widths
gt_ctr_y = reference_boxes[..., 1] + 0.5 * gt_heights
wx, wy, ww, wh = self.weights
targets_dx = wx * (gt_ctr_x - ex_ctr_x) / ex_widths
targets_dy = wy * (gt_ctr_y - ex_ctr_y) / ex_heights
targets_dw = ww * Tensor.log(gt_widths / ex_widths)
targets_dh = wh * Tensor.log(gt_heights / ex_heights)
targets = Tensor.stack(targets_dx, targets_dy, targets_dw, targets_dh, dim=-1)
return targets
def decode(self, rel_codes, boxes):
boxes = boxes.cast(rel_codes.dtype)
rel_codes = rel_codes
TO_REMOVE = self.apply_to_remove # TODO remove
widths = boxes[:, 2] - boxes[:, 0] + TO_REMOVE
heights = boxes[:, 3] - boxes[:, 1] + TO_REMOVE
ctr_x = boxes[:, 0] + 0.5 * widths
ctr_y = boxes[:, 1] + 0.5 * heights
wx, wy, ww, wh = self.weights
dx = rel_codes[:, 0::4] / wx
dy = rel_codes[:, 1::4] / wy
dw = rel_codes[:, 2::4] / ww
dh = rel_codes[:, 3::4] / wh
# Prevent sending too large values into Tensor.exp()
dw = dw.clip(min_=dw.min(), max_=self.bbox_xform_clip)
dh = dh.clip(min_=dh.min(), max_=self.bbox_xform_clip)
pred_ctr_x = dx * widths[:, None] + ctr_x[:, None]
pred_ctr_y = dy * heights[:, None] + ctr_y[:, None]
pred_w = dw.exp() * widths[:, None]
pred_h = dh.exp() * heights[:, None]
x = pred_ctr_x - 0.5 * pred_w
y = pred_ctr_y - 0.5 * pred_h
w = pred_ctr_x + 0.5 * pred_w - 1
h = pred_ctr_y + 0.5 * pred_h - 1
pred_boxes = Tensor.stack(x, y, w, h).permute(1,2,0).reshape(rel_codes.shape[0], rel_codes.shape[1])
return pred_boxes
+62 -1
View File
@@ -53,7 +53,9 @@ class EmbeddingBert(nn.Embedding):
arange_shp, weight_shp, big_shp = (1, 1, self.vocab_sz, 1), (1, 1, self.vocab_sz, self.embed_sz), idx.shape+(self.vocab_sz, self.embed_sz,)
if not hasattr(self, 'arange'): self.arange = Tensor.arange(self.vocab_sz, requires_grad=False, device=self.weight.device).reshape(arange_shp)
arange, idx, vals = self.arange.expand(big_shp), idx.reshape(idx.shape+(1, 1,)).expand(big_shp), self.weight.cast(dtypes.default_float).reshape(weight_shp).expand(big_shp)
return (arange == idx).mul(vals).sum(2, acc_dtype=vals.dtype)
# TODO: contiguous() here because the embedding dropout creates different asts on each device, and search becomes very slow.
# Should fix with fixing random ast on multi device, and fuse arange to make embedding fast.
return (arange == idx).mul(vals).sum(2, dtype=vals.dtype).contiguous()
class LayerNormBert:
def __init__(self, normalized_shape:Union[int, tuple[int, ...]], eps:float=1e-12, elementwise_affine:bool=True):
@@ -66,3 +68,62 @@ class LayerNormBert:
xn = x.cast(dtypes.float32).layernorm(eps=self.eps, axis=self.axis).cast(x.dtype)
if not self.elementwise_affine: return xn
return (xn * self.weight.cast(dtypes.default_float) + self.bias.cast(dtypes.default_float))
class FrozenBatchNorm2dRetinaNet(nn.BatchNorm2d):
def __init__(self, sz:int, eps=1e-5, affine=True, track_running_stats=True, momentum=0.1):
self.eps, self.track_running_stats, self.momentum = eps, track_running_stats, momentum
self.weight = Tensor.ones(sz, dtype=dtypes.float32, requires_grad=False) if affine else None
self.bias = Tensor.zeros(sz, dtype=dtypes.float32, requires_grad=False) if affine else None
if track_running_stats: self.running_mean, self.running_var = Tensor.zeros(sz, dtype=dtypes.float32, requires_grad=False), Tensor.ones(sz, dtype=dtypes.float32, requires_grad=False)
self.num_batches_tracked = Tensor.zeros(1, dtype=dtypes.long, requires_grad=False)
def __call__(self, x:Tensor) -> Tensor:
batch_mean, batch_var = super().calc_stats(x.cast(dtypes.float32))
if self.track_running_stats and Tensor.training:
self.running_mean.assign((1-self.momentum) * self.running_mean + self.momentum * batch_mean.detach().cast(self.running_mean.dtype))
self.running_var.assign((1-self.momentum) * self.running_var + self.momentum * x.numel()/(x.numel()-x.shape[1]) * batch_var.detach().cast(self.running_var.dtype))
self.num_batches_tracked += 1
return x.cast(dtypes.float32).batchnorm(self.weight, self.bias, batch_mean, batch_var.add(self.eps).rsqrt()).cast(x.dtype)
class Conv2dNormalRetinaNet(nn.Conv2d):
def __init__(self, in_channels:int, out_channels:int, kernel_size:int|tuple[int, ...],
stride:int=1, padding:int|tuple[int, ...]|str=0, dilation:int=1, groups:int=1,
bias:bool=True, prior_prob:float|None=None):
super().__init__(in_channels, out_channels, kernel_size, stride=stride, padding=padding, dilation=dilation, groups=groups, bias=bias)
self.weight = Tensor.normal(*self.weight.shape, std=0.01, dtype=dtypes.float32)
if bias:
if prior_prob:
prior_prob = Tensor(prior_prob, device=self.bias.device, dtype=dtypes.float32).expand(*self.bias.shape)
self.bias = -(((1 - prior_prob) / prior_prob).log())
else: self.bias = Tensor.zeros_like(self.bias, dtype=dtypes.float32)
def __call__(self, x:Tensor) -> Tensor:
return x.conv2d(self.weight.cast(dtypes.default_float), self.bias.cast(dtypes.default_float) if self.bias is not None else None,
groups=self.groups, stride=self.stride, padding=self.padding)
class Conv2dKaimingUniformRetinaNet(nn.Conv2d):
def __init__(self, in_channels:int, out_channels:int, kernel_size:int|tuple[int, ...],
stride:int=1, padding:int|tuple[int, ...]|str=0, dilation:int=1, groups:int=1,
bias:bool=True):
super().__init__(in_channels, out_channels, kernel_size, stride=stride, padding=padding, dilation=dilation, groups=groups, bias=bias)
self.weight = Tensor.kaiming_uniform(*self.weight.shape, a=1, dtype=dtypes.float32)
if bias: self.bias = Tensor.zeros_like(self.bias, dtype=dtypes.float32)
def __call__(self, x:Tensor) -> Tensor:
return x.conv2d(self.weight.cast(dtypes.default_float), self.bias.cast(dtypes.default_float) if self.bias is not None else None,
groups=self.groups, stride=self.stride, padding=self.padding)
class Conv2dRetinaNet(nn.Conv2d):
def __init__(self, in_channels:int, out_channels:int, kernel_size:int|tuple[int, ...],
stride:int=1, padding:int|tuple[int, ...]|str=0, dilation:int=1, groups:int=1,
bias:bool=True):
super().__init__(in_channels, out_channels, kernel_size, stride=stride, padding=padding, dilation=dilation, groups=groups, bias=bias)
scale = 1 / math.sqrt(in_channels * prod(self.kernel_size))
self.weight = Tensor.uniform(out_channels, in_channels//groups, *self.kernel_size, low=-scale, high=scale, dtype=dtypes.float32)
self.bias: Tensor|None = Tensor.uniform(out_channels, low=-scale, high=scale, dtype=dtypes.float32) if bias else None
def __call__(self, x:Tensor) -> Tensor:
return x.conv2d(self.weight.cast(dtypes.default_float), self.bias.cast(dtypes.default_float) if self.bias is not None else None,
groups=self.groups, stride=self.stride, dilation=self.dilation, padding=self.padding)
+23
View File
@@ -1,6 +1,29 @@
from examples.mlperf.metrics import dice_score
from tinygrad import Tensor
def dice_ce_loss(pred, tgt):
ce = pred.permute(0, 2, 3, 4, 1).sparse_categorical_crossentropy(tgt.squeeze(1))
dice = (1.0 - dice_score(pred, tgt, argmax=False, to_one_hot_x=False)).mean()
return (dice + ce) / 2
def sigmoid_focal_loss(pred:Tensor, tgt:Tensor, alpha:float=0.25, gamma:float=2.0, reduction:str="none") -> Tensor:
assert reduction in ["mean", "sum", "none"], f"unsupported reduction {reduction}"
p, ce_loss = pred.sigmoid(), pred.binary_crossentropy_logits(tgt, reduction="none")
p_t = p * tgt + (1 - p) * (1 - tgt)
loss = ce_loss * ((1 - p_t) ** gamma)
if alpha >= 0:
alpha_t = alpha * tgt + (1 - alpha) * (1 - tgt)
loss = loss * alpha_t
if reduction == "mean": loss = loss.mean()
elif reduction == "sum": loss = loss.sum()
return loss
def l1_loss(pred:Tensor, tgt:Tensor, reduction:str="none") -> Tensor:
assert reduction in ["mean", "sum", "none"], f"unsupported reduction {reduction}"
loss = (pred - tgt).abs()
if reduction == "mean": loss = loss.mean()
elif reduction == "sum": loss = loss.sum()
return loss
+34 -33
View File
@@ -81,47 +81,43 @@ def eval_unet3d():
def eval_retinanet():
# RetinaNet with ResNeXt50_32X4D
from examples.mlperf.dataloader import batch_load_retinanet
from extra.datasets.openimages import normalize, download_dataset, BASEDIR
from extra.models.resnet import ResNeXt50_32X4D
from extra.models.retinanet import RetinaNet
mdl = RetinaNet(ResNeXt50_32X4D())
mdl.load_from_pretrained()
input_mean = Tensor([0.485, 0.456, 0.406]).reshape(1, -1, 1, 1)
input_std = Tensor([0.229, 0.224, 0.225]).reshape(1, -1, 1, 1)
def input_fixup(x):
x = x.permute([0,3,1,2]) / 255.0
x -= input_mean
x /= input_std
return x
from extra.datasets.openimages import download_dataset, iterate, BASEDIR
from pycocotools.coco import COCO
from pycocotools.cocoeval import COCOeval
from contextlib import redirect_stdout
coco = COCO(download_dataset(base_dir:=getenv("BASE_DIR", BASEDIR), 'validation'))
tlog("imports")
mdl = RetinaNet(ResNeXt50_32X4D())
mdl.load_from_pretrained()
tlog("loaded models")
coco = COCO(download_dataset(base_dir:=getenv("BASEDIR", BASEDIR), 'validation'))
coco_eval = COCOeval(coco, iouType="bbox")
coco_evalimgs, evaluated_imgs, ncats, narea = [], [], len(coco_eval.params.catIds), len(coco_eval.params.areaRng)
tlog("loaded dataset")
from tinygrad.engine.jit import TinyJit
mdlrun = TinyJit(lambda x: mdl(input_fixup(x)).realize())
n, bs = 0, 8
iterator = batch_load_retinanet(coco, True, Path(base_dir), getenv("BS", 8), shuffle=False)
def data_get():
x, img_ids, img_sizes, cookie = next(iterator)
return x.to(Device.DEFAULT).realize(), img_ids, img_sizes, cookie
n = 0
proc = data_get()
tlog("loaded initial data")
st = time.perf_counter()
for x, targets in iterate(coco, base_dir, bs):
dat = Tensor(x.astype(np.float32))
mt = time.perf_counter()
if dat.shape[0] == bs:
outs = mdlrun(dat).numpy()
else:
mdlrun._jit_cache = []
outs = mdl(input_fixup(dat)).numpy()
et = time.perf_counter()
predictions = mdl.postprocess_detections(outs, input_size=dat.shape[1:3], orig_image_sizes=[t["image_size"] for t in targets])
ext = time.perf_counter()
n += len(targets)
print(f"[{n}/{len(coco.imgs)}] == {(mt-st)*1000:.2f} ms loading data, {(et-mt)*1000:.2f} ms to run model, {(ext-et)*1000:.2f} ms for postprocessing")
img_ids = [t["image_id"] for t in targets]
coco_results = [{"image_id": targets[i]["image_id"], "category_id": label, "bbox": box.tolist(), "score": score}
while proc is not None:
GlobalCounters.reset()
proc = (mdl(normalize(proc[0])), proc[1], proc[2], proc[3])
run = time.perf_counter()
# load the next data here
try: next_proc = data_get()
except StopIteration: next_proc = None
nd = time.perf_counter()
predictions, img_ids = mdl.postprocess_detections(proc[0].numpy(), orig_image_sizes=proc[2]), proc[1]
pd = time.perf_counter()
coco_results = [{"image_id": img_ids[i], "category_id": label, "bbox": box.tolist(), "score": score}
for i, prediction in enumerate(predictions) for box, score, label in zip(*prediction.values())]
with redirect_stdout(None):
coco_eval.cocoDt = coco.loadRes(coco_results)
@@ -129,13 +125,18 @@ def eval_retinanet():
coco_eval.evaluate()
evaluated_imgs.extend(img_ids)
coco_evalimgs.append(np.array(coco_eval.evalImgs).reshape(ncats, narea, len(img_ids)))
st = time.perf_counter()
n += len(proc[0])
et = time.perf_counter()
tlog(f"****** {(run-st)*1000:7.2f} ms to enqueue, {(et-run)*1000:7.2f} ms to realize ({(nd-run)*1000:7.2f} ms fetching, {(pd-run)*1000:4.2f} ms postprocess_detections). {(len(proc))/(et-st):8.2f} examples/sec. {GlobalCounters.global_ops*1e-12/(et-st):5.2f} TFLOPS")
st = et
proc, next_proc = next_proc, None
coco_eval.params.imgIds = evaluated_imgs
coco_eval._paramsEval.imgIds = evaluated_imgs
coco_eval.evalImgs = list(np.concatenate(coco_evalimgs, -1).flatten())
coco_eval.accumulate()
coco_eval.summarize()
tlog("done")
def eval_rnnt():
# RNN-T
+426 -69
View File
@@ -1,11 +1,11 @@
import os, time, math, functools
import os, time, math, functools, random
from pathlib import Path
import multiprocessing
from tinygrad import Device, GlobalCounters, Tensor, TinyJit, dtypes
from tinygrad.helpers import getenv, BEAM, WINO, round_up, diskcache_clear, FUSE_CONV_BW
from tinygrad.helpers import getenv, BEAM, WINO, round_up, diskcache_clear, FUSE_CONV_BW, Profiling
from tinygrad.nn.state import get_parameters, get_state_dict, safe_load, safe_save
from tinygrad.nn.optim import LAMB, LARS, SGD, OptimizerGroup
from tinygrad.nn.optim import LAMB, LARS, SGD, OptimizerGroup, Adam
from extra.lr_scheduler import LRSchedulerGroup
from examples.mlperf.helpers import get_training_state, load_training_state
@@ -273,7 +273,7 @@ def train_resnet():
else:
it = iter(tqdm(batch_load_resnet(batch_size=EVAL_BS, val=True, shuffle=False, pad_first_batch=True), total=steps_in_val_epoch))
i, proc = 0, data_get(it)
prev_cookies = []
while proc is not None:
GlobalCounters.reset()
@@ -343,8 +343,347 @@ def train_resnet():
safe_save(get_training_state(model, optimizer_group, scheduler_group), fn)
def train_retinanet():
# TODO: Retinanet
pass
from contextlib import redirect_stdout
from examples.mlperf.dataloader import batch_load_retinanet
from examples.mlperf.initializers import FrozenBatchNorm2dRetinaNet, Conv2dNormalRetinaNet, Conv2dKaimingUniformRetinaNet, Linear, Conv2dRetinaNet
from extra.datasets.openimages import MLPERF_CLASSES, BASEDIR, download_dataset, normalize, get_dataset_count
from extra.models import resnet, retinanet
from pycocotools.coco import COCO
from pycocotools.cocoeval import COCOeval
from tinygrad.helpers import colored
from typing import Iterator
import numpy as np
config, target_metric = {}, 0.34
config["SEED"] = SEED = getenv("SEED", random.SystemRandom().randint(0, 2**32 - 1))
Tensor.manual_seed(SEED)
NUM_CLASSES = len(MLPERF_CLASSES)
BASEDIR = getenv("BASEDIR", BASEDIR)
BENCHMARK = getenv("BENCHMARK")
INITMLPERF = getenv("INITMLPERF")
RUNMLPERF = getenv("RUNMLPERF")
if getenv("LOGMLPERF"):
from mlperf_logging import mllog
import mlperf_logging.mllog.constants as mllog_constants
mllog.config(filename=f"result_retinanet_{SEED}.log")
mllog.config(root_dir=Path(__file__).parents[3].as_posix())
MLLOGGER = mllog.get_mllogger()
MLLOGGER.logger.propagate = False
if INITMLPERF:
assert BENCHMARK, "BENCHMARK must be set for INITMLPERF"
MLLOGGER.event(key=mllog_constants.SUBMISSION_ORG, value="tinycorp")
MLLOGGER.event(key=mllog_constants.SUBMISSION_PLATFORM, value=getenv("SUBMISSION_PLATFORM", "tinybox"))
MLLOGGER.event(key=mllog_constants.SUBMISSION_DIVISION, value=mllog_constants.CLOSED)
MLLOGGER.event(key=mllog_constants.SUBMISSION_STATUS, value=mllog_constants.ONPREM)
MLLOGGER.event(key=mllog_constants.SUBMISSION_BENCHMARK, value=mllog_constants.RETINANET)
diskcache_clear()
MLLOGGER.event(key=mllog_constants.CACHE_CLEAR, value=True)
MLLOGGER.start(key=mllog_constants.INIT_START)
if RUNMLPERF:
MLLOGGER.start(key=mllog_constants.RUN_START)
MLLOGGER.event(key=mllog_constants.SEED, value=SEED)
else:
MLLOGGER = None
config["gpus"] = GPUS = [f"{Device.DEFAULT}:{i}" for i in range(getenv("GPUS", 6))]
for x in GPUS: Device[x]
print(f"training on {GPUS}")
def _freeze_backbone_layers(backbone:resnet.ResNet, trainable_layers:int):
layers_to_train = ["layer4", "layer3", "layer2", "layer1", "conv1"][:trainable_layers]
for k, v in get_state_dict(backbone).items():
if all([not k.startswith(layer) for layer in layers_to_train]):
v.requires_grad = False
def _data_get(it:Iterator[tuple[Tensor, ...]], val:bool=False):
if val:
x, img_ids, img_sizes, cookie = next(it)
return x.shard(GPUS, axis=0), img_ids, img_sizes, cookie
x, y_boxes, y_labels, matches, anchors, cookie = next(it)
return x.shard(GPUS, axis=0), y_boxes.shard(GPUS, axis=0), y_labels.shard(GPUS, axis=0), matches.shard(GPUS, axis=0), anchors.shard(GPUS, axis=0), cookie
def _fake_data_get(bs:int, val:bool=False):
x = Tensor.empty(bs, 800, 800, 3, dtype=dtypes.uint8)
if val:
img_ids, img_sizes = [0] * bs, [(800, 800)] * bs
return x.shard(GPUS, axis=0), img_ids, img_sizes, None
y_boxes = Tensor.empty(bs, 120087, 4, dtype=dtypes.float32)
y_labels = Tensor.empty(bs, 120087, dtype=dtypes.int64)
matches = Tensor.empty(bs, 120087, dtype=dtypes.int64)
anchors = Tensor.empty(bs, 120087, 4, dtype=dtypes.float64)
return x.shard(GPUS, axis=0), y_boxes.shard(GPUS, axis=0), y_labels.shard(GPUS, axis=0), matches.shard(GPUS, axis=0), anchors.shard(GPUS, axis=0), None
@TinyJit
def _train_step(model, optim, loss_scaler, x, **kwargs):
optim.zero_grad()
losses = model(normalize(x, GPUS), **kwargs)
loss = sum(losses.values())
(loss * loss_scaler).backward()
for t in optim.params: t.grad = t.grad / loss_scaler
optim.step()
return loss.realize(), losses
@TinyJit
def _eval_step(model, x, **kwargs):
out = model(normalize(x, GPUS), **kwargs)
# reassemble on GPUS[0] before sending back to CPU for speed
return out.to(GPUS[0]).realize()
# ** hyperparameters **
config["BS"] = BS = getenv("BS", 16 * len(GPUS) if dtypes.default_float == dtypes.float16 else 12 * len(GPUS))
config["EVAL_BS"] = EVAL_BS = getenv("EVAL_BS", BS)
config["EPOCHS"] = EPOCHS = getenv("EPOCHS", 4)
config["TRAIN_BEAM"] = TRAIN_BEAM = getenv("TRAIN_BEAM", BEAM.value)
config["EVAL_BEAM"] = EVAL_BEAM = getenv("EVAL_BEAM", BEAM.value)
config["LR"] = lr = getenv("LR", 9.5e-5 * (BS / 96))
config["LOSS_SCALER"] = loss_scaler = getenv("LOSS_SCALER", 2**11 if dtypes.default_float == dtypes.float16 else 1.0)
config["DEFAULT_FLOAT"] = dtypes.default_float.name
config["EVAL_FREQ"] = eval_freq = getenv("EVAL_FREQ", 1)
# ** initialize wandb **
if (WANDB:=getenv("WANDB")):
import wandb
wandb.init(config=config, project="MLPerf-RetinaNet")
# ** model initializers **
resnet.BatchNorm = FrozenBatchNorm2dRetinaNet
resnet.Linear = Linear
resnet.Conv2d = Conv2dRetinaNet
retinanet.ConvHead = Conv2dNormalRetinaNet
retinanet.ConvClassificationHeadLogits = functools.partial(Conv2dNormalRetinaNet, prior_prob=0.01)
retinanet.ConvFPN = Conv2dKaimingUniformRetinaNet
# ** model setup **
backbone = resnet.ResNeXt50_32X4D(num_classes=None)
if RUNMLPERF:
backbone.load_from_pretrained()
_freeze_backbone_layers(backbone, 3)
model = retinanet.RetinaNet(backbone, num_classes=NUM_CLASSES)
params = get_parameters(model)
if not RUNMLPERF:
# for init, zero out all weights
for p in params:
p = p.assign(Tensor.zeros_like(p).contiguous()).realize()
if len(GPUS) > 1:
for p in params: p.to_(GPUS)
step_times, start_epoch = [], 0
# ** optimizer **
optim = Adam(params, lr=lr)
# ** dataset **
config["STEPS_IN_TRAIN_EPOCH"] = steps_in_train_epoch = round_up(get_dataset_count((base_dir_path:=Path(BASEDIR)), False), BS) // BS
config["STEPS_IN_VAL_EPOCH"] = steps_in_val_epoch = (round_up(get_dataset_count(base_dir_path, True), EVAL_BS) // EVAL_BS)
# log mlperf hparams
if MLLOGGER:
if RUNMLPERF:
MLLOGGER.event(key=mllog_constants.GLOBAL_BATCH_SIZE, value=config["BS"])
MLLOGGER.event(key=mllog_constants.TRAIN_SAMPLES, value=config["STEPS_IN_TRAIN_EPOCH"])
MLLOGGER.event(key=mllog_constants.EVAL_SAMPLES, value=config["STEPS_IN_VAL_EPOCH"])
MLLOGGER.event(key=mllog_constants.EPOCH_COUNT, value=config["EPOCHS"])
MLLOGGER.event(key=mllog_constants.FIRST_EPOCH_NUM, value=start_epoch)
MLLOGGER.event(key=mllog_constants.OPT_NAME, value=mllog_constants.ADAM)
MLLOGGER.event(key=mllog_constants.OPT_BASE_LR, value=config["LR"])
MLLOGGER.event(key=mllog_constants.OPT_WEIGHT_DECAY, value=0)
MLLOGGER.event(key=mllog_constants.OPT_LR_WARMUP_EPOCHS, value=0)
MLLOGGER.event(key=mllog_constants.OPT_LR_WARMUP_FACTOR, value=0)
MLLOGGER.event(key=mllog_constants.GRADIENT_ACCUMULATION_STEPS, value=1)
if RUNMLPERF:
train_dataset = COCO(download_dataset(BASEDIR, "train"))
val_dataset = COCO(download_dataset(BASEDIR, "validation"))
coco_val = COCOeval(cocoGt=val_dataset, iouType="bbox")
print(f"training with batch size {BS} for {EPOCHS} epochs")
for e in range(start_epoch, EPOCHS):
# ** training loop **
if MLLOGGER and RUNMLPERF:
MLLOGGER.start(key=mllog_constants.EPOCH_START, value=e + 1, metadata={"epoch_num": e + 1})
BEAM.value = TRAIN_BEAM
if not RUNMLPERF:
i, proc = 0, _fake_data_get(BS)
else:
train_dataloader = batch_load_retinanet(train_dataset, False, base_dir_path, batch_size=BS, seed=SEED)
it = iter(tqdm(train_dataloader, total=steps_in_train_epoch, desc=f"epoch {e + 1}", disable=BENCHMARK))
i, proc = 0, _data_get(it)
prev_cookies = []
st = time.perf_counter()
while proc is not None:
GlobalCounters.reset()
x, y_bboxes, y_labels, matches, anchors, proc = proc
loss, losses = _train_step(model, optim, loss_scaler, x, labels=y_labels, matches=matches, anchors=anchors, bboxes=y_bboxes)
pt = time.perf_counter()
if len(prev_cookies) == getenv("STORE_COOKIES", 1): prev_cookies = [] # free previous cookies after gpu work has been enqueued
try:
if not RUNMLPERF:
next_proc = _fake_data_get(BS)
else:
next_proc = _data_get(it)
except StopIteration:
next_proc = None
dt = time.perf_counter()
device_str = loss.device if isinstance(loss.device, str) else f"{loss.device[0]} * {len(loss.device)}"
loss = loss.item()
cl = time.perf_counter()
if BENCHMARK: step_times.append(cl - st)
if not math.isfinite(loss):
print("loss is nan")
return
tqdm.write(
f"{i:5} {((cl - st)) * 1000.0:7.2f} ms run, {(pt - st) * 1000.0:7.2f} ms python, {(dt - pt) * 1000.0:6.2f} ms fetch data, "
f"{(cl - dt) * 1000.0:7.2f} ms {device_str}, {loss:5.2f} loss, {losses['classification_loss'].item():5.4f} classification loss, {losses['regression_loss'].item():5.4f} regression loss, "
f"{optim.lr.numpy()[0]:.6f} LR, {GlobalCounters.mem_used / 1e9:.2f} GB used, {GlobalCounters.global_ops * 1e-9 / (cl - st):9.2f} GFLOPS"
)
if WANDB:
wandb.log({"lr": optim.lr.numpy(), "train/loss": loss, "train/classification_loss": losses["classification_loss"].item(), "train/regression_loss": losses["regression_loss"].item(),
"train/step_time": cl - st, "train/python_time": pt - st, "train/data_time": dt - pt, "train/cl_time": cl - dt,
"train/GFLOPS": GlobalCounters.global_ops * 1e-9 / (cl - st), "epoch": e + (i + 1) / steps_in_train_epoch})
st = cl
prev_cookies.append(proc)
proc, next_proc = next_proc, None # return old cookie
i += 1
if i == BENCHMARK:
assert not math.isnan(loss)
median_step_time = sorted(step_times)[(BENCHMARK + 1) // 2] # in seconds
estimated_total_minutes = int(median_step_time * steps_in_train_epoch * EPOCHS / 60)
print(f"Estimated training time: {estimated_total_minutes // 60}h{estimated_total_minutes % 60}m")
print(f"epoch global_ops: {steps_in_train_epoch * GlobalCounters.global_ops:_}, "
f"epoch global_mem: {steps_in_train_epoch * GlobalCounters.global_mem:_}")
# if we are doing beam search, run the first eval too
if (TRAIN_BEAM or EVAL_BEAM) and e == start_epoch: break
return
if MLLOGGER and RUNMLPERF:
MLLOGGER.event(key=mllog_constants.EPOCH_STOP, value=e + 1, metadata={"epoch_num": e + 1})
# ** eval loop **
if (e + 1) % eval_freq == 0:
if MLLOGGER and RUNMLPERF:
MLLOGGER.start(key=mllog_constants.EVAL_START, value=e + 1, metadata={"epoch_num": e + 1})
BEAM.value = EVAL_BEAM
if getenv("RESET_STEP", 1): _train_step.reset()
with Tensor.train(mode=False), Tensor.test():
if not RUNMLPERF:
i, proc = 0, _fake_data_get(EVAL_BS, val=(val:=True))
else:
val_dataloader = batch_load_retinanet(val_dataset, (val:=True), Path(BASEDIR), batch_size=EVAL_BS, shuffle=False, seed=SEED)
it = iter(tqdm(val_dataloader, total=steps_in_val_epoch))
i, proc = 0, _data_get(it, val=val)
val_img_ids, val_imgs, ncats, narea = [], [], len(coco_val.params.catIds), len(coco_val.params.areaRng)
eval_times, prev_cookies = [], []
while proc is not None:
GlobalCounters.reset()
st = time.time()
out, img_ids, img_sizes, proc = _eval_step(model, (x:=proc[0])).numpy(), proc[1], proc[2], proc[3]
if RUNMLPERF:
out = model.postprocess_detections(out, input_size=x.shape[1:3], orig_image_sizes=img_sizes)
coco_results = [{"image_id": img_ids[i], "category_id": label, "bbox": box.tolist(), "score": score}
for i, prediction in enumerate(out) for box, score, label in zip(*prediction.values())]
with redirect_stdout(None):
coco_val.cocoDt = val_dataset.loadRes(coco_results)
coco_val.params.imgIds = img_ids
coco_val.evaluate()
val_img_ids.extend(img_ids)
val_imgs.append(np.array(coco_val.evalImgs).reshape(ncats, narea, len(img_ids)))
if len(prev_cookies) == getenv("STORE_COOKIES", 1): prev_cookies = [] # free previous cookies after gpu work has been enqueued
try:
if not RUNMLPERF:
next_proc = _fake_data_get(EVAL_BS, val=val)
else:
next_proc = _data_get(it, val=val)
except StopIteration:
next_proc = None
prev_cookies.append(proc)
proc, next_proc = next_proc, None
i += 1
et = time.time()
eval_times.append(et - st)
if i == BENCHMARK:
# assume INITMLPERF has BENCHMARK set
if MLLOGGER and INITMLPERF:
MLLOGGER.event(key=mllog_constants.INIT_STOP)
return
if getenv("RESET_STEP", 1): _eval_step.reset()
total_fw_time = sum(eval_times) / len(eval_times)
if RUNMLPERF:
coco_val.params.imgIds = val_img_ids
coco_val._paramsEval.imgIds = val_img_ids
coco_val.evalImgs = list(np.concatenate(val_imgs, -1).flatten())
coco_val.accumulate()
coco_val.summarize()
val_metric = coco_val.stats[0]
tqdm.write(f"eval time: {total_fw_time:.2f}, eval metric: {val_metric:.4f}")
if WANDB:
wandb.log({"eval/forward_time": total_fw_time, "eval/metric": val_metric, "epoch": e + 1})
if MLLOGGER:
MLLOGGER.event(key=mllog_constants.EVAL_ACCURACY, value=val_metric, metadata={"epoch_num": e + 1}, clear_line=True)
MLLOGGER.end(key=mllog_constants.EVAL_STOP, value=e + 1, metadata={"epoch_num": e + 1})
if val_metric >= target_metric:
print(colored(f"target metric reached: {val_metric:.2f}/{target_metric:.2f}", color="green"))
if MLLOGGER:
MLLOGGER.end(key=mllog_constants.RUN_STOP, metadata={"status": mllog_constants.SUCCESS})
break
def train_unet3d():
"""
@@ -446,7 +785,7 @@ def train_unet3d():
loss.backward()
optim.step()
return loss.realize()
@Tensor.train(mode=False)
@Tensor.test()
def eval_step(model, x, y):
@@ -455,7 +794,7 @@ def train_unet3d():
loss = dice_ce_loss(y_hat, y)
score = dice_score(y_hat, y)
return loss.realize(), score.realize()
if WANDB: wandb.init(config=config, project=PROJ_NAME)
step_times, start_epoch = [], 1
@@ -464,7 +803,7 @@ def train_unet3d():
next_eval_at = start_eval_at
print(f"Training on {GPUS}")
if BENCHMARK: print("Benchmarking UNet3D")
else: print(f"Start evaluation at epoch {start_eval_at} and every {evaluate_every} epoch(s) afterwards")
@@ -551,7 +890,7 @@ def train_unet3d():
if mean_dice >= TARGET_METRIC:
is_successful = True
save_checkpoint(get_state_dict(model), f"./ckpts/unet3d.safe")
save_checkpoint(get_state_dict(model), "./ckpts/unet3d.safe")
elif mean_dice < 1e-6:
print("Model diverging. Aborting.")
diverged = True
@@ -575,33 +914,41 @@ def train_rnnt():
def train_step_bert(model, optimizer, scheduler, loss_scaler:float, input_ids:Tensor, segment_ids:Tensor, attention_mask:Tensor,
masked_positions:Tensor, masked_lm_ids:Tensor, masked_lm_weights:Tensor, next_sentence_labels:Tensor, GPUS):
for t in [input_ids, segment_ids, attention_mask, masked_positions, masked_lm_ids, masked_lm_weights, next_sentence_labels]:
t.shard_(GPUS, axis=0)
if len(GPUS) > 1: t.shard_(GPUS, axis=0)
else: t.to_(GPUS[0])
optimizer.zero_grad()
lm_logits, seq_relationship_logits = model(input_ids, attention_mask, masked_positions, segment_ids)
loss = model.loss(lm_logits, seq_relationship_logits, masked_lm_ids, masked_lm_weights, next_sentence_labels)
(loss * loss_scaler).backward()
global_norm = Tensor([0.0], dtype=dtypes.float32, device=optimizer[0].device).realize()
for p in optimizer.params:
global_norm = Tensor([0.0], dtype=dtypes.float32, device=optimizer[0].device)
for p in optimizer.params:
p.grad = p.grad / loss_scaler
global_norm += p.grad.float().square().sum()
global_norm = global_norm.sqrt()
for p in optimizer.params: p.grad = (p.grad / Tensor.where(global_norm > 1.0, global_norm, 1.0)).cast(p.grad.dtype)
global_norm = global_norm.sqrt().contiguous()
for p in optimizer.params:
p.grad = (global_norm > 1.0).where((p.grad/global_norm).cast(p.grad.dtype), p.grad)
optimizer.step()
scheduler.step()
return loss.realize(), global_norm.realize()
# TODO: no to("CPU") here because it blocks and messes the python time
Tensor.realize(loss, global_norm, optimizer.optimizers[0].lr)
return loss, global_norm, optimizer.optimizers[0].lr
@TinyJit
def eval_step_bert(model, input_ids:Tensor, segment_ids:Tensor, attention_mask:Tensor, masked_positions:Tensor, masked_lm_ids:Tensor,
masked_lm_weights:Tensor, next_sentence_labels:Tensor, GPUS):
for t in [input_ids, segment_ids, attention_mask, masked_positions, masked_lm_ids, masked_lm_weights, next_sentence_labels]:
t.shard_(GPUS, axis=0)
if len(GPUS) > 1: t.shard_(GPUS, axis=0)
else: t.to_(GPUS[0])
lm_logits, seq_relationship_logits = model(input_ids, attention_mask, masked_positions, segment_ids)
masked_lm_accuracy, seq_relationship_accuracy, masked_lm_loss, next_sentence_loss = \
model.accuracy(lm_logits, seq_relationship_logits, masked_lm_ids, masked_lm_weights, next_sentence_labels)
return masked_lm_accuracy.realize(), seq_relationship_accuracy.realize(), masked_lm_loss.realize(), next_sentence_loss.realize()
for t in [masked_lm_accuracy, seq_relationship_accuracy, masked_lm_loss, next_sentence_loss]:
t.to_("CPU")
Tensor.realize(masked_lm_accuracy, seq_relationship_accuracy, masked_lm_loss, next_sentence_loss)
return masked_lm_accuracy, seq_relationship_accuracy, masked_lm_loss, next_sentence_loss
def train_bert():
# NOTE: pip install tensorflow, wandb required
@@ -630,7 +977,7 @@ def train_bert():
MLLOGGER.logger.propagate = False
if INITMLPERF:
assert BENCHMARK, f"BENCHMARK must be set for INITMLPERF"
assert BENCHMARK, "BENCHMARK must be set for INITMLPERF"
MLLOGGER.event(key=mllog_constants.SUBMISSION_ORG, value="tinycorp")
MLLOGGER.event(key=mllog_constants.SUBMISSION_PLATFORM, value=getenv("SUBMISSION_PLATFORM", "tinybox"))
MLLOGGER.event(key=mllog_constants.SUBMISSION_DIVISION, value=mllog_constants.CLOSED)
@@ -651,9 +998,11 @@ def train_bert():
# ** hyperparameters **
BS = config["GLOBAL_BATCH_SIZE"] = getenv("BS", 11 * len(GPUS) if dtypes.default_float in (dtypes.float16, dtypes.bfloat16) else 8 * len(GPUS))
EVAL_BS = config["EVAL_BS"] = getenv("EVAL_BS", 1 * len(GPUS))
max_lr = config["OPT_BASE_LEARNING_RATE"] = getenv("OPT_BASE_LEARNING_RATE", 0.00011 * math.sqrt(BS/66))
max_lr = config["OPT_BASE_LEARNING_RATE"] = getenv("OPT_BASE_LEARNING_RATE", 0.000175 * math.sqrt(BS/96))
opt_lamb_beta_1 = config["OPT_LAMB_BETA_1"] = getenv("OPT_LAMB_BETA_1", 0.9)
opt_lamb_beta_2 = config["OPT_LAMB_BETA_2"] = getenv("OPT_LAMB_BETA_2", 0.999)
train_steps = config["TRAIN_STEPS"] = getenv("TRAIN_STEPS", 3630000 // BS)
train_steps = config["TRAIN_STEPS"] = getenv("TRAIN_STEPS", 3600000 // BS)
warmup_steps = config["NUM_WARMUP_STEPS"] = getenv("NUM_WARMUP_STEPS", 1)
max_eval_steps = config["MAX_EVAL_STEPS"] = getenv("MAX_EVAL_STEPS", (10000 + EVAL_BS - 1) // EVAL_BS) # EVAL_BS * MAX_EVAL_STEPS >= 10000
eval_step_freq = config["EVAL_STEP_FREQ"] = getenv("EVAL_STEP_FREQ", int((math.floor(0.05 * (230.23 * BS + 3000000) / 25000) * 25000) / BS)) # Round down
@@ -662,7 +1011,7 @@ def train_bert():
save_ckpt_dir = config["SAVE_CKPT_DIR"] = getenv("SAVE_CKPT_DIR", "./ckpts")
init_ckpt = config["INIT_CKPT_DIR"] = getenv("INIT_CKPT_DIR", BASEDIR)
loss_scaler = config["LOSS_SCALER"] = getenv("LOSS_SCALER", 2.0**10 if dtypes.default_float == dtypes.float16 else 1.0)
loss_scaler = config["LOSS_SCALER"] = getenv("LOSS_SCALER", 2.0**11 if dtypes.default_float == dtypes.float16 else 1.0)
decay = config["DECAY"] = getenv("DECAY", 0.01)
epsilon = config["EPSILON"] = getenv("EPSILON", 1e-6)
poly_power = config["POLY_POWER"] = getenv("POLY_POWER", 1.0)
@@ -696,8 +1045,9 @@ def train_bert():
p = p.assign(Tensor.zeros_like(p).contiguous()).realize()
parameters = get_parameters(model)
for p in parameters:
p.to_(GPUS)
if len(GPUS) > 1:
for p in parameters:
p.to_(GPUS)
# ** Log run config **
for key, value in config.items(): print(f'HParam: "{key}": {value}')
@@ -705,8 +1055,8 @@ def train_bert():
# ** Optimizer **
parameters_no_wd = [v for k, v in get_state_dict(model).items() if "bias" in k or "LayerNorm" in k]
parameters = [x for x in parameters if x not in set(parameters_no_wd)]
optimizer_wd = LAMB(parameters, lr=max_lr, eps=epsilon, weight_decay=decay, adam=False)
optimizer_no_wd = LAMB(parameters_no_wd, lr=max_lr, eps=epsilon, weight_decay=0.0, adam=False)
optimizer_wd = LAMB(parameters, lr=max_lr, b1=opt_lamb_beta_1, b2=opt_lamb_beta_2, eps=epsilon, weight_decay=decay, adam=False)
optimizer_no_wd = LAMB(parameters_no_wd, lr=max_lr, b1=opt_lamb_beta_1, b2=opt_lamb_beta_2, eps=epsilon, weight_decay=0.0, adam=False)
optimizer_group = OptimizerGroup(optimizer_wd, optimizer_no_wd)
# ** LR scheduler **
@@ -725,8 +1075,8 @@ def train_bert():
MLLOGGER.event(key=mllog_constants.OPT_NAME, value="LAMB")
MLLOGGER.event(key=mllog_constants.OPT_BASE_LR, value=config["OPT_BASE_LEARNING_RATE"])
MLLOGGER.event(key=mllog_constants.OPT_LAMB_WEIGHT_DECAY, value=config["DECAY"])
MLLOGGER.event(key=mllog_constants.OPT_LAMB_BETA_1, value=optimizer_wd.b1)
MLLOGGER.event(key=mllog_constants.OPT_LAMB_BETA_2, value=optimizer_wd.b2)
MLLOGGER.event(key=mllog_constants.OPT_LAMB_BETA_1, value=config["OPT_LAMB_BETA_1"])
MLLOGGER.event(key=mllog_constants.OPT_LAMB_BETA_2, value=config["OPT_LAMB_BETA_2"])
MLLOGGER.event(key=mllog_constants.OPT_LAMB_LR_DECAY_POLY_POWER, value=config["POLY_POWER"])
MLLOGGER.event(key=mllog_constants.OPT_LAMB_EPSILON, value=config["EPSILON"])
@@ -769,54 +1119,57 @@ def train_bert():
MLLOGGER.start(key=mllog_constants.EPOCH_START, value=i*BS, metadata={"epoch_num": i*BS})
while train_data is not None and i < train_steps and not achieved:
Tensor.training = True
BEAM.value = TRAIN_BEAM
st = time.perf_counter()
GlobalCounters.reset()
loss, global_norm = train_step_bert(model, optimizer_group, scheduler_group, loss_scaler,
train_data["input_ids"], train_data["segment_ids"], train_data["input_mask"], train_data["masked_lm_positions"], \
train_data["masked_lm_ids"], train_data["masked_lm_weights"], train_data["next_sentence_labels"], GPUS)
if getenv("TRAIN", 1):
Tensor.training = True
BEAM.value = TRAIN_BEAM
st = time.perf_counter()
GlobalCounters.reset()
loss, global_norm, lr = train_step_bert(model, optimizer_group, scheduler_group, loss_scaler,
train_data["input_ids"], train_data["segment_ids"], train_data["input_mask"], train_data["masked_lm_positions"], \
train_data["masked_lm_ids"], train_data["masked_lm_weights"], train_data["next_sentence_labels"], GPUS)
pt = time.perf_counter()
pt = time.perf_counter()
try:
next_data = next(train_it)
except StopIteration:
next_data = None
try:
next_data = next(train_it)
except StopIteration:
next_data = None
dt = time.perf_counter()
dt = time.perf_counter()
device_str = loss.device if isinstance(loss.device, str) else f"{loss.device[0]} * {len(loss.device)}"
loss = loss.item()
device_str = parameters[0].device if isinstance(parameters[0].device, str) else f"{parameters[0].device[0]} * {len(parameters[0].device)}"
loss = loss.item()
assert not math.isnan(loss)
lr = lr.item()
cl = time.perf_counter()
if BENCHMARK: step_times.append(cl - st)
cl = time.perf_counter()
if BENCHMARK: step_times.append(cl - st)
tqdm.write(
f"{i:5} {((cl - st)) * 1000.0:7.2f} ms run, {(pt - st) * 1000.0:7.2f} ms python, {(dt - pt) * 1000.0:6.2f} ms fetch data, "
f"{(cl - dt) * 1000.0:7.2f} ms {device_str}, {loss:5.2f} loss, {optimizer_wd.lr.numpy()[0]:.6f} LR, "
f"{GlobalCounters.mem_used / 1e9:.2f} GB used, {GlobalCounters.global_ops * 1e-9 / (cl - st):9.2f} GFLOPS")
if WANDB:
wandb.log({"lr": optimizer_wd.lr.numpy(), "train/loss": loss, "train/global_norm": global_norm.item(), "train/step_time": cl - st,
"train/python_time": pt - st, "train/data_time": dt - pt, "train/cl_time": cl - dt,
"train/GFLOPS": GlobalCounters.global_ops * 1e-9 / (cl - st), "epoch": (i+1)*BS})
tqdm.write(
f"{i:5} {((cl - st)) * 1000.0:7.2f} ms run, {(pt - st) * 1000.0:7.2f} ms python, {(dt - pt) * 1000.0:6.2f} ms fetch data, "
f"{(cl - dt) * 1000.0:7.2f} ms {device_str}, {loss:5.2f} loss, {lr:.6f} LR, "
f"{GlobalCounters.mem_used / 1e9:.2f} GB used, {GlobalCounters.global_ops * 1e-9 / (cl - st):9.2f} GFLOPS")
if WANDB:
wandb.log({"lr": lr, "train/loss": loss, "train/global_norm": global_norm.item(), "train/step_time": cl - st,
"train/python_time": pt - st, "train/data_time": dt - pt, "train/cl_time": cl - dt,
"train/GFLOPS": GlobalCounters.global_ops * 1e-9 / (cl - st), "epoch": (i+1)*BS})
train_data, next_data = next_data, None
i += 1
train_data, next_data = next_data, None
i += 1
if i == BENCHMARK:
median_step_time = sorted(step_times)[(BENCHMARK + 1) // 2] # in seconds
estimated_total_minutes = int(median_step_time * train_steps / 60)
print(f"Estimated training time: {estimated_total_minutes // 60}h{estimated_total_minutes % 60}m")
print(f"epoch global_ops: {train_steps * GlobalCounters.global_ops:_}, "
f"epoch global_mem: {train_steps * GlobalCounters.global_mem:_}")
if i == BENCHMARK:
median_step_time = sorted(step_times)[(BENCHMARK + 1) // 2] # in seconds
estimated_total_minutes = int(median_step_time * train_steps / 60)
print(f"Estimated training time: {estimated_total_minutes // 60}h{estimated_total_minutes % 60}m")
print(f"epoch global_ops: {train_steps * GlobalCounters.global_ops:_}, "
f"epoch global_mem: {train_steps * GlobalCounters.global_mem:_}")
# ** eval loop **
if i % eval_step_freq == 0 or (BENCHMARK and i == BENCHMARK) or i == train_steps:
if MLLOGGER and RUNMLPERF:
MLLOGGER.start(key=mllog_constants.EVAL_START, value=None, metadata={"epoch_num": i*BS, "step_num": i})
if getenv("RESET_STEP", 0) or INITMLPERF: train_step_bert.reset()
else: train_step_bert.captured.free_intermediates()
if getenv("RESET_STEP"): train_step_bert.reset()
elif getenv("FREE_INTERMEDIATE", 1) and train_step_bert.captured is not None: train_step_bert.captured.free_intermediates()
eval_lm_losses = []
eval_clsf_losses = []
eval_lm_accs = []
@@ -843,14 +1196,15 @@ def train_bert():
et = time.time()
eval_times.append(et - st)
if BENCHMARK and j == BENCHMARK:
if BENCHMARK and (j+1) == min(BENCHMARK, max_eval_steps):
# assume INITMLPERF has BENCHMARK set
if MLLOGGER and INITMLPERF:
MLLOGGER.event(key=mllog_constants.INIT_STOP, value=None)
return
if getenv("RESET_STEP", 0): eval_step_bert.reset()
else: eval_step_bert.captured.free_intermediates()
if getenv("RESET_STEP"): eval_step_bert.reset()
elif getenv("FREE_INTERMEDIATE", 1) and eval_step_bert.captured is not None: eval_step_bert.captured.free_intermediates()
del eval_data
avg_lm_loss = sum(eval_lm_losses) / len(eval_lm_losses)
avg_clsf_loss = sum(eval_clsf_losses) / len(eval_clsf_losses)
@@ -863,7 +1217,7 @@ def train_bert():
if WANDB:
wandb.log({"eval/lm_loss": avg_lm_loss, "eval/clsf_loss": avg_clsf_loss, "eval/lm_accuracy": avg_lm_acc, \
"eval/clsf_accuracy": avg_clsf_acc, "eval/forward_time": avg_fw_time})
"eval/clsf_accuracy": avg_clsf_acc, "eval/forward_time": avg_fw_time, "epoch": (i+1)*BS})
if MLLOGGER and RUNMLPERF:
MLLOGGER.end(key=mllog_constants.EVAL_STOP, value=i*BS, metadata={"epoch_count": i*BS, "step_num": i, "samples_count": config["EVAL_BS"] * config["MAX_EVAL_STEPS"]})
@@ -890,11 +1244,14 @@ def train_bert():
# stop once hitting the target
break
# should not happen, BENCHMARK not properly terminated
if BENCHMARK: assert i < BENCHMARK, i
if getenv("CKPT") and i % save_ckpt_freq == 0:
if MLLOGGER and RUNMLPERF:
if previous_step:
MLLOGGER.end(key=mllog_constants.BLOCK_STOP, value=None, metadata={"first_epoch_num": 1, "epoch_num": 1, "first_step_num": i, "step_num": i, "step_count": i - previous_step})
MLLOGGER.start(key="checkpoint_start", value=None, metadata={"step_num" : i})
MLLOGGER.start(key="checkpoint_start", value=None, metadata={"step_num": i})
if not os.path.exists(ckpt_dir := save_ckpt_dir): os.mkdir(ckpt_dir)
if WANDB and wandb.run is not None:
fn = f"{ckpt_dir}/{time.strftime('%Y%m%d_%H%M%S')}_{wandb.run.id}.safe"
@@ -924,4 +1281,4 @@ if __name__ == "__main__":
nm = f"train_{m}"
if nm in globals():
print(f"training {m}")
globals()[nm]()
with Profiling(enabled=getenv("PYPROFILE")): globals()[nm]()
@@ -0,0 +1,15 @@
#!/bin/bash
export PYTHONPATH="." AMD=1
export MODEL="bert"
export DEFAULT_FLOAT="HALF" GPUS=1 BS=128 EVAL_BS=128
export BEAM=3 BEAM_UOPS_MAX=4000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5
export IGNORE_JIT_FIRST_BEAM=1
# export BEAM_LOG_SURPASS_MAX=1
# export BASEDIR="/raid/datasets/wiki"
export RESET_STEP=1
export BENCHMARK=10 BERT_LAYERS=2 DEBUG=2
python3 examples/mlperf/model_train.py
@@ -0,0 +1,69 @@
# 1. Problem
This problem uses BERT for NLP.
## Requirements
Install tinygrad and mlperf-logging (uncomment mlperf from setup.py) from branch mlperf_training_v5.0.
```
git clone https://github.com/tinygrad/tinygrad.git
python3 -m pip install -e ".[mlperf]"
```
Also install gdown (for dataset), numpy, tqdm and tensorflow.
```
pip install gdown numpy tqdm tensorflow
```
### tinybox_green
Install the p2p driver per [README](https://github.com/tinygrad/open-gpu-kernel-modules/blob/550.54.15-p2p/README.md)
This is the default on production tinybox green.
# 2. Directions
## Steps to download and verify data
### 1. Download raw data
```
BASEDIR="/raid/datasets/wiki" WIKI_TRAIN=1 VERIFY_CHECKSUM=1 python3 extra/datasets/wikipedia_download.py
```
### 2. Preprocess train and validation data
Note: The number of threads used for preprocessing is limited by available memory. With 128GB of RAM, a maximum of 16 threads is recommended.
#### Training:
```
BASEDIR="/raid/datasets/wiki" NUM_WORKERS=16 python3 extra/datasets/wikipedia.py pre-train all
```
Generating a specific topic (Between 0 and 499)
```
BASEDIR="/raid/datasets/wiki" python3 extra/datasets/wikipedia.py pre-train 42
```
#### Validation:
```
BASEDIR="/raid/datasets/wiki" python3 extra/datasets/wikipedia.py pre-eval
```
## Running
### tinybox_green
#### Steps to run benchmark
```
examples/mlperf/training_submission_v5.0/tinycorp/benchmarks/bert/implementations/tinybox_green/run_and_time.sh
```
### tinybox_red
#### Steps to run benchmark
```
examples/mlperf/training_submission_v5.0/tinycorp/benchmarks/bert/implementations/tinybox_red/run_and_time.sh
```
### tinybox_8xMI300X
#### Steps to run benchmark
```
examples/mlperf/training_submission_v5.0/tinycorp/benchmarks/bert/implementations/tinybox_8xMI300X/run_and_time.sh
```
@@ -0,0 +1,14 @@
#!/bin/bash
export PYTHONPATH="." AMD=1
export MODEL="bert"
export DEFAULT_FLOAT="HALF" GPUS=8 BS=1024 EVAL_BS=1024
export OPT_BASE_LEARNING_RATE=0.0011 OPT_LAMB_BETA_1=0.60466 OPT_LAMB_BETA_2=0.85437 DECAY=0.1
export BEAM=3 BEAM_UOPS_MAX=6000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5
export IGNORE_JIT_FIRST_BEAM=1 FREE_INTERMEDIATE=0
export BASEDIR="/raid/datasets/wiki"
export BENCHMARK=10 BERT_LAYERS=2 DEBUG=2
python3 examples/mlperf/model_train.py
@@ -0,0 +1,17 @@
#!/bin/bash
export PYTHONPATH="." AMD=1
export MODEL="bert"
export DEFAULT_FLOAT="HALF" GPUS=8 BS=1024 EVAL_BS=1024
# similar to https://github.com/mlcommons/training_results_v3.1/blob/d06288b2bd675a9d88e0e6181f5bb5626b71ec19/Quanta_Cloud_Technology/results/D54U-3U/bert/result_1.txt#L54
export OPT_BASE_LEARNING_RATE=0.0011 OPT_LAMB_BETA_1=0.60466 OPT_LAMB_BETA_2=0.85437 DECAY=0.1
export TRAIN_STEPS=3900
export BEAM=3 BEAM_UOPS_MAX=6000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5
export IGNORE_JIT_FIRST_BEAM=1 FREE_INTERMEDIATE=0
export BASEDIR="/raid/datasets/wiki"
export WANDB=1 PARALLEL=0
RUNMLPERF=1 python3 examples/mlperf/model_train.py
@@ -0,0 +1,27 @@
#!/bin/bash
export PYTHONPATH="." AMD=1
export MODEL="bert"
export SUBMISSION_PLATFORM="tinybox_8xMI300X"
export DEFAULT_FLOAT="HALF" GPUS=8 BS=1024 EVAL_BS=1024
# similar to https://github.com/mlcommons/training_results_v3.1/blob/d06288b2bd675a9d88e0e6181f5bb5626b71ec19/Quanta_Cloud_Technology/results/D54U-3U/bert/result_1.txt#L54
export OPT_BASE_LEARNING_RATE=0.0011 OPT_LAMB_BETA_1=0.60466 OPT_LAMB_BETA_2=0.85437 DECAY=0.1
export TRAIN_STEPS=3900
export BEAM=3 BEAM_UOPS_MAX=6000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5
export IGNORE_JIT_FIRST_BEAM=1 FREE_INTERMEDIATE=0
export BASEDIR="/raid/datasets/wiki"
# pip install -e ".[mlperf]"
export LOGMLPERF=1
export SEED=$RANDOM
DATETIME=$(date "+%m%d%H%M")
LOGFILE="bert_8xMI300x_${DATETIME}_${SEED}.log"
# init # TODO: without DEBUG=2 it hangs
BENCHMARK=10 INITMLPERF=1 BERT_LAYERS=2 DEBUG=2 python3 examples/mlperf/model_train.py | tee $LOGFILE
# run
PARALLEL=0 RUNMLPERF=1 python3 examples/mlperf/model_train.py | tee -a $LOGFILE
@@ -4,24 +4,20 @@ This problem uses BERT for NLP.
## Requirements
Install tinygrad and mlperf-logging from master.
Install tinygrad and mlperf-logging (uncomment mlperf from setup.py) from branch mlperf_training_v5.0.
```
git clone https://github.com/tinygrad/tinygrad.git
python3 -m pip install -e ".[mlperf]"
```
Also install tqdm and tensorflow.
Also install gdown (for dataset), numpy, tqdm and tensorflow.
```
pip install tqdm tensorflow
pip install gdown numpy tqdm tensorflow
```
### tinybox_green
Install the p2p driver per [README](https://github.com/tinygrad/open-gpu-kernel-modules/blob/550.54.15-p2p/README.md)
This is the default on production tinybox green.
### tinybox_red
Disable cwsr + increase mes timeout.
Install the custom amdgpu driver per [README](https://github.com/nimlgen/amdgpu_ubuntu_22_04/blob/v6.1.3/readme.md)
# 2. Directions
## Steps to download and verify data
@@ -56,18 +52,18 @@ BASEDIR="/raid/datasets/wiki" python3 extra/datasets/wikipedia.py pre-eval
#### Steps to run benchmark
```
examples/mlperf/training_submission_v4.1/tinycorp/benchmarks/bert/implementations/tinybox_green/run_and_time.sh
examples/mlperf/training_submission_v5.0/tinycorp/benchmarks/bert/implementations/tinybox_green/run_and_time.sh
```
### tinybox_red
#### One time setup
#### Steps to run benchmark
```
examples/mlperf/training_submission_v4.1/tinycorp/benchmarks/bert/implementations/tinybox_red/setup.sh
examples/mlperf/training_submission_v5.0/tinycorp/benchmarks/bert/implementations/tinybox_red/run_and_time.sh
```
### tinybox_8xMI300X
#### Steps to run benchmark
```
examples/mlperf/training_submission_v4.1/tinycorp/benchmarks/bert/implementations/tinybox_red/run_and_time.sh
examples/mlperf/training_submission_v5.0/tinycorp/benchmarks/bert/implementations/tinybox_8xMI300X/run_and_time.sh
```
@@ -1,13 +1,16 @@
#!/bin/bash
export PYTHONPATH="."
export PYTHONPATH="." NV=1
export MODEL="bert"
export DEFAULT_FLOAT="HALF" GPUS=6 BS=66 EVAL_BS=66
export DEFAULT_FLOAT="HALF" SUM_DTYPE="HALF" GPUS=6 BS=96 EVAL_BS=96
export BEAM=4 BEAM_UOPS_MAX=2000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024
export FUSE_ARANGE=1 FUSE_ARANGE_UINT=0
export BEAM=8 BEAM_UOPS_MAX=10000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5
export IGNORE_JIT_FIRST_BEAM=1
export BEAM_LOG_SURPASS_MAX=1
export BASEDIR="/raid/datasets/wiki"
export BENCHMARK=10 DEBUG=2
export BENCHMARK=10 BERT_LAYERS=2 DEBUG=2
python3 examples/mlperf/model_train.py
@@ -1,10 +1,12 @@
#!/bin/bash
export PYTHONPATH="."
export PYTHONPATH="." NV=1
export MODEL="bert"
export DEFAULT_FLOAT="HALF" GPUS=6 BS=66 EVAL_BS=66
export DEFAULT_FLOAT="HALF" SUM_DTYPE="HALF" GPUS=6 BS=96 EVAL_BS=96
export BEAM=4 BEAM_UOPS_MAX=2000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024
export FUSE_ARANGE=1 FUSE_ARANGE_UINT=0
export BEAM=8 BEAM_UOPS_MAX=10000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5
export IGNORE_JIT_FIRST_BEAM=1
export BASEDIR="/raid/datasets/wiki"
@@ -1,11 +1,13 @@
#!/bin/bash
export PYTHONPATH="."
export PYTHONPATH="." NV=1
export MODEL="bert"
export SUBMISSION_PLATFORM="tinybox_green"
export DEFAULT_FLOAT="HALF" GPUS=6 BS=66 EVAL_BS=66
export DEFAULT_FLOAT="HALF" SUM_DTYPE="HALF" GPUS=6 BS=96 EVAL_BS=96
export BEAM=4 BEAM_UOPS_MAX=2000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024
export FUSE_ARANGE=1 FUSE_ARANGE_UINT=0
export BEAM=8 BEAM_UOPS_MAX=10000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5
export IGNORE_JIT_FIRST_BEAM=1
export BASEDIR="/raid/datasets/wiki"
@@ -17,7 +19,7 @@ DATETIME=$(date "+%m%d%H%M")
LOGFILE="bert_green_${DATETIME}_${SEED}.log"
# init
BENCHMARK=10 INITMLPERF=1 python3 examples/mlperf/model_train.py | tee $LOGFILE
BENCHMARK=10 INITMLPERF=1 BERT_LAYERS=2 python3 examples/mlperf/model_train.py | tee $LOGFILE
# run
PARALLEL=0 RUNMLPERF=1 python3 examples/mlperf/model_train.py | tee -a $LOGFILE
@@ -4,24 +4,20 @@ This problem uses BERT for NLP.
## Requirements
Install tinygrad and mlperf-logging from master.
Install tinygrad and mlperf-logging (uncomment mlperf from setup.py) from branch mlperf_training_v5.0.
```
git clone https://github.com/tinygrad/tinygrad.git
python3 -m pip install -e ".[mlperf]"
```
Also install tqdm and tensorflow.
Also install gdown (for dataset), numpy, tqdm and tensorflow.
```
pip install tqdm tensorflow
pip install gdown numpy tqdm tensorflow
```
### tinybox_green
Install the p2p driver per [README](https://github.com/tinygrad/open-gpu-kernel-modules/blob/550.54.15-p2p/README.md)
This is the default on production tinybox green.
### tinybox_red
Disable cwsr + increase mes timeout.
Install the custom amdgpu driver per [README](https://github.com/nimlgen/amdgpu_ubuntu_22_04/blob/v6.1.3/readme.md)
# 2. Directions
## Steps to download and verify data
@@ -56,18 +52,18 @@ BASEDIR="/raid/datasets/wiki" python3 extra/datasets/wikipedia.py pre-eval
#### Steps to run benchmark
```
examples/mlperf/training_submission_v4.1/tinycorp/benchmarks/bert/implementations/tinybox_green/run_and_time.sh
examples/mlperf/training_submission_v5.0/tinycorp/benchmarks/bert/implementations/tinybox_green/run_and_time.sh
```
### tinybox_red
#### One time setup
#### Steps to run benchmark
```
examples/mlperf/training_submission_v4.1/tinycorp/benchmarks/bert/implementations/tinybox_red/setup.sh
examples/mlperf/training_submission_v5.0/tinycorp/benchmarks/bert/implementations/tinybox_red/run_and_time.sh
```
### tinybox_8xMI300X
#### Steps to run benchmark
```
examples/mlperf/training_submission_v4.1/tinycorp/benchmarks/bert/implementations/tinybox_red/run_and_time.sh
examples/mlperf/training_submission_v5.0/tinycorp/benchmarks/bert/implementations/tinybox_8xMI300X/run_and_time.sh
```
@@ -1,13 +1,17 @@
#!/bin/bash
export PYTHONPATH="."
export PYTHONPATH="." AMD=1
export MODEL="bert"
export DEFAULT_FLOAT="HALF" GPUS=6 BS=66 EVAL_BS=66
export DEFAULT_FLOAT="HALF" SUM_DTYPE="HALF" GPUS=6 BS=96 EVAL_BS=96
export BEAM=3 BEAM_UOPS_MAX=3000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024
export FUSE_ARANGE=1 FUSE_ARANGE_UINT=0
export BEAM=5 BEAM_UOPS_MAX=8000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5
export IGNORE_JIT_FIRST_BEAM=1
export BEAM_LOG_SURPASS_MAX=1
export BASEDIR="/raid/datasets/wiki"
export BENCHMARK=10 DEBUG=2
export RESET_STEP=1
export BENCHMARK=10 BERT_LAYERS=2 DEBUG=2
python3 examples/mlperf/model_train.py
@@ -1,10 +1,12 @@
#!/bin/bash
export PYTHONPATH="."
export PYTHONPATH="." AMD=1
export MODEL="bert"
export DEFAULT_FLOAT="HALF" GPUS=6 BS=66 EVAL_BS=66
export DEFAULT_FLOAT="HALF" SUM_DTYPE="HALF" GPUS=6 BS=96 EVAL_BS=96
export BEAM=3 BEAM_UOPS_MAX=3000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024
export FUSE_ARANGE=1 FUSE_ARANGE_UINT=0
export BEAM=5 BEAM_UOPS_MAX=8000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5
export IGNORE_JIT_FIRST_BEAM=1
export BASEDIR="/raid/datasets/wiki"
@@ -1,11 +1,13 @@
#!/bin/bash
export PYTHONPATH="."
export PYTHONPATH="." AMD=1
export MODEL="bert"
export SUBMISSION_PLATFORM="tinybox_red"
export DEFAULT_FLOAT="HALF" GPUS=6 BS=66 EVAL_BS=66
export DEFAULT_FLOAT="HALF" SUM_DTYPE="HALF" GPUS=6 BS=96 EVAL_BS=96
export BEAM=3 BEAM_UOPS_MAX=3000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024
export FUSE_ARANGE=1 FUSE_ARANGE_UINT=0
export BEAM=5 BEAM_UOPS_MAX=8000 BEAM_UPCAST_MAX=256 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5
export IGNORE_JIT_FIRST_BEAM=1
export BASEDIR="/raid/datasets/wiki"
@@ -16,8 +18,13 @@ export SEED=$RANDOM
DATETIME=$(date "+%m%d%H%M")
LOGFILE="bert_red_${DATETIME}_${SEED}.log"
export HCQDEV_WAIT_TIMEOUT_MS=100000 # prevents hang?
# init
BENCHMARK=10 INITMLPERF=1 python3 examples/mlperf/model_train.py | tee $LOGFILE
sleep 5 && sudo rmmod amdgpu || true
BENCHMARK=10 INITMLPERF=1 BERT_LAYERS=2 python3 examples/mlperf/model_train.py | tee $LOGFILE
# run
# TODO: AM driver resulted in nan
sudo modprobe amdgpu
PARALLEL=0 RUNMLPERF=1 python3 examples/mlperf/model_train.py | tee -a $LOGFILE
@@ -1,8 +0,0 @@
#!/bin/bash
rocm-smi --setprofile compute
rocm-smi --setmclk 3
rocm-smi --setperflevel high
# power cap to 350W
# echo "350000000" | sudo tee /sys/class/drm/card{1..6}/device/hwmon/hwmon*/power1_cap
@@ -1,6 +1,6 @@
#!/bin/bash
export PYTHONPATH="."
export PYTHONPATH="." NV=1
export MODEL="resnet"
export DEFAULT_FLOAT="HALF" GPUS=6 BS=1536 EVAL_BS=192
@@ -1,6 +1,6 @@
#!/bin/bash
export PYTHONPATH="."
export PYTHONPATH="." NV=1
export MODEL="resnet"
export DEFAULT_FLOAT="HALF" GPUS=6 BS=1536 EVAL_BS=192
@@ -1,6 +1,6 @@
#!/bin/bash
export PYTHONPATH="."
export PYTHONPATH="." NV=1
export MODEL="resnet"
export SUBMISSION_PLATFORM="tinybox_green"
export DEFAULT_FLOAT="HALF" GPUS=6 BS=1536 EVAL_BS=192
@@ -1,6 +1,6 @@
#!/bin/bash
export PYTHONPATH="."
export PYTHONPATH="." AMD=1
export MODEL="resnet"
export DEFAULT_FLOAT="HALF" GPUS=6 BS=1536 EVAL_BS=192
@@ -1,6 +1,6 @@
#!/bin/bash
export PYTHONPATH="."
export PYTHONPATH="." AMD=1
export MODEL="resnet"
export DEFAULT_FLOAT="HALF" GPUS=6 BS=1536 EVAL_BS=192
@@ -1,6 +1,6 @@
#!/bin/bash
export PYTHONPATH="."
export PYTHONPATH="." AMD=1
export MODEL="resnet"
export SUBMISSION_PLATFORM="tinybox_red"
export DEFAULT_FLOAT="HALF" GPUS=6 BS=1536 EVAL_BS=192
@@ -0,0 +1,38 @@
# 1. Problem
This problem uses RetinaNet for SSD.
## Requirements
Install tinygrad and mlperf-logging (uncomment mlperf from setup.py) from branch mlperf_training_v5.0.
```
git clone https://github.com/tinygrad/tinygrad.git
python3 -m pip install -e ".[mlperf]"
```
Also install the following dependencies:
```
pip install tqdm numpy pycocotools boto3 pandas torch torchvision
```
### tinybox_green
Install the p2p driver per [README](https://github.com/tinygrad/open-gpu-kernel-modules/blob/550.54.15-p2p/README.md)
This is the default on production tinybox green.
# 2. Directions
## Steps to download data
Run the following:
```
BASEDIR=/raid/datasets/openimages python3 extra/datasets/openimages.py
```
## Running
### tinybox_green
#### Steps to run benchmark
```
examples/mlperf/training_submission_v5.0/tinycorp/benchmarks/retinanet/implementations/tinybox_green/run_and_time.sh
```
@@ -0,0 +1,14 @@
#!/bin/bash
export PYTHONPATH="." NV=1
export MODEL="retinanet"
export DEFAULT_FLOAT="HALF" GPUS=6 BS=96 EVAL_BS=96
export BASEDIR="/raid/datasets/openimages"
# export RESET_STEP=0
export TRAIN_BEAM=2 IGNORE_JIT_FIRST_BEAM=1 BEAM_UOPS_MAX=1500 BEAM_UPCAST_MAX=64 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5 BEAM_PADTO=0
export BENCHMARK=5 DEBUG=2
python examples/mlperf/model_train.py
@@ -0,0 +1,15 @@
#!/bin/bash
export PYTHONPATH="." NV=1
export MODEL="retinanet"
export DEFAULT_FLOAT="HALF" GPUS=6 BS=96 EVAL_BS=96
export BASEDIR="/raid/datasets/openimages"
# export RESET_STEP=0
export TRAIN_BEAM=2 IGNORE_JIT_FIRST_BEAM=1 BEAM_UOPS_MAX=1500 BEAM_UPCAST_MAX=64 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5 BEAM_PADTO=0
export WANDB=1 PARALLEL=0
export RUNMLPERF=1
python examples/mlperf/model_train.py
@@ -0,0 +1,23 @@
#!/bin/bash
export PYTHONPATH="." NV=1
export MODEL="retinanet"
export SUBMISSION_PLATFORM="tinybox_green"
export DEFAULT_FLOAT="HALF" GPUS=6 BS=96 EVAL_BS=96
export TRAIN_BEAM=2 BEAM_UOPS_MAX=1500 BEAM_UPCAST_MAX=64 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5 BEAM_PADTO=0
export IGNORE_JIT_FIRST_BEAM=1
export BASEDIR="/raid/datasets/openimages"
# pip install -e ".[mlperf]"
export LOGMLPERF=1
export SEED=$RANDOM
DATETIME=$(date "+%m%d%H%M")
LOGFILE="retinanet_green_${DATETIME}_${SEED}.log"
# init
BENCHMARK=10 INITMLPERF=1 python3 examples/mlperf/model_train.py | tee $LOGFILE
# run
PARALLEL=0 RUNMLPERF=1 python3 examples/mlperf/model_train.py | tee -a $LOGFILE
@@ -0,0 +1,14 @@
#!/bin/bash
export PYTHONPATH="." AMD=1
export MODEL="retinanet"
export DEFAULT_FLOAT="HALF" GPUS=6 BS=96 EVAL_BS=96
export BASEDIR="/raid/datasets/openimages"
# export RESET_STEP=0
export TRAIN_BEAM=2 IGNORE_JIT_FIRST_BEAM=1 BEAM_UOPS_MAX=1500 BEAM_UPCAST_MAX=64 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5 BEAM_PADTO=0
export BENCHMARK=5 DEBUG=2
python examples/mlperf/model_train.py
@@ -0,0 +1,15 @@
#!/bin/bash
export PYTHONPATH="." AMD=1
export MODEL="retinanet"
export DEFAULT_FLOAT="HALF" GPUS=6 BS=96 EVAL_BS=96
export BASEDIR="/raid/datasets/openimages"
# export RESET_STEP=0
export TRAIN_BEAM=2 IGNORE_JIT_FIRST_BEAM=1 BEAM_UOPS_MAX=1500 BEAM_UPCAST_MAX=64 BEAM_LOCAL_MAX=1024 BEAM_MIN_PROGRESS=5 BEAM_PADTO=0
export WANDB=1 PARALLEL=0
export RUNMLPERF=1
python examples/mlperf/model_train.py
@@ -0,0 +1,39 @@
{
"submitter": "tinycorp",
"division": "closed",
"status": "Available on-premise",
"system_name": "tinybox 8xMI300X",
"number_of_nodes": "1",
"host_processors_per_node": "2",
"host_processor_model_name": "AMD EPYC 9354 32-Core Processor",
"host_processor_core_count": "32",
"host_processor_vcpu_count": "64",
"host_processor_frequency": "",
"host_processor_caches": "",
"host_processor_interconnect": "",
"host_memory_capacity": "2304GB",
"host_storage_type": "NVMe SSD",
"host_storage_capacity": "3x 4TB raid array",
"host_networking": "",
"host_networking_topology": "",
"host_memory_configuration": "24x 96GB DDR5",
"accelerators_per_node": "8",
"accelerator_model_name": "AMD Instinct MI300X",
"accelerator_host_interconnect": "PCIe 5.0 x16",
"accelerator_frequency": "",
"accelerator_on-chip_memories": "",
"accelerator_memory_configuration": "HBM3",
"accelerator_memory_capacity": "192GB",
"accelerator_interconnect": "",
"accelerator_interconnect_topology": "",
"cooling": "air",
"hw_notes": "",
"framework": "tinygrad, branch mlperf_training_v5.0",
"other_software_stack": {
"python": "3.10.16",
"ROCm": "3.0.0+94441cb"
},
"operating_system": "Ubuntu 24.04.1 LTS",
"sw_notes": ""
}
@@ -28,7 +28,7 @@
"accelerator_interconnect_topology": "",
"cooling": "air",
"hw_notes": "",
"framework": "tinygrad, commit b5546912e24e0a864b35924da4efa5d71cfe368b",
"framework": "tinygrad, branch mlperf_training_v5.0",
"other_software_stack": {
"python": "3.10.12",
"CUDA": "12.4"
@@ -28,10 +28,9 @@
"accelerator_interconnect_topology": "",
"cooling": "air",
"hw_notes": "",
"framework": "tinygrad, commit b5546912e24e0a864b35924da4efa5d71cfe368b",
"framework": "tinygrad, branch mlperf_training_v5.0",
"other_software_stack": {
"python": "3.10.12",
"ROCm": "6.1.3"
"python": "3.10.12"
},
"operating_system": "Ubuntu 22.04.4",
"sw_notes": ""
+6 -6
View File
@@ -16,9 +16,9 @@ class LinearGen:
self.l4 = Tensor.scaled_uniform(1024, 784)
def forward(self, x):
x = x.dot(self.l1).leakyrelu(0.2)
x = x.dot(self.l2).leakyrelu(0.2)
x = x.dot(self.l3).leakyrelu(0.2)
x = x.dot(self.l1).leaky_relu(0.2)
x = x.dot(self.l2).leaky_relu(0.2)
x = x.dot(self.l3).leaky_relu(0.2)
x = x.dot(self.l4).tanh()
return x
@@ -31,9 +31,9 @@ class LinearDisc:
def forward(self, x):
# balance the discriminator inputs with const bias (.add(1))
x = x.dot(self.l1).add(1).leakyrelu(0.2).dropout(0.3)
x = x.dot(self.l2).leakyrelu(0.2).dropout(0.3)
x = x.dot(self.l3).leakyrelu(0.2).dropout(0.3)
x = x.dot(self.l1).add(1).leaky_relu(0.2).dropout(0.3)
x = x.dot(self.l2).leaky_relu(0.2).dropout(0.3)
x = x.dot(self.l3).leaky_relu(0.2).dropout(0.3)
x = x.dot(self.l4).log_softmax()
return x
+94
View File
@@ -0,0 +1,94 @@
# https://arxiv.org/pdf/2409.02060
import time
import numpy as np
np.set_printoptions(suppress=True, linewidth=1000)
import functools
from tinygrad import Tensor, nn, Device, GlobalCounters
from tinygrad.helpers import Timing, getenv
from extra.models.llama import Transformer, convert_from_huggingface
class MixtureFeedForward:
def __init__(self, num_experts:int, activated_experts:int, dim:int, hidden_dim:int, linear=nn.Linear):
self.activated_experts = activated_experts
self.gate = nn.Linear(dim, num_experts, bias=False)
self.up_proj = Tensor.zeros(num_experts, hidden_dim, dim, dtype='bfloat16')
self.down_proj = Tensor.zeros(num_experts, dim, hidden_dim, dtype='bfloat16')
self.gate_proj = Tensor.zeros(num_experts, hidden_dim, dim, dtype='bfloat16')
def __call__(self, x:Tensor) -> Tensor:
assert x.shape[0] == 1, "only BS=1"
assert x.shape[1] == 1, "only length=1"
g = self.gate(x).float().softmax(-1)
g = g.squeeze() # (BS, length, num_experts) -> (num_experts,)
probs, sel = g.topk(self.activated_experts)
# run MoE
x_up_gate = x.dot(self.gate_proj[sel].permute(0,2,1)).silu() * x.dot(self.up_proj[sel].permute(0,2,1))
x_down = x_up_gate.dot(self.down_proj[sel].permute(0,2,1))
return (x_down.float() * probs.reshape(self.activated_experts, 1, 1)).sum(axis=0)
# model is bf16, 1.3B active, 6.9B total
# M3 Max is 400 GB/s, so 400/2.6 = ~154 tok/s
def fetch_weights() -> dict[str, Tensor]:
# TODO: make this lazy so the 3 fetches can happen in parallel
m1 = Tensor.from_url("https://huggingface.co/allenai/OLMoE-1B-7B-0924/resolve/main/model-00001-of-00003.safetensors").to(Device.DEFAULT)
m2 = Tensor.from_url("https://huggingface.co/allenai/OLMoE-1B-7B-0924/resolve/main/model-00002-of-00003.safetensors").to(Device.DEFAULT)
m3 = Tensor.from_url("https://huggingface.co/allenai/OLMoE-1B-7B-0924/resolve/main/model-00003-of-00003.safetensors").to(Device.DEFAULT)
return {**nn.state.safe_load(m1), **nn.state.safe_load(m2), **nn.state.safe_load(m3)}
if __name__ == "__main__":
if getenv("TORCH"):
from transformers import OlmoeForCausalLM, AutoTokenizer
model = OlmoeForCausalLM.from_pretrained("allenai/OLMoE-1B-7B-0924")
tokenizer = AutoTokenizer.from_pretrained("allenai/OLMoE-1B-7B-0924")
inputs = tokenizer("Hello", return_tensors="pt")
generate_ids = model.generate(inputs.input_ids, max_length=30)
out = tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
print(out)
exit(0)
with Timing("create model: "):
model = Transformer(n_layers=16, dim=2048, hidden_dim=1024, n_heads=16, norm_eps=1e-5, qk_norm=1e-5, max_context=1024,
vocab_size=50304, feed_forward=functools.partial(MixtureFeedForward, 64, 8))
model_state_dict = nn.state.get_state_dict(model)
del model_state_dict['freqs_cis']
with Timing("load weights to GPU: "):
nhf_state = convert_from_huggingface(fetch_weights(), 16, 16, 16)
# NOTE: i'm not sure this actually needs float32, it may just change the type of things downstream from it. but doesn't match torch w/o this
for needs_float32 in ['tok_embeddings.weight']: nhf_state[needs_float32] = nhf_state[needs_float32].float()
print(f"ram used: {GlobalCounters.mem_used/1e9:.2f} GB")
with Timing("unpack weights: "):
nn.state.load_state_dict(model, nhf_state, verbose=False, strict=False, consume=True, realize=False)
assert len(nhf_state) == 0
Tensor.realize(*list(nn.state.get_state_dict(model).values()))
print(f"ram used: {GlobalCounters.mem_used/1e9:.2f} GB")
count = 30
temperature = 0
with Timing("load tokenizer: "):
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("allenai/OLMoE-1B-7B-0924")
toks = [12092]
start_pos = 0
timings = []
for i in range(count):
GlobalCounters.reset()
st = time.perf_counter()
tok = model(Tensor([toks[start_pos:]]), start_pos, temperature).item()
timings.append(time.perf_counter()-st)
toks.append(tok)
start_pos += 1
print(toks)
print(tokenizer.decode(toks))
print(f"fastest token {min(timings)*1e3:.2f} ms, {1/min(timings):.1f} tok/s")
if temperature == 0:
# Hello, I am a newbie to this forum and I am trying to get a better understanding of the different types of data that can be stored in a
assert toks == [12092, 13, 309, 717, 247, 747, 17782, 281, 436, 12209, 285, 309, 717, 2820, 281, 755,
247, 1805, 4685, 273, 253, 1027, 3510, 273, 941, 326, 476, 320, 7141, 275, 247], "BAD OUTPUT!"
+6 -5
View File
@@ -12,7 +12,7 @@ from tinygrad.engine.realize import CompiledRunner
import onnx
from onnx.helper import tensor_dtype_to_np_dtype
from extra.onnx import OnnxRunner # TODO: port to main tinygrad
from tinygrad.frontend.onnx import OnnxRunner
OPENPILOT_MODEL = sys.argv[1] if len(sys.argv) > 1 else "https://github.com/commaai/openpilot/raw/v0.9.7/selfdrive/modeld/models/supercombo.onnx"
OUTPUT = sys.argv[2] if len(sys.argv) > 2 else "/tmp/openpilot.pkl"
@@ -92,10 +92,11 @@ def test_vs_compile(run, new_inputs, test_val=None):
print("**** test done ****")
# test that changing the numpy changes the model outputs
for v in new_inputs_numpy.values(): v *= 2
out = run(**inputs)
changed_val = out.numpy()
np.testing.assert_raises(AssertionError, np.testing.assert_array_equal, val, changed_val)
if any([x.device == 'NPY' for x in inputs.values()]):
for v in new_inputs_numpy.values(): v *= 2
out = run(**inputs)
changed_val = out.numpy()
np.testing.assert_raises(AssertionError, np.testing.assert_array_equal, val, changed_val)
return val
def test_vs_onnx(new_inputs, test_val, onnx_file, ort=False):
+23 -9
View File
@@ -1,5 +1,5 @@
from tinygrad import dtypes
from tinygrad.helpers import trange
from tinygrad import dtypes, getenv, Device
from tinygrad.helpers import trange, colored, DEBUG, temp
from tinygrad.nn.datasets import mnist
import torch
from torch import nn, optim
@@ -26,14 +26,20 @@ class Model(nn.Module):
return self.lin(torch.flatten(x, 1))
if __name__ == "__main__":
mps_device = torch.device("mps")
if getenv("TINY_BACKEND"):
import tinygrad.frontend.torch
device = torch.device("tiny")
else:
device = torch.device({"METAL":"mps","NV":"cuda"}.get(Device.DEFAULT, "cpu"))
if DEBUG >= 1: print(f"using torch backend {device}")
X_train, Y_train, X_test, Y_test = mnist()
X_train = torch.tensor(X_train.float().numpy(), device=mps_device)
Y_train = torch.tensor(Y_train.cast(dtypes.int64).numpy(), device=mps_device)
X_test = torch.tensor(X_test.float().numpy(), device=mps_device)
Y_test = torch.tensor(Y_test.cast(dtypes.int64).numpy(), device=mps_device)
X_train = torch.tensor(X_train.float().numpy(), device=device)
Y_train = torch.tensor(Y_train.cast(dtypes.int64).numpy(), device=device)
X_test = torch.tensor(X_test.float().numpy(), device=device)
Y_test = torch.tensor(Y_test.cast(dtypes.int64).numpy(), device=device)
model = Model().to(mps_device)
if getenv("TORCHVIZ"): torch.cuda.memory._record_memory_history()
model = Model().to(device)
optimizer = optim.Adam(model.parameters(), 1e-3)
loss_fn = nn.CrossEntropyLoss()
@@ -48,8 +54,16 @@ if __name__ == "__main__":
return loss
test_acc = float('nan')
for i in (t:=trange(70)):
for i in (t:=trange(getenv("STEPS", 70))):
samples = torch.randint(0, X_train.shape[0], (512,)) # putting this in JIT didn't work well
loss = step(samples)
if i%10 == 9: test_acc = ((model(X_test).argmax(axis=-1) == Y_test).sum() * 100 / X_test.shape[0]).item()
t.set_description(f"loss: {loss.item():6.2f} test_accuracy: {test_acc:5.2f}%")
# verify eval acc
if target := getenv("TARGET_EVAL_ACC_PCT", 0.0):
if test_acc >= target and test_acc != 100.0: print(colored(f"{test_acc=} >= {target}", "green"))
else: raise ValueError(colored(f"{test_acc=} < {target}", "red"))
if getenv("TORCHVIZ"):
torch.cuda.memory._dump_snapshot(fp:=temp("torchviz.pkl", append_user=True))
print(f"saved torch memory snapshot to {fp}, view in https://pytorch.org/memory_viz")
+1 -1
View File
@@ -44,7 +44,7 @@ def load_model(model_path:Path, model_params:Dict[str, Union[int, float]]) -> Tr
model.layers = updated_layers
# load weights
weights = fix_bf16(convert_from_huggingface(load(str(model_path / "model.safetensors.index.json")), model, model_params["n_heads"], model_params["n_kv_heads"], permute_layers=False))
weights = fix_bf16(convert_from_huggingface(load(str(model_path / "model.safetensors.index.json")), model_params["n_layers"], model_params["n_heads"], model_params["n_kv_heads"], permute_layers=False))
# replace weights in model
load_state_dict(model, weights, strict=False, consume=True)
+9 -6
View File
@@ -5,7 +5,7 @@
from tinygrad import Tensor, TinyJit, dtypes, GlobalCounters
from tinygrad.nn import Conv2d, GroupNorm
from tinygrad.nn.state import safe_load, load_state_dict
from tinygrad.nn.state import safe_load, load_state_dict, get_state_dict
from tinygrad.helpers import fetch, trange, colored, Timing
from extra.models.clip import Embedder, FrozenClosedClipEmbedder, FrozenOpenClipEmbedder
from extra.models.unet import UNetModel, Upsample, Downsample, timestep_embedding
@@ -356,8 +356,7 @@ class DPMPP2MSampler:
c=c,
uc=uc,
)
x.realize()
old_denoised.realize()
x.realize(old_denoised)
return x
@@ -385,7 +384,12 @@ if __name__ == "__main__":
default_weight_url = 'https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/sd_xl_base_1.0.safetensors'
weights = args.weights if args.weights else fetch(default_weight_url, 'sd_xl_base_1.0.safetensors')
load_state_dict(model, safe_load(weights), strict=False)
loaded_weights = load_state_dict(model, safe_load(weights), strict=False, verbose=False, realize=False)
start_mem_used = GlobalCounters.mem_used
with Timing("loaded weights in ", lambda et_ns: f", {(B:=(GlobalCounters.mem_used-start_mem_used))/1e9:.2f} GB loaded at {B/et_ns:.2f} GB/s"):
Tensor.realize(*loaded_weights)
del loaded_weights
N = 1
C = 4
@@ -396,8 +400,7 @@ if __name__ == "__main__":
c, uc = model.create_conditioning([args.prompt], args.width, args.height)
del model.conditioner
for v in c .values(): v.realize()
for v in uc.values(): v.realize()
Tensor.realize(*c.values(), *uc.values())
print("created batch")
# https://github.com/Stability-AI/generative-models/blob/fbdc58cab9f4ee2be7a5e1f2e2787ecd9311942f/sgm/inference/helpers.py#L101
+3 -3
View File
@@ -437,14 +437,14 @@ class Generator:
x = self.conv_pre(x)
if g is not None: x = x + self.cond(g)
for i in range(self.num_upsamples):
x, xs = self.ups[i](x.leakyrelu(LRELU_SLOPE)), None
x, xs = self.ups[i](x.leaky_relu(LRELU_SLOPE)), None
x_source = self.noise_convs[i](har_source)
x = x + x_source
for j in range(self.num_kernels):
if xs is None: xs = self.resblocks[i * self.num_kernels + j].forward(x)
else: xs += self.resblocks[i * self.num_kernels + j].forward(x)
x = xs / self.num_kernels
return self.conv_post(x.leakyrelu()).tanh()
return self.conv_post(x.leaky_relu()).tanh()
# **** helpers ****
@@ -504,7 +504,7 @@ def load_checkpoint_enc(checkpoint_path, model: ContentVec, optimizer=None, skip
obj, v = getattr(parent, "weight"), weight_norm(weight_v, weight_g, 0)
weight_g, weight_v, parent, skip = None, None, None, False
if not skip and obj.shape == v.shape:
if "feature_extractor" in key and (isinstance(parent, nn.GroupNorm) or isinstance(parent, nn.LayerNorm)): # cast
if "feature_extractor" in key and (isinstance(parent, (nn.GroupNorm, nn.LayerNorm))): # cast
obj.assign(v.to(obj.device).float())
else:
obj.assign(v.to(obj.device))
+14 -6
View File
@@ -5,10 +5,13 @@
# - symbolic removal
from examples.beautiful_mnist import Model
from tinygrad import Tensor, nn, getenv, GlobalCounters
from tinygrad import Tensor, nn, getenv, GlobalCounters, Variable
from tinygrad.nn.datasets import mnist
from tinygrad.helpers import trange, DEBUG
# STEPS=70 python3 examples/stunning_mnist.py
# NOTE: it's broken with STACK=1, why?
if __name__ == "__main__":
X_train, Y_train, X_test, Y_test = mnist()
print("*** got data")
@@ -24,19 +27,21 @@ if __name__ == "__main__":
print("*** got samples")
with Tensor.train():
# TODO: this shouldn't be a for loop. something like: (contract is still up in the air)
"""
i = UOp.range(samples.shape[0]) # TODO: fix range function on UOp
losses = model(X_samp[i]).sparse_categorical_crossentropy(Y_samp[i]).backward().contract(i)
opt.schedule_steps(i)
"""
# TODO: this shouldn't be a for loop. something like: (contract is still up in the air)
vi = Variable('i', 0, samples.shape[0]-1)
losses = []
for i in range(samples.shape[0]):
vib = vi.bind(i)
opt.zero_grad()
losses.append(model(X_samp[i]).sparse_categorical_crossentropy(Y_samp[i]).backward())
losses.append(model(X_samp[vib]).sparse_categorical_crossentropy(Y_samp[vib]).backward())
opt.schedule_step()
# TODO: this stack currently breaks the "generator" aspect of losses. it probably shouldn't
#losses = Tensor.stack(*losses)
if getenv("STACK", 0): losses = Tensor.stack(*losses)
print("*** scheduled training")
# evaluate the model
@@ -49,5 +54,8 @@ if __name__ == "__main__":
# only actually do anything at the end
if getenv("LOSS", 1):
for i in (t:=trange(len(losses))): t.set_description(f"loss: {losses[i].item():6.2f}")
print(f"test_accuracy: {test_acc.item():5.2f}%")
for i in (t:=trange(len(losses))):
GlobalCounters.reset()
t.set_description(f"loss: {losses[i].item():6.2f}")
if getenv("TEST", 1):
print(f"test_accuracy: {test_acc.item():5.2f}%")
+5 -2
View File
@@ -58,7 +58,7 @@ if __name__ == "__main__":
return None
return {"input": img.numpy()}
quantize_static(model_fp32, fn, ImagenetReader(), quant_format=QuantFormat.QDQ, per_channel=False,
activation_type=QuantType.QUInt8, weight_type=QuantType.QInt8,
activation_type=QuantType.QUInt8, weight_type=QuantType.QUInt8,
extra_options={"ActivationSymmetric": False})
run_onnx_jit, input_specs = load_onnx_model(fetch(fn))
@@ -70,9 +70,12 @@ if __name__ == "__main__":
GlobalCounters.reset()
p = run_onnx_jit(**{t_name:img})
assert p.shape == (1,1000)
t = p.argmax().item()
t = p.to('cpu').argmax().item()
hit += y==t
print(f"target: {y:3d} pred: {t:3d} acc: {hit/(i+1)*100:.2f}%")
MS_TARGET = 13.4
print(f"need {GlobalCounters.global_ops/1e9*(1000/MS_TARGET):.2f} GFLOPS for {MS_TARGET:.2f} ms")
import pickle
with open("/tmp/im.pkl", "wb") as f: pickle.dump(run_onnx_jit, f)
+19
View File
@@ -0,0 +1,19 @@
import sys, pickle
from tinygrad import GlobalCounters
from tinygrad.helpers import fetch, getenv
from examples.test_onnx_imagenet import imagenet_dataloader
if __name__ == "__main__":
with open(fetch(sys.argv[1]), "rb") as f:
run_onnx_jit = pickle.load(f)
input_name = run_onnx_jit.captured.expected_names[0]
device = run_onnx_jit.captured.expected_st_vars_dtype_device[0][-1]
print(f"input goes into {input_name=} on {device=}")
hit = 0
for i,(img,y) in enumerate(imagenet_dataloader(cnt=getenv("CNT", 100))):
GlobalCounters.reset()
p = run_onnx_jit(**{input_name:img.to(device)})
assert p.shape == (1,1000)
t = p.to('cpu').argmax().item()
hit += y==t
print(f"target: {y:3d} pred: {t:3d} acc: {hit/(i+1)*100:.2f}%")
@@ -0,0 +1,11 @@
/*!
Pure v3.0.0
Copyright 2013 Yahoo!
Licensed under the BSD License.
https://github.com/pure-css/pure/blob/master/LICENSE
*/
/*!
normalize.css v | MIT License | https://necolas.github.io/normalize.css/
Copyright (c) Nicolas Gallagher and Jonathan Neal
*/
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}html{font-family:sans-serif}.hidden,[hidden]{display:none!important}.pure-img{max-width:100%;height:auto;display:block}
@@ -0,0 +1,5 @@
net_*
llama3-2.tiktoken
tiktoken.js
tiktoken_bg.wasm
transformer*
@@ -0,0 +1,8 @@
# How to build and run tinychat in browser (WebGPU and WASM)
- `PYTHONPATH=. python examples/tinychat/tinychat-browser/compile.py`
- `./examples/tinychat/tinychat-browser/compile_wasm.sh`
- Prerequisite: [install emscripten](https://emscripten.org/docs/getting_started/downloads.html). This script looks for `~/emsdk/emsdk_env.sh`, adjust this based on your installation.
- `./examples/tinychat/tinychat-browser/make_tiktoken_js.sh`
- Prerequisite: install `npm`, `webpack`.
- `cd examples/tinychat && python -m http.server 7776`
- In browser: open either `localhost:7776/tinychat-browser` (WebGPU), or `localhost:7776/tinychat-browser/?backend=wasm` (WASM)
@@ -0,0 +1,149 @@
import os, json, hashlib, math
from extra.export_model import export_model
from examples.llama3 import build_transformer, Tokenizer
from tinygrad.nn.state import get_state_dict, load_state_dict
from tinygrad import Device, Variable, Tensor, dtypes, TinyJit
from tinygrad.helpers import fetch, Context
from tiktoken.load import load_tiktoken_bpe, dump_tiktoken_bpe
def prepare_browser_chunks(model):
# split weights into browser-friendly chunks
state_dict = get_state_dict(model)
del state_dict['output.weight'], state_dict['output.scale'] # same as tok_embeddings; ensures consistency with model export
chunk_size = 16 * 1024 * 1024 # small chunks based on iphone browser constraints
metadata = {}
# We won't export cache_kv bytes (because we start inference on client at start_pos=0), but we will tell the client how big cache_kv needs to be
t_infos = [(v.lazydata.base.realized.nbytes, k, v.dtype) for k,v in state_dict.items() if "cache_kv" not in k]
empty_t_infos = [(v.lazydata.base.realized.nbytes, k, v.dtype) for k,v in state_dict.items() if "cache_kv" in k]
split_t_infos = []
for size, name, dtype in t_infos:
if size <= chunk_size:
split_t_infos.append((size, name, dtype, ()))
else: # split large weights into multiple parts
for i in range(0, size, chunk_size):
split_t_infos.append((min(chunk_size, size-i), f"{name}_part{math.ceil(i/chunk_size)}", dtype, (i, min(i+chunk_size, size))))
files = []
# pack weights into files with FFD bin packing
split_t_infos = sorted(split_t_infos, reverse=True)
for info in split_t_infos:
placed = False
for file in files:
if sum(i[0] for i in file) + info[0] <= chunk_size:
if info[3] and any(i[3] for i in file): continue # no two split tensors can touch the same file, due to wasm loading constraints
file.append(info)
placed = True
break
if not placed:
files.append([info])
tinygrad_dtypes = {dtypes.float32: "float32", dtypes.float16: "float16", dtypes.int8: "int8", dtypes.int32: "int32"}
for i, file in enumerate(files):
cursor = 0
with open(os.path.join(os.path.dirname(__file__), f'./net_part{i}.chunk'), "wb+") as writer:
for size, name, dtype, offsets in file:
name, part_num = (name, 0) if "_part" not in name else (name.split("_part")[0], int(name.split("_part")[1]))
default = {"parts": {}, "dtype": tinygrad_dtypes[dtype]}
weight_metadata = metadata.get(name, default)
weight_metadata["parts"][part_num] = {"file": i, "file_start_pos": cursor, "size": size}
metadata[name] = weight_metadata
data = bytes(state_dict[name].lazydata.base.realized.as_buffer())
data = data if not offsets else data[offsets[0]:offsets[1]]
writer.write(data)
cursor += size
metadata.update({name: {"parts": {0: {"empty": True, "size": size}}, "dtype": tinygrad_dtypes[dtype]} for size, name, dtype in empty_t_infos})
for k in metadata:
metadata[k]["parts"] = [part for part_num, part in sorted(metadata[k]["parts"].items(), key = lambda x: x[0])]
cursor = 0
for i, part in enumerate(metadata[k]["parts"]):
metadata[k]["parts"][i]["target_start_pos"] = cursor
cursor += part["size"]
metadata[k]["size"] = cursor
# compute hashes, which client app will check to determine whether to update with new weights and/or detect integrity issues
state_dict_hash = hashlib.sha256(json.dumps(metadata, sort_keys=True).encode("utf-8")).hexdigest()
metadata = {"state_dict": metadata, "state_dict_hash": state_dict_hash, "files": []}
hashes = set()
for i in range(len(files)):
with open(os.path.join(os.path.dirname(__file__), f'./net_part{i}.chunk'), "rb") as reader:
hash = hashlib.sha256(reader.read()).hexdigest()
hashes.add(hash)
metadata["files"].append({"name": f'net_part{i}.chunk', "hash": hash})
if len(hashes) != len(files): print(f"WARNING: {len(files)} files were exported, but only {len(hashes)} are unique: something may have gone wrong")
metadata_hash = hashlib.sha256(json.dumps(metadata, sort_keys=True).encode("utf-8")).hexdigest()
metadata = {"metadata": metadata, "metadata_hash": metadata_hash}
with open(os.path.join(os.path.dirname(__file__), f'./net_metadata.json'), "w") as writer: json.dump(metadata, writer, indent=4)
return metadata
def validate_model(model, tokenizer):
prompt = "yo"
toks = [tokenizer.bos_id]
toks += [tokenizer.special_tokens["<|start_header_id|>"]] + tokenizer.encode("user") + [tokenizer.special_tokens["<|end_header_id|>"]] + tokenizer.encode("\n\n")
toks += tokenizer.encode(prompt) + [tokenizer.special_tokens["<|eot_id|>"]]
toks += [tokenizer.special_tokens["<|start_header_id|>"]] + tokenizer.encode("assistant") + [tokenizer.special_tokens["<|end_header_id|>"]] + tokenizer.encode("\n\n")
start_pos = 0
run = TinyJit(model.forward)
for tok in toks[:-1]:
run(Tensor([[tok]]), Variable("start_pos", 0, model.max_context).bind(start_pos), 0.0, 0, 0.0, 0.0, 0.0).realize()
start_pos += 1
tok = toks[-1]
result = ""
expected = "How's it going?"
while True:
tok = run(Tensor([[tok]]), Variable("start_pos", 0, model.max_context).bind(start_pos), 0.0, 0, 0.0, 0.0, 0.0).item()
start_pos += 1
if tok in tokenizer.stop_tokens or len(result) > len(expected): break
result += tokenizer.decode([tok])
assert result == expected, f"Model validation failed, expected output: {expected}, actual output: {result}"
if __name__=="__main__":
# Export BPE data for use with tiktoken.js
tokenizer_path = fetch("https://huggingface.co/bofenghuang/Meta-Llama-3-8B/resolve/main/original/tokenizer.model", "tokenizer.model", subdir="llama3-1b-instruct")
mergeable_ranks = load_tiktoken_bpe(str(tokenizer_path))
bpe_path = os.path.join(os.path.dirname(__file__), "llama3-2.tiktoken")
dump_tiktoken_bpe(mergeable_ranks, bpe_path)
tokenizer = Tokenizer(str(tokenizer_path))
model_path = fetch("https://huggingface.co/bartowski/Llama-3.2-1B-Instruct-GGUF/resolve/main/Llama-3.2-1B-Instruct-f16.gguf", "Llama-3.2-1B-Instruct-f16.gguf", subdir="llama3-1b-instruct")
Tensor.no_grad = True
max_context=1024
tok = 128000
TEMPERATURE, TOP_K, TOP_P, ALPHA_F, ALPHA_P = 0.95, 0, 0.0, 0.0, 0.0
start_pos = Variable("start_pos", 0, max_context).bind(0)
model_input = lambda: [Tensor([[tok]]), start_pos, TEMPERATURE, TOP_K, TOP_P, ALPHA_F, ALPHA_P]
Device.DEFAULT="CPU"
model = build_transformer(model_path, model_size="1B", quantize="int8", scale_dtype=dtypes.float32, device=Device.DEFAULT, max_context=max_context)
state_dict = get_state_dict(model)
validate_model(model, tokenizer)
model_name = "transformer"
with Context(BEAM=3):
cprog, js_wrapper = export_model(model, "wasm", *model_input(), model_name=model_name)
# ensure consistency with exported weights
js_wrapper = js_wrapper.replace("output.weight", "tok_embeddings.weight").replace("output.scale", "tok_embeddings.scale")
with open(os.path.join(os.path.dirname(__file__), f"{model_name}.c"), "w") as f: f.write(cprog)
with open(os.path.join(os.path.dirname(__file__), "net_clang.js"), "w") as f: f.write(js_wrapper)
Device.DEFAULT="WEBGPU"
# float16 is not yet supported for dawn/Vulkan/NVIDIA stack, see: https://issues.chromium.org/issues/42251215
# therefore for now, we used CLANG to quantize the float16 llama to int8 with float32 scales, then load to WEBGPU
model = build_transformer(model_path, model_size="1B", quantize="int8", max_context=max_context, load_weights=False)
load_state_dict(model, state_dict)
# these were the same before load_state_dict
model.output.weight, model.output.scale = model.tok_embeddings.weight, model.tok_embeddings.scale
validate_model(model, tokenizer)
metadata = prepare_browser_chunks(model) # export weights to disk
with Context(BEAM=3):
prg, input_sizes, output_sizes, state = export_model(model, "webgpu", *model_input(), model_name=model_name, stream_weights=True)
# ensure consistency with exported weights
prg = prg.replace("output.weight", "tok_embeddings.weight").replace("output.scale", "tok_embeddings.scale")
with open(os.path.join(os.path.dirname(__file__), "net.js"), "w") as f: f.write(prg)
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
cd "$(dirname "$0")"
# prereq: install emscripten: https://emscripten.org/docs/getting_started/downloads.html
EMSCRIPTEN_PATH=~/emsdk/emsdk_env.sh
source $EMSCRIPTEN_PATH
step="transformer"
initial_memory=6553600
max_memory=1500053504
exported_functions='["_net", "_malloc", "_free", "_set_buf"]'
emcc "${step}.c" \
-O3 -msimd128 -ffast-math -flto \
-o "${step}.js" \
-s MODULARIZE=1 \
-s EXPORT_ES6=1 \
-s EXPORTED_FUNCTIONS="${exported_functions}" \
-s ENVIRONMENT='worker' \
-s FILESYSTEM=0 \
-s EVAL_CTORS \
-s ALLOW_MEMORY_GROWTH=1 \
-s INITIAL_MEMORY="$initial_memory" \
-s MAXIMUM_MEMORY="$max_memory"
@@ -0,0 +1,322 @@
/* define colors */
:root {
--primary-color: #fff;
--secondary-color: #2a2a2a;
--secondary-color-transparent: #ffffff66;
--primary-bg-color: #1a1a1a;
--foreground-color: #f0f0f0;
}
main {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
place-items: center;
}
.home {
width: 100%;
height: 90%;
margin-bottom: 10rem;
}
.title {
font-size: 3rem;
margin: 1rem 0;
margin-top: 3rem;
}
.histories-container-container {
width: 100%;
max-height: 75%;
position: relative;
}
.histories-container {
overflow-y: auto;
overflow-x: hidden;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
gap: 1rem;
align-items: center;
margin: 0;
padding: 3rem 1rem;
}
.histories-start {
height: 3rem;
width: 100%;
z-index: 999;
top: 0;
position: absolute;
background: linear-gradient(
180deg,
var(--primary-bg-color) 0%,
transparent 100%
);
}
.histories-end {
height: 3rem;
width: 100%;
z-index: 999;
bottom: 0;
position: absolute;
background: linear-gradient(
0deg,
var(--primary-bg-color) 0%,
transparent 100%
);
}
.history {
padding: 1rem;
width: 100%;
max-width: 40rem;
background-color: var(--secondary-color);
border-radius: 10px;
border-left: 2px solid var(--primary-color);
cursor: pointer;
transform: translateX(calc(1px * var(--tx, 0)));
opacity: var(--opacity, 1);
}
.history:hover {
background-color: var(--secondary-color);
}
.history-delete-button {
position: absolute;
top: 0;
right: 0;
padding: 0.5rem;
margin: 0;
outline: none;
border: none;
background-color: var(--secondary-color);
color: var(--foreground-color);
border-radius: 0 0 0 10px;
cursor: pointer;
transition: 0.2s;
}
.history-delete-button:hover {
background-color: var(--secondary-color);
padding: 0.75rem;
}
.messages {
overflow-y: auto;
height: 100%;
width: 100%;
max-width: 1200px;
display: flex;
flex-direction: column;
gap: 1rem;
align-items: center;
padding-top: 1rem;
padding-bottom: 11rem;
}
.message {
max-width: 75%;
padding: 0.5rem 1rem;
border-radius: 20px;
}
.message-role-assistant {
background-color: var(--secondary-color);
margin-right: auto;
color: #fff;
}
.message-role-user {
margin-left: auto;
background-color: var(--primary-color);
color: #000;
}
.message > pre {
white-space: pre-wrap;
}
.hljs {
width: 100%;
position: relative;
border-radius: 10px;
/* wrap code blocks */
white-space: pre-wrap;
}
/* put clipboard button in the top right corner of the code block */
.clipboard-button {
position: absolute;
top: 0;
right: 0;
padding: 0.5rem;
margin: 0;
outline: none;
border: none;
background-color: var(--secondary-color);
color: var(--foreground-color);
border-radius: 0 0 0 10px;
cursor: pointer;
transition: 0.2s;
}
.clipboard-button:hover {
background-color: var(--secondary-color);
padding: 0.75rem;
}
.input-container {
position: absolute;
bottom: 0;
/* linear gradient from background-color to transparent on the top */
background: linear-gradient(
0deg,
var(--primary-bg-color) 55%,
transparent 100%
);
width: 100%;
max-width: 1200px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 999;
}
.input-performance {
margin-top: 4rem;
display: flex;
flex-direction: row;
gap: 1rem;
}
.input-performance-point {
display: flex;
flex-direction: row;
place-items: center;
gap: 0.5rem;
}
.input-performance-point > p {
height: 1rem;
line-height: normal;
}
.input {
width: 90%;
min-height: 3rem;
flex-shrink: 0;
display: flex;
flex-direction: row;
justify-content: center;
gap: 0.5rem;
align-items: flex-end;
margin-bottom: 2rem;
}
.input-form {
width: 100%;
padding: 1rem;
min-height: 3rem;
max-height: 8rem;
background-color: var(--secondary-color);
color: var(--foreground-color);
border-radius: 10px;
border: none;
resize: none;
outline: none;
}
.mobile .input-form { /* prevent auto-zoom on touching prompt box */
font-size: 16px;
}
.input-button {
height: 3rem;
width: 4rem;
background-color: var(--primary-color);
color: var(--secondary-color);
border-radius: 10px;
padding: 0.5rem;
cursor: pointer;
}
.input-button:hover {
background-color: var(--secondary-color-transparent);
}
.input-button:disabled {
background-color: var(--secondary-color);
cursor: not-allowed;
}
/* wrap text */
p {
white-space: pre-wrap;
}
/* fonts */
.megrim-regular {
font-family: monospace;
font-weight: 400;
font-style: normal;
}
.monospace {
font-family: monospace;
}
.loading-bar {
display: flex;
flex-direction: row;
align-items: center;
gap: 0.5rem;
width: 100%;
min-height: 3rem;
margin-bottom: 2rem;
}
.loading-text {
color: var(--foreground-color);
font-size: 1rem;
white-space: nowrap;
}
#progress-percentage {
color: var(--foreground-color);
font-size: 1rem;
white-space: nowrap;
}
.progress-bar {
flex-grow: 1;
height: 0.5rem;
background-color: var(--secondary-color);
border-radius: 5px;
overflow: hidden;
position: relative;
}
.progress {
width: 0%;
height: 100%;
background-color: var(--primary-color);
transition: width 0.2s ease-in-out;
}
@@ -0,0 +1,182 @@
<!DOCTYPE html>
<head>
<title>tinychat</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="../favicon.svg" type="image/svg+xml">
<script defer src="../assets/cdn.jsdelivr.net/npm/@alpine-collective/[email protected]/dist/cdn.min.js"></script>
<script defer src="../assets/cdn.jsdelivr.net/npm/@alpinejs/[email protected]/dist/cdn.min.js"></script>
<script defer src="../assets/cdn.jsdelivr.net/npm/@alpinejs/[email protected]/dist/cdn.min.js"></script>
<script defer src="../assets/unpkg.com/@marcreichel/[email protected]/dist/alpine-autosize.min.js"></script>
<script defer src="../assets/unpkg.com/[email protected]/dist/cdn.min.js"></script>
<script src="../assets/unpkg.com/[email protected]/dist/purify.min.js"></script>
<script src="../assets/unpkg.com/[email protected]/marked.min.js"></script>
<script src="../assets/unpkg.com/[email protected]/lib/index.umd.js"></script>
<script src="../assets/unpkg.com/@highlightjs/[email protected]/highlight.min.js"></script>
<script src="index.js"></script>
<link rel="stylesheet" href="../assets/cdn.jsdelivr.net/npm/[email protected]/build/base-min.css">
<link rel="stylesheet" href="../assets/cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"
integrity="sha512-SnH5WK+bZxgPHs44uWIX+LLJAJ9/2PkPKZ5QiAj6Ta86w+fsb2TkcmfRyVX3pBnMFcV7oQPJkl9QevSCWr3W6A=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="../assets/unpkg.com/@highlightjs/[email protected]/styles/vs2015.min.css">
<link rel="stylesheet" href="index.css">
<link rel="stylesheet" href="../common.css">
</head>
<body>
<main x-data="state" x-init="console.log(endpoint)">
<div class="home centered" x-show="home === 0" x-transition x-effect="
$refs.inputForm.focus();
if (home === 1) setTimeout(() => home = 2, 100);
if (home === -1) setTimeout(() => home = 0, 100);
" @popstate.window="
if (home === 2) {
cancelGeneration = true;
if (maxContextReached) generating = false;
if (!generating) cstate = { time: null, messages: [] };
home = -1;
time_till_first = 0;
tokens_per_second = 0;
total_tokens = 0;
}
">
<h1 class="title megrim-regular">tinychat</h1>
<div class="histories-container-container">
<template x-if="histories.length">
<div class="histories-start"></div>
</template>
<div class="histories-container" x-intersect="
$el.scrollTo({ top: 0, behavior: 'smooth' });
">
<template x-for="_state in histories.toSorted((a, b) => b.time - a.time)">
<div x-data="{ otx: 0, trigger: 75 }" class="history" @click="
cstate = _state;
updateTotalTokens(cstate.messages);
home = 1;
// ensure that going back in history will go back to home
window.history.pushState({}, '', window.TINYCHAT_ROOT || '/');
" @touchstart="
otx = $event.changedTouches[0].clientX;
" @touchmove="
$el.style.setProperty('--tx', $event.changedTouches[0].clientX - otx);
$el.style.setProperty('--opacity', 1 - (Math.abs($event.changedTouches[0].clientX - otx) / trigger));
" @touchend="
if (Math.abs($event.changedTouches[0].clientX - otx) > trigger) removeHistory(_state);
$el.style.setProperty('--tx', 0);
$el.style.setProperty('--opacity', 1);
">
<h3 x-text="new Date(_state.time).toLocaleString()"></h3>
<p x-text="$truncate(_state.messages[0].content, 80)"></p>
<!-- delete button -->
<button class="history-delete-button" @click.stop="removeHistory(_state);">
<i class=" fas fa-trash"></i>
</button>
</div>
</template>
</div>
<template x-if="histories.length">
<div class="histories-end"></div>
</template>
</div>
</div>
<div x-ref="messages" class="messages" x-init="
$watch('cstate', value => {
$el.innerHTML = '';
value.messages.forEach(({ role, content }) => {
const div = document.createElement('div');
div.className = `message message-role-${role}`;
try {
div.innerHTML = DOMPurify.sanitize(marked.parse(content));
} catch (e) {
console.log(content);
console.error(e);
}
// add a clipboard button to all code blocks
const codeBlocks = div.querySelectorAll('.hljs');
codeBlocks.forEach(codeBlock => {
const button = document.createElement('button');
button.className = 'clipboard-button';
button.innerHTML = '<i class=\'fas fa-clipboard\'></i>';
button.onclick = () => {
// navigator.clipboard.writeText(codeBlock.textContent);
const range = document.createRange();
range.setStartBefore(codeBlock);
range.setEndAfter(codeBlock);
window.getSelection()?.removeAllRanges();
window.getSelection()?.addRange(range);
document.execCommand('copy');
window.getSelection()?.removeAllRanges();
button.innerHTML = '<i class=\'fas fa-check\'></i>';
setTimeout(() => button.innerHTML = '<i class=\'fas fa-clipboard\'></i>', 1000);
};
codeBlock.appendChild(button);
});
$el.appendChild(div);
});
$el.scrollTo({ top: $el.scrollHeight, behavior: 'smooth' });
});
" x-intersect="
$el.scrollTo({ top: $el.scrollHeight, behavior: 'smooth' });
" x-show="home === 2" x-transition>
</div>
<div class="input-container">
<div class="input-performance">
<span class="input-performance-point">
<p class="monospace" x-text="(time_till_first / 1000).toFixed(2)"></p>
<p class="megrim-regular">SEC TO FIRST TOKEN</p>
</span>
<span class="input-performance-point">
<p class="monospace" x-text="tokens_per_second.toFixed(1)"></p>
<p class="megrim-regular">TOKENS/SEC</p>
</span>
<span class="input-performance-point">
<p class="monospace" x-text="total_tokens"></p>
<p class="megrim-regular">TOKENS</p>
</span>
</div>
<div class="loading-bar" x-show="loadingMessage !== ''">
<p class="loading-text" id="loading-message">Loading:</p>
<span id="progress-percentage">0%</span>
<div class="progress-bar">
<div class="progress"></div>
</div>
</div>
<div class="input" x-show="loadingMessage === ''">
<textarea x-ref="inputForm" id="input-form" class="input-form" autofocus rows=1 x-autosize
:placeholder="generating ? placeholderText : 'Say something'" :disabled="generating" @input="
home = (home === 0) ? 1 : home
if (cstate.messages.length === 0 && $el.value === '') home = -1;
if ($el.value !== '') {
const messages = [...cstate.messages];
messages.push({ role: 'user', content: $el.value });
updateTotalTokens(messages);
} else {
if (cstate.messages.length === 0) total_tokens = 0;
else updateTotalTokens(cstate.messages);
}
" x-effect="
console.log(generating);
if (!generating) $nextTick(() => {
$el.focus();
setTimeout(() => $refs.messages.scrollTo({ top: $refs.messages.scrollHeight, behavior: 'smooth' }), 100);
});
" @keydown.enter="await handleEnter($event)" @keydown.escape.window="$focus.focus($el)"></textarea>
<button class="input-button" :disabled="generating" @click="await handleSend()">
<i class="fas" :class="generating ? 'fa-spinner fa-spin' : 'fa-paper-plane'"></i>
</button>
</div>
</div>
</main>
</body>
</html>
+927
View File
@@ -0,0 +1,927 @@
window.TINYCHAT_ROOT = "/tinychat-browser/";
const queryParams = new URLSearchParams(window.location.search);
const normalizedParams = Object.fromEntries([...queryParams].map(([key, value]) => [key.toUpperCase(), value.toUpperCase()]));
window.BACKEND = (normalizedParams["BACKEND"] === "WASM") ? "WASM" : "WebGPU";
const isMobileAgent = /Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
const hasTouchScreen = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
window.isMobile = isMobileAgent || hasTouchScreen;
if (window.isMobile) document.documentElement.classList.add('mobile'); // prevent annoying auto-zoom when entering prompt on mobile
// MODEL_BASE_URL is where the weights are hosted, WEBGPU_EXPORT is the JS-wrapped WebGPU code exported from tinygrad
window.PC_MODEL_BASE_URL = ".";
window.PC_WEBGPU_EXPORT = './net.js'
window.PC_MAX_CONTEXT = 1024;
window.MOBILE_MODEL_BASE_URL = ".";
window.MOBILE_WEBGPU_EXPORT = './net.js'
window.MOBILE_MAX_CONTEXT = 1024;
const tiktokenReady = (async () => {
const { init, get_encoding, Tiktoken, load } = await import('./tiktoken.js');
window.Tiktoken = Tiktoken;
window.tiktokenInit = init;
window.tiktokenGetEncoding = get_encoding;
window.tiktokenLoad = load;
})();
async function getDevice() {
let adapter;
try {
adapter = await navigator.gpu.requestAdapter();
if (!adapter) {
this.loadingMessage = "Loading WASM (WebGPU not enabled):";
throw new Error("No WebGPU adapter found");
}
} catch(error) {
this.loadingMessage = "Loading WASM (WebGPU not enabled):";
throw error;
}
const requiredLimits = {};
const maxBufferSize = 322122544;
requiredLimits.maxStorageBufferBindingSize = maxBufferSize;
requiredLimits.maxBufferSize = maxBufferSize;
requiredLimits.maxComputeInvocationsPerWorkgroup = 512; // may need to vary based on what the WEBGPU backend produces
try {
return await adapter.requestDevice({ requiredLimits });
} catch(error) {
this.loadingMessage = "Loading WASM (WebGPU error):";
throw error;
}
};
// copied from examples/webgpu/stable_diffusion/index.html
function initDb() {
return new Promise((resolve, reject) => {
let db;
const request = indexedDB.open('tinydb', 1);
request.onerror = (event) => {
console.error('Database error:', event.target.error);
resolve(null);
};
request.onsuccess = (event) => {
db = event.target.result;
console.log("Db initialized.");
resolve(db);
};
request.onupgradeneeded = (event) => {
db = event.target.result;
if (!db.objectStoreNames.contains('tensors')) {
db.createObjectStore('tensors', { keyPath: 'id' });
}
};
});
}
// copied from examples/webgpu/stable_diffusion/index.html
function readTensorFromDb(db, id) {
return new Promise((resolve, reject) => {
if (db == null) {
resolve(null);
}
const transaction = db.transaction(['tensors'], 'readonly');
const store = transaction.objectStore('tensors');
const request = store.get(id);
transaction.onabort = (event) => {
console.log("Transaction error while reading tensor: " + event.target.error);
resolve(null);
};
request.onsuccess = (event) => {
const result = event.target.result;
if (result) {
resolve(result);
} else {
resolve(null);
}
};
request.onerror = (event) => {
console.error('Tensor retrieve failed: ', event.target.error);
resolve(null);
};
});
}
function getAllKeysFromDb(db) {
return new Promise((resolve, reject) => {
if (db == null) {resolve([]);}
const transaction = db.transaction(['tensors'], 'readonly');
const store = transaction.objectStore('tensors');
const request = store.getAllKeys();
transaction.onabort = (event) => {
console.log("Transaction error while reading IndexedDB keys: " + event.target.error);
resolve([]);
};
request.onsuccess = function (event) {resolve(event.target.result);};
request.onerror = (event) => {
console.error('Retrieval of IndexedDB keys failed: ', event.target.error);
resolve([]);
};
});
}
// modified from examples/webgpu/stable_diffusion/index.html
function saveTensorToDb(db, id, tensor) {
return readTensorFromDb(db, id).then((result) => {
if (!result) {
new Promise((resolve, reject) => {
if (db == null) {
resolve(null);
}
const transaction = db.transaction(['tensors'], 'readwrite');
const store = transaction.objectStore('tensors');
const request = store.put({ id: id, content: tensor });
transaction.onabort = (event) => {
console.log("Transaction error while saving tensor: " + event.target.error);
resolve(null);
};
request.onsuccess = () => {
console.log('Tensor saved successfully.');
resolve();
};
request.onerror = (event) => {
console.error('Tensor save failed:', event.target.error);
resolve(null);
};
});
} else {
return null;
}
}).catch(()=> null);
}
function deleteTensorFromDb(db, id) {
return new Promise((resolve, reject) => {
if (db == null) {
console.error("Database is not initialized.");
resolve(null);
return;
}
const transaction = db.transaction(['tensors'], 'readwrite');
const store = transaction.objectStore('tensors');
const request = store.delete(id);
transaction.oncomplete = () => {
console.log(`Tensor with ID '${id}' deleted successfully.`);
resolve();
};
transaction.onerror = (event) => {
console.error("Transaction error while deleting tensor:", event.target.error);
resolve(null);
};
request.onerror = (event) => {
console.error('Tensor deletion failed:', event.target.error);
resolve(null);
};
request.onsuccess = () => {
console.log(`Delete request for tensor with ID '${id}' succeeded.`);
};
});
}
function makeProgress(total) {
let acc = 0;
const ret = function progress(amount, message) {
if (amount >= 0) { // allow updating message only
acc += amount;
const percentage = total ? Math.trunc((acc / total) * 100) : 0;
document.querySelector('.progress').style.width = `${percentage}%`;
document.getElementById('progress-percentage').textContent = `${percentage}%`;
}
if (message) {
this.loadingMessage = message;
document.getElementById('loading-message').textContent = this.loadingMessage;
}
}.bind(this);
ret.total = total;
return ret;
}
function sendMessageToWorker(worker, message) {
return new Promise((resolve, reject) => {
const onMessage = (event) => {
resolve(event.data);
worker.removeEventListener('message', onMessage);
worker.removeEventListener('error', onError);
};
const onError = (error) => {
reject(error);
worker.removeEventListener('message', onMessage);
worker.removeEventListener('error', onError);
};
worker.addEventListener('message', onMessage);
worker.addEventListener('error', onError);
if (message.header === "token") worker.postMessage(message.data);
else if (message.header === "load_state_dict") {
if (message.data === "done") worker.postMessage(message.data);
else worker.postMessage(message.data, message.data.map(file => file.bytes.buffer));
}
else if (message.header === "init") worker.postMessage("init");
});
}
async function load_state_dict (data, device, progress) {
let state_dict = data.metadata.state_dict;
let completed = 0;
// modified from examples/webgpu/stable_diffusion/index.html getProgressDlForPart
const loadPart = async (part) => {
const response = await fetch(part);
const res = new Response(new ReadableStream({
async start(controller) {
const reader = response.body.getReader();
for (;;) {
const { done, value } = await reader.read();
if (done) break;
progress(value.byteLength);
controller.enqueue(value);
}
controller.close();
},
}));
return res.arrayBuffer();
};
let db = await initDb();
const getPart = async(filename, hash) => {
let part = await readTensorFromDb(db, hash);
if (part) {
console.log(`Cache hit: ${filename}, hash: ${hash}`);
progress(part.content.byteLength);
return Promise.resolve(part.content);
} else {
console.log(`Cache miss: ${filename}, hash: ${hash}`);
return loadPart(`${window.MODEL_BASE_URL}/${filename}`);
}
}
const correctHashes = data.metadata.files.map(file => file.hash)
// delete unused cached buffers to free disk space -- if we update weights, user will otherwise have obsolete cached buffers
const dbKeys = await getAllKeysFromDb(db);
const correctHashesSet = new Set(correctHashes);
const notInCorrectHashes = dbKeys.filter(key => !correctHashesSet.has(key));
// await these right before starting to save new stuff
const deletionPromises = notInCorrectHashes.map(async (hash) => deleteTensorFromDb(db, hash));
// instantiates empty weight buffers on WebGPU, attaches buffers to state_dict
let model;
if (window.BACKEND === "WebGPU") {
//model = await transformer().setup(device, state_dict, progress);
model = await transformer.setupNet(device, state_dict);
progress(0.15 * progress.total);
}
else if (window.BACKEND === "WASM") {
progress(0.02 * progress.total);
model = new Worker(`./worker.js?version=${Date.now()}`);
await sendMessageToWorker(model, {header: "init"});
progress(0.02 * progress.total);
progress(0.11 * progress.total);
}
const downloaded = [];
const triggerChainDownload = async (toDownload) => {
const numDownloaders = window.isMobile ? 4 : toDownload.length; // TODO: dynamically base this on DL file size? current assumption is 16 MiB chunks
const chainDownload = async() => {
const file = toDownload.shift();
loadPart(`${window.MODEL_BASE_URL}/${file.name}`) // triggers download
.then(async (arraybuf) => {
downloaded.push({ ...file, bytes: new Uint8Array(arraybuf)});
// pause downloads if further processing is a bottleneck
while (toDownload.length && downloaded.length >= numDownloaders) await new Promise(resolve => setTimeout(resolve, 5));
if (toDownload.length && downloaded.length < numDownloaders) chainDownload(); // start next download
})
}
for (let i=0; i<numDownloaders; i++) if (toDownload.length) chainDownload();
}
const loadFileToStateDict = async(file) => {
if (window.BACKEND === "WebGPU") {
for (const part of file.parts) {
if (part.empty) continue;
part.bytes = (part.size === file.bytes.length) ? file.bytes : file.bytes.slice(part.file_start_pos, part.file_start_pos + part.size);
device.queue.writeBuffer(state_dict[part.key].bytes, part.target_start_pos, part.bytes); // improves stability over mappedAtCreation writing
part.bytes = null;
}
}
else if (window.BACKEND === "WASM") {
await sendMessageToWorker(model, {header: "load_state_dict", data: [file]});
}
file.bytes = null;
}
if (window.BACKEND === "WebGPU") { // contiguous loading not needed for WebGPU stability
const files = data.tensor_file_groups.flatMap(obj => obj.files);
data.tensor_file_groups = [{contiguous: false, files: files}];
}
for (const group of data.tensor_file_groups) {
const contiguous = group.contiguous;
const files = group.files;
const tensor_file_indices = files.map(file => file.index);
const contiguousFiles = [];
const fileHashes = new Set(files.map(file => file.hash));
const cachedFileHashes = new Set(dbKeys.filter(key => fileHashes.has(key)));
const cachedFiles = files.filter(file => cachedFileHashes.has(file.hash));
const toDownload = files.filter(file => !cachedFileHashes.has(file.hash));
triggerChainDownload(toDownload);
const loadDelay = 5;
await Promise.all(deletionPromises);
while (completed < files.length) {
const start = performance.now();
// prioritize files from downloaded queue, so we can continue downloading more files
if (downloaded.length) {
const file = downloaded.shift();
await saveTensorToDb(db, file.hash, file.bytes); // for wasm, must await to prevent race between indexedDB and transfer to worker
if (!contiguous) await loadFileToStateDict(file);
else contiguousFiles.push(file);
completed += 1;
}
else if (!downloaded.length && cachedFiles.length) {
const file = cachedFiles.shift();
file.bytes = await getPart(file.name, file.hash); // reads data from IndexedDB
if (!contiguous) await loadFileToStateDict(file);
else contiguousFiles.push(file);
completed += 1;
}
const end = performance.now();
const elapsed = end - start;
if (elapsed < loadDelay) await new Promise(resolve => setTimeout(resolve, loadDelay - elapsed));
}
if (contiguous) {
const orderMap = tensor_file_indices.reduce((acc, id, index) => {acc[id] = index; return acc;}, {});
contiguousFiles.sort((a, b) => orderMap[a.index] - orderMap[b.index]); // glue files together in the right order
await sendMessageToWorker(model, {header: "load_state_dict", data: contiguousFiles});
}
completed = 0;
}
// initialize empty kv_caches, which were part of exported model's state_dict, but which we didn't want to package/download
if (window.BACKEND === "WASM") {
for (const [k, v] of Object.entries(state_dict).filter(([_, v]) => v.empty === true)) {
v.parts[0].file_start_pos = 0;
const file = { parts: v.parts, size: v.size, bytes: new Uint8Array(v.size).fill(0) };
await loadFileToStateDict(file);
}
}
return model;
};
document.addEventListener("alpine:init", () => {
Alpine.data("state", () => ({
// loadingMessage updates the user on page load progress, including weights download and decompression
// if loadingMessage is not '', then prompt box will be hidden: this is default behavior on page load
placeholderText: "Generating...",
loadingMessage: `Loading ${window.BACKEND} model:`,
// model
nets: {},
tokenizer: null,
max_context: 1024,
lastSeenToks: [],
progress: null,
async init() {
var device = null;
var webgpuErrorMessage = null;
if (window.BACKEND === "WebGPU") {
try {
device = await getDevice.call(this);
console.log("WebGPU device initialized");
} catch (error) {
window.BACKEND = "WASM";
console.log(`error: ${error}\nFailed to launch WebGPU. Loading WASM model instead...`); // return;
webgpuErrorMessage = this.loadingMessage;
}
}
window.MODEL_BASE_URL = (window.BACKEND === "WebGPU" && !window.isMobile) ? window.PC_MODEL_BASE_URL : window.MOBILE_MODEL_BASE_URL;
this.max_context = (window.BACKEND === "WebGPU" && !window.isMobile) ? window.PC_MAX_CONTEXT : window.MOBILE_MAX_CONTEXT;
const kernelsReady = (async () => {
if (window.BACKEND === "WASM") {var exports = await import(`./net_clang.js?version=${Date.now()}`);}
else if (window.BACKEND === "WebGPU" && !window.isMobile) {var exports = await import(`${PC_WEBGPU_EXPORT}?version=${Date.now()}`);}
else if (window.BACKEND === "WebGPU" && window.isMobile) {var exports = await import(`${MOBILE_WEBGPU_EXPORT}?version=${Date.now()}`);}
self.transformer = exports.default;
})();
const response = await fetch(`${window.MODEL_BASE_URL}/net_metadata.json`);
// TODO: cache metadata (and everything else, including tokenizer)
// TODO: use service worker to reload page when offline
const data = await response.json();
data.metadata.files = data.metadata.files.map((file, index) => ({...file, index}));
const state_dict = data.metadata.state_dict;
/*
- allocating memory to WASM on mobile has longstanding issues: https://github.com/WebAssembly/design/issues/1397
- the below pattern, while yielding a succesfully-functioning model when it doesn't crash, causes regular crashes on iOS Safari (iphone 15 iOS 18.3):
- call WASM malloc (to fit all tensors, or one per tensor) for all tensors up front, then load tensor byte chunks into the buffers in random order
- the below pattern has been stable on iOS Safari (iphone 15 iOS 18.3):
- call only one WASM malloc at a time before filling the allocated bytes, as small as possible (malloc up to 256 MiB has been tested)
- fill the malloc'd memory in linear order from start to end (what has been tested is calling wasm.HEAPU8.set on 16 MiB chunks from start to end)
- use ALLOW_MEMORY_GROWTH=1 in wasm compilation, minimize initial memory
- additional considerations affecting loading design, for WASM:
- it seems that copying bytes into wasm memory cannot be zero-copy without sharedarraybuffer, which isn't currently used due to increased hosting complexity
- non-zero copies create memory pressure, which is not reliably capped because of lack of control over garbage collection
- to minimize peak memory pressure if GC is delayed, we process (i.e. download + copy into WASM) large tensors (> 16 MiB) one at a time, in descending size order
*/
data.tensor_file_groups = []; // see above: for WASM, limit processing of multi-file Tensors to one at a time, in descending order based on Tensor size
const unsplit_tensors = [];
const sortedEntries = Object.entries(state_dict).sort(([, objA], [, objB]) => objB.size - objA.size);
let totalSize = 0;
const seen = new Set();
for (const [k,v] of sortedEntries) {
const files_in_tensor = [];
for (const part of v.parts) {
part.key = k;
if (part.empty) state_dict[k].empty = true; // assumes no other parts of this weight exist and are non-empty
else {
const file = data.metadata.files[part.file];
if (!seen.has(file.index)) {
seen.add(file.index);
files_in_tensor.push(file);
}
totalSize += part.size;
part.dtype = v.dtype;
if (!data.metadata.files[part.file].parts) data.metadata.files[part.file].parts = [];
data.metadata.files[part.file].size ??= 0;
data.metadata.files[part.file].size += part.size;
data.metadata.files[part.file].parts.push(part);
}
}
if (files_in_tensor.length > 1) data.tensor_file_groups.push({contiguous: true, files: files_in_tensor}); // [tensorN_file0, tensorN_file1, ...]
else if (files_in_tensor.length > 0) unsplit_tensors.push(files_in_tensor[0]);
}
data.tensor_file_groups.push({contiguous: false, files: unsplit_tensors});
data.totalSize = totalSize;
totalSize = totalSize / 0.8; // give space in progress bar for initializing model bufs, and tokenizer
this.progress = makeProgress.call(this, totalSize); // creates closure with totalSize
try {
this.progress(0.01 * totalSize, "Loading tokenizer:");
const wasmResponse = await fetch(`${window.MODEL_BASE_URL}/tiktoken_bg.wasm`);
this.progress(0.01 * totalSize);
const wasmBytes = await wasmResponse.arrayBuffer();
await tiktokenReady;
await window.tiktokenInit((imports) => WebAssembly.instantiate(wasmBytes, imports));
this.progress(0.01 * totalSize);
this.tokenizer = await createTokenizer(`${window.MODEL_BASE_URL}/llama3-2.tiktoken`);
const tokenizer_works = (new TextDecoder().decode(this.tokenizer.decode(this.tokenizer.encode("hello world"))) === "hello world");
console.log("tokenizer works:", tokenizer_works)
this.progress(0.01 * totalSize);
} catch (error) {this.progress(-1, `Error launching tokenizer: ${error}`); console.log(error); return;}
try {
const loadModelMessage = (webgpuErrorMessage) ? webgpuErrorMessage : `Loading ${window.BACKEND} model:`
this.progress(0, loadModelMessage);
await kernelsReady;
const model = await load_state_dict(data, device, this.progress);
if (window.BACKEND === "WebGPU") {
this.nets = {"transformer": model};
}
else if (window.BACKEND === "WASM") {
const msg = await sendMessageToWorker(model, {header: "load_state_dict", data: "done"});
this.nets = {"transformer": async (tok, start_pos) => sendMessageToWorker(model, {header: "token", data: [tok, start_pos]})};
}
this.progress(0.01 * totalSize, `Launching ${window.BACKEND} model:`);
this.loadingMessage = ""; // Triggers removal of loading bar, display of prompt box
} catch (error) {this.progress(-1, `Error launching model: ${error}`); console.log(error); return;}
},
// current state
cstate: {
time: null,
messages: [],
},
// historical state
histories: JSON.parse(localStorage.getItem("histories")) || [],
home: 0,
generating: false,
maxContextReached: false,
cancelGeneration: false,
endpoint: `${window.location.origin}/v1`,
// performance tracking
time_till_first: 0,
tokens_per_second: 0,
total_tokens: 0,
max_context: 0,
removeHistory(cstate) {
const index = this.histories.findIndex((state) => {
return state.time === cstate.time;
});
if (index !== -1) {
this.histories.splice(index, 1);
localStorage.setItem("histories", JSON.stringify(this.histories));
}
},
async handleSend() {
const el = document.getElementById("input-form");
const value = el.value.trim();
if (!value) return;
if (this.generating) return;
this.maxContextReached = false;
this.placeholderText = "Generating...";
this.generating = true;
this.cancelGeneration = false;
if (this.home === 0) this.home = 1;
// ensure that going back in history will go back to home
window.history.pushState({}, "", window.TINYCHAT_ROOT || "/");
// add message to list
this.cstate.messages.push({ role: "user", content: value });
// clear textarea
el.value = "";
el.style.height = "auto";
el.style.height = el.scrollHeight + "px";
// reset performance tracking
const prefill_start = Date.now();
let start_time = 0;
let tokens = 0;
this.tokens_per_second = 0;
let gottenFirstChunk = false;
try {
for await (
const chunk of this.openaiChatCompletion(this.cstate.messages)
) {
if (!gottenFirstChunk) {
this.cstate.messages.push({ role: "assistant", content: "" });
gottenFirstChunk = true;
}
// add chunk to the last message
// TODO: handle localStorage overflow
// possible example: this.cstate.messages[...] was undefined when trying to prompt within an old cstate (chat session)
this.cstate.messages[this.cstate.messages.length - 1].content += chunk;
// calculate performance tracking
tokens += 1;
this.total_tokens += 1;
if (start_time === 0) {
start_time = Date.now();
this.time_till_first = start_time - prefill_start;
} else {
const diff = Date.now() - start_time;
if (diff > 0) {
this.tokens_per_second = tokens / (diff / 1000);
}
}
this.checkMaxContext(this.total_tokens);
if (this.cancelGeneration) break;
}
} finally {
// update the state in histories or add it if it doesn't exist
const index = this.histories.findIndex((cstate) => {
return cstate.time === this.cstate.time;
});
this.cstate.time = Date.now();
if (index !== -1) {
// update the time
this.histories[index] = this.cstate;
} else {
this.histories.push(this.cstate);
}
// update in local storage
localStorage.setItem("histories", JSON.stringify(this.histories));
if (!this.maxContextReached) this.generating = false;
if (this.cancelGeneration && !this.maxContextReached) this.cstate = { time: null, messages: [] };
}
},
async handleEnter(event) {
// if shift is not pressed
if (!event.shiftKey) {
event.preventDefault();
await this.handleSend();
}
},
updateTotalTokens(messages) {
try {
let toks = [this.tokenizer.bos_id];
messages.forEach((message) => {
if (!message.role || !message.content) {
throw new Error("Each message must have a 'role' and 'content' property.");
}
toks = toks.concat(this.tokenizer.encodeMessage(message.role, message.content));
if (messages.length > 0 && messages[messages.length - 1].role === "user") {
toks = toks.concat(this.tokenizer.encodeRole("assistant"));
}
this.total_tokens = toks.length;
});
} catch (error) {
console.error("Error updating total tokens:", error);
}
},
checkMaxContext(num_tokens) {
if (num_tokens >= this.max_context) {
this.cancelGeneration = true;
this.maxContextReached = true;
this.placeholderText = `Max context reached: ${this.max_context} tokens`;
}
},
async *openaiChatCompletion(messages) {
let tokens = [this.tokenizer.bos_id];
for (const message of messages) {
tokens = tokens.concat(this.tokenizer.encodeMessage(message.role, message.content));
}
tokens = tokens.concat(this.tokenizer.encodeRole("assistant"));
this.checkMaxContext(tokens.length); // don't waste time prefilling if we know we're over the token limit
let startPos = 0
const prefillToks = tokens.slice(0, -1);
// Skip the largest possible sequence of tokens already represented at the beginning of the model's kv caches
for (let i=0; i <= prefillToks.length; i++) {
startPos = i;
if (i == prefillToks.length) break;
if (i == this.lastSeenToks.length) break;
if (prefillToks[i] !== this.lastSeenToks[i]) break;
}
//this.lastSeenToks = prefillToks;
//prefillToks = prefillToks.slice(startPos);
const unprocessedPrefillToks = prefillToks.slice(startPos);
this.lastSeenToks = prefillToks.slice(0, startPos);
this.progress = makeProgress(unprocessedPrefillToks.length);
this.loadingMessage = (window.BACKEND === "WebGPU") ? "Reading input:" : "Loading (enable WebGPU for speed):";
this.progress(0, this.loadingMessage);
for (const tok of unprocessedPrefillToks) {
if (this.cancelGeneration) {this.loadingMessage=""; return;}
if (window.BACKEND === "WebGPU") {await this.nets["transformer"](new Int32Array([tok]), new Int32Array([startPos]));}
else {await this.nets["transformer"](tok, startPos);}
this.lastSeenToks.push(tok)
startPos += 1;
this.progress(1);
}
this.loadingMessage = ""; // hides progress bar
let lastTok = tokens[tokens.length - 1];
while (true) {
if (window.BACKEND === "WebGPU") {var tok = await this.nets["transformer"](new Int32Array([lastTok]), new Int32Array([startPos])); tok = tok[0][0];}
else {var tok = await this.nets["transformer"](lastTok, startPos);}
this.lastSeenToks.push(lastTok); // lets us skip prefilling with these tokens at the next prompt in this chain
startPos += 1;
lastTok = tok;
if (this.tokenizer.stop_tokens.has(lastTok)) break;
yield new TextDecoder().decode(this.tokenizer.decode([lastTok]));
}
},
}));
});
const { markedHighlight } = globalThis.markedHighlight;
marked.use(markedHighlight({
langPrefix: "hljs language-",
highlight(code, lang, _info) {
const language = hljs.getLanguage(lang) ? lang : "plaintext";
return hljs.highlight(code, { language }).value;
},
}));
// **** eventsource-parser ****
class EventSourceParserStream extends TransformStream {
constructor() {
let parser;
super({
start(controller) {
parser = createParser((event) => {
if (event.type === "event") {
controller.enqueue(event);
}
});
},
transform(chunk) {
parser.feed(chunk);
},
});
}
}
function createParser(onParse) {
let isFirstChunk;
let buffer;
let startingPosition;
let startingFieldLength;
let eventId;
let eventName;
let data;
reset();
return {
feed,
reset,
};
function reset() {
isFirstChunk = true;
buffer = "";
startingPosition = 0;
startingFieldLength = -1;
eventId = void 0;
eventName = void 0;
data = "";
}
function feed(chunk) {
buffer = buffer ? buffer + chunk : chunk;
if (isFirstChunk && hasBom(buffer)) {
buffer = buffer.slice(BOM.length);
}
isFirstChunk = false;
const length = buffer.length;
let position = 0;
let discardTrailingNewline = false;
while (position < length) {
if (discardTrailingNewline) {
if (buffer[position] === "\n") {
++position;
}
discardTrailingNewline = false;
}
let lineLength = -1;
let fieldLength = startingFieldLength;
let character;
for (
let index = startingPosition;
lineLength < 0 && index < length;
++index
) {
character = buffer[index];
if (character === ":" && fieldLength < 0) {
fieldLength = index - position;
} else if (character === "\r") {
discardTrailingNewline = true;
lineLength = index - position;
} else if (character === "\n") {
lineLength = index - position;
}
}
if (lineLength < 0) {
startingPosition = length - position;
startingFieldLength = fieldLength;
break;
} else {
startingPosition = 0;
startingFieldLength = -1;
}
parseEventStreamLine(buffer, position, fieldLength, lineLength);
position += lineLength + 1;
}
if (position === length) {
buffer = "";
} else if (position > 0) {
buffer = buffer.slice(position);
}
}
function parseEventStreamLine(lineBuffer, index, fieldLength, lineLength) {
if (lineLength === 0) {
if (data.length > 0) {
onParse({
type: "event",
id: eventId,
event: eventName || void 0,
data: data.slice(0, -1),
// remove trailing newline
});
data = "";
eventId = void 0;
}
eventName = void 0;
return;
}
const noValue = fieldLength < 0;
const field = lineBuffer.slice(
index,
index + (noValue ? lineLength : fieldLength),
);
let step = 0;
if (noValue) {
step = lineLength;
} else if (lineBuffer[index + fieldLength + 1] === " ") {
step = fieldLength + 2;
} else {
step = fieldLength + 1;
}
const position = index + step;
const valueLength = lineLength - step;
const value = lineBuffer.slice(position, position + valueLength).toString();
if (field === "data") {
data += value ? "".concat(value, "\n") : "\n";
} else if (field === "event") {
eventName = value;
} else if (field === "id" && !value.includes("\0")) {
eventId = value;
} else if (field === "retry") {
const retry = parseInt(value, 10);
if (!Number.isNaN(retry)) {
onParse({
type: "reconnect-interval",
value: retry,
});
}
}
}
}
const BOM = [239, 187, 191];
function hasBom(buffer) {
return BOM.every((charCode, index) => buffer.charCodeAt(index) === charCode);
}
const PAT_STR = "(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\r\n\\p{L}\\p{N}]?\\p{L}+|\\p{N}{1,3}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+";
async function createTokenizer(bpeUrl) {
const num_base_tokens = 128000;
const special_tokens = {
"<|begin_of_text|>": 128000,
"<|end_of_text|>": 128001,
"<|start_header_id|>": 128006,
"<|end_header_id|>": 128007,
"<|eot_id|>": 128009
};
const model = await window.tiktokenLoad({
"load_tiktoken_bpe": bpeUrl,
"special_tokens": special_tokens,
"pat_str": PAT_STR
});
const tokenizer = new window.Tiktoken(model.bpe_ranks, model.special_tokens, model.pat_str)
return {
get bos_id() {
return special_tokens["<|begin_of_text|>"];
},
get stop_tokens() {
return new Set([
special_tokens["<|end_of_text|>"],
special_tokens["<|eot_id|>"],
]);
},
decode(toks) {
const filtered = toks.filter((t) => t < num_base_tokens);
return tokenizer.decode(filtered);
},
encode(text, allow_special = false) {
const allowedSpecial = allow_special ? "all" : new Set();
const disallowedSpecial = new Set();
return tokenizer.encode(text, allowedSpecial, disallowedSpecial);
},
encodeRole(role) {
const tokens = [];
tokens.push(special_tokens["<|start_header_id|>"]);
tokens.push(...this.encode(role));
tokens.push(special_tokens["<|end_header_id|>"]);
tokens.push(...this.encode("\n\n"));
return tokens;
},
encodeMessage(role, content) {
const roleTokens = this.encodeRole(role);
const contentTokens = this.encode(content.trim());
return [...roleTokens, ...contentTokens, special_tokens["<|eot_id|>"]];
},
};
}
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/env bash
cd "$(dirname "$0")"
npm init -y && \
npm install --save-dev webpack webpack-cli && \
npm install tiktoken && \
jq '.scripts.build = "webpack"' package.json > package.tmp.json && \
mv package.tmp.json package.json && \
npm run build && \
mv dist/*.wasm ./tiktoken_bg.wasm && \
mv dist/* ./ && \
rm -rf dist node_modules package-lock.json package.json
@@ -0,0 +1,5 @@
// Force Webpack to copy the WASM
import 'tiktoken/tiktoken_bg.wasm';
import { init, get_encoding, encoding_for_model, Tiktoken } from 'tiktoken/init';
import { load } from 'tiktoken/load';
export { init, get_encoding, encoding_for_model, Tiktoken, load };
@@ -0,0 +1,25 @@
const path = require("path");
module.exports = {
mode: "production",
entry: "./tiktoken-export.js",
output: {
filename: "tiktoken.js",
path: path.resolve(__dirname, "dist"),
library: {
type: "module"
}
},
experiments: {
outputModule: true,
asyncWebAssembly: true
},
module: {
rules: [
{
test: /\.wasm$/,
type: "asset/resource",
}
]
}
};
@@ -0,0 +1,62 @@
const kernelsReady = (async () => {
// can't get browser to use updated versions except with cache-busting query string
const exports = await import(`./net_clang.js?version=${Date.now()}`);
Object.assign(self, exports);
})();
async function init(event) {
await kernelsReady;
self.model = await self.transformer();
self.addEventListener("message", loadStateDict);
self.removeEventListener("message", init);
self.postMessage("success");
}
function loadStateDict(event) {
if (event.data === "done") {
self.addEventListener("message", inference);
self.removeEventListener("message", loadStateDict);
}
else {
if (event.data.length > 1) {
// the bytes from files are set contiguously in WASM memory
const malloc_size = event.data.reduce((sum, file) => sum + file.bytes.length, 0);
const malloc_ptr = self.model.wasm._malloc(malloc_size);
let cursor = 0;
for (const file of event.data) {
self.model.wasm.HEAPU8.set(file.bytes, malloc_ptr + cursor);
for (const part of file.parts) {
if (part.target_start_pos === 0) {
// tell WASM code where the tensor is in memory
self.model.wasm._set_buf(self.transformer_name_to_id[part.key], malloc_ptr + cursor);
}
cursor += part.size;
}
file.bytes = null;
}
}
else {
// the bytes from files are not guaranteed to be set contiguously in WASM memory
const file = event.data[0];
const malloc_ptr = self.model.wasm._malloc(file.size);
self.model.wasm.HEAPU8.set(file.bytes, malloc_ptr);
for (const part of file.parts) {
if (part.target_start_pos === 0) {
self.model.wasm._set_buf(self.transformer_name_to_id[part.key], malloc_ptr + part.file_start_pos);
}
}
file.bytes = null;
}
}
self.postMessage("success");
}
function inference(event) {
const [tok, start_pos] = event.data;
const int32tok = new Int32Array([tok]);
const model_out = self.model.run(new Uint8Array(int32tok.buffer), start_pos);
const int32nextTok = new Int32Array(model_out[0].buffer);
self.postMessage(int32nextTok[0]);
}
self.addEventListener("message", init);
+38
View File
@@ -0,0 +1,38 @@
#!POPCORN leaderboard grayscale
#!POPCORN gpu A100
# not a stable API, but works
import torch, functools
from tinygrad import Tensor, TinyJit, Device
from tinygrad.engine.realize import CompiledRunner
from tinygrad.helpers import get_single_element, Context, OSX
from tinygrad.dtype import _from_torch_dtype
@TinyJit
def f(tg_out, tg_data): return tg_out.assign(tg_data[:, :, 0] * 0.2989 + tg_data[:, :, 1] * 0.5870 + tg_data[:, :, 2] * 0.1140).realize()
def custom_kernel(data: torch.Tensor, device="CUDA") -> torch.Tensor:
assert data.dtype == torch.float32
tg_data = Tensor.from_blob(data.data_ptr(), data.shape, dtype=_from_torch_dtype(data.dtype), device=device)
out = torch.empty((data.shape[0], data.shape[1]), dtype=data.dtype, device=data.device)
tg_out = Tensor.from_blob(out.data_ptr(), out.shape, dtype=_from_torch_dtype(out.dtype), device=device)
# Need to sync torch to make sure the data is valid.
if data.device.type == "mps": torch.mps.synchronize()
else: torch.cuda.synchronize()
with Context(BEAM=2): f(tg_out, tg_data)
# Wait for computation to finish and the data is valid.
Device[device].synchronize()
return out
if __name__ == "__main__":
for i in range(3):
if OSX:
out = custom_kernel(inp:=torch.rand(16, 16, 3, device=torch.device("mps")), device="METAL")
else:
out = custom_kernel(inp:=torch.rand(16, 16, 3, device=torch.device("cuda")), device="CUDA")
assert torch.allclose(out, inp[:, :, 0] * 0.2989 + inp[:, :, 1] * 0.5870 + inp[:, :, 2] * 0.1140)
+1 -1
View File
@@ -17,7 +17,7 @@ def make_dataset():
random.shuffle(ds)
ds = np.array(ds).astype(np.float32)
ds_X = ds[:, 0:6]
ds_Y = np.copy(ds[:, 1:])
ds_Y = np.copy(ds[:, 1:]).astype(np.int32)
ds_X_train, ds_X_test = ds_X[0:8000], ds_X[8000:]
ds_Y_train, ds_Y_test = ds_Y[0:8000], ds_Y[8000:]
return ds_X_train, ds_Y_train, ds_X_test, ds_Y_test
+6 -6
View File
@@ -105,12 +105,12 @@ class Vgg7:
Output format: (1, 3, Y - 14, X - 14)
(the - 14 represents the 7-pixel context border that is lost)
"""
x = self.conv1.forward(x).leakyrelu(0.1)
x = self.conv2.forward(x).leakyrelu(0.1)
x = self.conv3.forward(x).leakyrelu(0.1)
x = self.conv4.forward(x).leakyrelu(0.1)
x = self.conv5.forward(x).leakyrelu(0.1)
x = self.conv6.forward(x).leakyrelu(0.1)
x = self.conv1.forward(x).leaky_relu(0.1)
x = self.conv2.forward(x).leaky_relu(0.1)
x = self.conv3.forward(x).leaky_relu(0.1)
x = self.conv4.forward(x).leaky_relu(0.1)
x = self.conv5.forward(x).leaky_relu(0.1)
x = self.conv6.forward(x).leaky_relu(0.1)
x = self.conv7.forward(x)
return x
+4 -4
View File
@@ -193,10 +193,10 @@ class Generator:
x = self.conv_pre(x)
if g is not None: x = x + self.cond(g)
for i in range(self.num_upsamples):
x = self.ups[i](x.leakyrelu(LRELU_SLOPE))
x = self.ups[i](x.leaky_relu(LRELU_SLOPE))
xs = sum(self.resblocks[i * self.num_kernels + j].forward(x) for j in range(self.num_kernels))
x = (xs / self.num_kernels).realize()
res = self.conv_post(x.leakyrelu()).tanh().realize()
res = self.conv_post(x.leaky_relu()).tanh().realize()
return res
class LayerNorm(nn.LayerNorm):
@@ -238,8 +238,8 @@ class ResBlock1:
self.convs2 = [nn.Conv1d(channels, channels, kernel_size, 1, dilation=1, padding=get_padding(kernel_size, 1)) for _ in range(3)]
def forward(self, x: Tensor, x_mask=None):
for c1, c2 in zip(self.convs1, self.convs2):
xt = x.leakyrelu(LRELU_SLOPE)
xt = c1(xt if x_mask is None else xt * x_mask).leakyrelu(LRELU_SLOPE)
xt = x.leaky_relu(LRELU_SLOPE)
xt = c1(xt if x_mask is None else xt * x_mask).leaky_relu(LRELU_SLOPE)
x = c2(xt if x_mask is None else xt * x_mask) + x
return x if x_mask is None else x * x_mask
+1 -4
View File
@@ -18,10 +18,6 @@ canvas { display: none; }
</style>
<title>tinygrad has WebGPU</title>
<link rel="icon" type="image/x-icon" href="https://raw.githubusercontent.com/tinygrad/tinygrad/master/docs/logo.png">
<script type="module">
import model from "../../net.js";
window.model = model;
</script>
</head>
<body>
<h1>WebGPU <a href="https://github.com/geohot/tinygrad">tinygrad</a> EfficientNet!</h1>
@@ -102,6 +98,7 @@ canvas { display: none; }
resultText.innerHTML = "loading..."
labels = await getLabels();
const device = await getDevice();
const model = (await import("../../net.js")).default;
net = await timer(() => model.load(device, '../../net.safetensors'), "(compilation)");
resultText.innerHTML = "ready"
} catch (e) {
+1 -1
View File
@@ -12,7 +12,7 @@ if __name__ == "__main__":
yolo_infer = YOLOv8(w=0.25, r=2.0, d=0.33, num_classes=80)
state_dict = safe_load(get_weights_location(yolo_variant))
load_state_dict(yolo_infer, state_dict)
prg, inp_sizes, out_sizes, state = export_model(yolo_infer, Device.DEFAULT.lower(), Tensor.randn(1,3,416,416), model_name="yolov8")
prg, inp_sizes, out_sizes, state = export_model(yolo_infer, Device.DEFAULT.lower(), Tensor.randn(1,3,640,640), model_name="yolov8")
dirname = Path(__file__).parent
safe_save(state, (dirname / "net.safetensors").as_posix())
with open(dirname / f"net.js", "w") as text_file:
+22 -72
View File
@@ -111,7 +111,7 @@
</div>
<script>
let net = null;
const modelInputSize = 416;
const modelInputSize = 640;
let lastCalledTime;
let fps = 0, accumFps = 0, frameCounter = 0;
@@ -127,14 +127,22 @@
const offscreenContext = offscreenCanvas.getContext('2d');
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({ audio: false, video: { facingMode: { ideal: "environment" }}}).then(function (stream) {
if (navigator.mediaDevices?.getUserMedia) {
const tryCamera = facing => navigator.mediaDevices.getUserMedia({ audio: false, video: { facingMode: { ideal: facing } } });
const handle = stream => {
video.srcObject = stream;
video.onloadedmetadata = function() {
canvas.width = video.clientWidth;
canvas.height = video.clientHeight;
}
});
};
};
tryCamera("environment").then(handle).catch(() =>
tryCamera("user").then(handle).catch(e => {
wgpuError.textContent = "Error: Could not access camera."
wgpuError.style.display = "block";
loadingContainer.style.display = "none";
})
);
}
async function processFrame() {
@@ -176,10 +184,12 @@
offscreenContext.clearRect(0, 0, modelInputSize, modelInputSize);
offscreenContext.drawImage(video, offsetX, offsetY, targetWidth, targetHeight);
const boxes = await detectObjectsOnFrame(offscreenContext);
drawBoxes(offscreenCanvas, boxes, targetWidth, targetHeight, offsetX, offsetY);
const validBoxes = [];
for (let i = 0; i < boxes.length; i += 6)
if (boxes[i + 4] > 0) validBoxes.push([boxes[i], boxes[i + 1], boxes[i + 2], boxes[i + 3], boxes[i + 5]]);
drawBoxes(offscreenCanvas, validBoxes, targetWidth, targetHeight, offsetX, offsetY);
requestAnimationFrame(processFrame);
}
requestAnimationFrame(processFrame);
function drawBoxes(offscreenCanvas, boxes, targetWidth, targetHeight, offsetX, offsetY) {
@@ -190,8 +200,8 @@
const scaleX = canvas.width / targetWidth;
const scaleY = canvas.height / targetHeight;
boxes.forEach(([x1, y1, x2, y2, label]) => {
const classIndex = yolo_classes.indexOf(label);
boxes.forEach(([x1, y1, x2, y2, classIndex]) => {
const label = yolo_classes[classIndex];
const color = classColors[classIndex];
ctx.strokeStyle = color;
ctx.fillStyle = color;
@@ -219,21 +229,13 @@
net = await yolov8.load(device, "./net.safetensors");
loadingContainer.style.display = "none";
}
let start = performance.now();
const [input,img_width,img_height] = await prepareInput(offscreenContext);
console.log("Preprocess took: " + (performance.now() - start) + " ms");
start = performance.now();
const input = await prepareInput(offscreenContext);
const output = await net(new Float32Array(input));
console.log("Inference took: " + (performance.now() - start) + " ms");
start = performance.now();
let out = processOutput(output[0],img_width,img_height);
console.log("Postprocess took: " + (performance.now() - start) + " ms");
return out;
return output[0];
}
async function prepareInput(offscreenContext) {
return new Promise(resolve => {
const [img_width,img_height] = [modelInputSize, modelInputSize]
const imgData = offscreenContext.getImageData(0,0,modelInputSize,modelInputSize);
const pixels = imgData.data;
const red = [], green = [], blue = [];
@@ -244,7 +246,7 @@
blue.push(pixels[index+2]/255.0);
}
const input = [...red, ...green, ...blue];
resolve([input, img_width, img_height])
resolve(input)
})
}
@@ -252,62 +254,10 @@
if (!navigator.gpu) return false;
const adapter = await navigator.gpu.requestAdapter();
return await adapter.requestDevice({
requiredFeatures: ["shader-f16"],
powerPreference: "high-performance"
});
};
function processOutput(output, img_width, img_height) {
let boxes = [];
const numPredictions = Math.pow(modelInputSize/32, 2) * 21;
for (let index=0;index<numPredictions;index++) {
const [class_id,prob] = [...Array(80).keys()]
.map(col => [col, output[numPredictions*(col+4)+index]])
.reduce((accum, item) => item[1]>accum[1] ? item : accum,[0,0]);
if (prob < 0.25) continue;
const label = yolo_classes[class_id];
const xc = output[index];
const yc = output[numPredictions+index];
const w = output[2*numPredictions+index];
const h = output[3*numPredictions+index];
const x1 = (xc-w/2)/modelInputSize*img_width;
const y1 = (yc-h/2)/modelInputSize*img_height;
const x2 = (xc+w/2)/modelInputSize*img_width;
const y2 = (yc+h/2)/modelInputSize*img_height;
boxes.push([x1,y1,x2,y2,label,prob]);
}
boxes = boxes.sort((box1,box2) => box2[5]-box1[5])
const result = [];
while (boxes.length>0) {
result.push(boxes[0]);
boxes = boxes.filter(box => iou(boxes[0],box)<0.7);
}
return result;
}
function iou(box1,box2) {
return intersection(box1,box2)/union(box1,box2);
}
function union(box1,box2) {
const [box1_x1,box1_y1,box1_x2,box1_y2] = box1;
const [box2_x1,box2_y1,box2_x2,box2_y2] = box2;
const box1_area = (box1_x2-box1_x1)*(box1_y2-box1_y1)
const box2_area = (box2_x2-box2_x1)*(box2_y2-box2_y1)
return box1_area + box2_area - intersection(box1,box2)
}
function intersection(box1,box2) {
const [box1_x1,box1_y1,box1_x2,box1_y2] = box1;
const [box2_x1,box2_y1,box2_x2,box2_y2] = box2;
const x1 = Math.max(box1_x1,box2_x1);
const y1 = Math.max(box1_y1,box2_y1);
const x2 = Math.min(box1_x2,box2_x2);
const y2 = Math.min(box1_y2,box2_y2);
return (x2-x1)*(y2-y1)
}
const yolo_classes = [
'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat',
+1 -1
View File
@@ -228,7 +228,7 @@ class Darknet:
module.append(BatchNorm2d(filters, eps=1e-05, track_running_stats=True))
# LeakyReLU activation
if activation == "leaky":
module.append(lambda x: x.leakyrelu(0.1))
module.append(lambda x: x.leaky_relu(0.1))
elif module_type == "maxpool":
size, stride = int(x["size"]), int(x["stride"])
module.append(lambda x: x.max_pool2d(kernel_size=(size, size), stride=stride))
+1 -1
View File
@@ -3,7 +3,7 @@ import os
from ultralytics import YOLO
import onnx
from pathlib import Path
from extra.onnx import OnnxRunner
from tinygrad.frontend.onnx import OnnxRunner
from extra.onnx_helpers import get_example_inputs
from tinygrad.tensor import Tensor
+82 -143
View File
@@ -42,69 +42,8 @@ def preprocess(im, imgsz=640, model_stride=32, model_pt=True):
im = im / 255.0 # 0 - 255 to 0.0 - 1.0
return im
# Post Processing functions
def box_area(box):
return (box[:, 2] - box[:, 0]) * (box[:, 3] - box[:, 1])
def box_iou(box1, box2):
lt = np.maximum(box1[:, None, :2], box2[:, :2])
rb = np.minimum(box1[:, None, 2:], box2[:, 2:])
wh = np.clip(rb - lt, 0, None)
inter = wh[:, :, 0] * wh[:, :, 1]
area1 = box_area(box1)[:, None]
area2 = box_area(box2)[None, :]
iou = inter / (area1 + area2 - inter)
return iou
def compute_nms(boxes, scores, iou_threshold):
order, keep = scores.argsort()[::-1], []
while order.size > 0:
i = order[0]
keep.append(i)
if order.size == 1:
break
iou = box_iou(boxes[i][None, :], boxes[order[1:]])
inds = np.where(np.atleast_1d(iou.squeeze()) <= iou_threshold)[0]
order = order[inds + 1]
return np.array(keep)
def non_max_suppression(prediction, conf_thres=0.25, iou_thres=0.45, agnostic=False, max_det=300, nc=0, max_wh=7680):
prediction = prediction[0] if isinstance(prediction, (list, tuple)) else prediction
bs, nc = prediction.shape[0], nc or (prediction.shape[1] - 4)
xc = np.amax(prediction[:, 4:4 + nc], axis=1) > conf_thres
nm = prediction.shape[1] - nc - 4
output = [np.zeros((0, 6 + nm))] * bs
for xi, x in enumerate(prediction):
x = x.swapaxes(0, -1)[xc[xi]]
if not x.shape[0]: continue
box, cls, mask = np.split(x, [4, 4 + nc], axis=1)
conf, j = np.max(cls, axis=1, keepdims=True), np.argmax(cls, axis=1, keepdims=True)
x = np.concatenate((xywh2xyxy(box), conf, j.astype(np.float32), mask), axis=1)
x = x[conf.ravel() > conf_thres]
if not x.shape[0]: continue
x = x[np.argsort(-x[:, 4])]
c = x[:, 5:6] * (0 if agnostic else max_wh)
boxes, scores = x[:, :4] + c, x[:, 4]
i = compute_nms(boxes, scores, iou_thres)[:max_det]
output[xi] = x[i]
return output
def postprocess(preds, img, orig_imgs):
print('copying to CPU now for post processing')
#if you are on CPU, this causes an overflow runtime error. doesn't "seem" to make any difference in the predictions though.
# TODO: make non_max_suppression in tinygrad - to make this faster
preds = preds.numpy() if isinstance(preds, Tensor) else preds
preds = non_max_suppression(prediction=preds, conf_thres=0.25, iou_thres=0.7, agnostic=False, max_det=300)
all_preds = []
for i, pred in enumerate(preds):
orig_img = orig_imgs[i] if isinstance(orig_imgs, list) else orig_imgs
if not isinstance(orig_imgs, Tensor):
pred[:, :4] = scale_boxes(img.shape[2:], pred[:, :4], orig_img.shape)
all_preds.append(pred)
return all_preds
def draw_bounding_boxes_and_save(orig_img_paths, output_img_paths, all_predictions, class_labels, iou_threshold=0.5):
def draw_bounding_boxes_and_save(orig_img_path, output_img_path, predictions, class_labels):
color_dict = {label: tuple((((i+1) * 50) % 256, ((i+1) * 100) % 256, ((i+1) * 150) % 256)) for i, label in enumerate(class_labels)}
font = cv2.FONT_HERSHEY_SIMPLEX
@@ -113,52 +52,32 @@ def draw_bounding_boxes_and_save(orig_img_paths, output_img_paths, all_predictio
brightness = (r * 299 + g * 587 + b * 114) / 1000
return brightness > 127
for img_idx, (orig_img_path, output_img_path, predictions) in enumerate(zip(orig_img_paths, output_img_paths, all_predictions)):
predictions = np.array(predictions)
orig_img = cv2.imread(orig_img_path) if not isinstance(orig_img_path, np.ndarray) else cv2.imdecode(orig_img_path, 1)
height, width, _ = orig_img.shape
box_thickness = int((height + width) / 400)
font_scale = (height + width) / 2500
orig_img = cv2.imread(orig_img_path) if not isinstance(orig_img_path, np.ndarray) else cv2.imdecode(orig_img_path, 1)
height, width, _ = orig_img.shape
box_thickness = int((height + width) / 400)
font_scale = (height + width) / 2500
object_count = defaultdict(int)
grouped_preds = defaultdict(list)
object_count = defaultdict(int)
for pred in predictions:
x1, y1, x2, y2, conf, class_id = pred
if conf == 0: continue
x1, y1, x2, y2, class_id = map(int, (x1, y1, x2, y2, class_id))
color = color_dict[class_labels[class_id]]
cv2.rectangle(orig_img, (x1, y1), (x2, y2), color, box_thickness)
label = f"{class_labels[class_id]} {conf:.2f}"
text_size, _ = cv2.getTextSize(label, font, font_scale, 1)
label_y, bg_y = (y1 - 4, y1 - text_size[1] - 4) if y1 - text_size[1] - 4 > 0 else (y1 + text_size[1], y1)
cv2.rectangle(orig_img, (x1, bg_y), (x1 + text_size[0], bg_y + text_size[1]), color, -1)
font_color = (0, 0, 0) if is_bright_color(color) else (255, 255, 255)
cv2.putText(orig_img, label, (x1, label_y), font, font_scale, font_color, 1, cv2.LINE_AA)
object_count[class_labels[class_id]] += 1
for pred_np in predictions:
grouped_preds[int(pred_np[-1])].append(pred_np)
print("Objects detected:")
for obj, count in object_count.items():
print(f"- {obj}: {count}")
def draw_box_and_label(pred, color):
x1, y1, x2, y2, conf, _ = pred
x1, y1, x2, y2 = map(int, (x1, y1, x2, y2))
cv2.rectangle(orig_img, (x1, y1), (x2, y2), color, box_thickness)
label = f"{class_labels[class_id]} {conf:.2f}"
text_size, _ = cv2.getTextSize(label, font, font_scale, 1)
label_y, bg_y = (y1 - 4, y1 - text_size[1] - 4) if y1 - text_size[1] - 4 > 0 else (y1 + text_size[1], y1)
cv2.rectangle(orig_img, (x1, bg_y), (x1 + text_size[0], bg_y + text_size[1]), color, -1)
font_color = (0, 0, 0) if is_bright_color(color) else (255, 255, 255)
cv2.putText(orig_img, label, (x1, label_y), font, font_scale, font_color, 1, cv2.LINE_AA)
for class_id, pred_list in grouped_preds.items():
pred_list = np.array(pred_list)
while len(pred_list) > 0:
max_conf_idx = np.argmax(pred_list[:, 4])
max_conf_pred = pred_list[max_conf_idx]
pred_list = np.delete(pred_list, max_conf_idx, axis=0)
color = color_dict[class_labels[class_id]]
draw_box_and_label(max_conf_pred, color)
object_count[class_labels[class_id]] += 1
iou_scores = box_iou(np.array([max_conf_pred[:4]]), pred_list[:, :4])
low_iou_indices = np.where(iou_scores[0] < iou_threshold)[0]
pred_list = pred_list[low_iou_indices]
for low_conf_pred in pred_list:
draw_box_and_label(low_conf_pred, color)
print(f"Image {img_idx + 1}:")
print("Objects detected:")
for obj, count in object_count.items():
print(f"- {obj}: {count}")
cv2.imwrite(output_img_path, orig_img)
print(f'saved detections at {output_img_path}')
cv2.imwrite(output_img_path, orig_img)
print(f'saved detections at {output_img_path}')
# utility functions for forward pass.
def dist2bbox(distance, anchor_points, xywh=True, dim=-1):
@@ -202,34 +121,26 @@ def clip_boxes(boxes, shape):
boxes[..., [1, 3]] = np.clip(boxes[..., [1, 3]], 0, shape[0]) # y1, y2
return boxes
def scale_boxes(img1_shape, boxes, img0_shape, ratio_pad=None):
def scale_boxes(img1_shape, predictions, img0_shape, ratio_pad=None):
gain = ratio_pad if ratio_pad else min(img1_shape[0] / img0_shape[0], img1_shape[1] / img0_shape[1])
pad = ((img1_shape[1] - img0_shape[1] * gain) / 2, (img1_shape[0] - img0_shape[0] * gain) / 2)
boxes_np = boxes.numpy() if isinstance(boxes, Tensor) else boxes
boxes_np[..., [0, 2]] -= pad[0]
boxes_np[..., [1, 3]] -= pad[1]
boxes_np[..., :4] /= gain
boxes_np = clip_boxes(boxes_np, img0_shape)
return boxes_np
def xywh2xyxy(x):
xy = x[..., :2] # center x, y
wh = x[..., 2:4] # width, height
xy1 = xy - wh / 2 # top left x, y
xy2 = xy + wh / 2 # bottom right x, y
result = np.concatenate((xy1, xy2), axis=-1)
return Tensor(result) if isinstance(x, Tensor) else result
for pred in predictions:
boxes_np = pred[:4].numpy() if isinstance(pred[:4], Tensor) else pred[:4]
boxes_np[..., [0, 2]] -= pad[0]
boxes_np[..., [1, 3]] -= pad[1]
boxes_np[..., :4] /= gain
boxes_np = clip_boxes(boxes_np, img0_shape)
pred[:4] = boxes_np
return predictions
def get_variant_multiples(variant):
return {'n':(0.33, 0.25, 2.0), 's':(0.33, 0.50, 2.0), 'm':(0.67, 0.75, 1.5), 'l':(1.0, 1.0, 1.0), 'x':(1, 1.25, 1.0) }.get(variant, None)
def label_predictions(all_predictions):
class_index_count = defaultdict(int)
for predictions in all_predictions:
predictions = np.array(predictions)
for pred_np in predictions:
class_id = int(pred_np[-1])
class_index_count[class_id] += 1
for pred in all_predictions:
class_id = int(pred[-1])
if pred[-2] != 0: class_index_count[class_id] += 1
return dict(class_index_count)
@@ -380,7 +291,9 @@ class YOLOv8:
def __call__(self, x):
x = self.net(x)
x = self.fpn(*x)
return self.head(x)
x = self.head(x)
# TODO: postprocess needs to be in the model to be compiled to webgpu
return postprocess(x)
def return_all_trainable_modules(self):
backbone_modules = [*range(10)]
@@ -403,16 +316,45 @@ def convert_f16_safetensor_to_f32(input_file: Path, output_file: Path):
f.write(new_metadata_bytes)
float32_values.tofile(f)
def compute_iou_matrix(boxes):
x1, y1, x2, y2 = boxes[:, 0], boxes[:, 1], boxes[:, 2], boxes[:, 3]
areas = (x2 - x1) * (y2 - y1)
x1 = Tensor.maximum(x1[:, None], x1[None, :])
y1 = Tensor.maximum(y1[:, None], y1[None, :])
x2 = Tensor.minimum(x2[:, None], x2[None, :])
y2 = Tensor.minimum(y2[:, None], y2[None, :])
w = Tensor.maximum(Tensor(0), x2 - x1)
h = Tensor.maximum(Tensor(0), y2 - y1)
intersection = w * h
union = areas[:, None] + areas[None, :] - intersection
return intersection / union
def postprocess(output, max_det=300, conf_threshold=0.25, iou_threshold=0.45):
xc, yc, w, h, class_scores = output[0][0], output[0][1], output[0][2], output[0][3], output[0][4:]
class_ids = Tensor.argmax(class_scores, axis=0)
probs = Tensor.max(class_scores, axis=0)
probs = Tensor.where(probs >= conf_threshold, probs, 0)
x1 = xc - w / 2
y1 = yc - h / 2
x2 = xc + w / 2
y2 = yc + h / 2
boxes = Tensor.stack(x1, y1, x2, y2, probs, class_ids, dim=1)
order = Tensor.topk(probs, max_det)[1]
boxes = boxes[order]
iou = compute_iou_matrix(boxes[:, :4])
iou = Tensor.triu(iou, diagonal=1)
same_class_mask = boxes[:, -1][:, None] == boxes[:, -1][None, :]
high_iou_mask = (iou > iou_threshold) & same_class_mask
no_overlap_mask = high_iou_mask.sum(axis=0) == 0
boxes = boxes * no_overlap_mask.unsqueeze(-1)
return boxes
def get_weights_location(yolo_variant: str) -> Path:
weights_location = Path(__file__).parents[1] / "weights" / f'yolov8{yolo_variant}.safetensors'
fetch(f'https://gitlab.com/r3sist/yolov8_weights/-/raw/master/yolov8{yolo_variant}.safetensors', weights_location)
if not is_dtype_supported(dtypes.half):
f32_weights = weights_location.with_name(f"{weights_location.stem}_f32.safetensors")
if not f32_weights.exists(): convert_f16_safetensor_to_f32(weights_location, f32_weights)
weights_location = f32_weights
return weights_location
f32_weights = weights_location.with_name(f"{weights_location.stem}_f32.safetensors")
if not f32_weights.exists(): convert_f16_safetensor_to_f32(weights_location, f32_weights)
return f32_weights
if __name__ == '__main__':
@@ -428,14 +370,13 @@ if __name__ == '__main__':
output_folder_path = Path('./outputs_yolov8')
output_folder_path.mkdir(parents=True, exist_ok=True)
#absolute image path or URL
image_location = [np.frombuffer(fetch(img_path).read_bytes(), np.uint8)]
image = [cv2.imdecode(image_location[0], 1)]
out_paths = [(output_folder_path / f"{Path(img_path).stem}_output{Path(img_path).suffix or '.png'}").as_posix()]
image_location = np.frombuffer(fetch(img_path).read_bytes(), np.uint8)
image = [cv2.imdecode(image_location, 1)]
out_path = (output_folder_path / f"{Path(img_path).stem}_output{Path(img_path).suffix or '.png'}").as_posix()
if not isinstance(image[0], np.ndarray):
print('Error in image loading. Check your image file.')
sys.exit(1)
pre_processed_image = preprocess(image)
# Different YOLOv8 variants use different w , r, and d multiples. For a list , refer to this yaml file (the scales section) https://github.com/ultralytics/ultralytics/blob/main/ultralytics/cfg/models/v8/yolov8.yaml
depth, width, ratio = get_variant_multiples(yolo_variant)
yolo_infer = YOLOv8(w=width, r=ratio, d=depth, num_classes=80)
@@ -443,15 +384,13 @@ if __name__ == '__main__':
load_state_dict(yolo_infer, state_dict)
st = time.time()
predictions = yolo_infer(pre_processed_image)
predictions = yolo_infer(pre_processed_image).numpy()
print(f'did inference in {int(round(((time.time() - st) * 1000)))}ms')
post_predictions = postprocess(preds=predictions, img=pre_processed_image, orig_imgs=image)
#v8 and v3 have same 80 class names for Object Detection
class_labels = fetch('https://raw.githubusercontent.com/pjreddie/darknet/master/data/coco.names').read_text().split("\n")
draw_bounding_boxes_and_save(orig_img_paths=image_location, output_img_paths=out_paths, all_predictions=post_predictions, class_labels=class_labels)
predictions = scale_boxes(pre_processed_image.shape[2:], predictions, image[0].shape)
draw_bounding_boxes_and_save(orig_img_path=image_location, output_img_path=out_path, predictions=predictions, class_labels=class_labels)
# TODO for later:
# 1. Fix SPPF minor difference due to maxpool
+112 -42
View File
@@ -1,16 +1,25 @@
#!/usr/bin/env python3
import time, mmap, sys, shutil, os, glob, subprocess
from tinygrad.helpers import to_mv, DEBUG, colored, ansilen
from tinygrad.helpers import DEBUG, colored, ansilen
from tinygrad.runtime.autogen import libc
from tinygrad.runtime.autogen.am import smu_v13_0_0
from tinygrad.runtime.autogen.am import am
from tinygrad.runtime.support.hcq import MMIOInterface
from tinygrad.runtime.support.am.amdev import AMDev, AMMemoryManager
from tinygrad.runtime.support.am.ip import AM_SOC21, AM_GMC, AM_IH, AM_PSP, AM_SMU, AM_GFX, AM_SDMA
from tinygrad.runtime.support.am.ip import AM_SOC, AM_GMC, AM_IH, AM_PSP, AM_SMU, AM_GFX, AM_SDMA
AM_VERSION = 0xA0000002
AM_VERSION = 0xA0000004
def bold(s): return f"\033[1m{s}\033[0m"
def trim(s:str, length:int) -> str:
if len(s) > length: return s[:length-3] + "..."
return s
def pad(x:str, length:int) -> str:
if len(x) < length: return x + " " * (length - len(x))
return x
def color_temp(temp):
if temp >= 87: return colored(f"{temp:>3}", "red")
elif temp >= 80: return colored(f"{temp:>3}", "yellow")
@@ -23,14 +32,17 @@ def draw_bar(percentage, width=40, fill='█', empty='░'):
bar = fill * filled_width + empty * (width - filled_width)
return f'[{bar}] {percentage*100:5.1f}%'
def same_line(strs:list[list[str]], split=8) -> list[str]:
def same_line(strs:list[list[str]|None], split=8) -> list[str]:
strs = [s for s in strs if s is not None]
if len(strs) == 0: return []
ret = []
max_width_in_block = [max(ansilen(line) for line in block) for block in strs]
max_height = max(len(block) for block in strs)
for i in range(max_height):
line = []
for bid, block in enumerate(strs):
if i < len(block): line.append(block[i] + ' ' * (split + max_width_in_block[bid] - ansilen(block[i])))
if i < len(block): line.append(block[i] + (' ' * (split + max_width_in_block[bid] - ansilen(block[i])) if bid != len(strs) - 1 else ''))
else: line.append(' ' * (split + max_width_in_block[bid]))
ret.append(' '.join(line))
return ret
@@ -47,9 +59,9 @@ def get_bar0_size(pcibus):
return int(end_hex, 16) - int(start_hex, 16) + 1
class AMSMI(AMDev):
def __init__(self, pcibus, vram_bar:memoryview, doorbell_bar:memoryview, mmio_bar:memoryview):
def __init__(self, pcibus, vram_bar:MMIOInterface, doorbell_bar:MMIOInterface, mmio_bar:MMIOInterface):
self.pcibus = pcibus
self.vram, self.doorbell64, self.mmio = vram_bar, doorbell_bar, mmio_bar
self.vram, self.doorbell64, self.mmio, self.dma_regions = vram_bar, doorbell_bar, mmio_bar, None
self.pci_state = self.read_pci_state()
if self.pci_state == "D0": self._init_from_d0()
@@ -65,12 +77,14 @@ class AMSMI(AMDev):
self.mm = AMMemoryManager(self, self.vram_size)
# Initialize IP blocks
self.soc21:AM_SOC21 = AM_SOC21(self)
self.soc:AM_SOC = AM_SOC(self)
self.gmc:AM_GMC = AM_GMC(self)
self.ih:AM_IH = AM_IH(self)
self.psp:AM_PSP = AM_PSP(self)
self.smu:AM_SMU = AM_SMU(self)
for ip in [self.soc, self.gmc, self.ih, self.psp, self.smu]: ip.init_sw()
def read_pci_state(self):
with open(f"/sys/bus/pci/devices/{self.pcibus}/power_state", "r") as f: return f.read().strip().rstrip()
@@ -80,6 +94,7 @@ class SMICtx:
self.opened_pcidevs = []
self.opened_pci_resources = {}
self.prev_lines_cnt = 0
self.prev_terminal_width = 0
remove_parts = ["Advanced Micro Devices, Inc. [AMD/ATI]", "VGA compatible controller:"]
lspci = subprocess.check_output(["lspci"]).decode("utf-8").splitlines()
@@ -92,9 +107,9 @@ class SMICtx:
bar_fds = {bar: os.open(f"/sys/bus/pci/devices/{pcibus}/resource{bar}", os.O_RDWR | os.O_SYNC) for bar in [0, 2, 5]}
bar_size = {0: get_bar0_size(pcibus), 2: os.fstat(bar_fds[2]).st_size, 5: os.fstat(bar_fds[5]).st_size}
def map_pci_range(bar):
return to_mv(libc.mmap(0, bar_size[bar], mmap.PROT_READ | mmap.PROT_WRITE, mmap.MAP_SHARED, bar_fds[bar], 0), bar_size[bar])
self.opened_pci_resources[pcibus] = (map_pci_range(0), None, map_pci_range(5).cast('I'))
def map_pci_range(bar, fmt='B'):
return MMIOInterface(libc.mmap(0, bar_size[bar], mmap.PROT_READ | mmap.PROT_WRITE, mmap.MAP_SHARED, bar_fds[bar], 0), bar_size[bar], fmt)
self.opened_pci_resources[pcibus] = (map_pci_range(0), None, map_pci_range(5, 'I'))
try:
self.devs.append(AMSMI(pcibus, *self.opened_pci_resources[pcibus]))
@@ -125,52 +140,107 @@ class SMICtx:
def collect(self): return {d: d.smu.read_metrics() if d.pci_state == "D0" else None for d in self.devs}
def get_gfx_activity(self, dev, metrics): return metrics.SmuMetrics.AverageGfxActivity
def get_mem_activity(self, dev, metrics): return metrics.SmuMetrics.AverageUclkActivity
def get_temps(self, dev, metrics, compact=False):
temps_keys = [(k, name) for k, name in dev.smu.smu_mod.c__EA_TEMP_e__enumvalues.items()
if k < dev.smu.smu_mod.TEMP_COUNT and metrics.SmuMetrics.AvgTemperature[k] != 0]
if compact: temps_keys = [(k, name) for k, name in temps_keys if k in (dev.smu.smu_mod.TEMP_HOTSPOT, dev.smu.smu_mod.TEMP_MEM)]
return {name: metrics.SmuMetrics.AvgTemperature[k] for k, name in temps_keys}
def get_voltage(self, dev, metrics, compact=False):
voltage_keys = [(k, name) for k, name in dev.smu.smu_mod.c__EA_SVI_PLANE_e__enumvalues.items()
if k < dev.smu.smu_mod.SVI_PLANE_COUNT and metrics.SmuMetrics.AvgVoltage[k] != 0]
return {name: metrics.SmuMetrics.AvgVoltage[k] for k, name in voltage_keys}
def get_busy_threshold(self, dev):
match dev.ip_ver[am.MP1_HWIP]:
case (14, 0, 2): return 5
case _: return 15
def get_gfx_freq(self, dev, metrics):
return metrics.SmuMetrics.AverageGfxclkFrequencyPostDs if self.get_gfx_activity(dev, metrics) <= self.get_busy_threshold(dev) else \
metrics.SmuMetrics.AverageGfxclkFrequencyPreDs
def get_mem_freq(self, dev, metrics):
return metrics.SmuMetrics.AverageMemclkFrequencyPostDs if self.get_mem_activity(dev, metrics) <= self.get_busy_threshold(dev) else \
metrics.SmuMetrics.AverageMemclkFrequencyPreDs
def get_fckl_freq(self, dev, metrics):
return metrics.SmuMetrics.AverageFclkFrequencyPostDs if self.get_mem_activity(dev, metrics) <= self.get_busy_threshold(dev) else \
metrics.SmuMetrics.AverageFclkFrequencyPreDs
def get_fan_rpm_pwm(self, dev, metrics): return metrics.SmuMetrics.AvgFanRpm, metrics.SmuMetrics.AvgFanPwm
def get_power(self, dev, metrics): return metrics.SmuMetrics.AverageSocketPower, metrics.SmuMetrics.dGPU_W_MAX
def draw(self):
terminal_width, _ = shutil.get_terminal_size()
terminal_width, terminal_height = shutil.get_terminal_size()
if self.prev_terminal_width != terminal_width or self.prev_terminal_height != terminal_height:
os.system('clear')
self.prev_terminal_width, self.prev_terminal_height = terminal_width, terminal_height
padding = 8
col_size = (terminal_width) // 2 - padding - 2
activity_line_width = 50 if terminal_width > 170 else \
(30 if terminal_width > 130 else \
(16 if terminal_width > 92 else \
max(0, terminal_width - 77)))
dev_metrics = self.collect()
dev_content = []
for dev, metrics in dev_metrics.items():
if dev.pci_state != "D0":
dev_content.append([f"{colored('(sleep)', 'yellow')} {bold(dev.pcibus)}: {self.lspci[dev.pcibus[5:]]}"] +
[f"PCI State: {dev.pci_state}"] + [" "*107])
dev_content.append([f"{colored('(sleep)', 'yellow')} {bold(dev.pcibus)}: {trim(self.lspci[dev.pcibus[5:]], col_size - 20)}"] +
[pad(f"PCI State: {dev.pci_state}", col_size)])
continue
device_line = [f"{bold(dev.pcibus)}: {self.lspci[dev.pcibus[5:]]}"] + [""]
activity_line = [f"GFX Activity {draw_bar(metrics.SmuMetrics.AverageGfxActivity / 100, 50)}"] \
+ [f"MEM Activity {draw_bar(metrics.SmuMetrics.AverageUclkActivity / 100, 50)}"] + [""]
device_line = [f"{bold(dev.pcibus)} {trim(self.lspci[dev.pcibus[5:]], col_size - 20)}"] + [pad("", col_size)]
activity_line = [f"GFX Activity {draw_bar(self.get_gfx_activity(dev, metrics) / 100, activity_line_width)}"] \
+ [f"MEM Activity {draw_bar(self.get_mem_activity(dev, metrics) / 100, activity_line_width)}"]
# draw_metrics_table(metrics, dev)
temps_keys = [(k, name) for k, name in smu_v13_0_0.c__EA_TEMP_e__enumvalues.items()
if k < smu_v13_0_0.TEMP_COUNT and metrics.SmuMetrics.AvgTemperature[k] != 0]
temps_table = ["=== Temps (C) ==="] + [f"{name:<15}: {color_temp(metrics.SmuMetrics.AvgTemperature[k])}" for k, name in temps_keys]
temps_data, temps_data_compact = self.get_temps(dev, metrics), self.get_temps(dev, metrics, compact=True)
temps_table = ["=== Temps (°C) ==="] + [f"{name:<16}: {color_temp(val)}" for name, val in temps_data.items()]
temps_table_compact = ["Temps (°C):" + '/'.join([f"{color_temp(val)} {name}" for name, val in temps_data_compact.items()])]
voltage_keys = [(k, name) for k, name in smu_v13_0_0.c__EA_SVI_PLANE_e__enumvalues.items() if k < smu_v13_0_0.SVI_PLANE_COUNT]
power_table = ["=== Power ==="] \
+ [f"Fan Speed: {metrics.SmuMetrics.AvgFanRpm} RPM"] \
+ [f"Fan Power: {metrics.SmuMetrics.AvgFanPwm}%"] \
+ [f"Power: {metrics.SmuMetrics.AverageSocketPower:>3}W " +
draw_bar(metrics.SmuMetrics.AverageSocketPower / metrics.SmuMetrics.dGPU_W_MAX, 16)] \
+ ["", "=== Voltages ==="] + [f"{name:<20}: {color_voltage(metrics.SmuMetrics.AvgVoltage[k])}" for k, name in voltage_keys]
fan_rpm, fan_pwm = self.get_fan_rpm_pwm(dev, metrics)
power_table = ["=== Power ==="] + [f"Fan Speed: {fan_rpm} RPM"] + [f"Fan Power: {fan_pwm}%"]
frequency_table = ["=== Frequencies ===",
f"GFXCLK Target : {metrics.SmuMetrics.AverageGfxclkFrequencyTarget:>4} MHz",
f"GFXCLK PreDs : {metrics.SmuMetrics.AverageGfxclkFrequencyPreDs:>4} MHz",
f"GFXCLK PostDs : {metrics.SmuMetrics.AverageGfxclkFrequencyPostDs:>4} MHz",
f"FCLK PreDs : {metrics.SmuMetrics.AverageFclkFrequencyPreDs:>4} MHz",
f"FCLK PostDs : {metrics.SmuMetrics.AverageFclkFrequencyPostDs:>4} MHz",
f"MCLK PreDs : {metrics.SmuMetrics.AverageMemclkFrequencyPreDs:>4} MHz",
f"MCLK PostDs : {metrics.SmuMetrics.AverageMemclkFrequencyPostDs:>4} MHz",
f"VCLK0 : {metrics.SmuMetrics.AverageVclk0Frequency:>4} MHz",
f"DCLK0 : {metrics.SmuMetrics.AverageDclk0Frequency:>4} MHz",
f"VCLK1 : {metrics.SmuMetrics.AverageVclk1Frequency:>4} MHz",
f"DCLK1 : {metrics.SmuMetrics.AverageDclk1Frequency:>4} MHz"]
total_power, max_power = self.get_power(dev, metrics)
power_line = [f"Power: {total_power:>3}W " + draw_bar(total_power / max_power, 16)]
power_line_compact = [f"Power: {total_power:>3}W " + draw_bar(total_power / max_power, activity_line_width)]
voltage_data = self.get_voltage(dev, metrics)
voltage_table = ["=== Voltages ==="] + [f"{name:<20}: {color_voltage(voltage)}" for name, voltage in voltage_data.items()]
gfx_freq = self.get_gfx_freq(dev, metrics)
mclk_freq = self.get_mem_freq(dev, metrics)
fclk_freq = self.get_fckl_freq(dev, metrics)
frequency_table = ["=== Frequencies ===", f"GFXCLK: {gfx_freq:>4} MHz", f"FCLK : {fclk_freq:>4} MHz", f"MCLK : {mclk_freq:>4} MHz"]
if self.prev_terminal_width >= 231:
power_table += power_line + [""] + voltage_table
activity_line += [""]
elif self.prev_terminal_width >= 171:
power_table += power_line + [""] + frequency_table
activity_line += [""]
frequency_table = None
elif self.prev_terminal_width >= 121:
temps_table = None
activity_line += power_line_compact
else:
temps_table = None
power_table = None
frequency_table = None
activity_line += power_line_compact
dev_content.append(device_line + activity_line + same_line([temps_table, power_table, frequency_table]))
raw_text = 'AM Monitor'.center(terminal_width) + "\n" + "=" * terminal_width + "\n\n"
for i in range(0, len(dev_content), 2):
if i + 1 < len(dev_content): raw_text += '\n'.join(same_line([dev_content[i], dev_content[i+1]]))
if i + 1 < len(dev_content): raw_text += '\n'.join(same_line([dev_content[i], dev_content[i+1]], split=padding))
else: raw_text += '\n'.join(dev_content[i])
if i + 2 < len(dev_content): raw_text += "\n" + "=" * terminal_width + "\n\n"
+422 -389
View File
@@ -21,395 +21,426 @@
*
*/
#ifndef _DISCOVERY_H_
#define _DISCOVERY_H_
#define uint32_t unsigned int
#define uint8_t unsigned char
#define uint16_t unsigned short
#define uint64_t unsigned long long
#define u32 unsigned int
#define u8 unsigned char
#define u16 unsigned short
#define u64 unsigned long long
#define bool unsigned char
#define PSP_HEADER_SIZE 256
#define BINARY_SIGNATURE 0x28211407
#define DISCOVERY_TABLE_SIGNATURE 0x53445049
#define GC_TABLE_ID 0x4347
#define HARVEST_TABLE_SIGNATURE 0x56524148
#define VCN_INFO_TABLE_ID 0x004E4356
#define MALL_INFO_TABLE_ID 0x4C4C414D
#define NPS_INFO_TABLE_ID 0x0053504E
typedef enum {
IP_DISCOVERY = 0,
GC,
HARVEST_INFO,
VCN_INFO,
MALL_INFO,
NPS_INFO,
TOTAL_TABLES = 6
} table;
#pragma pack(1)
typedef struct table_info
{
uint16_t offset; /* Byte offset */
uint16_t checksum; /* Byte sum of the table */
uint16_t size; /* Table size */
uint16_t padding;
} table_info;
typedef struct binary_header
{
/* psp structure should go at the top of this structure */
uint32_t binary_signature; /* 0x7, 0x14, 0x21, 0x28 */
uint16_t version_major;
uint16_t version_minor;
uint16_t binary_checksum; /* Byte sum of the binary after this field */
uint16_t binary_size; /* Binary Size*/
table_info table_list[TOTAL_TABLES];
} binary_header;
typedef struct die_info
{
uint16_t die_id;
uint16_t die_offset; /* Points to the corresponding die_header structure */
} die_info;
typedef struct ip_discovery_header
{
uint32_t signature; /* Table Signature */
uint16_t version; /* Table Version */
uint16_t size; /* Table Size */
uint32_t id; /* Table ID */
uint16_t num_dies; /* Number of Dies */
die_info die_info[16]; /* list die information for up to 16 dies */
union {
uint16_t padding[1]; /* version <= 3 */
struct { /* version == 4 */
uint8_t base_addr_64_bit : 1; /* ip structures are using 64 bit base address */
uint8_t reserved : 7;
uint8_t reserved2;
};
};
} ip_discovery_header;
typedef struct ip
{
uint16_t hw_id; /* Hardware ID */
uint8_t number_instance; /* instance of the IP */
uint8_t num_base_address; /* Number of Base Addresses */
uint8_t major; /* HCID Major */
uint8_t minor; /* HCID Minor */
uint8_t revision; /* HCID Revision */
#if defined(__BIG_ENDIAN)
uint8_t reserved : 4; /* Placeholder field */
uint8_t harvest : 4; /* Harvest */
#else
uint8_t harvest : 4; /* Harvest */
uint8_t reserved : 4; /* Placeholder field */
#endif
uint32_t base_address[1]; /* variable number of Addresses */
} ip;
typedef struct ip_v3
{
uint16_t hw_id; /* Hardware ID */
uint8_t instance_number; /* Instance number for the IP */
uint8_t num_base_address; /* Number of base addresses*/
uint8_t major; /* Hardware ID.major version */
uint8_t minor; /* Hardware ID.minor version */
uint8_t revision; /* Hardware ID.revision version */
#if defined(__BIG_ENDIAN)
uint8_t variant : 4; /* HW variant */
uint8_t sub_revision : 4; /* HCID Sub-Revision */
#else
uint8_t sub_revision : 4; /* HCID Sub-Revision */
uint8_t variant : 4; /* HW variant */
#endif
uint32_t base_address[1]; /* Base Address list. Corresponds to the num_base_address field*/
} ip_v3;
typedef struct ip_v4 {
uint16_t hw_id; /* Hardware ID */
uint8_t instance_number; /* Instance number for the IP */
uint8_t num_base_address; /* Number of base addresses*/
uint8_t major; /* Hardware ID.major version */
uint8_t minor; /* Hardware ID.minor version */
uint8_t revision; /* Hardware ID.revision version */
#if defined(LITTLEENDIAN_CPU)
uint8_t sub_revision : 4; /* HCID Sub-Revision */
uint8_t variant : 4; /* HW variant */
#elif defined(BIGENDIAN_CPU)
uint8_t variant : 4; /* HW variant */
uint8_t sub_revision : 4; /* HCID Sub-Revision */
#endif
uint64_t base_address_64[1];
} ip_v4;
typedef struct die_header
{
uint16_t die_id;
uint16_t num_ips;
} die_header;
typedef struct ip_structure
{
ip_discovery_header* header;
struct die
{
die_header *die_header;
union
{
ip *ip_list;
ip_v3 *ip_v3_list;
ip_v4 *ip_v4_list;
}; /* IP list. Variable size*/
} die;
} ip_structure;
struct gpu_info_header {
uint32_t table_id; /* table ID */
uint16_t version_major; /* table version */
uint16_t version_minor; /* table version */
uint32_t size; /* size of the entire header+data in bytes */
};
struct gc_info_v1_0 {
struct gpu_info_header header;
uint32_t gc_num_se;
uint32_t gc_num_wgp0_per_sa;
uint32_t gc_num_wgp1_per_sa;
uint32_t gc_num_rb_per_se;
uint32_t gc_num_gl2c;
uint32_t gc_num_gprs;
uint32_t gc_num_max_gs_thds;
uint32_t gc_gs_table_depth;
uint32_t gc_gsprim_buff_depth;
uint32_t gc_parameter_cache_depth;
uint32_t gc_double_offchip_lds_buffer;
uint32_t gc_wave_size;
uint32_t gc_max_waves_per_simd;
uint32_t gc_max_scratch_slots_per_cu;
uint32_t gc_lds_size;
uint32_t gc_num_sc_per_se;
uint32_t gc_num_sa_per_se;
uint32_t gc_num_packer_per_sc;
uint32_t gc_num_gl2a;
};
struct gc_info_v1_1 {
struct gpu_info_header header;
uint32_t gc_num_se;
uint32_t gc_num_wgp0_per_sa;
uint32_t gc_num_wgp1_per_sa;
uint32_t gc_num_rb_per_se;
uint32_t gc_num_gl2c;
uint32_t gc_num_gprs;
uint32_t gc_num_max_gs_thds;
uint32_t gc_gs_table_depth;
uint32_t gc_gsprim_buff_depth;
uint32_t gc_parameter_cache_depth;
uint32_t gc_double_offchip_lds_buffer;
uint32_t gc_wave_size;
uint32_t gc_max_waves_per_simd;
uint32_t gc_max_scratch_slots_per_cu;
uint32_t gc_lds_size;
uint32_t gc_num_sc_per_se;
uint32_t gc_num_sa_per_se;
uint32_t gc_num_packer_per_sc;
uint32_t gc_num_gl2a;
uint32_t gc_num_tcp_per_sa;
uint32_t gc_num_sdp_interface;
uint32_t gc_num_tcps;
};
struct gc_info_v1_2 {
struct gpu_info_header header;
uint32_t gc_num_se;
uint32_t gc_num_wgp0_per_sa;
uint32_t gc_num_wgp1_per_sa;
uint32_t gc_num_rb_per_se;
uint32_t gc_num_gl2c;
uint32_t gc_num_gprs;
uint32_t gc_num_max_gs_thds;
uint32_t gc_gs_table_depth;
uint32_t gc_gsprim_buff_depth;
uint32_t gc_parameter_cache_depth;
uint32_t gc_double_offchip_lds_buffer;
uint32_t gc_wave_size;
uint32_t gc_max_waves_per_simd;
uint32_t gc_max_scratch_slots_per_cu;
uint32_t gc_lds_size;
uint32_t gc_num_sc_per_se;
uint32_t gc_num_sa_per_se;
uint32_t gc_num_packer_per_sc;
uint32_t gc_num_gl2a;
uint32_t gc_num_tcp_per_sa;
uint32_t gc_num_sdp_interface;
uint32_t gc_num_tcps;
uint32_t gc_num_tcp_per_wpg;
uint32_t gc_tcp_l1_size;
uint32_t gc_num_sqc_per_wgp;
uint32_t gc_l1_instruction_cache_size_per_sqc;
uint32_t gc_l1_data_cache_size_per_sqc;
uint32_t gc_gl1c_per_sa;
uint32_t gc_gl1c_size_per_instance;
uint32_t gc_gl2c_per_gpu;
};
struct gc_info_v2_0 {
struct gpu_info_header header;
uint32_t gc_num_se;
uint32_t gc_num_cu_per_sh;
uint32_t gc_num_sh_per_se;
uint32_t gc_num_rb_per_se;
uint32_t gc_num_tccs;
uint32_t gc_num_gprs;
uint32_t gc_num_max_gs_thds;
uint32_t gc_gs_table_depth;
uint32_t gc_gsprim_buff_depth;
uint32_t gc_parameter_cache_depth;
uint32_t gc_double_offchip_lds_buffer;
uint32_t gc_wave_size;
uint32_t gc_max_waves_per_simd;
uint32_t gc_max_scratch_slots_per_cu;
uint32_t gc_lds_size;
uint32_t gc_num_sc_per_se;
uint32_t gc_num_packer_per_sc;
};
struct gc_info_v2_1 {
struct gpu_info_header header;
uint32_t gc_num_se;
uint32_t gc_num_cu_per_sh;
uint32_t gc_num_sh_per_se;
uint32_t gc_num_rb_per_se;
uint32_t gc_num_tccs;
uint32_t gc_num_gprs;
uint32_t gc_num_max_gs_thds;
uint32_t gc_gs_table_depth;
uint32_t gc_gsprim_buff_depth;
uint32_t gc_parameter_cache_depth;
uint32_t gc_double_offchip_lds_buffer;
uint32_t gc_wave_size;
uint32_t gc_max_waves_per_simd;
uint32_t gc_max_scratch_slots_per_cu;
uint32_t gc_lds_size;
uint32_t gc_num_sc_per_se;
uint32_t gc_num_packer_per_sc;
/* new for v2_1 */
uint32_t gc_num_tcp_per_sh;
uint32_t gc_tcp_size_per_cu;
uint32_t gc_num_sdp_interface;
uint32_t gc_num_cu_per_sqc;
uint32_t gc_instruction_cache_size_per_sqc;
uint32_t gc_scalar_data_cache_size_per_sqc;
uint32_t gc_tcc_size;
};
typedef struct harvest_info_header {
uint32_t signature; /* Table Signature */
uint32_t version; /* Table Version */
} harvest_info_header;
typedef struct harvest_info {
uint16_t hw_id; /* Hardware ID */
uint8_t number_instance; /* Instance of the IP */
uint8_t reserved; /* Reserved for alignment */
} harvest_info;
typedef struct harvest_table {
harvest_info_header header;
harvest_info list[32];
} harvest_table;
struct mall_info_header {
uint32_t table_id; /* table ID */
uint16_t version_major; /* table version */
uint16_t version_minor; /* table version */
uint32_t size_bytes; /* size of the entire header+data in bytes */
};
struct mall_info_v1_0 {
struct mall_info_header header;
uint32_t mall_size_per_m;
uint32_t m_s_present;
uint32_t m_half_use;
uint32_t m_mall_config;
uint32_t reserved[5];
};
struct mall_info_v2_0 {
struct mall_info_header header;
uint32_t mall_size_per_umc;
uint32_t reserved[8];
};
#define VCN_INFO_TABLE_MAX_NUM_INSTANCES 4
struct vcn_info_header {
uint32_t table_id; /* table ID */
uint16_t version_major; /* table version */
uint16_t version_minor; /* table version */
uint32_t size_bytes; /* size of the entire header+data in bytes */
};
struct vcn_instance_info_v1_0
{
uint32_t instance_num; /* VCN IP instance number. 0 - VCN0; 1 - VCN1 etc*/
union _fuse_data {
struct {
uint32_t av1_disabled : 1;
uint32_t vp9_disabled : 1;
uint32_t hevc_disabled : 1;
uint32_t h264_disabled : 1;
uint32_t reserved : 28;
} bits;
uint32_t all_bits;
} fuse_data;
uint32_t reserved[2];
};
struct vcn_info_v1_0 {
struct vcn_info_header header;
uint32_t num_of_instances; /* number of entries used in instance_info below*/
struct vcn_instance_info_v1_0 instance_info[VCN_INFO_TABLE_MAX_NUM_INSTANCES];
uint32_t reserved[4];
};
#define NPS_INFO_TABLE_MAX_NUM_INSTANCES 12
struct nps_info_header {
uint32_t table_id; /* table ID */
uint16_t version_major; /* table version */
uint16_t version_minor; /* table version */
uint32_t size_bytes; /* size of the entire header+data in bytes = 0x000000D4 (212) */
};
struct nps_instance_info_v1_0 {
uint64_t base_address;
uint64_t limit_address;
};
struct nps_info_v1_0 {
struct nps_info_header header;
uint32_t nps_type;
uint32_t count;
struct nps_instance_info_v1_0
instance_info[NPS_INFO_TABLE_MAX_NUM_INSTANCES];
};
enum amd_hw_ip_block_type {
#ifndef _DISCOVERY_H_
#define _DISCOVERY_H_
#define PSP_HEADER_SIZE 256
#define BINARY_SIGNATURE 0x28211407
#define DISCOVERY_TABLE_SIGNATURE 0x53445049
#define GC_TABLE_ID 0x4347
#define HARVEST_TABLE_SIGNATURE 0x56524148
#define VCN_INFO_TABLE_ID 0x004E4356
#define MALL_INFO_TABLE_ID 0x4C4C414D
#define NPS_INFO_TABLE_ID 0x0053504E
typedef enum {
IP_DISCOVERY = 0,
GC,
HARVEST_INFO,
VCN_INFO,
MALL_INFO,
NPS_INFO,
TOTAL_TABLES = 6
} table;
#pragma pack(1)
typedef struct table_info
{
uint16_t offset; /* Byte offset */
uint16_t checksum; /* Byte sum of the table */
uint16_t size; /* Table size */
uint16_t padding;
} table_info;
typedef struct binary_header
{
/* psp structure should go at the top of this structure */
uint32_t binary_signature; /* 0x7, 0x14, 0x21, 0x28 */
uint16_t version_major;
uint16_t version_minor;
uint16_t binary_checksum; /* Byte sum of the binary after this field */
uint16_t binary_size; /* Binary Size*/
table_info table_list[TOTAL_TABLES];
} binary_header;
typedef struct die_info
{
uint16_t die_id;
uint16_t die_offset; /* Points to the corresponding die_header structure */
} die_info;
typedef struct ip_discovery_header
{
uint32_t signature; /* Table Signature */
uint16_t version; /* Table Version */
uint16_t size; /* Table Size */
uint32_t id; /* Table ID */
uint16_t num_dies; /* Number of Dies */
die_info die_info[16]; /* list die information for up to 16 dies */
union {
uint16_t padding[1]; /* version <= 3 */
struct { /* version == 4 */
uint8_t base_addr_64_bit : 1; /* ip structures are using 64 bit base address */
uint8_t reserved : 7;
uint8_t reserved2;
};
};
} ip_discovery_header;
typedef struct ip
{
uint16_t hw_id; /* Hardware ID */
uint8_t number_instance; /* instance of the IP */
uint8_t num_base_address; /* Number of Base Addresses */
uint8_t major; /* HCID Major */
uint8_t minor; /* HCID Minor */
uint8_t revision; /* HCID Revision */
#if defined(__BIG_ENDIAN)
uint8_t reserved : 4; /* Placeholder field */
uint8_t harvest : 4; /* Harvest */
#else
uint8_t harvest : 4; /* Harvest */
uint8_t reserved : 4; /* Placeholder field */
#endif
uint32_t base_address[]; /* variable number of Addresses */
} ip;
typedef struct ip_v3
{
uint16_t hw_id; /* Hardware ID */
uint8_t instance_number; /* Instance number for the IP */
uint8_t num_base_address; /* Number of base addresses*/
uint8_t major; /* Hardware ID.major version */
uint8_t minor; /* Hardware ID.minor version */
uint8_t revision; /* Hardware ID.revision version */
#if defined(__BIG_ENDIAN)
uint8_t variant : 4; /* HW variant */
uint8_t sub_revision : 4; /* HCID Sub-Revision */
#else
uint8_t sub_revision : 4; /* HCID Sub-Revision */
uint8_t variant : 4; /* HW variant */
#endif
uint32_t base_address[]; /* Base Address list. Corresponds to the num_base_address field*/
} ip_v3;
typedef struct ip_v4 {
uint16_t hw_id; /* Hardware ID */
uint8_t instance_number; /* Instance number for the IP */
uint8_t num_base_address; /* Number of base addresses*/
uint8_t major; /* Hardware ID.major version */
uint8_t minor; /* Hardware ID.minor version */
uint8_t revision; /* Hardware ID.revision version */
#if defined(LITTLEENDIAN_CPU)
uint8_t sub_revision : 4; /* HCID Sub-Revision */
uint8_t variant : 4; /* HW variant */
#elif defined(BIGENDIAN_CPU)
uint8_t variant : 4; /* HW variant */
uint8_t sub_revision : 4; /* HCID Sub-Revision */
#endif
} ip_v4;
typedef struct die_header
{
uint16_t die_id;
uint16_t num_ips;
} die_header;
typedef struct ip_structure
{
ip_discovery_header* header;
struct die
{
die_header *die_header;
union
{
ip *ip_list;
ip_v3 *ip_v3_list;
ip_v4 *ip_v4_list;
}; /* IP list. Variable size*/
} die;
} ip_structure;
struct gpu_info_header {
uint32_t table_id; /* table ID */
uint16_t version_major; /* table version */
uint16_t version_minor; /* table version */
uint32_t size; /* size of the entire header+data in bytes */
};
struct gc_info_v1_0 {
struct gpu_info_header header;
uint32_t gc_num_se;
uint32_t gc_num_wgp0_per_sa;
uint32_t gc_num_wgp1_per_sa;
uint32_t gc_num_rb_per_se;
uint32_t gc_num_gl2c;
uint32_t gc_num_gprs;
uint32_t gc_num_max_gs_thds;
uint32_t gc_gs_table_depth;
uint32_t gc_gsprim_buff_depth;
uint32_t gc_parameter_cache_depth;
uint32_t gc_double_offchip_lds_buffer;
uint32_t gc_wave_size;
uint32_t gc_max_waves_per_simd;
uint32_t gc_max_scratch_slots_per_cu;
uint32_t gc_lds_size;
uint32_t gc_num_sc_per_se;
uint32_t gc_num_sa_per_se;
uint32_t gc_num_packer_per_sc;
uint32_t gc_num_gl2a;
};
struct gc_info_v1_1 {
struct gpu_info_header header;
uint32_t gc_num_se;
uint32_t gc_num_wgp0_per_sa;
uint32_t gc_num_wgp1_per_sa;
uint32_t gc_num_rb_per_se;
uint32_t gc_num_gl2c;
uint32_t gc_num_gprs;
uint32_t gc_num_max_gs_thds;
uint32_t gc_gs_table_depth;
uint32_t gc_gsprim_buff_depth;
uint32_t gc_parameter_cache_depth;
uint32_t gc_double_offchip_lds_buffer;
uint32_t gc_wave_size;
uint32_t gc_max_waves_per_simd;
uint32_t gc_max_scratch_slots_per_cu;
uint32_t gc_lds_size;
uint32_t gc_num_sc_per_se;
uint32_t gc_num_sa_per_se;
uint32_t gc_num_packer_per_sc;
uint32_t gc_num_gl2a;
uint32_t gc_num_tcp_per_sa;
uint32_t gc_num_sdp_interface;
uint32_t gc_num_tcps;
};
struct gc_info_v1_2 {
struct gpu_info_header header;
uint32_t gc_num_se;
uint32_t gc_num_wgp0_per_sa;
uint32_t gc_num_wgp1_per_sa;
uint32_t gc_num_rb_per_se;
uint32_t gc_num_gl2c;
uint32_t gc_num_gprs;
uint32_t gc_num_max_gs_thds;
uint32_t gc_gs_table_depth;
uint32_t gc_gsprim_buff_depth;
uint32_t gc_parameter_cache_depth;
uint32_t gc_double_offchip_lds_buffer;
uint32_t gc_wave_size;
uint32_t gc_max_waves_per_simd;
uint32_t gc_max_scratch_slots_per_cu;
uint32_t gc_lds_size;
uint32_t gc_num_sc_per_se;
uint32_t gc_num_sa_per_se;
uint32_t gc_num_packer_per_sc;
uint32_t gc_num_gl2a;
uint32_t gc_num_tcp_per_sa;
uint32_t gc_num_sdp_interface;
uint32_t gc_num_tcps;
uint32_t gc_num_tcp_per_wpg;
uint32_t gc_tcp_l1_size;
uint32_t gc_num_sqc_per_wgp;
uint32_t gc_l1_instruction_cache_size_per_sqc;
uint32_t gc_l1_data_cache_size_per_sqc;
uint32_t gc_gl1c_per_sa;
uint32_t gc_gl1c_size_per_instance;
uint32_t gc_gl2c_per_gpu;
};
struct gc_info_v1_3 {
struct gpu_info_header header;
uint32_t gc_num_se;
uint32_t gc_num_wgp0_per_sa;
uint32_t gc_num_wgp1_per_sa;
uint32_t gc_num_rb_per_se;
uint32_t gc_num_gl2c;
uint32_t gc_num_gprs;
uint32_t gc_num_max_gs_thds;
uint32_t gc_gs_table_depth;
uint32_t gc_gsprim_buff_depth;
uint32_t gc_parameter_cache_depth;
uint32_t gc_double_offchip_lds_buffer;
uint32_t gc_wave_size;
uint32_t gc_max_waves_per_simd;
uint32_t gc_max_scratch_slots_per_cu;
uint32_t gc_lds_size;
uint32_t gc_num_sc_per_se;
uint32_t gc_num_sa_per_se;
uint32_t gc_num_packer_per_sc;
uint32_t gc_num_gl2a;
uint32_t gc_num_tcp_per_sa;
uint32_t gc_num_sdp_interface;
uint32_t gc_num_tcps;
uint32_t gc_num_tcp_per_wpg;
uint32_t gc_tcp_l1_size;
uint32_t gc_num_sqc_per_wgp;
uint32_t gc_l1_instruction_cache_size_per_sqc;
uint32_t gc_l1_data_cache_size_per_sqc;
uint32_t gc_gl1c_per_sa;
uint32_t gc_gl1c_size_per_instance;
uint32_t gc_gl2c_per_gpu;
uint32_t gc_tcp_size_per_cu;
uint32_t gc_tcp_cache_line_size;
uint32_t gc_instruction_cache_size_per_sqc;
uint32_t gc_instruction_cache_line_size;
uint32_t gc_scalar_data_cache_size_per_sqc;
uint32_t gc_scalar_data_cache_line_size;
uint32_t gc_tcc_size;
uint32_t gc_tcc_cache_line_size;
};
struct gc_info_v2_0 {
struct gpu_info_header header;
uint32_t gc_num_se;
uint32_t gc_num_cu_per_sh;
uint32_t gc_num_sh_per_se;
uint32_t gc_num_rb_per_se;
uint32_t gc_num_tccs;
uint32_t gc_num_gprs;
uint32_t gc_num_max_gs_thds;
uint32_t gc_gs_table_depth;
uint32_t gc_gsprim_buff_depth;
uint32_t gc_parameter_cache_depth;
uint32_t gc_double_offchip_lds_buffer;
uint32_t gc_wave_size;
uint32_t gc_max_waves_per_simd;
uint32_t gc_max_scratch_slots_per_cu;
uint32_t gc_lds_size;
uint32_t gc_num_sc_per_se;
uint32_t gc_num_packer_per_sc;
};
struct gc_info_v2_1 {
struct gpu_info_header header;
uint32_t gc_num_se;
uint32_t gc_num_cu_per_sh;
uint32_t gc_num_sh_per_se;
uint32_t gc_num_rb_per_se;
uint32_t gc_num_tccs;
uint32_t gc_num_gprs;
uint32_t gc_num_max_gs_thds;
uint32_t gc_gs_table_depth;
uint32_t gc_gsprim_buff_depth;
uint32_t gc_parameter_cache_depth;
uint32_t gc_double_offchip_lds_buffer;
uint32_t gc_wave_size;
uint32_t gc_max_waves_per_simd;
uint32_t gc_max_scratch_slots_per_cu;
uint32_t gc_lds_size;
uint32_t gc_num_sc_per_se;
uint32_t gc_num_packer_per_sc;
/* new for v2_1 */
uint32_t gc_num_tcp_per_sh;
uint32_t gc_tcp_size_per_cu;
uint32_t gc_num_sdp_interface;
uint32_t gc_num_cu_per_sqc;
uint32_t gc_instruction_cache_size_per_sqc;
uint32_t gc_scalar_data_cache_size_per_sqc;
uint32_t gc_tcc_size;
};
typedef struct harvest_info_header {
uint32_t signature; /* Table Signature */
uint32_t version; /* Table Version */
} harvest_info_header;
typedef struct harvest_info {
uint16_t hw_id; /* Hardware ID */
uint8_t number_instance; /* Instance of the IP */
uint8_t reserved; /* Reserved for alignment */
} harvest_info;
typedef struct harvest_table {
harvest_info_header header;
harvest_info list[32];
} harvest_table;
struct mall_info_header {
uint32_t table_id; /* table ID */
uint16_t version_major; /* table version */
uint16_t version_minor; /* table version */
uint32_t size_bytes; /* size of the entire header+data in bytes */
};
struct mall_info_v1_0 {
struct mall_info_header header;
uint32_t mall_size_per_m;
uint32_t m_s_present;
uint32_t m_half_use;
uint32_t m_mall_config;
uint32_t reserved[5];
};
struct mall_info_v2_0 {
struct mall_info_header header;
uint32_t mall_size_per_umc;
uint32_t reserved[8];
};
#define VCN_INFO_TABLE_MAX_NUM_INSTANCES 4
struct vcn_info_header {
uint32_t table_id; /* table ID */
uint16_t version_major; /* table version */
uint16_t version_minor; /* table version */
uint32_t size_bytes; /* size of the entire header+data in bytes */
};
struct vcn_instance_info_v1_0
{
uint32_t instance_num; /* VCN IP instance number. 0 - VCN0; 1 - VCN1 etc*/
union _fuse_data {
struct {
uint32_t av1_disabled : 1;
uint32_t vp9_disabled : 1;
uint32_t hevc_disabled : 1;
uint32_t h264_disabled : 1;
uint32_t reserved : 28;
} bits;
uint32_t all_bits;
} fuse_data;
uint32_t reserved[2];
};
struct vcn_info_v1_0 {
struct vcn_info_header header;
uint32_t num_of_instances; /* number of entries used in instance_info below*/
struct vcn_instance_info_v1_0 instance_info[VCN_INFO_TABLE_MAX_NUM_INSTANCES];
uint32_t reserved[4];
};
#define NPS_INFO_TABLE_MAX_NUM_INSTANCES 12
struct nps_info_header {
uint32_t table_id; /* table ID */
uint16_t version_major; /* table version */
uint16_t version_minor; /* table version */
uint32_t size_bytes; /* size of the entire header+data in bytes = 0x000000D4 (212) */
};
struct nps_instance_info_v1_0 {
uint64_t base_address;
uint64_t limit_address;
};
struct nps_info_v1_0 {
struct nps_info_header header;
uint32_t nps_type;
uint32_t count;
struct nps_instance_info_v1_0
instance_info[NPS_INFO_TABLE_MAX_NUM_INSTANCES];
};
enum amd_hw_ip_block_type {
GC_HWIP = 1,
HDP_HWIP,
SDMA0_HWIP,
@@ -565,3 +596,5 @@ static int hw_id_map[MAX_HWIP] = {
};
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More