# kernel


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

``` mermaid
flowchart TD
    A[Start a remote IPython kernel] --> B[Register the remote IPython kernel]
    B --> C[Swap SolveIt's IPython kernel with the remote one]
```

``` python
from solveit_modal.sandbox import *
```

We’ll first spin up a sandbox.

``` python
app = mk_app('solveit-sandbox')
img = mk_img(pips=['ipykernel', 'torch'], apts=['openssh-server'])
vol = mk_vol('solveit-volume')
sb = mk_sandbox(app, img, vol, timeout=600, gpu='T4', secrets={})
host,port = get_tunnel(sb)
inject_pubkey(sb, get_pubkey()); start_ssh(sb)
ssh = mk_ssh(host, port)
verify_ssh(ssh)
```

    INFO - ∞ creating sandbox; this may take 5-10 minutes if you are creating this sandbox for the first time... | 2026-06-17 06:27:28,629
    INFO - ✔ sandbox ready | 2026-06-17 06:28:25,941
    INFO - ✔ gotten tunnel: r451.modal.host:34457 | 2026-06-17 06:28:41,496
    INFO - ✔ public key injected | 2026-06-17 06:28:42,020
    INFO - ✔ started ssh service | 2026-06-17 06:28:42,656

    System: Linux
    Hostname: modal
    User: root
    Kernel: 4.4.0
    Architecture: x86_64
    OS Type: GNU/Linux
    GPU: Tesla T4

Next up is starting a remote IPython kernel.

------------------------------------------------------------------------

### start_remote_kernel

``` python

def start_remote_kernel(
    ssh:Callable, # SSH caller from mk_ssh
    kernel_path:str='/root/.local/share/jupyter/runtime/kernel-ipyf.json', # kernel JSON path
):

```

*Start remote kernel and wait until ready.*

``` python
start_remote_kernel(ssh)
```

    INFO - ∞ starting kernel | 2026-06-17 06:28:45,403
    INFO - ✔ remote kernel ready: /root/.local/share/jupyter/runtime/kernel-ipyf.json | 2026-06-17 06:28:49,862

We’ll also need to fetch which Python is being used.

------------------------------------------------------------------------

### get_remote_python

``` python

def get_remote_python(
    ssh:Callable, # SSH caller from mk_ssh
)->str: # path to remote python

```

*Return the path of Python on the remote machine.*

``` python
p = get_remote_python(ssh); p
```

    '/usr/local/bin/python3'

Now that the an IPython kernel is up and running on the Modal sandbox,
it’s time to register that kernel to SolveIt, and then swap it.

We’ll be doing that with [Dr. Scott
Hawley’s](https://www.scotthawley.com/) awesome
[ipyfernel](https://drscotthawley.github.io/ipyfernel/) library.

I’d do `_all_ = ipyfernel.core.__all__`, but nbdev would through an
error.

``` python
register_remote_kernel(remote_python=p)
connect_existing_kernel(f'{host}:{port}')
```

    ipyf_remote_kernel is already a registered kernel
    /app/data/.ssh/config file updated.
    Successfully created connection file and forwarded ports!
    Success: connected to remote kernel via r451.modal.host:34457

And we’re done! Use the `%remote` line magic or `%%remote` cell magic to
run code on Modal’s sandbox.

``` python
#%%remote <-- cell magic (remove # when actually using)
import platform
platform.uname()
```

    uname_result(system='Linux', node='modal', release='4.4.0', version='#1 SMP Sun Jan 10 15:06:54 PST 2016', machine='x86_64')

``` python
#%%remote <-- cell magic (remove # when actually using)
!nvidia-smi
```

    Wed Jun 17 06:28:53 2026       
    +-----------------------------------------------------------------------------------------+
    | NVIDIA-SMI 580.95.05              Driver Version: 580.95.05      CUDA Version: 13.0     |
    +-----------------------------------------+------------------------+----------------------+
    | GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
    | Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
    |                                         |                        |               MIG M. |
    |=========================================+========================+======================|
    |   0  Tesla T4                       On  |   00000000:E7:00.0 Off |                    0 |
    | N/A   30C    P8              9W /   70W |       0MiB /  15360MiB |      0%      Default |
    |                                         |                        |                  N/A |
    +-----------------------------------------+------------------------+----------------------+

    +-----------------------------------------------------------------------------------------+
    | Processes:                                                                              |
    |  GPU   GI   CI              PID   Type   Process name                        GPU Memory |
    |        ID   ID                                                               Usage      |
    |=========================================================================================|
    |  No running processes found                                                             |
    +-----------------------------------------------------------------------------------------+

Alternatively, ipyfernel also has a sticky mode allowing us to run code
remotely by default.

``` python
set_sticky()
```

    Code cells will now execute remotely.

``` python
import torch
```

    /usr/local/lib/python3.12/site-packages/torch/_subclasses/functional_tensor.py:362: UserWarning: Failed to initialize NumPy: No module named 'numpy' (Triggered internally at /pytorch/torch/csrc/utils/tensor_numpy.cpp:84.)
      cpu = _conversion_method_template(device=torch.device("cpu"))

``` python
torch.cuda.is_available()
```

    True

`%%local` to run code locally.

``` python
#%%local <-- cell magic (remove # when actually using)
unset_sticky()
```

    Code cells will now run locally.

``` python
stop_remote()
```

    Code cells will now run locally.
    Shutting down remote kernel

``` python
sb.terminate()
```
