tinygrad 0.10.1__py3-none-any.whl → 0.10.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tinygrad/codegen/devectorizer.py +247 -0
 - tinygrad/codegen/expander.py +121 -0
 - tinygrad/codegen/kernel.py +35 -37
 - tinygrad/codegen/linearize.py +19 -10
 - tinygrad/codegen/lowerer.py +31 -8
 - tinygrad/codegen/symbolic.py +476 -0
 - tinygrad/codegen/transcendental.py +10 -0
 - tinygrad/device.py +28 -11
 - tinygrad/dtype.py +12 -3
 - tinygrad/engine/jit.py +3 -2
 - tinygrad/engine/multi.py +0 -1
 - tinygrad/engine/realize.py +7 -4
 - tinygrad/engine/schedule.py +227 -255
 - tinygrad/engine/search.py +20 -27
 - tinygrad/gradient.py +3 -0
 - tinygrad/helpers.py +7 -4
 - tinygrad/nn/state.py +2 -2
 - tinygrad/ops.py +64 -329
 - tinygrad/renderer/__init__.py +19 -3
 - tinygrad/renderer/cstyle.py +39 -18
 - tinygrad/renderer/llvmir.py +55 -18
 - tinygrad/renderer/ptx.py +6 -2
 - tinygrad/renderer/wgsl.py +20 -12
 - tinygrad/runtime/autogen/libc.py +404 -71
 - tinygrad/runtime/autogen/{libpciaccess.py → pci.py} +25 -715
 - tinygrad/runtime/autogen/webgpu.py +6985 -0
 - tinygrad/runtime/graph/metal.py +28 -29
 - tinygrad/runtime/ops_amd.py +37 -34
 - tinygrad/runtime/{ops_clang.py → ops_cpu.py} +4 -2
 - tinygrad/runtime/ops_disk.py +1 -1
 - tinygrad/runtime/ops_dsp.py +59 -33
 - tinygrad/runtime/ops_llvm.py +14 -12
 - tinygrad/runtime/ops_metal.py +78 -62
 - tinygrad/runtime/ops_nv.py +9 -6
 - tinygrad/runtime/ops_python.py +5 -5
 - tinygrad/runtime/ops_webgpu.py +200 -38
 - tinygrad/runtime/support/am/amdev.py +23 -11
 - tinygrad/runtime/support/am/ip.py +10 -10
 - tinygrad/runtime/support/elf.py +2 -0
 - tinygrad/runtime/support/hcq.py +7 -5
 - tinygrad/runtime/support/llvm.py +8 -14
 - tinygrad/shape/shapetracker.py +3 -2
 - tinygrad/shape/view.py +2 -3
 - tinygrad/spec.py +21 -20
 - tinygrad/tensor.py +150 -90
 - tinygrad/viz/assets/cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/highlight.min.js +1232 -0
 - tinygrad/viz/assets/cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/languages/cpp.min.js +47 -0
 - tinygrad/viz/assets/cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/languages/python.min.js +42 -0
 - tinygrad/viz/assets/cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/default.min.css +9 -0
 - tinygrad/viz/assets/d3js.org/d3.v5.min.js +2 -0
 - tinygrad/viz/assets/dagrejs.github.io/project/dagre-d3/latest/dagre-d3.min.js +4816 -0
 - tinygrad/viz/assets/unpkg.com/@highlightjs/cdn-assets@11.10.0/styles/tokyo-night-dark.min.css +8 -0
 - tinygrad/viz/index.html +544 -0
 - tinygrad/viz/perfetto.html +178 -0
 - tinygrad/viz/serve.py +205 -0
 - {tinygrad-0.10.1.dist-info → tinygrad-0.10.2.dist-info}/METADATA +20 -8
 - tinygrad-0.10.2.dist-info/RECORD +99 -0
 - tinygrad/codegen/rewriter.py +0 -516
 - tinygrad-0.10.1.dist-info/RECORD +0 -86
 - {tinygrad-0.10.1.dist-info → tinygrad-0.10.2.dist-info}/LICENSE +0 -0
 - {tinygrad-0.10.1.dist-info → tinygrad-0.10.2.dist-info}/WHEEL +0 -0
 - {tinygrad-0.10.1.dist-info → tinygrad-0.10.2.dist-info}/top_level.txt +0 -0
 
| 
         @@ -0,0 +1,178 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            <!DOCTYPE html>
         
     | 
| 
      
 2 
     | 
    
         
            +
            <html lang="en-us">
         
     | 
| 
      
 3 
     | 
    
         
            +
            <head>
         
     | 
| 
      
 4 
     | 
    
         
            +
              <style>
         
     | 
| 
      
 5 
     | 
    
         
            +
                * {
         
     | 
| 
      
 6 
     | 
    
         
            +
                  margin: 0;
         
     | 
| 
      
 7 
     | 
    
         
            +
                  padding: 0;
         
     | 
| 
      
 8 
     | 
    
         
            +
                  box-sizing: border-box;
         
     | 
| 
      
 9 
     | 
    
         
            +
                }
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                body, html {
         
     | 
| 
      
 12 
     | 
    
         
            +
                  width: 100%;
         
     | 
| 
      
 13 
     | 
    
         
            +
                  height: 100%;
         
     | 
| 
      
 14 
     | 
    
         
            +
                  overflow: hidden;
         
     | 
| 
      
 15 
     | 
    
         
            +
                  font-family: "Noto Sans", sans-serif;
         
     | 
| 
      
 16 
     | 
    
         
            +
                  font-optical-sizing: auto;
         
     | 
| 
      
 17 
     | 
    
         
            +
                  font-weight: 400;
         
     | 
| 
      
 18 
     | 
    
         
            +
                  font-style: normal;
         
     | 
| 
      
 19 
     | 
    
         
            +
                  font-variation-settings: "wdth" 100;
         
     | 
| 
      
 20 
     | 
    
         
            +
                  font-size: 14px;
         
     | 
| 
      
 21 
     | 
    
         
            +
                }
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                header {
         
     | 
| 
      
 24 
     | 
    
         
            +
                  width: 100%;
         
     | 
| 
      
 25 
     | 
    
         
            +
                  height: 48px;
         
     | 
| 
      
 26 
     | 
    
         
            +
                  background: #0f1018;
         
     | 
| 
      
 27 
     | 
    
         
            +
                }
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                #perfetto_frame {
         
     | 
| 
      
 30 
     | 
    
         
            +
                  width: 100vw;
         
     | 
| 
      
 31 
     | 
    
         
            +
                  height: calc(100vh - 40px);
         
     | 
| 
      
 32 
     | 
    
         
            +
                  border: none;
         
     | 
| 
      
 33 
     | 
    
         
            +
                }
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                #loading_screen {
         
     | 
| 
      
 36 
     | 
    
         
            +
                  position: fixed;
         
     | 
| 
      
 37 
     | 
    
         
            +
                  top: 0;
         
     | 
| 
      
 38 
     | 
    
         
            +
                  left: 0;
         
     | 
| 
      
 39 
     | 
    
         
            +
                  width: 100vw;
         
     | 
| 
      
 40 
     | 
    
         
            +
                  height: 100vh;
         
     | 
| 
      
 41 
     | 
    
         
            +
                  background: #0f1018;
         
     | 
| 
      
 42 
     | 
    
         
            +
                  display: flex;
         
     | 
| 
      
 43 
     | 
    
         
            +
                  flex-direction: column;
         
     | 
| 
      
 44 
     | 
    
         
            +
                  justify-content: center;
         
     | 
| 
      
 45 
     | 
    
         
            +
                  align-items: center;
         
     | 
| 
      
 46 
     | 
    
         
            +
                  color: white;
         
     | 
| 
      
 47 
     | 
    
         
            +
                  font-family: Arial, sans-serif;
         
     | 
| 
      
 48 
     | 
    
         
            +
                  z-index: 1;
         
     | 
| 
      
 49 
     | 
    
         
            +
                }
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                .loader {
         
     | 
| 
      
 52 
     | 
    
         
            +
                  width: 48px;
         
     | 
| 
      
 53 
     | 
    
         
            +
                  height: 48px;
         
     | 
| 
      
 54 
     | 
    
         
            +
                  border: 5px solid #FFF;
         
     | 
| 
      
 55 
     | 
    
         
            +
                  border-bottom-color: transparent;
         
     | 
| 
      
 56 
     | 
    
         
            +
                  border-radius: 50%;
         
     | 
| 
      
 57 
     | 
    
         
            +
                  margin-bottom: 20px;
         
     | 
| 
      
 58 
     | 
    
         
            +
                  animation: rotation 1s linear infinite;
         
     | 
| 
      
 59 
     | 
    
         
            +
                }
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                @keyframes rotation {
         
     | 
| 
      
 62 
     | 
    
         
            +
                  0% { transform: rotate(0deg); }
         
     | 
| 
      
 63 
     | 
    
         
            +
                  100% { transform: rotate(360deg); }
         
     | 
| 
      
 64 
     | 
    
         
            +
                }
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                #loading_text {
         
     | 
| 
      
 67 
     | 
    
         
            +
                  font-size: 18px;
         
     | 
| 
      
 68 
     | 
    
         
            +
                }
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                .floating-container {
         
     | 
| 
      
 71 
     | 
    
         
            +
                  position: fixed;
         
     | 
| 
      
 72 
     | 
    
         
            +
                  top: 8px;
         
     | 
| 
      
 73 
     | 
    
         
            +
                  left: 16px;
         
     | 
| 
      
 74 
     | 
    
         
            +
                  z-index: 4;
         
     | 
| 
      
 75 
     | 
    
         
            +
                  display: flex;
         
     | 
| 
      
 76 
     | 
    
         
            +
                  flex-direction: row;
         
     | 
| 
      
 77 
     | 
    
         
            +
                  gap: 8px;
         
     | 
| 
      
 78 
     | 
    
         
            +
                }
         
     | 
| 
      
 79 
     | 
    
         
            +
                .nav-btn {
         
     | 
| 
      
 80 
     | 
    
         
            +
                  background-color: #1a1b26;
         
     | 
| 
      
 81 
     | 
    
         
            +
                  border: 1px solid #4a4b56;
         
     | 
| 
      
 82 
     | 
    
         
            +
                  color: #f0f0f5;
         
     | 
| 
      
 83 
     | 
    
         
            +
                  height: 32px;
         
     | 
| 
      
 84 
     | 
    
         
            +
                  border-radius: 8px;
         
     | 
| 
      
 85 
     | 
    
         
            +
                  cursor: pointer;
         
     | 
| 
      
 86 
     | 
    
         
            +
                  text-decoration: none;
         
     | 
| 
      
 87 
     | 
    
         
            +
                  display: flex;
         
     | 
| 
      
 88 
     | 
    
         
            +
                  align-items: center;
         
     | 
| 
      
 89 
     | 
    
         
            +
                  padding: 0 6px;
         
     | 
| 
      
 90 
     | 
    
         
            +
                  font-weight: bold;
         
     | 
| 
      
 91 
     | 
    
         
            +
                }
         
     | 
| 
      
 92 
     | 
    
         
            +
                .btn {
         
     | 
| 
      
 93 
     | 
    
         
            +
                  height: 32px;
         
     | 
| 
      
 94 
     | 
    
         
            +
                  background-color: #1a1b26;
         
     | 
| 
      
 95 
     | 
    
         
            +
                  border: 1px solid #4a4b56;
         
     | 
| 
      
 96 
     | 
    
         
            +
                  color: #f0f0f5;
         
     | 
| 
      
 97 
     | 
    
         
            +
                  border-radius: 8px;
         
     | 
| 
      
 98 
     | 
    
         
            +
                  cursor: pointer;
         
     | 
| 
      
 99 
     | 
    
         
            +
                  transition-duration: .5s;
         
     | 
| 
      
 100 
     | 
    
         
            +
                }
         
     | 
| 
      
 101 
     | 
    
         
            +
                .btn:hover {
         
     | 
| 
      
 102 
     | 
    
         
            +
                  background-color: #2a2b36;
         
     | 
| 
      
 103 
     | 
    
         
            +
                  border-color: #5a5b66;
         
     | 
| 
      
 104 
     | 
    
         
            +
                  color: #ffffff;
         
     | 
| 
      
 105 
     | 
    
         
            +
                  transform: translateY(-1px);
         
     | 
| 
      
 106 
     | 
    
         
            +
                }
         
     | 
| 
      
 107 
     | 
    
         
            +
              </style>
         
     | 
| 
      
 108 
     | 
    
         
            +
            </head>
         
     | 
| 
      
 109 
     | 
    
         
            +
            <body>
         
     | 
| 
      
 110 
     | 
    
         
            +
              <header></header>
         
     | 
| 
      
 111 
     | 
    
         
            +
              <div class="floating-container">
         
     | 
| 
      
 112 
     | 
    
         
            +
                <a class="btn nav-btn" href="/">UOps</a>
         
     | 
| 
      
 113 
     | 
    
         
            +
              </div>
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
              <div id="loading_screen">
         
     | 
| 
      
 116 
     | 
    
         
            +
                <div class="loader" id="spinner"></div>
         
     | 
| 
      
 117 
     | 
    
         
            +
                <div id="loading_text">Loading trace data...</div>
         
     | 
| 
      
 118 
     | 
    
         
            +
              </div>
         
     | 
| 
      
 119 
     | 
    
         
            +
              
         
     | 
| 
      
 120 
     | 
    
         
            +
              <iframe id="perfetto_frame" src="https://ui.perfetto.dev" allow="clipboard-write"></iframe>
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
              <script type="text/javascript">
         
     | 
| 
      
 123 
     | 
    
         
            +
                const ORIGIN = 'https://ui.perfetto.dev';
         
     | 
| 
      
 124 
     | 
    
         
            +
                const API_ENDPOINT = '/get_profile';
         
     | 
| 
      
 125 
     | 
    
         
            +
                const iframe = document.getElementById('perfetto_frame');
         
     | 
| 
      
 126 
     | 
    
         
            +
                const loadingScreen = document.getElementById('loading_screen');
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                async function fetchFromApi() {
         
     | 
| 
      
 129 
     | 
    
         
            +
                  try {
         
     | 
| 
      
 130 
     | 
    
         
            +
                    const response = await fetch(API_ENDPOINT);
         
     | 
| 
      
 131 
     | 
    
         
            +
                    if (!response.ok) {
         
     | 
| 
      
 132 
     | 
    
         
            +
                      throw new Error(`HTTP error! status: ${response.status}`);
         
     | 
| 
      
 133 
     | 
    
         
            +
                    }
         
     | 
| 
      
 134 
     | 
    
         
            +
                    const jsonData = await response.json();
         
     | 
| 
      
 135 
     | 
    
         
            +
                    
         
     | 
| 
      
 136 
     | 
    
         
            +
                    // Convert JSON to string and then to blob
         
     | 
| 
      
 137 
     | 
    
         
            +
                    const jsonString = JSON.stringify(jsonData);
         
     | 
| 
      
 138 
     | 
    
         
            +
                    const blob = new Blob([jsonString], { type: 'application/json' });
         
     | 
| 
      
 139 
     | 
    
         
            +
                    const arrayBuffer = await blob.arrayBuffer();
         
     | 
| 
      
 140 
     | 
    
         
            +
                    
         
     | 
| 
      
 141 
     | 
    
         
            +
                    openTrace(arrayBuffer);
         
     | 
| 
      
 142 
     | 
    
         
            +
                  } catch (error) {
         
     | 
| 
      
 143 
     | 
    
         
            +
                    document.getElementById('spinner').remove();
         
     | 
| 
      
 144 
     | 
    
         
            +
                    document.getElementById('loading_text').innerHTML = 'Error loading trace data.<br>Please ensure PROFILE=1 is set and the VIZ server is running.';
         
     | 
| 
      
 145 
     | 
    
         
            +
                    console.error('Error loading trace:', error);
         
     | 
| 
      
 146 
     | 
    
         
            +
                  }
         
     | 
| 
      
 147 
     | 
    
         
            +
                }
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
                function openTrace(arrayBuffer) {
         
     | 
| 
      
 150 
     | 
    
         
            +
                  const timer = setInterval(() => iframe.contentWindow.postMessage('PING', ORIGIN), 50);
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                  const onMessageHandler = (evt) => {
         
     | 
| 
      
 153 
     | 
    
         
            +
                    if (evt.data !== 'PONG') return;
         
     | 
| 
      
 154 
     | 
    
         
            +
                    loadingScreen.style.transition = 'opacity 0.5s';
         
     | 
| 
      
 155 
     | 
    
         
            +
                    loadingScreen.style.opacity = '0';
         
     | 
| 
      
 156 
     | 
    
         
            +
                    setTimeout(() => {
         
     | 
| 
      
 157 
     | 
    
         
            +
                      loadingScreen.style.display = 'none';
         
     | 
| 
      
 158 
     | 
    
         
            +
                    }, 500);
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
                    window.clearInterval(timer);
         
     | 
| 
      
 161 
     | 
    
         
            +
                    window.removeEventListener('message', onMessageHandler);
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
                    iframe.contentWindow.postMessage({
         
     | 
| 
      
 164 
     | 
    
         
            +
                      perfetto: {
         
     | 
| 
      
 165 
     | 
    
         
            +
                        buffer: arrayBuffer,
         
     | 
| 
      
 166 
     | 
    
         
            +
                        title: 'Profile Viewer',
         
     | 
| 
      
 167 
     | 
    
         
            +
                        url: location.href,
         
     | 
| 
      
 168 
     | 
    
         
            +
                      }
         
     | 
| 
      
 169 
     | 
    
         
            +
                    }, ORIGIN);
         
     | 
| 
      
 170 
     | 
    
         
            +
                  };
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
                  window.addEventListener('message', onMessageHandler);
         
     | 
| 
      
 173 
     | 
    
         
            +
                }
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
                window.onload = fetchFromApi;
         
     | 
| 
      
 176 
     | 
    
         
            +
              </script>
         
     | 
| 
      
 177 
     | 
    
         
            +
            </body>
         
     | 
| 
      
 178 
     | 
    
         
            +
            </html>
         
     | 
    
        tinygrad/viz/serve.py
    ADDED
    
    | 
         @@ -0,0 +1,205 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env python3
         
     | 
| 
      
 2 
     | 
    
         
            +
            import multiprocessing, pickle, functools, difflib, os, threading, json, time, sys, webbrowser, socket, argparse, decimal
         
     | 
| 
      
 3 
     | 
    
         
            +
            from http.server import HTTPServer, BaseHTTPRequestHandler
         
     | 
| 
      
 4 
     | 
    
         
            +
            from urllib.parse import parse_qs, urlparse
         
     | 
| 
      
 5 
     | 
    
         
            +
            from typing import Any, Callable, TypedDict, Generator
         
     | 
| 
      
 6 
     | 
    
         
            +
            from tinygrad.helpers import colored, getenv, tqdm, unwrap, word_wrap
         
     | 
| 
      
 7 
     | 
    
         
            +
            from tinygrad.ops import TrackedGraphRewrite, UOp, Ops, lines, GroupOp
         
     | 
| 
      
 8 
     | 
    
         
            +
            from tinygrad.codegen.kernel import Kernel
         
     | 
| 
      
 9 
     | 
    
         
            +
            from tinygrad.device import ProfileEvent, ProfileDeviceEvent, ProfileRangeEvent, ProfileGraphEvent
         
     | 
| 
      
 10 
     | 
    
         
            +
            from tinygrad.dtype import dtypes
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            uops_colors = {Ops.LOAD: "#ffc0c0", Ops.STORE: "#87CEEB", Ops.CONST: "#e0e0e0", Ops.VCONST: "#e0e0e0",
         
     | 
| 
      
 13 
     | 
    
         
            +
                           Ops.DEFINE_GLOBAL: "#ffe0b0", Ops.DEFINE_LOCAL: "#ffe0d0", Ops.DEFINE_ACC: "#f0ffe0", Ops.REDUCE_AXIS: "#FF6B6B",
         
     | 
| 
      
 14 
     | 
    
         
            +
                           Ops.RANGE: "#c8a0e0", Ops.ASSIGN: "#e0ffc0", Ops.BARRIER: "#ff8080", Ops.IF: "#c8b0c0", Ops.SPECIAL: "#c0c0ff",
         
     | 
| 
      
 15 
     | 
    
         
            +
                           Ops.INDEX: "#e8ffa0", Ops.WMMA: "#efefc0", Ops.VIEW: "#C8F9D4", Ops.MULTI: "#f6ccff", Ops.KERNEL: "#3e7f55",
         
     | 
| 
      
 16 
     | 
    
         
            +
                           **{x:"#D8F9E4" for x in GroupOp.Movement}, **{x:"#ffffc0" for x in GroupOp.ALU}, Ops.THREEFRY:"#ffff80",
         
     | 
| 
      
 17 
     | 
    
         
            +
                           Ops.BLOCK: "#C4A484", Ops.BLOCKEND: "#C4A4A4", Ops.BUFFER: "#B0BDFF", Ops.COPY: "#a040a0", Ops.NAME:"#808080"}
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            # VIZ API
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            # NOTE: if any extra rendering in VIZ fails, we don't crash
         
     | 
| 
      
 22 
     | 
    
         
            +
            def pcall(fxn:Callable[..., str], *args, **kwargs) -> str:
         
     | 
| 
      
 23 
     | 
    
         
            +
              try: return fxn(*args, **kwargs)
         
     | 
| 
      
 24 
     | 
    
         
            +
              except Exception as e: return f"ERROR: {e}"
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            # ** Metadata for a track_rewrites scope
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            class GraphRewriteMetadata(TypedDict):
         
     | 
| 
      
 29 
     | 
    
         
            +
              loc: tuple[str, int]                   # [path, lineno] calling graph_rewrite
         
     | 
| 
      
 30 
     | 
    
         
            +
              match_count: int                       # total match count in this context
         
     | 
| 
      
 31 
     | 
    
         
            +
              code_line: str                         # source code calling graph_rewrite
         
     | 
| 
      
 32 
     | 
    
         
            +
              kernel_code: str|None                  # optionally render the final kernel code
         
     | 
| 
      
 33 
     | 
    
         
            +
              name: str|None                         # optional name of the rewrite
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            @functools.lru_cache(None)
         
     | 
| 
      
 36 
     | 
    
         
            +
            def _prg(k:Kernel): return k.to_program().src
         
     | 
| 
      
 37 
     | 
    
         
            +
            def to_metadata(k:Any, v:TrackedGraphRewrite) -> GraphRewriteMetadata:
         
     | 
| 
      
 38 
     | 
    
         
            +
              return {"loc":v.loc, "match_count":len(v.matches), "code_line":lines(v.loc[0])[v.loc[1]-1].strip(),
         
     | 
| 
      
 39 
     | 
    
         
            +
                      "kernel_code":pcall(_prg, k) if isinstance(k, Kernel) else None, "name":v.name}
         
     | 
| 
      
 40 
     | 
    
         
            +
            def get_metadata(keys:list[Any], contexts:list[list[TrackedGraphRewrite]]) -> list[tuple[str, list[GraphRewriteMetadata]]]:
         
     | 
| 
      
 41 
     | 
    
         
            +
              return [(k.name if isinstance(k, Kernel) else str(k), [to_metadata(k, v) for v in vals]) for k,vals in zip(keys, contexts)]
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            # ** Complete rewrite details for a graph_rewrite call
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
            class GraphRewriteDetails(TypedDict):
         
     | 
| 
      
 46 
     | 
    
         
            +
              graph: dict                            # JSON serialized UOp for this rewrite step
         
     | 
| 
      
 47 
     | 
    
         
            +
              uop: str                               # strigified UOp for this rewrite step
         
     | 
| 
      
 48 
     | 
    
         
            +
              diff: list[str]|None                   # string diff of the single UOp that changed
         
     | 
| 
      
 49 
     | 
    
         
            +
              changed_nodes: list[int]|None          # the changed UOp id + all its parents ids
         
     | 
| 
      
 50 
     | 
    
         
            +
              upat: tuple[tuple[str, int], str]|None # [loc, source_code] of the matched UPat
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            def uop_to_json(x:UOp) -> dict[int, tuple[str, list[int], str]]:
         
     | 
| 
      
 53 
     | 
    
         
            +
              assert isinstance(x, UOp)
         
     | 
| 
      
 54 
     | 
    
         
            +
              # NOTE: this is [id, [label, src_ids, color]]
         
     | 
| 
      
 55 
     | 
    
         
            +
              graph: dict[int, tuple[str, list[int], str]] = {}
         
     | 
| 
      
 56 
     | 
    
         
            +
              excluded: set[UOp] = set()
         
     | 
| 
      
 57 
     | 
    
         
            +
              for u in (toposort:=x.toposort):
         
     | 
| 
      
 58 
     | 
    
         
            +
                # always exclude DEVICE/CONST/UNIQUE
         
     | 
| 
      
 59 
     | 
    
         
            +
                if u.op in {Ops.DEVICE, Ops.CONST, Ops.UNIQUE}: excluded.add(u)
         
     | 
| 
      
 60 
     | 
    
         
            +
                # only exclude CONST VIEW source if it has no other children in the graph
         
     | 
| 
      
 61 
     | 
    
         
            +
                if u.op is Ops.CONST and len(u.src) != 0 and all(cr.op is Ops.CONST for c in u.src[0].children if (cr:=c()) is not None and cr in toposort):
         
     | 
| 
      
 62 
     | 
    
         
            +
                  excluded.update(u.src)
         
     | 
| 
      
 63 
     | 
    
         
            +
              for u in toposort:
         
     | 
| 
      
 64 
     | 
    
         
            +
                if u in excluded: continue
         
     | 
| 
      
 65 
     | 
    
         
            +
                argst = str(u.arg)
         
     | 
| 
      
 66 
     | 
    
         
            +
                if u.op is Ops.VIEW:
         
     | 
| 
      
 67 
     | 
    
         
            +
                  argst = ("\n".join([f"{v.shape} / {v.strides}"+(f"\nMASK {v.mask}" if v.mask is not None else "")+
         
     | 
| 
      
 68 
     | 
    
         
            +
                                      ("" if v.offset == 0 else f" / {v.offset}") for v in unwrap(u.st).views]))
         
     | 
| 
      
 69 
     | 
    
         
            +
                label = f"{str(u.op).split('.')[1]}{(chr(10)+word_wrap(argst.replace(':', ''))) if u.arg is not None else ''}"
         
     | 
| 
      
 70 
     | 
    
         
            +
                if u.dtype != dtypes.void: label += f"\n{u.dtype}"
         
     | 
| 
      
 71 
     | 
    
         
            +
                for idx,x in enumerate(u.src):
         
     | 
| 
      
 72 
     | 
    
         
            +
                  if x in excluded:
         
     | 
| 
      
 73 
     | 
    
         
            +
                    if x.op is Ops.CONST and dtypes.is_float(u.dtype): label += f"\nCONST{idx} {x.arg:g}"
         
     | 
| 
      
 74 
     | 
    
         
            +
                    else: label += f"\n{x.op.name}{idx} {x.arg}"
         
     | 
| 
      
 75 
     | 
    
         
            +
                graph[id(u)] = (label, [id(x) for x in u.src if x not in excluded], uops_colors.get(u.op, "#ffffff"))
         
     | 
| 
      
 76 
     | 
    
         
            +
              return graph
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
            def get_details(k:Any, ctx:TrackedGraphRewrite) -> Generator[GraphRewriteDetails, None, None]:
         
     | 
| 
      
 79 
     | 
    
         
            +
              yield {"graph":uop_to_json(next_sink:=ctx.sink), "uop":str(ctx.sink), "changed_nodes":None, "diff":None, "upat":None}
         
     | 
| 
      
 80 
     | 
    
         
            +
              replaces: dict[UOp, UOp] = {}
         
     | 
| 
      
 81 
     | 
    
         
            +
              for u0,u1,upat in tqdm(ctx.matches):
         
     | 
| 
      
 82 
     | 
    
         
            +
                replaces[u0] = u1
         
     | 
| 
      
 83 
     | 
    
         
            +
                new_sink = next_sink.substitute(replaces)
         
     | 
| 
      
 84 
     | 
    
         
            +
                yield {"graph": (sink_json:=uop_to_json(new_sink)), "uop":str(new_sink), "changed_nodes":[id(x) for x in u1.toposort if id(x) in sink_json],
         
     | 
| 
      
 85 
     | 
    
         
            +
                       "diff":list(difflib.unified_diff(pcall(str, u0).splitlines(), pcall(str, u1).splitlines())), "upat":(upat.location, upat.printable())}
         
     | 
| 
      
 86 
     | 
    
         
            +
                if not ctx.bottom_up: next_sink = new_sink
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
            # Profiler API
         
     | 
| 
      
 89 
     | 
    
         
            +
            devices:dict[str, tuple[decimal.Decimal, decimal.Decimal, int]] = {}
         
     | 
| 
      
 90 
     | 
    
         
            +
            def prep_ts(device:str, ts:decimal.Decimal, is_copy): return int(decimal.Decimal(ts) + devices[device][is_copy])
         
     | 
| 
      
 91 
     | 
    
         
            +
            def dev_to_pid(device:str, is_copy=False): return {"pid": devices[device][2], "tid": int(is_copy)}
         
     | 
| 
      
 92 
     | 
    
         
            +
            def dev_ev_to_perfetto_json(ev:ProfileDeviceEvent):
         
     | 
| 
      
 93 
     | 
    
         
            +
              devices[ev.device] = (ev.comp_tdiff, ev.copy_tdiff if ev.copy_tdiff is not None else ev.comp_tdiff, len(devices))
         
     | 
| 
      
 94 
     | 
    
         
            +
              return [{"name": "process_name", "ph": "M", "pid": dev_to_pid(ev.device)['pid'], "args": {"name": ev.device}},
         
     | 
| 
      
 95 
     | 
    
         
            +
                      {"name": "thread_name", "ph": "M", "pid": dev_to_pid(ev.device)['pid'], "tid": 0, "args": {"name": "COMPUTE"}},
         
     | 
| 
      
 96 
     | 
    
         
            +
                      {"name": "thread_name", "ph": "M", "pid": dev_to_pid(ev.device)['pid'], "tid": 1, "args": {"name": "COPY"}}]
         
     | 
| 
      
 97 
     | 
    
         
            +
            def range_ev_to_perfetto_json(ev:ProfileRangeEvent):
         
     | 
| 
      
 98 
     | 
    
         
            +
              return [{"name": ev.name, "ph": "X", "ts": prep_ts(ev.device, ev.st, ev.is_copy), "dur": float(ev.en-ev.st), **dev_to_pid(ev.device, ev.is_copy)}]
         
     | 
| 
      
 99 
     | 
    
         
            +
            def graph_ev_to_perfetto_json(ev:ProfileGraphEvent, reccnt):
         
     | 
| 
      
 100 
     | 
    
         
            +
              ret = []
         
     | 
| 
      
 101 
     | 
    
         
            +
              for i,e in enumerate(ev.ents):
         
     | 
| 
      
 102 
     | 
    
         
            +
                st, en = ev.sigs[e.st_id], ev.sigs[e.en_id]
         
     | 
| 
      
 103 
     | 
    
         
            +
                ret += [{"name": e.name, "ph": "X", "ts": prep_ts(e.device, st, e.is_copy), "dur": float(en-st), **dev_to_pid(e.device, e.is_copy)}]
         
     | 
| 
      
 104 
     | 
    
         
            +
                for dep in ev.deps[i]:
         
     | 
| 
      
 105 
     | 
    
         
            +
                  d = ev.ents[dep]
         
     | 
| 
      
 106 
     | 
    
         
            +
                  ret += [{"ph": "s", **dev_to_pid(d.device, d.is_copy), "id": reccnt+len(ret), "ts": prep_ts(d.device, ev.sigs[d.en_id], d.is_copy), "bp": "e"}]
         
     | 
| 
      
 107 
     | 
    
         
            +
                  ret += [{"ph": "f", **dev_to_pid(e.device, e.is_copy), "id": reccnt+len(ret)-1, "ts": prep_ts(e.device, st, e.is_copy), "bp": "e"}]
         
     | 
| 
      
 108 
     | 
    
         
            +
              return ret
         
     | 
| 
      
 109 
     | 
    
         
            +
            def to_perfetto(profile:list[ProfileEvent]):
         
     | 
| 
      
 110 
     | 
    
         
            +
              # Start json with devices.
         
     | 
| 
      
 111 
     | 
    
         
            +
              prof_json = [x for ev in profile if isinstance(ev, ProfileDeviceEvent) for x in dev_ev_to_perfetto_json(ev)]
         
     | 
| 
      
 112 
     | 
    
         
            +
              for ev in tqdm(profile, desc="preparing profile"):
         
     | 
| 
      
 113 
     | 
    
         
            +
                if isinstance(ev, ProfileRangeEvent): prof_json += range_ev_to_perfetto_json(ev)
         
     | 
| 
      
 114 
     | 
    
         
            +
                elif isinstance(ev, ProfileGraphEvent): prof_json += graph_ev_to_perfetto_json(ev, reccnt=len(prof_json))
         
     | 
| 
      
 115 
     | 
    
         
            +
              return json.dumps({"traceEvents": prof_json}).encode() if len(prof_json) > 0 else None
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
            # ** HTTP server
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
            class Handler(BaseHTTPRequestHandler):
         
     | 
| 
      
 120 
     | 
    
         
            +
              def do_GET(self):
         
     | 
| 
      
 121 
     | 
    
         
            +
                ret, status_code, content_type = b"", 200, "text/html"
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                if (url:=urlparse(self.path)).path == "/":
         
     | 
| 
      
 124 
     | 
    
         
            +
                  with open(os.path.join(os.path.dirname(__file__), "index.html"), "rb") as f: ret = f.read()
         
     | 
| 
      
 125 
     | 
    
         
            +
                elif (url:=urlparse(self.path)).path == "/profiler":
         
     | 
| 
      
 126 
     | 
    
         
            +
                  with open(os.path.join(os.path.dirname(__file__), "perfetto.html"), "rb") as f: ret = f.read()
         
     | 
| 
      
 127 
     | 
    
         
            +
                elif self.path.startswith("/assets/") and '/..' not in self.path:
         
     | 
| 
      
 128 
     | 
    
         
            +
                  try:
         
     | 
| 
      
 129 
     | 
    
         
            +
                    with open(os.path.join(os.path.dirname(__file__), self.path.strip('/')), "rb") as f: ret = f.read()
         
     | 
| 
      
 130 
     | 
    
         
            +
                    if url.path.endswith(".js"): content_type = "application/javascript"
         
     | 
| 
      
 131 
     | 
    
         
            +
                    if url.path.endswith(".css"): content_type = "text/css"
         
     | 
| 
      
 132 
     | 
    
         
            +
                  except FileNotFoundError: status_code = 404
         
     | 
| 
      
 133 
     | 
    
         
            +
                elif url.path == "/kernels":
         
     | 
| 
      
 134 
     | 
    
         
            +
                  if "kernel" in (query:=parse_qs(url.query)):
         
     | 
| 
      
 135 
     | 
    
         
            +
                    def getarg(k:str,default=0): return int(query[k][0]) if k in query else default
         
     | 
| 
      
 136 
     | 
    
         
            +
                    kidx, ridx = getarg("kernel"), getarg("idx")
         
     | 
| 
      
 137 
     | 
    
         
            +
                    try:
         
     | 
| 
      
 138 
     | 
    
         
            +
                      # stream details
         
     | 
| 
      
 139 
     | 
    
         
            +
                      self.send_response(200)
         
     | 
| 
      
 140 
     | 
    
         
            +
                      self.send_header("Content-Type", "text/event-stream")
         
     | 
| 
      
 141 
     | 
    
         
            +
                      self.send_header("Cache-Control", "no-cache")
         
     | 
| 
      
 142 
     | 
    
         
            +
                      self.end_headers()
         
     | 
| 
      
 143 
     | 
    
         
            +
                      for r in get_details(contexts[0][kidx], contexts[1][kidx][ridx]):
         
     | 
| 
      
 144 
     | 
    
         
            +
                        self.wfile.write(f"data: {json.dumps(r)}\n\n".encode("utf-8"))
         
     | 
| 
      
 145 
     | 
    
         
            +
                        self.wfile.flush()
         
     | 
| 
      
 146 
     | 
    
         
            +
                      self.wfile.write("data: END\n\n".encode("utf-8"))
         
     | 
| 
      
 147 
     | 
    
         
            +
                      return self.wfile.flush()
         
     | 
| 
      
 148 
     | 
    
         
            +
                    # pass if client closed connection
         
     | 
| 
      
 149 
     | 
    
         
            +
                    except (BrokenPipeError, ConnectionResetError): return
         
     | 
| 
      
 150 
     | 
    
         
            +
                  ret, content_type = json.dumps(kernels).encode(), "application/json"
         
     | 
| 
      
 151 
     | 
    
         
            +
                elif url.path == "/get_profile" and perfetto_profile is not None: ret, content_type = perfetto_profile, "application/json"
         
     | 
| 
      
 152 
     | 
    
         
            +
                else: status_code = 404
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
                # send response
         
     | 
| 
      
 155 
     | 
    
         
            +
                self.send_response(status_code)
         
     | 
| 
      
 156 
     | 
    
         
            +
                self.send_header('Content-Type', content_type)
         
     | 
| 
      
 157 
     | 
    
         
            +
                self.send_header('Content-Length', str(len(ret)))
         
     | 
| 
      
 158 
     | 
    
         
            +
                self.end_headers()
         
     | 
| 
      
 159 
     | 
    
         
            +
                return self.wfile.write(ret)
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
            # ** main loop
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
            def reloader():
         
     | 
| 
      
 164 
     | 
    
         
            +
              mtime = os.stat(__file__).st_mtime
         
     | 
| 
      
 165 
     | 
    
         
            +
              while not stop_reloader.is_set():
         
     | 
| 
      
 166 
     | 
    
         
            +
                if mtime != os.stat(__file__).st_mtime:
         
     | 
| 
      
 167 
     | 
    
         
            +
                  print("reloading server...")
         
     | 
| 
      
 168 
     | 
    
         
            +
                  os.execv(sys.executable, [sys.executable] + sys.argv)
         
     | 
| 
      
 169 
     | 
    
         
            +
                time.sleep(0.1)
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
            def load_pickle(path:str):
         
     | 
| 
      
 172 
     | 
    
         
            +
              if path is None or not os.path.exists(path): return None
         
     | 
| 
      
 173 
     | 
    
         
            +
              with open(path, "rb") as f: return pickle.load(f)
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
            if __name__ == "__main__":
         
     | 
| 
      
 176 
     | 
    
         
            +
              parser = argparse.ArgumentParser()
         
     | 
| 
      
 177 
     | 
    
         
            +
              parser.add_argument('--kernels', type=str, help='Path to kernels', default=None)
         
     | 
| 
      
 178 
     | 
    
         
            +
              parser.add_argument('--profile', type=str, help='Path profile', default=None)
         
     | 
| 
      
 179 
     | 
    
         
            +
              args = parser.parse_args()
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
              with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
         
     | 
| 
      
 182 
     | 
    
         
            +
                if s.connect_ex(((HOST:="http://127.0.0.1").replace("http://", ""), PORT:=getenv("PORT", 8000))) == 0:
         
     | 
| 
      
 183 
     | 
    
         
            +
                  raise RuntimeError(f"{HOST}:{PORT} is occupied! use PORT= to change.")
         
     | 
| 
      
 184 
     | 
    
         
            +
              stop_reloader = threading.Event()
         
     | 
| 
      
 185 
     | 
    
         
            +
              multiprocessing.current_process().name = "VizProcess"    # disallow opening of devices
         
     | 
| 
      
 186 
     | 
    
         
            +
              st = time.perf_counter()
         
     | 
| 
      
 187 
     | 
    
         
            +
              print("*** viz is starting")
         
     | 
| 
      
 188 
     | 
    
         
            +
             
     | 
| 
      
 189 
     | 
    
         
            +
              contexts, profile = load_pickle(args.kernels), load_pickle(args.profile)
         
     | 
| 
      
 190 
     | 
    
         
            +
             
     | 
| 
      
 191 
     | 
    
         
            +
              # NOTE: this context is a tuple of list[keys] and list[values]
         
     | 
| 
      
 192 
     | 
    
         
            +
              kernels = get_metadata(*contexts) if contexts is not None else []
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
              perfetto_profile = to_perfetto(profile) if profile is not None else None
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
              server = HTTPServer(('', PORT), Handler)
         
     | 
| 
      
 197 
     | 
    
         
            +
              reloader_thread = threading.Thread(target=reloader)
         
     | 
| 
      
 198 
     | 
    
         
            +
              reloader_thread.start()
         
     | 
| 
      
 199 
     | 
    
         
            +
              print(f"*** started viz on {HOST}:{PORT}")
         
     | 
| 
      
 200 
     | 
    
         
            +
              print(colored(f"*** ready in {(time.perf_counter()-st)*1e3:4.2f}ms", "green"))
         
     | 
| 
      
 201 
     | 
    
         
            +
              if len(getenv("BROWSER", "")) > 0: webbrowser.open(f"{HOST}:{PORT}{'/profiler' if contexts is None else ''}")
         
     | 
| 
      
 202 
     | 
    
         
            +
              try: server.serve_forever()
         
     | 
| 
      
 203 
     | 
    
         
            +
              except KeyboardInterrupt:
         
     | 
| 
      
 204 
     | 
    
         
            +
                print("*** viz is shutting down...")
         
     | 
| 
      
 205 
     | 
    
         
            +
                stop_reloader.set()
         
     | 
| 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            Metadata-Version: 2.2
         
     | 
| 
       2 
2 
     | 
    
         
             
            Name: tinygrad
         
     | 
| 
       3 
     | 
    
         
            -
            Version: 0.10. 
     | 
| 
      
 3 
     | 
    
         
            +
            Version: 0.10.2
         
     | 
| 
       4 
4 
     | 
    
         
             
            Summary: You like pytorch? You like micrograd? You love tinygrad! <3
         
     | 
| 
       5 
5 
     | 
    
         
             
            Author: George Hotz
         
     | 
| 
       6 
6 
     | 
    
         
             
            License: MIT
         
     | 
| 
         @@ -20,13 +20,28 @@ Requires-Dist: typing-extensions; extra == "linting" 
     | 
|
| 
       20 
20 
     | 
    
         
             
            Requires-Dist: pre-commit; extra == "linting"
         
     | 
| 
       21 
21 
     | 
    
         
             
            Requires-Dist: ruff; extra == "linting"
         
     | 
| 
       22 
22 
     | 
    
         
             
            Requires-Dist: types-tqdm; extra == "linting"
         
     | 
| 
      
 23 
     | 
    
         
            +
            Provides-Extra: testing-minimal
         
     | 
| 
      
 24 
     | 
    
         
            +
            Requires-Dist: numpy; extra == "testing-minimal"
         
     | 
| 
      
 25 
     | 
    
         
            +
            Requires-Dist: torch; extra == "testing-minimal"
         
     | 
| 
      
 26 
     | 
    
         
            +
            Requires-Dist: pytest; extra == "testing-minimal"
         
     | 
| 
      
 27 
     | 
    
         
            +
            Requires-Dist: pytest-xdist; extra == "testing-minimal"
         
     | 
| 
      
 28 
     | 
    
         
            +
            Requires-Dist: hypothesis; extra == "testing-minimal"
         
     | 
| 
      
 29 
     | 
    
         
            +
            Provides-Extra: testing-unit
         
     | 
| 
      
 30 
     | 
    
         
            +
            Requires-Dist: numpy; extra == "testing-unit"
         
     | 
| 
      
 31 
     | 
    
         
            +
            Requires-Dist: torch; extra == "testing-unit"
         
     | 
| 
      
 32 
     | 
    
         
            +
            Requires-Dist: pytest; extra == "testing-unit"
         
     | 
| 
      
 33 
     | 
    
         
            +
            Requires-Dist: pytest-xdist; extra == "testing-unit"
         
     | 
| 
      
 34 
     | 
    
         
            +
            Requires-Dist: hypothesis; extra == "testing-unit"
         
     | 
| 
      
 35 
     | 
    
         
            +
            Requires-Dist: tqdm; extra == "testing-unit"
         
     | 
| 
      
 36 
     | 
    
         
            +
            Requires-Dist: safetensors; extra == "testing-unit"
         
     | 
| 
      
 37 
     | 
    
         
            +
            Requires-Dist: tabulate; extra == "testing-unit"
         
     | 
| 
       23 
38 
     | 
    
         
             
            Provides-Extra: testing
         
     | 
| 
       24 
39 
     | 
    
         
             
            Requires-Dist: numpy; extra == "testing"
         
     | 
| 
       25 
40 
     | 
    
         
             
            Requires-Dist: torch; extra == "testing"
         
     | 
| 
       26 
     | 
    
         
            -
            Requires-Dist: jax; extra == "testing"
         
     | 
| 
       27 
     | 
    
         
            -
            Requires-Dist: pillow; extra == "testing"
         
     | 
| 
       28 
41 
     | 
    
         
             
            Requires-Dist: pytest; extra == "testing"
         
     | 
| 
       29 
42 
     | 
    
         
             
            Requires-Dist: pytest-xdist; extra == "testing"
         
     | 
| 
      
 43 
     | 
    
         
            +
            Requires-Dist: hypothesis; extra == "testing"
         
     | 
| 
      
 44 
     | 
    
         
            +
            Requires-Dist: pillow; extra == "testing"
         
     | 
| 
       30 
45 
     | 
    
         
             
            Requires-Dist: onnx==1.16.0; extra == "testing"
         
     | 
| 
       31 
46 
     | 
    
         
             
            Requires-Dist: onnx2torch; extra == "testing"
         
     | 
| 
       32 
47 
     | 
    
         
             
            Requires-Dist: opencv-python; extra == "testing"
         
     | 
| 
         @@ -39,13 +54,10 @@ Requires-Dist: tiktoken; extra == "testing" 
     | 
|
| 
       39 
54 
     | 
    
         
             
            Requires-Dist: blobfile; extra == "testing"
         
     | 
| 
       40 
55 
     | 
    
         
             
            Requires-Dist: librosa; extra == "testing"
         
     | 
| 
       41 
56 
     | 
    
         
             
            Requires-Dist: networkx; extra == "testing"
         
     | 
| 
       42 
     | 
    
         
            -
            Requires-Dist: hypothesis; extra == "testing"
         
     | 
| 
       43 
57 
     | 
    
         
             
            Requires-Dist: nibabel; extra == "testing"
         
     | 
| 
       44 
58 
     | 
    
         
             
            Requires-Dist: bottle; extra == "testing"
         
     | 
| 
       45 
59 
     | 
    
         
             
            Requires-Dist: ggml-python; extra == "testing"
         
     | 
| 
       46 
60 
     | 
    
         
             
            Requires-Dist: capstone; extra == "testing"
         
     | 
| 
       47 
     | 
    
         
            -
            Provides-Extra: webgpu
         
     | 
| 
       48 
     | 
    
         
            -
            Requires-Dist: wgpu; extra == "webgpu"
         
     | 
| 
       49 
61 
     | 
    
         
             
            Provides-Extra: docs
         
     | 
| 
       50 
62 
     | 
    
         
             
            Requires-Dist: mkdocs; extra == "docs"
         
     | 
| 
       51 
63 
     | 
    
         
             
            Requires-Dist: mkdocs-material; extra == "docs"
         
     | 
| 
         @@ -149,7 +161,7 @@ See [examples/beautiful_mnist.py](examples/beautiful_mnist.py) for the full vers 
     | 
|
| 
       149 
161 
     | 
    
         
             
            tinygrad already supports numerous accelerators, including:
         
     | 
| 
       150 
162 
     | 
    
         | 
| 
       151 
163 
     | 
    
         
             
            - [x] [GPU (OpenCL)](tinygrad/runtime/ops_gpu.py)
         
     | 
| 
       152 
     | 
    
         
            -
            - [x] [ 
     | 
| 
      
 164 
     | 
    
         
            +
            - [x] [CPU (C Code)](tinygrad/runtime/ops_cpu.py)
         
     | 
| 
       153 
165 
     | 
    
         
             
            - [x] [LLVM](tinygrad/runtime/ops_llvm.py)
         
     | 
| 
       154 
166 
     | 
    
         
             
            - [x] [METAL](tinygrad/runtime/ops_metal.py)
         
     | 
| 
       155 
167 
     | 
    
         
             
            - [x] [CUDA](tinygrad/runtime/ops_cuda.py)
         
     | 
| 
         @@ -219,7 +231,7 @@ We'll start with what will get your PR closed with a pointer to this section: 
     | 
|
| 
       219 
231 
     | 
    
         | 
| 
       220 
232 
     | 
    
         
             
            - No code golf! While low line count is a guiding light of this project, anything that remotely looks like code golf will be closed. The true goal is reducing complexity and increasing readability, and deleting `\n`s does nothing to help with that.
         
     | 
| 
       221 
233 
     | 
    
         
             
            - All docs and whitespace changes will be closed unless you are a well-known contributor. The people writing the docs should be those who know the codebase the absolute best. People who have not demonstrated that shouldn't be messing with docs. Whitespace changes are both useless *and* carry a risk of introducing bugs.
         
     | 
| 
       222 
     | 
    
         
            -
            - Anything you claim is a "speedup" must be benchmarked. In general, the goal is simplicity, so even if your PR makes things marginally faster, you have to consider the tradeoff with  
     | 
| 
      
 234 
     | 
    
         
            +
            - Anything you claim is a "speedup" must be benchmarked. In general, the goal is simplicity, so even if your PR makes things marginally faster, you have to consider the tradeoff with maintainability and readability.
         
     | 
| 
       223 
235 
     | 
    
         
             
            - In general, the code outside the core `tinygrad/` folder is not well tested, so unless the current code there is broken, you shouldn't be changing it.
         
     | 
| 
       224 
236 
     | 
    
         
             
            - If your PR looks "complex", is a big diff, or adds lots of lines, it won't be reviewed or merged. Consider breaking it up into smaller PRs that are individually clear wins. A common pattern I see is prerequisite refactors before adding new functionality. If you can (cleanly) refactor to the point that the feature is a 3 line change, this is great, and something easy for us to review.
         
     | 
| 
       225 
237 
     | 
    
         | 
| 
         @@ -0,0 +1,99 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            tinygrad/__init__.py,sha256=2Jhg7NSWlegCi4OAfGW0iHRVHeqMx09f7446rwAmc60,587
         
     | 
| 
      
 2 
     | 
    
         
            +
            tinygrad/device.py,sha256=y40tIC5HWH0GJgoiE-BoL-R1wNtwn0k9AuWpQS2VH-w,19927
         
     | 
| 
      
 3 
     | 
    
         
            +
            tinygrad/dtype.py,sha256=HkfFDmPFi2CFUJ3cXoN8hd8W0b6dtK8inRr_wNoBeBE,10245
         
     | 
| 
      
 4 
     | 
    
         
            +
            tinygrad/gradient.py,sha256=4FbtPDt3lFFLthq-uZMS1UPHqx-ssgrI3tlNTRUJAAw,4582
         
     | 
| 
      
 5 
     | 
    
         
            +
            tinygrad/helpers.py,sha256=14xmrdja59H3CyIchRe-IX61jCyuzxrT2nJ59SAbAZc,19523
         
     | 
| 
      
 6 
     | 
    
         
            +
            tinygrad/ops.py,sha256=Pdr96zni5LS31nR7RcvxcW4czXTSKjtOi-Z0lruL0ok,54874
         
     | 
| 
      
 7 
     | 
    
         
            +
            tinygrad/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         
     | 
| 
      
 8 
     | 
    
         
            +
            tinygrad/spec.py,sha256=5wIXRDSMwpQjnYE5kgplhTyo8yMSRdRFw5il8kpAMV0,8937
         
     | 
| 
      
 9 
     | 
    
         
            +
            tinygrad/tensor.py,sha256=w3L_O41XHK_MzoTzIASB2MM0w4vLb3km_RrKYDR4hKk,185155
         
     | 
| 
      
 10 
     | 
    
         
            +
            tinygrad/codegen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         
     | 
| 
      
 11 
     | 
    
         
            +
            tinygrad/codegen/devectorizer.py,sha256=bp-9DYLoB8XIBGHIpMe9ok0W42riQbbseqiGXg1-MrE,13584
         
     | 
| 
      
 12 
     | 
    
         
            +
            tinygrad/codegen/expander.py,sha256=U_cJVu4I65c2k4a8MjwKi16iSg0QD2oP1TajmVWB3Ls,5978
         
     | 
| 
      
 13 
     | 
    
         
            +
            tinygrad/codegen/kernel.py,sha256=9_bFVibBpoGkqhRit6dVxitxBUIulmJpGf-LAG474og,42808
         
     | 
| 
      
 14 
     | 
    
         
            +
            tinygrad/codegen/linearize.py,sha256=cs50ZG_AmeXvWOOV6ig7zUZhMcd2dxumsc0kjI6NyTY,10853
         
     | 
| 
      
 15 
     | 
    
         
            +
            tinygrad/codegen/lowerer.py,sha256=Ap8TAxzx3pAOVAUIFndeSMXf79TZxd8HveZraOeK4Qo,8935
         
     | 
| 
      
 16 
     | 
    
         
            +
            tinygrad/codegen/symbolic.py,sha256=VoZ1h3B5ewIjC-fNHpd2h2beyePfuBThgneWMfCJMI8,29831
         
     | 
| 
      
 17 
     | 
    
         
            +
            tinygrad/codegen/transcendental.py,sha256=tlQvQ4xJ2tjWyB_0ZmmTUvvVj05qffsVvkBaAQnnvVU,13733
         
     | 
| 
      
 18 
     | 
    
         
            +
            tinygrad/engine/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         
     | 
| 
      
 19 
     | 
    
         
            +
            tinygrad/engine/jit.py,sha256=Y1CRXauO-ySlpyO2FV0Igr8N4UCjpLOjuIqYSrVE4oc,16797
         
     | 
| 
      
 20 
     | 
    
         
            +
            tinygrad/engine/memory.py,sha256=UyiNYIoUjtcJ1SX6ApoCnbrSKZpbBbhfwr13TIaiqEM,3231
         
     | 
| 
      
 21 
     | 
    
         
            +
            tinygrad/engine/multi.py,sha256=5I_2qULp1L8K_je3OZoqSVeOpzjW6COhThlu_j09l58,10336
         
     | 
| 
      
 22 
     | 
    
         
            +
            tinygrad/engine/realize.py,sha256=rGDUWqYKx6h00Q4l-6BpT4sbe4ifbetjdiyBTTow6sA,9821
         
     | 
| 
      
 23 
     | 
    
         
            +
            tinygrad/engine/schedule.py,sha256=-tzKWF3MarUizLMiHiLT-ssyfI1Se8OkafLCGtvPHZY,24633
         
     | 
| 
      
 24 
     | 
    
         
            +
            tinygrad/engine/search.py,sha256=Uk2sfRhXvbgpRDjK4hIDO7dJFd2jdAxVkUde2SlKRIk,11685
         
     | 
| 
      
 25 
     | 
    
         
            +
            tinygrad/nn/__init__.py,sha256=BAxMz-g7v-v1A32KaBzmGiaEnvQ_dU9d3KoPdYYwLDQ,15156
         
     | 
| 
      
 26 
     | 
    
         
            +
            tinygrad/nn/datasets.py,sha256=wcT0Qrlpw_RzM7uBy8uphzKAjGT-ZE48fiP-0g3WvI0,1042
         
     | 
| 
      
 27 
     | 
    
         
            +
            tinygrad/nn/optim.py,sha256=qfdYKi_ssX5O_DU6h8GJ0WCzBzAZLyyS3p_946PJNsQ,6816
         
     | 
| 
      
 28 
     | 
    
         
            +
            tinygrad/nn/state.py,sha256=D7Q6yjGtfOf0pacVWRqJnaexiOxzOXlumMQXhieC_U0,16018
         
     | 
| 
      
 29 
     | 
    
         
            +
            tinygrad/renderer/__init__.py,sha256=X0BJ3h45w3qWP_fVMadpjTBhGJltFB2XxgxK8aHnwPc,7615
         
     | 
| 
      
 30 
     | 
    
         
            +
            tinygrad/renderer/cstyle.py,sha256=xOTSEGIJ0Sg1qeAAR8olro5_HnAjJkIWzr12AEIuRQs,31105
         
     | 
| 
      
 31 
     | 
    
         
            +
            tinygrad/renderer/llvmir.py,sha256=T-8I1dLGIkzMF5AZCqvEz8SnpkMWZQC3VkbFSf7JDFA,11290
         
     | 
| 
      
 32 
     | 
    
         
            +
            tinygrad/renderer/ptx.py,sha256=n58_vVi7eO3I4UIisRKCaKtzEZ5BO4Dle0yqMbDaI5s,14992
         
     | 
| 
      
 33 
     | 
    
         
            +
            tinygrad/renderer/wgsl.py,sha256=zLUI2AqSe0o_kRFuLeZg3a3Qbfzy685NeFT2v-2odxY,7467
         
     | 
| 
      
 34 
     | 
    
         
            +
            tinygrad/runtime/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         
     | 
| 
      
 35 
     | 
    
         
            +
            tinygrad/runtime/ops_amd.py,sha256=S0RBcJrIogrp0c5TMAk3ANTBwG5UUZbk13Yxgs3aTXk,37723
         
     | 
| 
      
 36 
     | 
    
         
            +
            tinygrad/runtime/ops_cloud.py,sha256=1umLappzYKg0ECC9C_EN1lzXquAQVqY7wj-mS0vTcSk,10362
         
     | 
| 
      
 37 
     | 
    
         
            +
            tinygrad/runtime/ops_cpu.py,sha256=mRiplNgA3rAYasy8VJd2GfYhuUVLp_x8V0xfBvJ7xik,1356
         
     | 
| 
      
 38 
     | 
    
         
            +
            tinygrad/runtime/ops_cuda.py,sha256=26ko2bTLT_jDmU2i8_xiL4BomD9krzvlz6wY5FE-e5c,7138
         
     | 
| 
      
 39 
     | 
    
         
            +
            tinygrad/runtime/ops_disk.py,sha256=pLIpvzlCVN47qBJ99nVEuwzYB3V0kuDldqG0XZBAblo,6642
         
     | 
| 
      
 40 
     | 
    
         
            +
            tinygrad/runtime/ops_dsp.py,sha256=m4hiegBFqEShmcJoBq3htaepivoFxbn1MWASqsR__jY,18737
         
     | 
| 
      
 41 
     | 
    
         
            +
            tinygrad/runtime/ops_gpu.py,sha256=VrY9iM5i44OQwTJE8sgUavCtr1TOpE96I5-JmqUFz-E,8972
         
     | 
| 
      
 42 
     | 
    
         
            +
            tinygrad/runtime/ops_hip.py,sha256=MbR4depxgHcaGpOJGvUCiLq5tdbpaDiqs-Xj41rY2xQ,3730
         
     | 
| 
      
 43 
     | 
    
         
            +
            tinygrad/runtime/ops_llvm.py,sha256=eiJ_UVlm_uX39j4K0-x6QTszxHwwv67I2g4F1ZGSyDk,3446
         
     | 
| 
      
 44 
     | 
    
         
            +
            tinygrad/runtime/ops_metal.py,sha256=zzZOhEhPfuK-_WIdX-ewuDq66KWtqnKEdVUCAa00XeU,14336
         
     | 
| 
      
 45 
     | 
    
         
            +
            tinygrad/runtime/ops_npy.py,sha256=8VNf1S5M_MRk9d3GxSsTPbfEz7I_aOwl7QMZ1mUG3As,370
         
     | 
| 
      
 46 
     | 
    
         
            +
            tinygrad/runtime/ops_nv.py,sha256=thiu7q_vDeJUvlnR6wYXtMni0OrRMXzrbwdf596Ilyc,34855
         
     | 
| 
      
 47 
     | 
    
         
            +
            tinygrad/runtime/ops_python.py,sha256=OsFSI12f4tCrS3-pWtpyXMochbTfcOq4wX7BHQ1wdOM,11687
         
     | 
| 
      
 48 
     | 
    
         
            +
            tinygrad/runtime/ops_qcom.py,sha256=Dt4hgAd6o13CxsOFRSt7lHY6bCOTLvtQpOr_jx_lYbc,22565
         
     | 
| 
      
 49 
     | 
    
         
            +
            tinygrad/runtime/ops_webgpu.py,sha256=DgWHSckZybr6w52-YcODTheRyIolNQiQ6n4Lb4dcjNY,12852
         
     | 
| 
      
 50 
     | 
    
         
            +
            tinygrad/runtime/autogen/adreno.py,sha256=u7VxIomPAlW3nFUs4gSTe-6ijam_ywkvDM9OuTLF-j8,897915
         
     | 
| 
      
 51 
     | 
    
         
            +
            tinygrad/runtime/autogen/amd_gpu.py,sha256=Iasq-zYiv8bvT43dtvPO1W5jaLEQ3d6hP0CoFVhSsak,3977783
         
     | 
| 
      
 52 
     | 
    
         
            +
            tinygrad/runtime/autogen/comgr.py,sha256=3pp3XyqEJDBLa9XtGx2-Gc1iJgBbbgIq4pdFEpYXT44,39874
         
     | 
| 
      
 53 
     | 
    
         
            +
            tinygrad/runtime/autogen/cuda.py,sha256=N0QyaMvQumr_HZh7fusCHM1d4o4mYti3Wq1MN7JSKr8,243920
         
     | 
| 
      
 54 
     | 
    
         
            +
            tinygrad/runtime/autogen/hip.py,sha256=1yUHDCwL3KkD15if2Q1Ud3GbJiR7DxsNorKZTCINw54,245532
         
     | 
| 
      
 55 
     | 
    
         
            +
            tinygrad/runtime/autogen/hsa.py,sha256=7Hsrn17HmChyeFOSX_3Fnzl9c0COtq2Z2ExqGu5FNiU,277716
         
     | 
| 
      
 56 
     | 
    
         
            +
            tinygrad/runtime/autogen/io_uring.py,sha256=ZIZ2YnQkLr8WIHMieBw9Dv-NZ1ar9TwdP4YBv3gJm28,59786
         
     | 
| 
      
 57 
     | 
    
         
            +
            tinygrad/runtime/autogen/kfd.py,sha256=VdhuG4qec0EgM-jJmWcdTS-8WrmywNkcjSX7ibbmvdk,30866
         
     | 
| 
      
 58 
     | 
    
         
            +
            tinygrad/runtime/autogen/kgsl.py,sha256=2EgJ5Kst4oRUv81hsV2srgwPvWpY-weaSB4E2lGMAyc,50656
         
     | 
| 
      
 59 
     | 
    
         
            +
            tinygrad/runtime/autogen/libc.py,sha256=KYy7QfWKFJ6NEhGGmcNl7cWkbxl-_pfRADApGi1WQd0,209051
         
     | 
| 
      
 60 
     | 
    
         
            +
            tinygrad/runtime/autogen/llvm.py,sha256=aeVd_ByohxbGRyqXzShPOupI2xtcdk34I6_OIBrMQHg,467606
         
     | 
| 
      
 61 
     | 
    
         
            +
            tinygrad/runtime/autogen/nv_gpu.py,sha256=9X2tPdv2E5JmXGZeT8i9jL19YJ4ETTsYwfU_Wn9mTwc,1679326
         
     | 
| 
      
 62 
     | 
    
         
            +
            tinygrad/runtime/autogen/nvrtc.py,sha256=19te2-TW5suFy85KnJox3CPOmeeml5YxqIDeL-Bx_m4,23132
         
     | 
| 
      
 63 
     | 
    
         
            +
            tinygrad/runtime/autogen/opencl.py,sha256=NL6fa8P3KC_McNZ8g2babdr3b8vrY-bFK0qzNAtL-rE,82656
         
     | 
| 
      
 64 
     | 
    
         
            +
            tinygrad/runtime/autogen/pci.py,sha256=XVo3T6F_7msIZO4uzqw4seWi0VNtHCx6gM8sZ5mdynE,56769
         
     | 
| 
      
 65 
     | 
    
         
            +
            tinygrad/runtime/autogen/qcom_dsp.py,sha256=jx36-zC6reTuWgfbHCrKVjOZcF4Q9fBnq3CuTbxztQk,61848
         
     | 
| 
      
 66 
     | 
    
         
            +
            tinygrad/runtime/autogen/vfio.py,sha256=IJV1eeWWllU6b9LAX_IH0bUW5NDzfhPQy_YzXGhD9-8,32431
         
     | 
| 
      
 67 
     | 
    
         
            +
            tinygrad/runtime/autogen/webgpu.py,sha256=vVGL2l8_XPuC2Xis7gYseIwCmm9ZidEoXU3E34rtNIw,325072
         
     | 
| 
      
 68 
     | 
    
         
            +
            tinygrad/runtime/graph/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         
     | 
| 
      
 69 
     | 
    
         
            +
            tinygrad/runtime/graph/cuda.py,sha256=vLjT_c93G6ia_1MsbYWP5Uq96Aeko0AOskRkwT5-MUI,4818
         
     | 
| 
      
 70 
     | 
    
         
            +
            tinygrad/runtime/graph/hcq.py,sha256=kKu2YnjAZU40XMACSbbcxJSi2xdTg3OYLO2zcPLyAf0,12600
         
     | 
| 
      
 71 
     | 
    
         
            +
            tinygrad/runtime/graph/metal.py,sha256=7xLmAUmNiV-QbcLohFZhAIQ_nWwQBbeNVZY8mp6Ou6o,5848
         
     | 
| 
      
 72 
     | 
    
         
            +
            tinygrad/runtime/support/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         
     | 
| 
      
 73 
     | 
    
         
            +
            tinygrad/runtime/support/allocator.py,sha256=INW6TaJxMi4cwMEDtkta2wFH3kJ87wy3SyFFu3_jJ9w,4721
         
     | 
| 
      
 74 
     | 
    
         
            +
            tinygrad/runtime/support/compiler_cuda.py,sha256=6cU1OMMW3aOUFNVALpDYWKXh-zFc5q81PSSQhRK9fLw,5471
         
     | 
| 
      
 75 
     | 
    
         
            +
            tinygrad/runtime/support/compiler_hip.py,sha256=fbRP82UdG4T-KCRYH_H2hEXlMFeHIJntSnY35ZWE5JY,4398
         
     | 
| 
      
 76 
     | 
    
         
            +
            tinygrad/runtime/support/elf.py,sha256=EEcH4giM149Tirzi_1ozpStWSCXh--hqHSkhNrLSgEQ,4045
         
     | 
| 
      
 77 
     | 
    
         
            +
            tinygrad/runtime/support/hcq.py,sha256=IHZsThsCB1o_xW208fBQw9ztpM8pcPNK_kPSKcOD9mE,22022
         
     | 
| 
      
 78 
     | 
    
         
            +
            tinygrad/runtime/support/llvm.py,sha256=zCg2WQjqYrNVf2XLUsud2BA41cndmAxC6MizR82OtPo,1500
         
     | 
| 
      
 79 
     | 
    
         
            +
            tinygrad/runtime/support/am/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         
     | 
| 
      
 80 
     | 
    
         
            +
            tinygrad/runtime/support/am/amdev.py,sha256=GP24gjQ7DI__eEvT_w14CqJzWCG0GDIaK1XDXj84kys,21293
         
     | 
| 
      
 81 
     | 
    
         
            +
            tinygrad/runtime/support/am/ip.py,sha256=8wIFEVdQghFe5bCSYx60gNpjrFCKhhrc6espW7KrCng,24430
         
     | 
| 
      
 82 
     | 
    
         
            +
            tinygrad/shape/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         
     | 
| 
      
 83 
     | 
    
         
            +
            tinygrad/shape/shapetracker.py,sha256=Ts8u2tSqgxs1Do3y3jNIMCIbR0c-hoDTjyVIkxgHqI4,7671
         
     | 
| 
      
 84 
     | 
    
         
            +
            tinygrad/shape/view.py,sha256=ciHPBhfn30iM0X0JCEQ_iyOihRgPdi9kFtIUj5QidNc,18074
         
     | 
| 
      
 85 
     | 
    
         
            +
            tinygrad/viz/index.html,sha256=qwG7LCOf49wWR_VnyhQGWSHtx8i_YnoedyvoVmxR9uQ,18544
         
     | 
| 
      
 86 
     | 
    
         
            +
            tinygrad/viz/perfetto.html,sha256=X5ouzfw20wbDdWCM7eEygCDhNPF7gKMRyNM7kyRjcIA,4458
         
     | 
| 
      
 87 
     | 
    
         
            +
            tinygrad/viz/serve.py,sha256=djOJkZYY75sqzAQ6pYRsTgeMV0UwrZrJcbsEx7Eke4g,11395
         
     | 
| 
      
 88 
     | 
    
         
            +
            tinygrad/viz/assets/cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/highlight.min.js,sha256=Rx75rpDEB69ED83Ejt_utWIQazJnvRLZkHHBYvtS7TI,124980
         
     | 
| 
      
 89 
     | 
    
         
            +
            tinygrad/viz/assets/cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/languages/cpp.min.js,sha256=_PnmV6YOH2gDppRwZRZGvzbyuLOqfIXPKcOO7D_1dXM,6005
         
     | 
| 
      
 90 
     | 
    
         
            +
            tinygrad/viz/assets/cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/languages/python.min.js,sha256=LD3MH9LYaIvzmcT-6MIg_poJtKvUOdifbSyyx2dzGlU,3590
         
     | 
| 
      
 91 
     | 
    
         
            +
            tinygrad/viz/assets/cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/default.min.css,sha256=-94KwJIdhsNWxBUy5zGciHojvRuP8ABgyrRHJJ8Dx88,1144
         
     | 
| 
      
 92 
     | 
    
         
            +
            tinygrad/viz/assets/d3js.org/d3.v5.min.js,sha256=Xb6SSzhH3wEPC4Vy3W70Lqh9Y3Du_3KxPqI2JHQSpTw,248314
         
     | 
| 
      
 93 
     | 
    
         
            +
            tinygrad/viz/assets/dagrejs.github.io/project/dagre-d3/latest/dagre-d3.min.js,sha256=dPm4TA8Y9PY5q5mmtWMkRGOCMHJDKy34ZrxdbBGA9cs,725181
         
     | 
| 
      
 94 
     | 
    
         
            +
            tinygrad/viz/assets/unpkg.com/@highlightjs/cdn-assets@11.10.0/styles/tokyo-night-dark.min.css,sha256=PCTQRtLh4Cuei-tkH53GOcdv9ErYnw-6yeq5Bi1V9Rs,1234
         
     | 
| 
      
 95 
     | 
    
         
            +
            tinygrad-0.10.2.dist-info/LICENSE,sha256=ABRhUPEILzINYIukgazD-_rPipkUNUwslrb0RxnV6Xc,1058
         
     | 
| 
      
 96 
     | 
    
         
            +
            tinygrad-0.10.2.dist-info/METADATA,sha256=zxbkNx4Cxx28E19m8YnZzvLMzA6UrPtu8i1FchTAErc,11846
         
     | 
| 
      
 97 
     | 
    
         
            +
            tinygrad-0.10.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
         
     | 
| 
      
 98 
     | 
    
         
            +
            tinygrad-0.10.2.dist-info/top_level.txt,sha256=vDABMCWBFQnx2kn9Azueu88FP-1klQdePoHikQhHymc,9
         
     | 
| 
      
 99 
     | 
    
         
            +
            tinygrad-0.10.2.dist-info/RECORD,,
         
     |