灵符lingfu

LingSys

↓ 0 downloads

Your 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 LingSys
LicenseMIT
AuthorsLing Lin <taellinglin@gmail.com>
READMECode / FilesVersionsDependency GraphDependentsSecurityBuildsSettings

Code / 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
    }
}

← Back to index