# Quickstart

Five commands: write a file, check it, read what the compiler made of it,
train a few steps on the CPU, and pack it for a GPU box.

## 1. Write the experiment

Save as `minimal.sx`. It is the smallest file the contract accepts: six
names and nothing else ([the run file](https://sexpgpu.041.io/docs/run-file.md) explains each).

```lisp
(require "sexpgpu/nn" cross-entropy gpt)
(require "sexpgpu/optim" sgd)

(defvar train-loader
  (loader :sources [(files ["data/tiny-train.jsonl.gz"] :encoding "jsonl.gz")]
          :fields [(field :tokens :from "input_ids" :dtype :i32 :shape [17])]
          :batch-size 4
          :infinite true))

(defun prepare (batch)
  (let ((tokens (field batch :tokens)))
    (list :inputs (slice tokens 1 0 16) :targets (slice tokens 1 1 17))))

(defvar model (gpt :vocab 32 :layers 2 :dim 32 :heads 2))

(defun objective (prediction targets) (cross-entropy prediction targets))

(defvar optimizer (sgd :lr 0.5))

(defrun :steps 20 :microbatches 2 :precision :f32 :seed 1)
```

The loader reads `data/tiny-train.jsonl.gz` next to the file: one JSON
object per line with an `input_ids` array of 17 token ids below 32, each a
counting sequence the model can learn. Download a 512-line sample:

```bash
mkdir -p data
curl -fsSL https://sexpgpu.041.io/data/tiny-train.jsonl.gz -o data/tiny-train.jsonl.gz
```

Any shape works once the `:shape`, the slices and `:vocab` agree; see
[loaders](https://sexpgpu.041.io/docs/data.md).

## 2. Check it

```console
$ sexpgpu check minimal.sx
ok: 32 parameters, 65 graphs, 20 steps
```

`check` needs no data and no GPU. Break a shape and it names your line; see
[check](https://sexpgpu.041.io/docs/check.md).

## 3. Read what it compiled to

```bash
sexpgpu explain minimal.sx
```

Parameters with their optimizer groups, every graph, one training step and
the peak activation memory. See [explain](https://sexpgpu.041.io/docs/explain.md).

## 4. Train a few steps

```console
$ sexpgpu run minimal.sx --steps 3 --device cpu
...
done: 3 steps, train/loss 3.1645
  counter records 24
```

`--device cpu` is the IR interpreter: every machine has it, and it holds
toy sizes only ([devices](https://sexpgpu.041.io/docs/devices.md)). On a GPU machine,
`--device cuda --metrics jsonl:minimal.jsonl` trains at full speed and
writes every number; see [run](https://sexpgpu.041.io/docs/run.md) and [metrics](https://sexpgpu.041.io/docs/metrics.md).

## 5. Pack it for a GPU box

```bash
sexpgpu bundle minimal.sx -o out/minimal --binary ./sexpgpu-linux-cuda
scp -r out/minimal gpu-box: && ssh gpu-box 'SEXPGPU_DEVICE=cuda minimal/run.sh'
```

See [bundle](https://sexpgpu.041.io/docs/bundle.md).

## Next

- Make it vary: [knobs, variants and sweeps](https://sexpgpu.041.io/docs/knobs.md).
- Start from a bigger run: [`sexpgpu new`](https://sexpgpu.041.io/docs/new.md).
- Write a model: [models](https://sexpgpu.041.io/docs/models.md) and [sexpgpu/nn](https://sexpgpu.041.io/docs/nn.md).
- Iterate with `sexpgpu watch minimal.sx`, which checks on every save.

---

SexpGPU documentation. Every page: https://sexpgpu.041.io/llms.txt
