Phase 6.3: Parallelitaet und Determinismus - gemessen statt behauptet

Neuer Abschnitt im CP-SAT-Kapitel plus Parallele_Suche.py (76. Programm).
Setzt Paket 2 aus Verbesserungen_02.md um.

Was fehlte, war nicht die Regel, sondern die Messung: Das Buch setzt an acht
Stellen num_workers = 1 mit dem Kommentar "fuer eine reproduzierbare
Ausgabe", nachgeprueft hatte es nie jemand. Gerechnet wird auf demselben
Job-Shop wie das Intervallvariablen-Kapitel, nur gross genug, dass die Suche
arbeitet: 12 Auftraege, 10 Maschinen, 120 Arbeitsgaenge.

Zwei Befunde, beide staerker als die Behauptung:

* Die Beschleunigung ist ueberlinear. Acht Arbeiter waren im abgedruckten
  Lauf nicht achtmal, sondern 12,3-mal schneller als einer. Kein Messfehler:
  CP-SAT vervielfacht nicht dieselbe Suche, sondern laesst verschiedene
  Strategien nebeneinander laufen, die einander ihre Schranken mitteilen.
* Der Seed genuegt nicht - und zwar schon ab ZWEI Arbeitern. Ein Arbeiter:
  1 Plan aus 4 Laeufen. Zwei Arbeiter: 3 verschiedene Plaene aus 4 Laeufen,
  bei identischem random_seed und identischem Zielwert 183.

Die vollstaendige Antwort kam erst ueber die Uebungsaufgabe: Mit
num_workers = 1, aber fuenf verschiedenen Seeds ergeben sich ebenfalls fuenf
verschiedene Plaene. Keiner der beiden Parameter sichert die
Reproduzierbarkeit allein - erst die Kombination traegt.

Weiter fuer die Aufgabe gemessen: Der Gewinn kehrt sich um (auf 24 Kernen
Faktor 10,2 bei 8 Arbeitern, 12,3 bei 16, 9,0 bei 24) - "so viele Arbeiter
wie Kerne" ist damit widerlegt. Und bei 15 Auftraegen laeuft ein Arbeiter
ins 60-s-Limit (FEASIBLE, Makespan 200), waehrend acht OPTIMAL mit
demselben Makespan 200 nach 26,4 s melden: Der Unterschied liegt nicht in
der Loesung, sondern im Beweis, dass es keine bessere gibt.

Die abgedruckte Ausgabe traegt die Kennzeichnung "Laufzeiten und die Zahl
der verschiedenen Plaene sind hardwareabhaengig" - nach dem Muster, das das
Testing-Kapitel fuer Benchmark_Skalierung.py schon verwendet. Der Vergleich
des extrahierten Programms mit dem Abdruck weicht denn auch in genau einer
Zelle ab (4 statt 3 verschiedene Plaene bei 4 Arbeitern); Zielwert und
Struktur sind identisch. Hier ist die Nichtreproduzierbarkeit der
abgedruckten Zahl die Aussage selbst.

Mitgezogen: Kapitelkopf, Lernziele, Selbsttest, Zusammenfassung,
Vorwort-Programmverzeichnis, Uebungsaufgabe und Loesung in Anhang A, ein
Verweis aus dem bestehenden Callout zu mehrdeutigen Optima und einer aus
Warmstart_Effekt.py im MILP-Kapitel (dort nach Regel 12 der Kapitelname).

Stand: 295 Abschnitte, 730 Querverweise, 328 Indexmarken, 76 Programme,
140 Aufgaben mit 140 Loesungen, 33 pytest-Tests, PDF 744 Seiten, 69
netzfreie Programme fehlerfrei.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
dschlueter 2026-09-08 11:19:53 +02:00
commit 293370b7a1
30 changed files with 12643 additions and 10385 deletions

View file

@ -77,14 +77,14 @@ sie unerwartet ab, ist etwas kaputtgegangen.
| Kapiteldateien | 22 | **31** |
| Kapitel | 15 | **23** |
| Anhänge | 4 | **5** |
| Zeilen im Gesamtdokument | 11 082 | **27 868** |
| Größe des Gesamtdokuments | 606 KB | **1 565 KB** |
| Hauptüberschriften | 131 | **297** |
| registrierte Abschnitte | 122 | **294** |
| aufgelöste Querverweise | 314 | **725** (0 unaufgelöst) |
| Zeilen im Gesamtdokument | 11 082 | **28 185** |
| Größe des Gesamtdokuments | 606 KB | **1 585 KB** |
| Hauptüberschriften | 131 | **298** |
| registrierte Abschnitte | 122 | **295** |
| aufgelöste Querverweise | 314 | **730** (0 unaufgelöst) |
| Indexmarken | 295 | **328** |
| Beispielprogramme | 41 | **75** (alle lauffähig) |
| PDF-Seiten | — | **737** |
| Beispielprogramme | 41 | **76** (alle lauffähig) |
| PDF-Seiten | — | **744** |
| Notebooks | — | **25** |
| Plotly-Figuren | — | **4** |
| Diagramme (SVG) | 26 | **32**, davon **18** mit Generatorskript (15 Skripte) |
@ -1565,6 +1565,59 @@ war. Genau der Fall, für den sie gebaut wurde.
Stand danach: 294 Abschnitte, 725 Querverweise, 328 Indexmarken, **75** Programme,
139 Aufgaben mit 139 Lösungen, PDF **737** Seiten.
### ✅ 6.3 Parallelität und Determinismus ({ref:kap:cpsat})
Neuer Abschnitt {ref:sec:cpsat-parallele-suche} plus `Parallele_Suche.py` (76. Programm).
Setzt Paket 2 aus `Verbesserungen_02.md` um.
**Was fehlte, war nicht die Regel, sondern die Messung.** Das Buch setzt an acht Stellen
`num_workers = 1` mit dem Kommentar „für eine reproduzierbare Ausgabe", und der Spickzettel
nennt den Grund. Nachgeprüft hatte es nie jemand. Gerechnet wird auf demselben Job-Shop wie
{ref:sec:cpsat-intervallvariablen-job-shop-scheduling}, nur groß genug, dass die Suche
arbeitet: 12 Aufträge, 10 Maschinen, 120 Arbeitsgänge.
**Zwei Befunde, beide stärker als die Behauptung:**
1. **Die Beschleunigung ist überlinear.** Acht Arbeiter waren im abgedruckten Lauf nicht
achtmal, sondern **12,3-mal** schneller als einer. Kein Messfehler: CP-SAT vervielfacht
nicht dieselbe Suche, sondern lässt **verschiedene Strategien** nebeneinander laufen, die
einander ihre Schranken mitteilen. Der zweite Arbeiter ist nicht „der zweite Kern",
sondern ein anderes Verfahren.
2. **Der Seed genügt nicht — und zwar schon ab zwei Arbeitern.** Ein Arbeiter: 1 Plan aus
4 Läufen. **Zwei** Arbeiter: 3 verschiedene Pläne aus 4 Läufen, bei identischem
`random_seed` und identischem Zielwert 183. Es braucht also keine acht Arbeiter, um die
Reproduzierbarkeit zu verlieren.
**Die vollständige Antwort kam erst über die Übungsaufgabe**, und sie ist besser als der
Abschnitt allein: Mit `num_workers = 1`, aber **fünf verschiedenen Seeds**, ergeben sich
ebenfalls **fünf verschiedene Pläne**. Keiner der beiden Parameter sichert die
Reproduzierbarkeit allein:
| | Seed fest | Seed variabel |
| --- | --- | --- |
| **1 Arbeiter** | reproduzierbar | 5 Pläne aus 5 Läufen |
| **mehrere Arbeiter** | 3 Pläne aus 4 Läufen | erst recht nicht |
Weiter gemessen für die Aufgabe: Der Gewinn kehrt sich um — auf 24 Kernen Faktor **10,2**
(8 Arbeiter), **12,3** (16), **9,0** (24). „So viele Arbeiter wie Kerne" ist damit
widerlegt. Und bei 15 Aufträgen läuft ein Arbeiter ins 60-s-Limit (`FEASIBLE`, Makespan
200), während acht `OPTIMAL` mit **demselben** Makespan 200 nach 26,4 s melden — der
Unterschied liegt nicht in der Lösung, sondern im **Beweis**, dass es keine bessere gibt.
**Zur abgedruckten Ausgabe:** Sie trägt die Kennzeichnung „Laufzeiten *und* die Zahl der
verschiedenen Pläne sind hardwareabhängig" — nach dem Muster, das
{ref:kap:testing} für `Benchmark_Skalierung.py` schon verwendet. Der Vergleich des
extrahierten Programms mit dem Abdruck weicht denn auch in genau einer Zelle ab (4 statt 3
verschiedene Pläne bei 4 Arbeitern); Zielwert und Struktur sind identisch. Hier ist die
Nichtreproduzierbarkeit der abgedruckten Zahl **die Aussage selbst** — der einzige Fall im
Buch, in dem das so ist.
Im MILP-Kapitel bekam die entsprechende Stelle in `Warmstart_Effekt.py` einen Verweis;
dort steht nach Regel 12 der Kapitel**name**, keine Nummer.
Stand danach: 295 Abschnitte, 730 Querverweise, **76** Programme, 140 Aufgaben mit
140 Lösungen, PDF **744** Seiten.
---
## 8. Commit-Historie des V04-Strangs