Hoppa till innehållet
AI-grafen
E· Universitetdatavetenskap· ca 60 min· utvecklande· verifierad 2026-09-20

Processer, trådar och resursgränser

Kunna förklara processer, trådar, cgroups och varför en sandlåda kan begränsa CPU och minne.

Förkunskaper

Intuition

En process har eget minne och egna resurser. En tråd delar minne med andra trådar i samma process.

I Python finns GIL (global interpreter lock): bara en tråd kör Python-bytekod åt gången. Konsekvensen:

UppgiftAnvänd
Väntar på nätverk eller disk (I/O)trådar eller async — GIL släpps under väntan
Räknar i Pythonprocesser (multiprocessing) — trådar hjälper inte
Räknar i NumPy/PyTorchtrådar fungerar — biblioteken släpper GIL i C-koden

Det är därför asyncio löser LLM-anrop men inte matrisberäkningar.

Formellt

cgroups (control groups) är Linux-kärnans mekanism för att begränsa vad en grupp processer får använda. Det är vad docker run --cpus 1 --memory 512m faktiskt sätter upp.

BegränsningEffekt när den nås
cpu.maxprocessen struypas — körs långsammare, dödas inte
memory.maxOOM-killer dödar processen (exit 137)
pids.maxfork() misslyckas — stoppar fork-bomber
io.maxdisk-I/O struypas

Skillnaden är viktig i praktiken: en labbkörning som når CPU-taket blir bara långsam och träffar så småningom sin timeout. En som når minnestaket dödas tvärt med exit 137 — och det felet ser ut som en krasch i användarens kod om man inte känner igen det.

Namespaces kompletterar cgroups genom att isolera vad processen ser: PID (egna processnummer), nätverk (--network none), mount (eget filsystem), user (uid-mappning). cgroups begränsar hur mycket, namespaces begränsar vad.

Tillsammans är det hela grunden för containerisolering — och precis det AI-grafens labbrunner använder (ADR-003).

Kod

import os, multiprocessing, threading, time

def cpu_tung(n=10_000_000):
    return sum(i * i for i in range(n))

def mat(fn, n=4):
    t0 = time.perf_counter(); fn(n); return round(time.perf_counter() - t0, 2)

def med_tradar(n):
    tr = [threading.Thread(target=cpu_tung) for _ in range(n)]
    [t.start() for t in tr]; [t.join() for t in tr]

def med_processer(n):
    with multiprocessing.Pool(n) as p:
        p.map(cpu_tung, [10_000_000] * n)

print("trådar:  ", mat(med_tradar))      # 4.1 s — GIL, ingen vinst
print("processer:", mat(med_processer))  # 1.1 s — fyra kärnor
# Se gränserna inifrån en container
cat /sys/fs/cgroup/memory.max     # 536870912  (512 MB)
cat /sys/fs/cgroup/cpu.max        # 100000 100000  (1 CPU)

# Exit 137 = 128 + 9 (SIGKILL) → OOM-killern tog processen
docker run --rm --memory 64m python:3.12-slim python -c "x = bytearray(200_000_000)"; echo $?

Behärskning innebär

  • Förklarar processer, trådar och GIL
  • Beskriver hur cgroups begränsar CPU och minne
  • Kopplar det till sandlådans säkerhet

Logga in för att göra övningarna och bygga upp din behärskning.

Källor

Alla källor och licenser