LingSys
↓ 0 downloadsYour machine's memory, GPU, motherboard and network, drawn and played in the Ling design system: LingSys, a small build for USB liquid-cooler displays, LingNet for IPv4/IPv6, DNS and packets, and a LingOS edition. 64-bit and 32-bit Windows builds included.
Keywords system-monitor, visualization, network, ipv6, gpu, lcd, lingos, ling
lingfu install LingSysCode / Files (48)
src/60_gpu.ling
# ───────────────────────────── GPU section ───────────────────────────────────
# Channels (rings, lanes, pulse categories): 3D, COMPUTE, COPY, DECODE, ENCODE, VRAM, POWER.
# Data: gpu.snap from sampler_hw.ps1 (nvidia-smi for the card, Windows GPU counters for engines and processes).
fn gpu_sel_vec(Z) {
bind gp = Z[Z_D][D_GPU]
return gp[GP_VEC][gp[GP_SEL]]
}
# ---- view 1: ENGINES, seven rings
fn view_gpu_engines(Z) {
bind gp = Z[Z_D][D_GPU]
bind g = gp[GP_SEL]
bind v = gp[GP_VEC][g]
bind e = gp[GP_ENG][g]
bind labels = ["3D " + pct(e[0]) + " ", "COMPUTE " + pct(e[1]) + " ", "COPY " + pct(e[2]) + " ", "DECODE " + pct(e[3]) + " ",
"ENCODE " + pct(e[4]) + " ", "VRAM " + fmt_mb(v[GV_VUSED]) + " OF " + fmt_mb(v[GV_VTOTAL]) + " ",
"POWER " + pct(v[GV_POWER]) + "W OF " + pct(v[GV_PLIM]) + " "]
ring_stack(Z, 7, IDM, labels, Z[Z_FRAC], pct(v[GV_UTIL]) + "%", short_gpu(gp[GP_NAME][g]) + " " + pct(v[GV_TEMP]) + "C", 3)
}
# ---- view 2: VRAM, a 32 x 32 page map along a Hilbert curve; each cell is 1/1024 of the card's memory
# The six biggest processes get a hue each, everything else (and what Windows does not attribute) is violet.
fn gpu_segments(pd, vused, vtotal) {
bind all = 0.0
bind i = 0
while i < len(pd) {
bind all = all + pd[i]
bind i = i + 1
}
bind scale = 1.0
if all > vused {
if all > 0.0 { bind scale = vused / all }
}
bind sizes = []
bind top = 0.0
bind i = 0
while i < 6 {
bind s = 0.0
if i < len(pd) { bind s = pd[i] * scale }
bind sizes = list_push(sizes, s)
bind top = top + s
bind i = i + 1
}
bind sizes = list_push(sizes, max(vused - top, 0.0))
bind cum = []
bind run = 0.0
bind i = 0
while i < 7 {
bind run = run + sizes[i] / max(vtotal, 1.0) * 1024.0
bind cum = list_push(cum, min(round(run), 1024))
bind i = i + 1
}
return [cum, sizes]
}
fn gcell(i, cum) {
bind k = 0
while k < 7 {
if i < cum[k] { return k }
bind k = k + 1
}
return 7
}
fn view_gpu_vram(Z) {
bind W = Z[Z_W]
bind H = Z[Z_H]
bind t = Z[Z_T]
bind hs = Z[Z_HS]
bind sat = Z[Z_SAT]
bind hil = Z[Z_HIL]
bind gp = Z[Z_D][D_GPU]
bind g = gp[GP_SEL]
bind v = gp[GP_VEC][g]
bind pr = gp[GP_PROC][g]
bind pn = pr[0]
bind pu = pr[3]
bind vt = max(v[GV_VTOTAL], v[GV_VUSED] * 1.02 + 1.0)
bind seg = gpu_segments(pr[1], v[GV_VUSED], vt)
bind cum = seg[0]
bind sizes = seg[1]
bind pe = []
bind k = 0
while k < 7 {
bind u = v[GV_UTIL] / 100.0
if k < 6 {
if k < len(pu) { bind u = pu[k] / 40.0 } else { bind u = 0.0 }
}
bind pe = list_push(pe, clamp(u, 0.0, 1.0))
bind k = k + 1
}
bind S = min(H * 0.76, W * 0.5)
bind cs = S / 32.0
bind mx = W * 0.36
bind my = H * 0.5
bind tilt = 0.09 * sin(t * 0.07) + 0.07 * sin(Z[Z_ROT] * 0.8)
bind ca = cos(tilt)
bind sa = sin(tilt)
bind i = 0
while i < 1024 {
bind c = gcell(i, cum)
bind gx = hil[i * 2] - 15.5
bind gy = hil[i * 2 + 1] - 15.5
bind x = mx + (gx * ca - gy * sa) * cs
bind y = my + (gx * sa + gy * ca) * cs
bind hv = fract(sin(i * 12.9898) * 43758.5453)
bind hv = fract(hv + 0.18 * sin(t * 0.6 + i * 0.37) + 1.0)
bind h = cs * 0.46
if c == 7 {
ink(9.0 + 6.0 * hv)
square(x, y, h, tilt)
ink(20.0)
draw_pixel(x, y)
} else {
bind e = pe[c]
col(c, sat * 0.8, 20.0 + 16.0 * hv + 14.0 * e, hs + (hv - 0.5) * 10.0)
square(x, y, h, tilt)
bind nl = 1 + floor(hv * 3.0 + e * 2.0)
bind m = 0
col(c, sat, 30.0 + 26.0 * hv + 22.0 * e, hs + (hv - 0.5) * 10.0)
while m < nl {
bind u = (m + 0.5) / nl
bind s0 = (u * 2.0 - 1.0) * h
bind an = tilt + ANG1[c]
bind dx = cos(an) * h * 0.9
bind dy = sin(an) * h * 0.9
bind ox = (0.0 - sin(an)) * s0
bind oy = cos(an) * s0
draw_line(x + ox - dx, y + oy - dy, x + ox + dx, y + oy + dy)
bind m = m + 1
}
}
bind i = i + 1
}
ink(30.0)
square(mx, my, S * 0.5 + cs * 0.9, tilt)
# pulses leave the cells of the process that did the work
bind ev = Z[Z_EV]
bind j = 0
while j < len(ev) {
bind p = (t - ev[j + 2]) / 1.8
bind sg = min(ev[j + 5], 6)
bind lo = 0
if sg > 0 { bind lo = cum[sg - 1] }
bind span = max(cum[sg] - lo, 1.0)
bind idx = min(floor(lo + ev[j + 3] * span), 1023)
bind gx = hil[idx * 2] - 15.5
bind gy = hil[idx * 2 + 1] - 15.5
bind x = mx + (gx * ca - gy * sa) * cs
bind y = my + (gx * sa + gy * ca) * cs
col(sg, sat, (1.0 - p) * (60.0 + 35.0 * ev[j + 4]), hs)
if ev[j] == 0 {
draw_circle(x, y, cs * (0.5 + 3.5 * p))
draw_circle(x, y, cs * (0.3 + 1.6 * p))
} else {
square(x, y, cs * (2.6 - 2.1 * p), tilt + p * 3.0)
square(x, y, cs * 0.5, tilt)
if p < 0.35 { draw_disc(x, y, cs * 0.35) }
}
bind j = j + 6
}
# legend
bind lx = W * 0.68
bind ts = min(H * 0.095, 62.0)
bind c = 0
while c < 7 {
bind ly = H * 0.1 + c * (ts + H * 0.03)
bind e = pe[c]
bind nm = "OTHER"
bind lt = "O"
if c < 6 {
bind nm = "-"
bind lt = "-"
if c < len(pn) {
bind nm = pn[c]
bind lt = str_slice(pn[c], 0, 1)
}
}
tile(lt, lx, ly, ts, 52.0 + 30.0 * e, c, sat, hs, 0.6 + e)
col(c, sat, 68.0, hs)
daemon_text(str_slice(nm, 0, 16), lx + ts + 14.0, ly + ts * 0.3, ts * 0.3)
ink(62.0)
daemon_text(fmt_mb(sizes[c]) + " " + num_str(round(sizes[c] / vt * 1000.0) / 10.0) + "%", lx + ts + 14.0, ly + ts * 0.68, ts * 0.26)
hbar(lx + ts + 14.0, ly + ts * 0.95, W * 0.28, sizes[c] / vt, c, sat, 60.0 + 20.0 * e, hs)
bind c = c + 1
}
ink(55.0)
daemon_text("FREE " + fmt_mb(max(vt - v[GV_VUSED], 0.0)) + " OF " + fmt_mb(vt), lx, H * 0.1 + 7.0 * (ts + H * 0.03) + ts * 0.2, ts * 0.26)
}
# ---- view 3: DIALS, four gauges and a minute of history under each
fn dial(cx, cy, r, frac, k, sat, hs, big, small, e, t) {
bind a0 = 0.0 - 2.356
bind sweep = 4.712
bind f = clamp(frac, 0.0, 1.0)
col(k, sat * 0.7, 26.0 + 14.0 * e, hs)
draw_circle(cx, cy, r)
draw_circle(cx, cy, r * 0.78)
bind i = 0
while i <= 40 {
bind a = a0 + sweep * i / 40.0
bind tl = 0.05
if i % 5 == 0 { bind tl = 0.12 }
if i / 40.0 <= f { col(k, sat, 62.0 + 28.0 * e, hs) } else { ink(22.0) }
pline(cx, cy, r * (1.0 - tl), a, r * 1.02, a)
bind i = i + 1
}
col(k, sat, 36.0 + 26.0 * e, hs)
bind n = floor(sweep * f / 0.03)
bind j = 0
while j < n {
bind a = a0 + j * 0.03
pline(cx, cy, r * 0.8, a, r * 0.94, a + 0.07)
bind j = j + 1
}
bind an = a0 + sweep * f
col(k, sat, 80.0, hs)
pline(cx, cy, r * 0.12, an, r * 0.74, an)
square(px(cx, r * 0.74, an), py(cy, r * 0.74, an), r * 0.04, an + t * 0.5)
draw_circle(cx, cy, r * 0.07)
bind bh = fit_h(big, r * 1.0, r * 0.3)
col(k, sat, 78.0, hs)
daemon_text(big, cx - text_w(big, bh) / 2.0, cy + r * 0.34, bh)
bind sh = fit_h(small, r * 1.0, r * 0.14)
ink(55.0)
daemon_text(small, cx - text_w(small, sh) / 2.0, cy + r * 0.62, sh)
}
fn view_gpu_dials(Z) {
bind W = Z[Z_W]
bind H = Z[Z_H]
bind t = Z[Z_T]
bind hs = Z[Z_HS]
bind sat = Z[Z_SAT]
bind en = Z[Z_ENERGY]
bind D = Z[Z_D]
bind gp = D[D_GPU]
bind g = gp[GP_SEL]
bind v = gp[GP_VEC][g]
bind hst = D[D_HS]
bind r = min(W * 0.105, H * 0.2)
bind cy = H * 0.3
bind fr = [v[GV_UTIL] / 100.0, v[GV_TEMP] / 100.0, v[GV_POWER] / max(v[GV_PLIM], 1.0), v[GV_CLK] / max(v[GV_CLKMAX], 1.0)]
bind bigs = [pct(v[GV_UTIL]) + "%", pct(v[GV_TEMP]) + "C", pct(v[GV_POWER]) + "W", pct(v[GV_CLK])]
bind smalls = ["UTILISATION", "TEMPERATURE", "POWER OF " + pct(v[GV_PLIM]) + "W", "CORE MHZ OF " + pct(v[GV_CLKMAX])]
bind hk = [3, 0, 2, 4]
bind sid = [0, 1, 2, 3]
bind d = 0
while d < 4 {
bind cx = W * (0.14 + 0.24 * d)
bind e = clamp(fr[d] + 0.15, 0.0, 1.0)
dial(cx, cy, r, fr[d], hk[d], sat, hs, bigs[d], smalls[d], e, t)
bind ser = hst[HS_GPU + g * 4 + sid[d]]
spark(cx - r, H * 0.57, r * 2.0, H * 0.17, ser, 100, hk[d], sat, 64.0, hs)
ink(46.0)
daemon_text("LAST 50 S", cx - r, H * 0.55, 11.0)
bind d = d + 1
}
# the rest of the card's vitals
bind thr = "NONE"
if v[GV_THP] > 0.5 { bind thr = "POWER LIMIT" }
if v[GV_THT] > 0.5 { bind thr = "THERMAL" }
bind lines = ["MEMORY CLOCK " + pct(v[GV_MCLK]) + " OF " + pct(v[GV_MCLKMAX]) + " MHZ FAN " + pct(v[GV_FAN]) + "% MEMORY BUS " + pct(v[GV_MUTIL]) + "%",
"PCIE GEN " + pct(v[GV_PGEN]) + " X" + pct(v[GV_PW]) + " THROTTLE " + thr + " DRIVER " + gp[GP_DRV][g]]
bind i = 0
while i < 2 {
ink(66.0 - 10.0 * i)
daemon_text(lines[i], W * 0.04, H * 0.83 + i * H * 0.065, 14.0)
bind i = i + 1
}
}
# ---- view 4: FLEET, every GPU at once. Click a card (or press Up / Down) to pick the one the other views show.
# [x, y, w, h] of GPU i's card out of n
fn fleet_rect(i, n, W, H) {
bind cols = min(n, 4)
bind rows = ceil(n / cols)
bind gap = 14.0
bind cw = (W - 36.0 - (cols - 1) * gap) / cols
bind ch = (H - 82.0 - (rows - 1) * gap) / rows
return [18.0 + (i % cols) * (cw + gap), 70.0 + floor(i / cols) * (ch + gap), cw, ch]
}
fn fleet_hit(mx, my, W, H, n) {
bind i = 0
while i < n {
bind r = fleet_rect(i, n, W, H)
if inside(mx, my, r) == 1 { return i }
bind i = i + 1
}
return 0 - 1
}
bind FLEET_HUE = [3, 4, 1, 6, 0, 2, 5, 3]
fn view_gpu_fleet(Z) {
bind W = Z[Z_W]
bind H = Z[Z_H]
bind t = Z[Z_T]
bind hs = Z[Z_HS]
bind sat = Z[Z_SAT]
bind D = Z[Z_D]
bind gp = D[D_GPU]
bind hst = D[D_HS]
bind n = gp[GP_N]
bind sel = gp[GP_SEL]
bind hov = fleet_hit(Z[Z_MX], Z[Z_MY], W, H, n)
bind rows = ceil(n / min(n, 4))
bind g = 0
while g < n {
bind v = gp[GP_VEC][g]
bind r = fleet_rect(g, n, W, H)
bind x = r[0]
bind y = r[1]
bind cw = r[2]
bind ch = r[3]
bind k = FLEET_HUE[g % 8]
bind on = 0
if g == sel { bind on = 1 }
bind lit = 30.0 + 40.0 * on
if g == hov { bind lit = lit + 14.0 }
col(k, sat * 0.7, lit, hs)
brect(x, y, 1.0, 0.0, 0.0, cw, ch)
if on == 1 {
bind a = 14.0
col(k, sat, 84.0, hs)
bline(x, y, 1.0, 0.0, a, 0.0, 0.0)
bline(x, y, 1.0, 0.0, 0.0, a, 0.0)
bline(x, y, 1.0, cw - a, 0.0, cw, 0.0)
bline(x, y, 1.0, cw, 0.0, cw, a)
bline(x, y, 1.0, cw, ch - a, cw, ch)
bline(x, y, 1.0, cw, ch, cw - a, ch)
bline(x, y, 1.0, a, ch, 0.0, ch)
bline(x, y, 1.0, 0.0, ch, 0.0, ch - a)
}
tile(num_str(g), x + 10.0, y + 10.0, 38.0, 54.0 + 28.0 * on, k, sat, hs, 0.5 + on)
col(k, sat, 78.0 + 12.0 * on, hs)
daemon_text(str_slice(gp[GP_NAME][g], 0, 22), x + 58.0, y + 24.0, min(14.0, (cw - 70.0) / 16.0))
ink(52.0)
bind link = "GEN" + pct(v[GV_PGEN]) + " X" + pct(v[GV_PW])
if v[GV_PW] < 1.0 { bind link = "NO NVIDIA DATA" }
daemon_text(link, x + 58.0, y + 44.0, 10.0)
bind u = clamp(v[GV_UTIL] / 100.0, 0.0, 1.0)
bind dr = min(cw * 0.28, (ch - 52.0) * 0.26)
bind dcy = y + 58.0 + dr
dial(x + cw / 2.0, dcy, dr, u, k, sat, hs, pct(v[GV_UTIL]) + "%", "UTIL", clamp(u + 0.15, 0.0, 1.0), t)
bind vt = max(v[GV_VTOTAL], v[GV_VUSED] * 1.02 + 1.0)
bind by0 = dcy + dr + 24.0
bind sp = 36.0
if rows > 1 { bind sp = 30.0 }
bind bw = cw - 24.0
bind tx = pct(v[GV_TEMP]) + "C"
if v[GV_FAN] > 0.5 { bind tx = tx + " FAN " + pct(v[GV_FAN]) + "%" }
bind lab = ["VRAM " + fmt_mb(v[GV_VUSED]) + " OF " + fmt_mb(vt), "POWER " + pct(v[GV_POWER]) + "W OF " + pct(v[GV_PLIM]), "TEMP " + tx]
bind fr = [v[GV_VUSED] / vt, v[GV_POWER] / max(v[GV_PLIM], 1.0), v[GV_TEMP] / 100.0]
bind bk = [5, 2, 0]
bind q = 0
while q < 3 {
ink(62.0)
daemon_text(lab[q], x + 12.0, by0 + q * sp, 11.0)
hbar(x + 12.0, by0 + q * sp + 13.0, bw, fr[q], bk[q], sat, 58.0, hs)
bind q = q + 1
}
if rows == 1 {
ink(46.0)
daemon_text("UTILISATION, LAST 50 S", x + 12.0, y + ch - 66.0, 10.0)
spark(x + 12.0, y + ch - 56.0, bw, 44.0, hst[HS_GPU + g * 4], 100, k, sat, 64.0, hs)
}
bind g = g + 1
}
}