Skip to content

Commit adac3bd

Browse files
committed
GPU: extern C for net send/receive buffering registration
NMODL-generated Traub mechs failed to load on NRN_ENABLE_GPU installs with undefined mangled hoc_register_net_send_buffering: GPU defs are extern "C" but public headers declared C++ linkage. Align declarations and CPU stubs. Also refresh GROK-GPU-NATIVE for #3826 absorb, ringtest re-green, and Traub NMODL CPU smoke (4474 spikes @ 100) on this install.
1 parent c267a07 commit adac3bd

4 files changed

Lines changed: 56 additions & 11 deletions

File tree

GROK-GPU-NATIVE.md

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,54 @@ points must flush NetReceiveBuffer.
101101
| **Th1** | OpenACC detect over slots (device `vec_v`, atomic hit buffer) | **Done** |
102102
| **Th2** | Skip full `vec_v` host pull when device detect handles SoA PreSyns (lazy pull for host/WATCH) | **Done** |
103103
| **Th3** | Re-qualify ringtest 0.025/1/1.025/100 after Th0–Th2; traffic notes | **Done** (2026-07-25) |
104-
| **Th4** | Traub-scale threshold load | Pending |
104+
| **Th4** | Traub-scale threshold load | **In progress** — NMODL Traub build/load on GPU install green; Gate B/C next |
105105

106106
Today: Th1 device `pscheck` + Th2 (no forced host voltage sync before detect) +
107107
Th3 green long gate. Host still pulls flags/hit indices then
108108
`deliver_threshold_spike`.
109109

110+
### Resume: Traub / Th4 (2026-07-25+)
111+
112+
NMODL **CPU** Traub M0–M2 is green in `~/neuron/nrnnmodl`
113+
(`local/nmodl-cpu-traub`; see `GROK-NMODL-CPU.md`). Do not re-do M0–M2 there.
114+
115+
**#3826 tip absorbed** via cherry-pick (full rebase of merge-heavy GPU history
116+
conflicted on unrelated commits):
117+
118+
| Cherry-pick | Content |
119+
|-------------|---------|
120+
| `3b273d4e3` (from `dcdbf97fe`) | Weight SoA by index (drop reverse NetCon map) — Traub hang fix |
121+
| `c267a0788` (from `a49fbad57`) | `nrnivmodl` defaults for `NMODL_PYLIB` / `NMODLHOME` |
122+
123+
**Progress after absorb:**
124+
125+
| Step | Status |
126+
|------|--------|
127+
| Rebuild + ringtest 688 @ 100 | **Green** (noise-level cellstate) |
128+
| NMODL Traub mechs on this install | **Green** — see recipe below |
129+
| CPU Traub smoke (`enable_gpu=0`) | **Green** — load ok; t=0.025 run; t=100 → **4474** spikes exact |
130+
| Gate B/C / Th4 GPU | **Next** |
131+
132+
#### Traub NMODL build on GPU install
133+
134+
```bash
135+
source ~/neuron/bin/nrnenv nrngpu build-gpu
136+
mkdir -p /tmp/traub-nrngpu-nmodl && cd /tmp/traub-nrngpu-nmodl
137+
ln -sfn ~/models/82894/mod/*.mod .
138+
# Default GPU nrnivmodl still uses nocmodl unless -nmodl is passed.
139+
nrnivmodl -nmodl "$(which nmodl)" .
140+
# special: /tmp/traub-nrngpu-nmodl/x86_64/special
141+
```
142+
143+
**Linkage fix (required for NMODL mechs on GPU installs):** public headers
144+
declared C++ `hoc_register_net_send_buffering` / `…_receive_…`, but GPU defs
145+
in `neuron/gpu/net_*_buffer.cpp` are `extern "C"` → runtime
146+
`undefined symbol: _Z31hoc_register_net_send_bufferingi`. Fixed by matching
147+
`extern "C"` in `mech_api.h`, `nrniv_mf.h`, and CPU stubs in `init.cpp`.
148+
149+
OpenACC/device mech codegen (`-nmodlflags` ACC path) and Gate B/C still open.
150+
`model_data.hpp` install may still matter for ACC only. M3 stays deferred.
151+
110152
---
111153

112154
## Key paths
@@ -140,11 +182,11 @@ After ACC codegen changes to built-ins: `rm -f build-gpu/src/nrnoc/expsyn.cpp &&
140182
```
141183
Read GROK-GPU-NATIVE.md and AGENTS.md.
142184
143-
Stages 2–3c + threshold Th0–Th3 done; long gate green: 688 spikes @ tstop=100,
144-
threshold dV=0, noise-level cellstate diffs only.
185+
Stages 2–3c + threshold Th0–Th3 done; long gate green: 688 spikes @ tstop=100.
186+
NMODL CPU Traub M0–M2 green in ~/neuron/nrnnmodl — do not re-do there.
145187
146-
Next options: Traub incremental (Th4 threshold load when ready); optional pure
147-
device NET_RECEIVE apply.
188+
#3826 tip absorbed; ringtest 688@100 green. NMODL Traub on GPU install builds
189+
and runs CPU (4474 spikes @ 100). Next: Gate B/C / Th4 GPU.
148190
149191
Do not reintroduce NetCon::weight_ heap or host vec_rhs voltage hot path.
150192
source ~/neuron/bin/nrnenv nrngpu build-gpu before GPU runs.

src/nrnoc/init.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,11 @@ void add_nrn_has_net_event(int mechtype) {
202202
}
203203

204204
#if !defined(NRN_ENABLE_GPU)
205-
void hoc_register_net_send_buffering(int type) {
205+
extern "C" void hoc_register_net_send_buffering(int type) {
206206
(void) type;
207207
}
208208

209-
void hoc_register_net_receive_buffering(void (*)(NrnThread*), int type) {
209+
extern "C" void hoc_register_net_receive_buffering(void (*)(NrnThread*), int type) {
210210
(void) type;
211211
}
212212
#endif

src/nrnoc/nrniv_mf.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ int point_register_mech(const char**,
6969
extern int nrn_get_mechtype(const char*);
7070
extern void nrn_writes_conc(int, int);
7171
extern void add_nrn_has_net_event(int);
72-
extern void hoc_register_net_send_buffering(int);
73-
extern void hoc_register_net_receive_buffering(void (*)(NrnThread*), int);
72+
extern "C" void hoc_register_net_send_buffering(int);
73+
extern "C" void hoc_register_net_receive_buffering(void (*)(NrnThread*), int);
7474
void hoc_register_cvode(int, nrn_ode_count_t, nrn_ode_map_t, nrn_ode_spec_t, nrn_ode_matsol_t);
7575
void hoc_register_synonym(int, nrn_ode_synonym_t);
7676
extern void register_destructor(Pvmp);

src/oc/mech_api.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,8 @@
2121
#include <cmath> // nocmodl uses std::isnan
2222
#include <iostream> // nocmodl uses std::cerr
2323

24-
void hoc_register_net_send_buffering(int);
25-
void hoc_register_net_receive_buffering(void (*)(struct NrnThread*), int);
24+
/* C linkage: GPU defs in neuron/gpu/net_*_buffer.cpp are extern "C"; NMODL
25+
* mechs include this header and must match. CPU stubs in init.cpp likewise. */
26+
extern "C" void hoc_register_net_send_buffering(int);
27+
extern "C" void hoc_register_net_receive_buffering(void (*)(struct NrnThread*),
28+
int);

0 commit comments

Comments
 (0)