{"id":862,"date":"2026-07-30T12:23:29","date_gmt":"2026-07-30T12:23:29","guid":{"rendered":"https:\/\/matforge.org\/?p=862","raw":"https:\/\/matforge.org\/?p=862"},"modified":"2026-07-30T12:23:29","modified_gmt":"2026-07-30T12:23:29","slug":"scientific-computing-performance-profiling-identifying-bottlenecks","status":"publish","type":"post","link":"https:\/\/matforge.org\/de\/scientific-computing-performance-profiling-identifying-bottlenecks\/","title":{"rendered":"Profiling der wissenschaftlichen Rechnerleistung: Identifizierung von Engp\u00e4ssen bei PDE-Solvern","raw":"Profiling der wissenschaftlichen Rechnerleistung: Identifizierung von Engp\u00e4ssen bei PDE-Solvern"},"content":{"rendered":"<span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Reading Time: <\/span> <span class=\"rt-time\"> 8<\/span> <span class=\"rt-label rt-postfix\">minutes<\/span><\/span><h2>Schl\u00fcssel zum Mitnehmen<\/h2>\n<ul>\n<li>Profil vor der Optimierung. Erraten Sie nicht, welcher Teil Ihres PDE-Solvers langsam ist. Messen Sie es zuerst. Der eigentliche Engpass ist oft nicht derjenige, den Sie erwarten.<\/li>\n<li>Python-Profiler sind praktisch. Tools wie <code>cProfile<\/code>, <code>py-spy<\/code>, <code>scalene<\/code> und <code>SnakeViz<\/code> unterst\u00fctzen jeweils unterschiedliche Profilierungsanforderungen.<\/li>\n<li>Gew\u00f6hnliche PDE-Solver-Engp\u00e4sse umfassen die Matrix-Assembly, lineare Solver-Iterationen, Overhead auf Python-Ebene im Gleichungsaufbau und Speicherzuordnungsmuster.<\/li>\n<li>Der Measure-Diagnose-Treat-Workflow verwandelt vage Leistungsprobleme in konkrete, fixierbare Erkenntnisse.<\/li>\n<li>Die Skalierung \u00e4ndert das, was langsam ist. Ein L\u00f6ser, der sich auf einem kleinen Gitter schnell anf\u00fchlt, kann bei realistischen Problemgr\u00f6\u00dfen verschiedene Engp\u00e4sse aufdecken.<\/li>\n<\/ul>\n<h2>Ihr L\u00f6ser ist langsam. Was jetzt?<\/h2>\n<p>Sie richten eine Simulation ein. Du rennst es. Dann dauert es viel zu lange.<\/p>\n<p>Der nat\u00fcrliche Instinkt besteht darin, Code zu \u00e4ndern. M\u00f6glicherweise m\u00f6chten Sie Schleifen vektorisieren, Solver tauschen oder Parallelit\u00e4t hinzuf\u00fcgen. Aber es gibt ein Problem, das viele Forscher \u00fcberspringen: Sie wissen vielleicht nicht, was tats\u00e4chlich langsam ist.<\/p>\n<p>Der Teil, der wie der Engpass aussieht, kann nur einen kleinen Teil der Laufzeit dauern. In der Zwischenzeit kann ein Versteckter Matrix-Montageschritt den gr\u00f6\u00dften Teil der Ausf\u00fchrungszeit in Anspruch nehmen.<\/p>\n<p>Leistungsprofilierung ist nicht optional. Es ist einer der wichtigsten Schritte, um einen PDE-Solver schneller zu machen, und es ist einfacher, als viele Forscher in Python erwarten.<\/p>\n<p>In diesem Handbuch werden die Tools, der Workflow und die h\u00e4ufigsten Engp\u00e4sse erl\u00e4utert, die beim Profiling von wissenschaftlichem Python-Code auftreten k\u00f6nnen.<\/p>\n<h2>Was ist ein Profiler und warum ist es wichtig?<\/h2>\n<p>Ein Profiler ist ein Tool, das aufzeichnet, welche Funktionen Ihr Programm aufruft, wie lange jede Funktion dauert und wie oft jede Funktion aufgerufen wird. Es erstellt einen Bericht, oft im Klartext oder als interaktives visuelles Diagramm, in dem angezeigt wird, wo Ihr Code Zeit verbringt.<\/p>\n<p>Ohne Profiler optimieren Sie basierend auf der Intuition. In der Performance-Arbeit ist Intuition oft falsch. Sie k\u00f6nnen Stunden damit verbringen, eine Funktion zu verbessern, die nur einen kleinen Teil der Laufzeit ben\u00f6tigt, w\u00e4hrend Sie die Funktion ignorieren, die den gesamten Lauf dominiert.<\/p>\n<p>Mit einem Profiler sehen Sie die Daten. Sie h\u00f6ren auf zu raten und zielen auf echte Leistungsprobleme ab.<\/p>\n<h2>Der Profiling-Workflow: messen, diagnostizieren, behandeln<\/h2>\n<p>Vor der Auswahl eines Tools hilft es, den Workflow zu verstehen. Ein praktischer Profiling-Prozess besteht aus drei Stufen:<\/p>\n<ol>\n<li>messen. Verwenden Sie einen Profiler, um herauszufinden, welcher Teil des Codes tats\u00e4chlich langsam ist.<\/li>\n<li>diagnostizieren. Verstehe, warum es langsam ist. Die Ursache kann Speicherzuordnung, Algorithmusauswahl, Overhead auf Python-Ebene oder Solver-Konfiguration sein.<\/li>\n<li>behandeln Beheben Sie die Ursache, anstatt zuf\u00e4llige Optimierungen anzuwenden.<\/li>\n<\/ol>\n<p>Dies ist \u00e4hnlich wie bei einer medizinischen Diagnose. Ein Arzt beginnt nicht mit der Behandlung, bevor er die Symptome und Testergebnisse \u00fcberpr\u00fcft. Profiling funktioniert genauso. Sie messen, bevor Sie den Code \u00e4ndern.<\/p>\n<p>Ein Schl\u00fcsseldetail ist die Problemgr\u00f6\u00dfe. Ihr Profiling-Lauf sollte eine Problemgr\u00f6\u00dfe verwenden, die Ihre tats\u00e4chliche Arbeitsbelastung darstellt. Wenn Sie nur mit einem winzigen Gitter profilieren, k\u00f6nnen Sie Engp\u00e4sse verpassen, die nur im Ma\u00dfstab auftreten.<\/p>\n<h2>Python-Profiling-Tools: Das praktische Toolkit<\/h2>\n<p>Python hat mehrere n\u00fctzliche Profilierungsoptionen. F\u00fcr das wissenschaftliche Rechnen sind die folgenden Tools besonders praktisch.<\/p>\n<h3>cProfile: Eingebaut, Nullinstallation, immer verf\u00fcgbar<\/h3>\n<p><code>cProfile<\/code> wird mit jeder Python-Installation geliefert. Es handelt sich um eine C-Erweiterung, die zwischen dem Dolmetscher und Ihrem Code sitzt und Operationen mit relativ geringem Overhead z\u00e4hlt.<\/p>\n<pre><code class=\"language-python\">import cProfile\n\n# Profile a single call\ncProfile.run('equation.solve(var=phi, dt=timeStep)', 'fi_py_profile.prof')\n<\/code><\/pre>\n<p>Sie k\u00f6nnen es auch \u00fcber die Befehlszeile ausf\u00fchren:<\/p>\n<pre><code class=\"language-bash\">$ python -m cProfile -s time my_solver.py 0 1.0 0.1 1000000 output.dat | head -n 20\n<\/code><\/pre>\n<p><code>cProfile<\/code> eignet sich am besten f\u00fcr schnelles First-Pass-Profiling. Sie m\u00fcssen nichts installieren, und es kann offensichtliche Engp\u00e4sse auftreten.<\/p>\n<p>Sortieroptionen sind wichtig. <code>-s time<\/code> Zeigt die interne Zeit an. <code>-s cumulative<\/code> Zeigt die Gesamtzeit einschlie\u00dflich Unteranrufe an. <code>-s ncalls<\/code> Zeigt Anrufanzahl an. W\u00e4hlen Sie die Option, die Ihre Frage beantwortet.<\/p>\n<h3>Py-Spy: Live-Profiler mit niedrigem Overhead-Probenahme<\/h3>\n<p><code>py-spy<\/code> ist ein in Rost geschriebener Probenahmeprofiler. Es kann einen laufenden Python-Prozess \u00fcberwachen, ohne ihn neu zu starten. Sie h\u00e4ngen es an, zeichnen den Prozess auf und erhalten eine visuelle Ausgabe.<\/p>\n<pre><code class=\"language-bash\">$ pip install py-spy\n$ py-spy dump -- python my_solver.py\n$ py-spy record -o profile.svg -- python my_solver.py\n<\/code><\/pre>\n<p><code>py-spy<\/code> ist n\u00fctzlich f\u00fcr Produktionscode, langlaufende Simulationen, bei denen ein Neustart unpraktisch ist, und eine Echtzeit-Engpasserkennung.<\/p>\n<p>Wissenschaftler m\u00f6gen es oft, weil es keine Code\u00e4nderungen erfordert, das Programm nicht neu startet und einen geringen Overhead hat.<\/p>\n<h3>scalene: CPU, GPU und Speicher in einem Tool<\/h3>\n<p><code>scalene<\/code> ist ein Hochleistungs-Profiler, der die CPU-Auslastung, die GPU-Nutzung und die Speicherzuordnung misst. Es erzeugt zeilenweise Ausf\u00e4lle und kann dabei helfen, Speicherlecks zu identifizieren.<\/p>\n<pre><code class=\"language-bash\">$ pip install scalene\n$ scalene my_solver.py\n<\/code><\/pre>\n<p><code>scalene<\/code> ist n\u00fctzlich f\u00fcr GPU-beschleunigte Workloads, speicherintensive Simulationen und F\u00e4lle, in denen Sie CPU- und Speicheranalyse in einem Tool ben\u00f6tigen.<\/p>\n<p>Dies ist wichtig, da wissenschaftliche Python-Engp\u00e4sse nicht immer reine CPU-Probleme sind. Eine dichte Array-Operation kann mehr Zeit damit verbringen, tempor\u00e4re Arrays zuzuordnen, als Mathe durchzuf\u00fchren.<\/p>\n<h3>SnakeViz: Visual CProfile-Ergebnisse<\/h3>\n<p><code>cProfile<\/code> Die Ausgabe ist textbasiert. <code>SnakeViz<\/code> Konvertiert diese Ausgabe in ein interaktives visuelles Diagramm. Sie k\u00f6nnen verschachtelte Funktionsaufrufe \u00fcberpr\u00fcfen, die in verschiedenen Filialen verbrachte Zeit vergleichen und tiefe Zeitsenken schnell identifizieren.<\/p>\n<pre><code class=\"language-bash\">$ pip install snakeviz\n$ snakeviz fi_py_profile.prof\n<\/code><\/pre>\n<p><code>SnakeViz<\/code> ist n\u00fctzlich, wenn Sie den Kollaboratoren Profiling-Ergebnisse pr\u00e4sentieren, Aufrufhierarchien verstehen oder Muster finden m\u00fcssen, die in der Terminalausgabe schwer zu lesen sind.<\/p>\n<h3>line_profiler: zeilenweises Detail<\/h3>\n<p><code>line_profiler<\/code> gibt Detail auf Funktionsebene auf der einzelnen Linienebene. Es ist langsamer als <code>cProfile<\/code> , aber es zeigt genau, welche Linie teuer ist.<\/p>\n<pre><code class=\"language-python\">from line_profiler import LineProfiler\n\nlp = LineProfiler()\nlp.add_function(my_heavy_function)\nlp.enable_by_count()\n\n# Run your code\nresult = equation.solve(var=phi)\nlp.print_stats()\n<\/code><\/pre>\n<p><code>line_profiler<\/code> eignet sich am besten f\u00fcr die gr\u00fcndliche Untersuchung einer Funktion, nachdem Sie bereits wissen, welcher Teil des Programms langsam ist.<\/p>\n<h2>H\u00e4ufige PDE-Solver-Engp\u00e4sse<\/h2>\n<p>Wenn Sie Python-basierte PDE-Solver wie FIPY, Fenics oder benutzerdefinierte Implementierungen profilieren, treten h\u00e4ufig mehrere Engp\u00e4sse auf.<\/p>\n<h3>1. Overhead der Matrixbaugruppe<\/h3>\n<p>Die Matrixmontage ist eine der h\u00e4ufigsten \u00dcberraschungen. Viele Forscher erwarten, dass der Linearl\u00f6ser die Laufzeit dominiert. Stattdessen kann der Code, der die Matrix erstellt, l\u00e4nger dauern als die L\u00f6sung selbst.<\/p>\n<p>In FIPY kann die <code>equation.prepare()<\/code>-Phase einen erheblichen Anteil an der Laufzeit verbrauchen, bevor <code>equation.solve()<\/code> abgeschlossen ist. Wenn die Vorbereitungsphase dominiert, kann der Flaschenhals eher in der Python-Level-Gleichungskonstruktion als im numerischen L\u00f6ser liegen.<\/p>\n<p>M\u00f6gliche Fixstrategien sind:<\/p>\n<ul>\n<li>Batch-Operationen anstelle von Maschenvariablen in reinem Python.<\/li>\n<li>Verwenden Sie vektorisierte Quellbegriffe und vermeiden Sie Python-Schleifen.<\/li>\n<li>Betrachten Sie vollst\u00e4ndig implizite Gleichungen, wenn explizite Quellenbegriffe h\u00e4ufige kleine Zeitschrittanpassungen erzwingen.<\/li>\n<\/ul>\n<h3>2. Lineare Solver-Leistung<\/h3>\n<p>Wenn die Matrix-Assembly nicht das Hauptproblem ist, kann der lineare Solver sein. Die <code>equation.solve()<\/code>-Schritt-Delegierten arbeiten an einem Backend wie <code>scipy.sparse.linalg<\/code>, Trilinos, Pysparse oder Pyamg.<\/p>\n<p>Wenn Sie zur GPU-Beschleunigung oder einem anderen Backend wechseln, \u00fcberpr\u00fcfen Sie, wo sich der serielle Overhead befindet. Ein Solver kann isoliert schnell aussehen, verliert aber w\u00e4hrend der Matrixkonstruktion oder des Datentransfers immer noch Zeit.<\/p>\n<p>M\u00f6gliche Fixstrategien sind:<\/p>\n<ul>\n<li>Testen Sie verschiedene Solver-Backends abh\u00e4ngig von der Problemskala.<\/li>\n<li>Verwenden Sie gegebenenfalls Vorkonditionierer.<\/li>\n<li>Vergleichen Sie die gesamte Build-and-Solve-Zeit, nicht nur die Iterationszeit des Solvers.<\/li>\n<\/ul>\n<h3>3. Speicherzuordnungsmuster<\/h3>\n<p>Pythons Garbage Collector und Allocator k\u00f6nnen die Laufzeit dominieren, wenn der Code wiederholt gro\u00dfe Arrays erstellt und verwirft. Dies ist h\u00e4ufig in Zeitschrittschleifen, iterativen Solvern und Netzoperationen mit fragmentierten Datenstrukturen \u00fcblich.<\/p>\n<p>Probleme mit der Speicherzuordnung treten h\u00e4ufig auf in:<\/p>\n<ul>\n<li>Iterative L\u00f6ser mit tempor\u00e4ren Vektoren.<\/li>\n<li>Zeitschritt-Schleifen, die Arrays bei jedem Schritt neu zuordnen.<\/li>\n<li>Netzoperationen, die fragmentierte Zwischenstrukturen erzeugen.<\/li>\n<\/ul>\n<p>M\u00f6gliche Fixstrategien sind:<\/p>\n<ul>\n<li>Ordnen Sie Arrays vor Zeitschleifen vor.<\/li>\n<li>Verwenden Sie <code>tracemalloc<\/code>, um Zuordnungs-Hotspots zu identifizieren.<\/li>\n<li>Verwenden Sie <code>scalene<\/code> f\u00fcr eine breitere Speicherprofilierung.<\/li>\n<li>Vermeiden Sie das Erstellen neuer Arrays in inneren Schleifen, wenn wiederverwendbare Puffer m\u00f6glich sind.<\/li>\n<\/ul>\n<h3>4. Overhead der Python-Level-Schleife<\/h3>\n<p>Python ist schnell, wenn die Arbeit in vektorisierte Numpy-Operationen gedr\u00fcckt wird. Es ist langsam, wenn Sie Python-Objekte Zelle f\u00fcr Zelle durchlaufen. Wenn Ihre Diskretisierung die Zellen in reinem Python durchl\u00e4uft, k\u00f6nnen Sie im Vergleich zu vektorisierten Alternativen erhebliche Leistung verlieren.<\/p>\n<pre><code class=\"language-python\"># Slow: Python-level loop\nfor cell in mesh.cells:\n    value[cell] = compute_stencil(cell)\n\n# Fast: Vectorized\nstencils = compute_stencils(mesh)\nvalues = apply_stencil(stencils)\n<\/code><\/pre>\n<p>M\u00f6gliche Fixstrategien sind:<\/p>\n<ul>\n<li>Verschieben Sie Schleifen mit Tools wie Cython oder Numba in kompilierte Erweiterungen.<\/li>\n<li>Verwenden Sie die vektorisierten Operationen von FIPY anstelle der Iteration auf Python-Ebene.<\/li>\n<li>Profil zuerst, denn manchmal ist die Schleife nicht der wahre Flaschenhals.<\/li>\n<\/ul>\n<h3>5. E\/A- und Datenkonvertierung<\/h3>\n<p>I\/O-Engp\u00e4sse k\u00f6nnen bis zur Skalierung des Workflows verborgen bleiben. Wenn der Code Mesh-Daten konvertiert, Zwischenergebnisse schreibt oder gro\u00dfe Parameterdateien wiederholt liest, kann E\/A die Laufzeit dominieren.<\/p>\n<pre><code class=\"language-python\"># This might look fast in isolation\nstart = time.time()\nimport numpy as np\ndata = np.load('large_mesh_data.npy')\nprint(f\"Loading took {time.time() - start:.3f}s\")  # Outputs: 0.001s\n\n# But if you do this inside a loop 1000 times: 1000x overhead\n<\/code><\/pre>\n<p>Der Schl\u00fcssel besteht darin, den vollst\u00e4ndigen Workflow zu profilieren, nicht nur den numerischen Kernel. Wiederholtes Laden, Konvertieren und Schreiben kann leise mehr Zeit in Anspruch nehmen als erwartet.<\/p>\n<h2>Ein praktisches Profiling-Beispiel<\/h2>\n<p>Hier ist eine praktische M\u00f6glichkeit, eine FIPY-Simulation zu profilieren.<\/p>\n<pre><code class=\"language-python\">import cProfile\nimport pstats\nimport fipy as fp\n\n# Create a simple diffusion problem\nnx = 100\ndx = 0.01\nmesh = fp.GridMesh(nx, dx)\nvar = fp.CellVariable(name=\"phi\", mesh=mesh)\n\n# Set up equation\nequation = fp.TransientDiffusionTerm(var)\n\n# Profile the solve\ncProfile.run('equation.solve(var=var, dt=0.001)', 'diffusion_profile.prof')\n\n# Analyze\nwith pstats.Stats('diffusion_profile.prof') as stats:\n    stats.sort_stats('cumulative')  # or 'time', 'ncalls', etc.\n    stats.print_stats(20)  # Top 20 functions\n<\/code><\/pre>\n<p>\u00d6ffnen Sie dann das Profil in <code>SnakeViz<\/code>:<\/p>\n<pre><code class=\"language-bash\">$ snakeviz diffusion_profile.prof\n<\/code><\/pre>\n<p>Der visuelle Bericht kann zeigen:<\/p>\n<ul>\n<li>Welche Funktionszweige brauchen die meiste Zeit.<\/li>\n<li>ob der Engpass im Inneren <code>equation.solve()<\/code> oder im Vorbereitungsschritt ist.<\/li>\n<li>Wie viel Zeit wird in Numpy im Vergleich zum Code auf Python-Ebene verbracht?<\/li>\n<\/ul>\n<p>In FIPY zeigt der Vorbereitungsschritt h\u00e4ufig, dass viel Zeit damit verbracht wird, die sp\u00e4rliche Matrix aufzubauen und Randbedingungen anzuwenden, nicht in der linearen L\u00f6sung selbst. Deshalb kann die Optimierung nur des Solvers den eigentlichen Engpass \u00fcbersehen.<\/p>\n<h2>Profiling im Ma\u00dfstab: Wenn Ihre Simulation Stunden dauert<\/h2>\n<p>Die gr\u00f6\u00dfte Herausforderung beim wissenschaftlichen Profiling ist nicht immer das Werkzeug. Es ist die Laufzeit. Einige Simulationen laufen stundenlang, und die Profilierung der gesamten Produktionssimulation kann enorme Leistungen erzeugen.<\/p>\n<p>Lange Simulationen ben\u00f6tigen eine sorgf\u00e4ltigere Profilierungsstrategie.<\/p>\n<h3>Die Problemumgehung: Profilieren Sie einen verkleinerten Fall<\/h3>\n<ol>\n<li>Reduzieren Sie die Netzaufl\u00f6sung oder die Anzahl der Zeitschritte.<\/li>\n<li>F\u00fchren Sie den Profiler auf diesem kleineren Fall aus.<\/li>\n<li>Suchen Sie nach Strukturmustern, in denen Operationen proportional dominieren.<\/li>\n<li>Extrapolieren Sie sorgf\u00e4ltig, da die Proportionen auch dann gelten k\u00f6nnen, wenn sich die absoluten Zeiten \u00e4ndern.<\/li>\n<\/ol>\n<p>Es gibt eine Einschr\u00e4nkung. Kleinere F\u00e4lle k\u00f6nnen Engp\u00e4sse verbergen, die nur in gr\u00f6\u00dferem Ma\u00dfstab auftreten. Dies kann Kommunikations-Overhead in parallelen Solvern, Cache-Fehlern auf gro\u00dfen Arrays oder Speicherdruck durch dichte Zwischendarstellungen sein.<\/p>\n<h3>Die Problemumgehung: Profilieren Sie ein repr\u00e4sentatives Slice<\/h3>\n<p>Wenn Sie eine transiente Simulation mit 10.000 Zeitschritten ausf\u00fchren, m\u00fcssen Sie nicht immer den gesamten Lauf profilieren. Stattdessen:<\/p>\n<ul>\n<li>Profil nur die ersten 100 Schritte.<\/li>\n<li>F\u00fchren Sie gen\u00fcgend Iterationen aus, so dass der Profiler-Overhead im Vergleich zur tats\u00e4chlichen Arbeit gering ist.<\/li>\n<li>\u00dcberpr\u00fcfen Sie, ob die Zeitverteilung mit zunehmender Anzahl der Schritte konsistent bleibt.<\/li>\n<\/ul>\n<h2>Auswahl des richtigen Profilers f\u00fcr Ihren Anwendungsfall<\/h2>\n<table class=\"custom-table\">\n<tbody>\n<tr>\n<th>Szenario<\/th>\n<th>Empfohlenes Werkzeug<\/th>\n<th>Warum<\/th>\n<\/tr>\n<tr>\n<td>Schnellpr\u00fcfung, keine Installation<\/td>\n<td><code>cProfile<\/code><\/td>\n<td>Eingebaut, Nullinstallation, immer verf\u00fcgbar<\/td>\n<\/tr>\n<tr>\n<td>Produktionscode, kann nicht neu gestartet werden<\/td>\n<td><code>py-spy<\/code><\/td>\n<td>Kann mit minimalem Overhead an einen laufenden Prozess angeh\u00e4ngt werden<\/td>\n<\/tr>\n<tr>\n<td>GPU, CPU und Speicherprofilierung<\/td>\n<td><code>scalene<\/code><\/td>\n<td>All-in-One-, GPU-bewusste Profilierung auf Linienebene<\/td>\n<\/tr>\n<tr>\n<td>Ergebnisse f\u00fcr Kollaborateure pr\u00e4sentieren<\/td>\n<td><code>cProfile<\/code> + <code>SnakeViz<\/code><\/td>\n<td>Visuell, interaktiv und leichter zu erkl\u00e4ren<\/td>\n<\/tr>\n<tr>\n<td>tief in eine Funktion eintauchen<\/td>\n<td><code>line_profiler<\/code><\/td>\n<td>Zeile-f\u00fcr-Linie-Detail<\/td>\n<\/tr>\n<tr>\n<td>Speicherzuordnungsmuster<\/td>\n<td><code>scalene<\/code> oder <code>tracemalloc<\/code><\/td>\n<td>Verfolgt Zuweisungen, Lecks und Fragmentierung<\/td>\n<\/tr>\n<tr>\n<td>Langlaufsimulation<\/td>\n<td><code>py-spy<\/code> plus verkleinert <code>cProfile<\/code><\/td>\n<td>Geringer Overhead und repr\u00e4sentative Probenahme<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Was Sie vermeiden sollten: h\u00e4ufige Profilierungsfehler<\/h2>\n<p>Fehler 1: Profilieren eines zu kleinen Problems. Ein 10 \u00d7 10-Mesh, das in weniger als einer Sekunde endet, zeigt keine Engp\u00e4sse im Ma\u00dfstab 1000 \u00d7 1000. Profil in repr\u00e4sentativer Gr\u00f6\u00dfe, wenn m\u00f6glich.<\/p>\n<p>Fehler 2: Optimierung vor Profiling. Wenn Sie Solver \u00e4ndern, Parallelit\u00e4t hinzuf\u00fcgen oder Schleifen neu schreiben, bevor Sie Profildaten sammeln, raten Sie.<\/p>\n<p>Fehler 3: Ignorieren der Vorbereitungsphase. Viele Forscher profilieren nur <code>equation.solve()<\/code> , aber die Vorbereitung kann l\u00e4nger dauern als die L\u00f6sung. Profil die vollst\u00e4ndige Pipeline.<\/p>\n<p>Fehler 4: Verwirrung am schnellsten isoliert mit dem schnellsten Overall. Ein Solver mit weniger Iterationen kann immer noch langsamer sein, wenn er eine teure Matrixmontage oder Datenkonvertierung erfordert.<\/p>\n<p>Fehler 5: Profiling nur einmal. Profil vor der Optimierung, \u00e4ndern Sie und dann erneut Profil. Stellen Sie sicher, dass sich der Engpass tats\u00e4chlich bewegt oder verbessert hat.<\/p>\n<h2>Interne Referenzen<\/h2>\n<ul>\n<li><a href=\"https:\/\/matforge.org\/what-is-fipy-and-when-should-you-use-it\/\">Was ist FIPY und wann sollten Sie es verwenden? <\/a> &#8211; Verstehen der Architektur und der vektorisierten Operationen von FIPY.<\/li>\n<li><a href=\"https:\/\/matforge.org\/gpu-acceleration-for-fipy-simulations-cupy-and-numba-integration-guide\/\">GPU-Beschleunigung f\u00fcr FIPY-Simulationen: Cupy- und Numba-Integrationshandbuch<\/a> \u2014 Leistungs\u00fcberlegungen F\u00fcr GPU-beschleunigte Workflows.<\/li>\n<li><a href=\"https:\/\/matforge.org\/validation-and-verification-for-pde-simulations-practical-framework\/\">Validierung und Verifizierung von PDE-Simulationen: Ein praktischer Rahmen<\/a> \u2014 Sicherstellen der Ergebnisse der Solver vor der Optimierung ihnen<\/li>\n<\/ul>\n<h2>Zusammenfassung: Die richtige Reihenfolge ist wichtig<\/h2>\n<p>Beim Performance-Profiling geht es nicht darum, den schnellsten Trick zu finden. Es geht um Disziplin.<\/p>\n<ol>\n<li>messen. F\u00fchren Sie <code>cProfile<\/code>, <code>py-spy<\/code> oder <code>scalene<\/code> f\u00fcr repr\u00e4sentative Problemgr\u00f6\u00dfen aus.<\/li>\n<li>diagnostizieren. Lesen Sie die Ergebnisse sorgf\u00e4ltig durch. Die Top-Funktion ist nicht immer der eigentliche Engpass.<\/li>\n<li>behandeln Fix, was du gemessen hast, nicht was du angenommen hast.<\/li>\n<li>wieder messen. Stellen Sie sicher, dass Ihr Fix tats\u00e4chlich geholfen hat.<\/li>\n<\/ol>\n<p>Die wertvollste Erkenntnis aus der Profilerstellung ist einfach: Der langsamste Teil Ihres Codes ist selten der Teil, den Sie f\u00fcr langsam hielten. Sobald Sie Daten haben, h\u00f6rt die Optimierung auf, Vermutungen zu sein, und beginnt zu Engineering.<\/p>\n<h2>Verwandte Anleitungen<\/h2>\n<ul>\n<li><a href=\"https:\/\/pages.nist.gov\/fipy\/en\/latest\/SOLVERS.html\">FIPY-Performance-Profiling- und Solver-Engpass-Identifizierung <\/a> &#8211; NISTs FIPY-Dokumentation zu Solver-Auswahl und Leistungsmustern.<\/li>\n<li><a href=\"https:\/\/aaltoscicomp.github.io\/python-for-scicomp\/profiling\/\">Profiling Python-Code <\/a> &#8211; Leitfaden zur Messung, Diagnose und Behandlung von Leistungsproblemen.<\/li>\n<li><a href=\"https:\/\/edbennett.github.io\/high-performance-python\/05-profiling\/index.html\">Hochleistungs-Python: Profiling zur Identifizierung von Engp\u00e4ssen<\/a> \u2014 Walkthrough im Workshop-Stil vom Anfang bis zur Flamme Diagramm<\/li>\n<\/ul>\n","protected":false,"raw":"<h2>Schl\u00fcssel zum Mitnehmen<\/h2>\n<ul>\n<li>Profil vor der Optimierung. Erraten Sie nicht, welcher Teil Ihres PDE-Solvers langsam ist. Messen Sie es zuerst. Der eigentliche Engpass ist oft nicht derjenige, den Sie erwarten.<\/li>\n<li>Python-Profiler sind praktisch. Tools wie <code>cProfile<\/code>, <code>py-spy<\/code>, <code>scalene<\/code> und <code>SnakeViz<\/code> unterst\u00fctzen jeweils unterschiedliche Profilierungsanforderungen.<\/li>\n<li>Gew\u00f6hnliche PDE-Solver-Engp\u00e4sse umfassen die Matrix-Assembly, lineare Solver-Iterationen, Overhead auf Python-Ebene im Gleichungsaufbau und Speicherzuordnungsmuster.<\/li>\n<li>Der Measure-Diagnose-Treat-Workflow verwandelt vage Leistungsprobleme in konkrete, fixierbare Erkenntnisse.<\/li>\n<li>Die Skalierung \u00e4ndert das, was langsam ist. Ein L\u00f6ser, der sich auf einem kleinen Gitter schnell anf\u00fchlt, kann bei realistischen Problemgr\u00f6\u00dfen verschiedene Engp\u00e4sse aufdecken.<\/li>\n<\/ul>\n<h2>Ihr L\u00f6ser ist langsam. Was jetzt?<\/h2>\n<p>Sie richten eine Simulation ein. Du rennst es. Dann dauert es viel zu lange.<\/p>\n<p>Der nat\u00fcrliche Instinkt besteht darin, Code zu \u00e4ndern. M\u00f6glicherweise m\u00f6chten Sie Schleifen vektorisieren, Solver tauschen oder Parallelit\u00e4t hinzuf\u00fcgen. Aber es gibt ein Problem, das viele Forscher \u00fcberspringen: Sie wissen vielleicht nicht, was tats\u00e4chlich langsam ist.<\/p>\n<p>Der Teil, der wie der Engpass aussieht, kann nur einen kleinen Teil der Laufzeit dauern. In der Zwischenzeit kann ein Versteckter Matrix-Montageschritt den gr\u00f6\u00dften Teil der Ausf\u00fchrungszeit in Anspruch nehmen.<\/p>\n<p>Leistungsprofilierung ist nicht optional. Es ist einer der wichtigsten Schritte, um einen PDE-Solver schneller zu machen, und es ist einfacher, als viele Forscher in Python erwarten.<\/p>\n<p>In diesem Handbuch werden die Tools, der Workflow und die h\u00e4ufigsten Engp\u00e4sse erl\u00e4utert, die beim Profiling von wissenschaftlichem Python-Code auftreten k\u00f6nnen.<\/p>\n<h2>Was ist ein Profiler und warum ist es wichtig?<\/h2>\n<p>Ein Profiler ist ein Tool, das aufzeichnet, welche Funktionen Ihr Programm aufruft, wie lange jede Funktion dauert und wie oft jede Funktion aufgerufen wird. Es erstellt einen Bericht, oft im Klartext oder als interaktives visuelles Diagramm, in dem angezeigt wird, wo Ihr Code Zeit verbringt.<\/p>\n<p>Ohne Profiler optimieren Sie basierend auf der Intuition. In der Performance-Arbeit ist Intuition oft falsch. Sie k\u00f6nnen Stunden damit verbringen, eine Funktion zu verbessern, die nur einen kleinen Teil der Laufzeit ben\u00f6tigt, w\u00e4hrend Sie die Funktion ignorieren, die den gesamten Lauf dominiert.<\/p>\n<p>Mit einem Profiler sehen Sie die Daten. Sie h\u00f6ren auf zu raten und zielen auf echte Leistungsprobleme ab.<\/p>\n<h2>Der Profiling-Workflow: messen, diagnostizieren, behandeln<\/h2>\n<p>Vor der Auswahl eines Tools hilft es, den Workflow zu verstehen. Ein praktischer Profiling-Prozess besteht aus drei Stufen:<\/p>\n<ol>\n<li>messen. Verwenden Sie einen Profiler, um herauszufinden, welcher Teil des Codes tats\u00e4chlich langsam ist.<\/li>\n<li>diagnostizieren. Verstehe, warum es langsam ist. Die Ursache kann Speicherzuordnung, Algorithmusauswahl, Overhead auf Python-Ebene oder Solver-Konfiguration sein.<\/li>\n<li>behandeln Beheben Sie die Ursache, anstatt zuf\u00e4llige Optimierungen anzuwenden.<\/li>\n<\/ol>\n<p>Dies ist \u00e4hnlich wie bei einer medizinischen Diagnose. Ein Arzt beginnt nicht mit der Behandlung, bevor er die Symptome und Testergebnisse \u00fcberpr\u00fcft. Profiling funktioniert genauso. Sie messen, bevor Sie den Code \u00e4ndern.<\/p>\n<p>Ein Schl\u00fcsseldetail ist die Problemgr\u00f6\u00dfe. Ihr Profiling-Lauf sollte eine Problemgr\u00f6\u00dfe verwenden, die Ihre tats\u00e4chliche Arbeitsbelastung darstellt. Wenn Sie nur mit einem winzigen Gitter profilieren, k\u00f6nnen Sie Engp\u00e4sse verpassen, die nur im Ma\u00dfstab auftreten.<\/p>\n<h2>Python-Profiling-Tools: Das praktische Toolkit<\/h2>\n<p>Python hat mehrere n\u00fctzliche Profilierungsoptionen. F\u00fcr das wissenschaftliche Rechnen sind die folgenden Tools besonders praktisch.<\/p>\n<h3>cProfile: Eingebaut, Nullinstallation, immer verf\u00fcgbar<\/h3>\n<p><code>cProfile<\/code> wird mit jeder Python-Installation geliefert. Es handelt sich um eine C-Erweiterung, die zwischen dem Dolmetscher und Ihrem Code sitzt und Operationen mit relativ geringem Overhead z\u00e4hlt.<\/p>\n<pre><code class=\"language-python\">import cProfile\n\n# Profile a single call\ncProfile.run('equation.solve(var=phi, dt=timeStep)', 'fi_py_profile.prof')\n<\/code><\/pre>\n<p>Sie k\u00f6nnen es auch \u00fcber die Befehlszeile ausf\u00fchren:<\/p>\n<pre><code class=\"language-bash\">$ python -m cProfile -s time my_solver.py 0 1.0 0.1 1000000 output.dat | head -n 20\n<\/code><\/pre>\n<p><code>cProfile<\/code> eignet sich am besten f\u00fcr schnelles First-Pass-Profiling. Sie m\u00fcssen nichts installieren, und es kann offensichtliche Engp\u00e4sse auftreten.<\/p>\n<p>Sortieroptionen sind wichtig. <code>-s time<\/code> Zeigt die interne Zeit an. <code>-s cumulative<\/code> Zeigt die Gesamtzeit einschlie\u00dflich Unteranrufe an. <code>-s ncalls<\/code> Zeigt Anrufanzahl an. W\u00e4hlen Sie die Option, die Ihre Frage beantwortet.<\/p>\n<h3>Py-Spy: Live-Profiler mit niedrigem Overhead-Probenahme<\/h3>\n<p><code>py-spy<\/code> ist ein in Rost geschriebener Probenahmeprofiler. Es kann einen laufenden Python-Prozess \u00fcberwachen, ohne ihn neu zu starten. Sie h\u00e4ngen es an, zeichnen den Prozess auf und erhalten eine visuelle Ausgabe.<\/p>\n<pre><code class=\"language-bash\">$ pip install py-spy\n$ py-spy dump -- python my_solver.py\n$ py-spy record -o profile.svg -- python my_solver.py\n<\/code><\/pre>\n<p><code>py-spy<\/code> ist n\u00fctzlich f\u00fcr Produktionscode, langlaufende Simulationen, bei denen ein Neustart unpraktisch ist, und eine Echtzeit-Engpasserkennung.<\/p>\n<p>Wissenschaftler m\u00f6gen es oft, weil es keine Code\u00e4nderungen erfordert, das Programm nicht neu startet und einen geringen Overhead hat.<\/p>\n<h3>scalene: CPU, GPU und Speicher in einem Tool<\/h3>\n<p><code>scalene<\/code> ist ein Hochleistungs-Profiler, der die CPU-Auslastung, die GPU-Nutzung und die Speicherzuordnung misst. Es erzeugt zeilenweise Ausf\u00e4lle und kann dabei helfen, Speicherlecks zu identifizieren.<\/p>\n<pre><code class=\"language-bash\">$ pip install scalene\n$ scalene my_solver.py\n<\/code><\/pre>\n<p><code>scalene<\/code> ist n\u00fctzlich f\u00fcr GPU-beschleunigte Workloads, speicherintensive Simulationen und F\u00e4lle, in denen Sie CPU- und Speicheranalyse in einem Tool ben\u00f6tigen.<\/p>\n<p>Dies ist wichtig, da wissenschaftliche Python-Engp\u00e4sse nicht immer reine CPU-Probleme sind. Eine dichte Array-Operation kann mehr Zeit damit verbringen, tempor\u00e4re Arrays zuzuordnen, als Mathe durchzuf\u00fchren.<\/p>\n<h3>SnakeViz: Visual CProfile-Ergebnisse<\/h3>\n<p><code>cProfile<\/code> Die Ausgabe ist textbasiert. <code>SnakeViz<\/code> Konvertiert diese Ausgabe in ein interaktives visuelles Diagramm. Sie k\u00f6nnen verschachtelte Funktionsaufrufe \u00fcberpr\u00fcfen, die in verschiedenen Filialen verbrachte Zeit vergleichen und tiefe Zeitsenken schnell identifizieren.<\/p>\n<pre><code class=\"language-bash\">$ pip install snakeviz\n$ snakeviz fi_py_profile.prof\n<\/code><\/pre>\n<p><code>SnakeViz<\/code> ist n\u00fctzlich, wenn Sie den Kollaboratoren Profiling-Ergebnisse pr\u00e4sentieren, Aufrufhierarchien verstehen oder Muster finden m\u00fcssen, die in der Terminalausgabe schwer zu lesen sind.<\/p>\n<h3>line_profiler: zeilenweises Detail<\/h3>\n<p><code>line_profiler<\/code> gibt Detail auf Funktionsebene auf der einzelnen Linienebene. Es ist langsamer als <code>cProfile<\/code> , aber es zeigt genau, welche Linie teuer ist.<\/p>\n<pre><code class=\"language-python\">from line_profiler import LineProfiler\n\nlp = LineProfiler()\nlp.add_function(my_heavy_function)\nlp.enable_by_count()\n\n# Run your code\nresult = equation.solve(var=phi)\nlp.print_stats()\n<\/code><\/pre>\n<p><code>line_profiler<\/code> eignet sich am besten f\u00fcr die gr\u00fcndliche Untersuchung einer Funktion, nachdem Sie bereits wissen, welcher Teil des Programms langsam ist.<\/p>\n<h2>H\u00e4ufige PDE-Solver-Engp\u00e4sse<\/h2>\n<p>Wenn Sie Python-basierte PDE-Solver wie FIPY, Fenics oder benutzerdefinierte Implementierungen profilieren, treten h\u00e4ufig mehrere Engp\u00e4sse auf.<\/p>\n<h3>1. Overhead der Matrixbaugruppe<\/h3>\n<p>Die Matrixmontage ist eine der h\u00e4ufigsten \u00dcberraschungen. Viele Forscher erwarten, dass der Linearl\u00f6ser die Laufzeit dominiert. Stattdessen kann der Code, der die Matrix erstellt, l\u00e4nger dauern als die L\u00f6sung selbst.<\/p>\n<p>In FIPY kann die <code>equation.prepare()<\/code>-Phase einen erheblichen Anteil an der Laufzeit verbrauchen, bevor <code>equation.solve()<\/code> abgeschlossen ist. Wenn die Vorbereitungsphase dominiert, kann der Flaschenhals eher in der Python-Level-Gleichungskonstruktion als im numerischen L\u00f6ser liegen.<\/p>\n<p>M\u00f6gliche Fixstrategien sind:<\/p>\n<ul>\n<li>Batch-Operationen anstelle von Maschenvariablen in reinem Python.<\/li>\n<li>Verwenden Sie vektorisierte Quellbegriffe und vermeiden Sie Python-Schleifen.<\/li>\n<li>Betrachten Sie vollst\u00e4ndig implizite Gleichungen, wenn explizite Quellenbegriffe h\u00e4ufige kleine Zeitschrittanpassungen erzwingen.<\/li>\n<\/ul>\n<h3>2. Lineare Solver-Leistung<\/h3>\n<p>Wenn die Matrix-Assembly nicht das Hauptproblem ist, kann der lineare Solver sein. Die <code>equation.solve()<\/code>-Schritt-Delegierten arbeiten an einem Backend wie <code>scipy.sparse.linalg<\/code>, Trilinos, Pysparse oder Pyamg.<\/p>\n<p>Wenn Sie zur GPU-Beschleunigung oder einem anderen Backend wechseln, \u00fcberpr\u00fcfen Sie, wo sich der serielle Overhead befindet. Ein Solver kann isoliert schnell aussehen, verliert aber w\u00e4hrend der Matrixkonstruktion oder des Datentransfers immer noch Zeit.<\/p>\n<p>M\u00f6gliche Fixstrategien sind:<\/p>\n<ul>\n<li>Testen Sie verschiedene Solver-Backends abh\u00e4ngig von der Problemskala.<\/li>\n<li>Verwenden Sie gegebenenfalls Vorkonditionierer.<\/li>\n<li>Vergleichen Sie die gesamte Build-and-Solve-Zeit, nicht nur die Iterationszeit des Solvers.<\/li>\n<\/ul>\n<h3>3. Speicherzuordnungsmuster<\/h3>\n<p>Pythons Garbage Collector und Allocator k\u00f6nnen die Laufzeit dominieren, wenn der Code wiederholt gro\u00dfe Arrays erstellt und verwirft. Dies ist h\u00e4ufig in Zeitschrittschleifen, iterativen Solvern und Netzoperationen mit fragmentierten Datenstrukturen \u00fcblich.<\/p>\n<p>Probleme mit der Speicherzuordnung treten h\u00e4ufig auf in:<\/p>\n<ul>\n<li>Iterative L\u00f6ser mit tempor\u00e4ren Vektoren.<\/li>\n<li>Zeitschritt-Schleifen, die Arrays bei jedem Schritt neu zuordnen.<\/li>\n<li>Netzoperationen, die fragmentierte Zwischenstrukturen erzeugen.<\/li>\n<\/ul>\n<p>M\u00f6gliche Fixstrategien sind:<\/p>\n<ul>\n<li>Ordnen Sie Arrays vor Zeitschleifen vor.<\/li>\n<li>Verwenden Sie <code>tracemalloc<\/code>, um Zuordnungs-Hotspots zu identifizieren.<\/li>\n<li>Verwenden Sie <code>scalene<\/code> f\u00fcr eine breitere Speicherprofilierung.<\/li>\n<li>Vermeiden Sie das Erstellen neuer Arrays in inneren Schleifen, wenn wiederverwendbare Puffer m\u00f6glich sind.<\/li>\n<\/ul>\n<h3>4. Overhead der Python-Level-Schleife<\/h3>\n<p>Python ist schnell, wenn die Arbeit in vektorisierte Numpy-Operationen gedr\u00fcckt wird. Es ist langsam, wenn Sie Python-Objekte Zelle f\u00fcr Zelle durchlaufen. Wenn Ihre Diskretisierung die Zellen in reinem Python durchl\u00e4uft, k\u00f6nnen Sie im Vergleich zu vektorisierten Alternativen erhebliche Leistung verlieren.<\/p>\n<pre><code class=\"language-python\"># Slow: Python-level loop\nfor cell in mesh.cells:\n    value[cell] = compute_stencil(cell)\n\n# Fast: Vectorized\nstencils = compute_stencils(mesh)\nvalues = apply_stencil(stencils)\n<\/code><\/pre>\n<p>M\u00f6gliche Fixstrategien sind:<\/p>\n<ul>\n<li>Verschieben Sie Schleifen mit Tools wie Cython oder Numba in kompilierte Erweiterungen.<\/li>\n<li>Verwenden Sie die vektorisierten Operationen von FIPY anstelle der Iteration auf Python-Ebene.<\/li>\n<li>Profil zuerst, denn manchmal ist die Schleife nicht der wahre Flaschenhals.<\/li>\n<\/ul>\n<h3>5. E\/A- und Datenkonvertierung<\/h3>\n<p>I\/O-Engp\u00e4sse k\u00f6nnen bis zur Skalierung des Workflows verborgen bleiben. Wenn der Code Mesh-Daten konvertiert, Zwischenergebnisse schreibt oder gro\u00dfe Parameterdateien wiederholt liest, kann E\/A die Laufzeit dominieren.<\/p>\n<pre><code class=\"language-python\"># This might look fast in isolation\nstart = time.time()\nimport numpy as np\ndata = np.load('large_mesh_data.npy')\nprint(f\"Loading took {time.time() - start:.3f}s\")  # Outputs: 0.001s\n\n# But if you do this inside a loop 1000 times: 1000x overhead\n<\/code><\/pre>\n<p>Der Schl\u00fcssel besteht darin, den vollst\u00e4ndigen Workflow zu profilieren, nicht nur den numerischen Kernel. Wiederholtes Laden, Konvertieren und Schreiben kann leise mehr Zeit in Anspruch nehmen als erwartet.<\/p>\n<h2>Ein praktisches Profiling-Beispiel<\/h2>\n<p>Hier ist eine praktische M\u00f6glichkeit, eine FIPY-Simulation zu profilieren.<\/p>\n<pre><code class=\"language-python\">import cProfile\nimport pstats\nimport fipy as fp\n\n# Create a simple diffusion problem\nnx = 100\ndx = 0.01\nmesh = fp.GridMesh(nx, dx)\nvar = fp.CellVariable(name=\"phi\", mesh=mesh)\n\n# Set up equation\nequation = fp.TransientDiffusionTerm(var)\n\n# Profile the solve\ncProfile.run('equation.solve(var=var, dt=0.001)', 'diffusion_profile.prof')\n\n# Analyze\nwith pstats.Stats('diffusion_profile.prof') as stats:\n    stats.sort_stats('cumulative')  # or 'time', 'ncalls', etc.\n    stats.print_stats(20)  # Top 20 functions\n<\/code><\/pre>\n<p>\u00d6ffnen Sie dann das Profil in <code>SnakeViz<\/code>:<\/p>\n<pre><code class=\"language-bash\">$ snakeviz diffusion_profile.prof\n<\/code><\/pre>\n<p>Der visuelle Bericht kann zeigen:<\/p>\n<ul>\n<li>Welche Funktionszweige brauchen die meiste Zeit.<\/li>\n<li>ob der Engpass im Inneren <code>equation.solve()<\/code> oder im Vorbereitungsschritt ist.<\/li>\n<li>Wie viel Zeit wird in Numpy im Vergleich zum Code auf Python-Ebene verbracht?<\/li>\n<\/ul>\n<p>In FIPY zeigt der Vorbereitungsschritt h\u00e4ufig, dass viel Zeit damit verbracht wird, die sp\u00e4rliche Matrix aufzubauen und Randbedingungen anzuwenden, nicht in der linearen L\u00f6sung selbst. Deshalb kann die Optimierung nur des Solvers den eigentlichen Engpass \u00fcbersehen.<\/p>\n<h2>Profiling im Ma\u00dfstab: Wenn Ihre Simulation Stunden dauert<\/h2>\n<p>Die gr\u00f6\u00dfte Herausforderung beim wissenschaftlichen Profiling ist nicht immer das Werkzeug. Es ist die Laufzeit. Einige Simulationen laufen stundenlang, und die Profilierung der gesamten Produktionssimulation kann enorme Leistungen erzeugen.<\/p>\n<p>Lange Simulationen ben\u00f6tigen eine sorgf\u00e4ltigere Profilierungsstrategie.<\/p>\n<h3>Die Problemumgehung: Profilieren Sie einen verkleinerten Fall<\/h3>\n<ol>\n<li>Reduzieren Sie die Netzaufl\u00f6sung oder die Anzahl der Zeitschritte.<\/li>\n<li>F\u00fchren Sie den Profiler auf diesem kleineren Fall aus.<\/li>\n<li>Suchen Sie nach Strukturmustern, in denen Operationen proportional dominieren.<\/li>\n<li>Extrapolieren Sie sorgf\u00e4ltig, da die Proportionen auch dann gelten k\u00f6nnen, wenn sich die absoluten Zeiten \u00e4ndern.<\/li>\n<\/ol>\n<p>Es gibt eine Einschr\u00e4nkung. Kleinere F\u00e4lle k\u00f6nnen Engp\u00e4sse verbergen, die nur in gr\u00f6\u00dferem Ma\u00dfstab auftreten. Dies kann Kommunikations-Overhead in parallelen Solvern, Cache-Fehlern auf gro\u00dfen Arrays oder Speicherdruck durch dichte Zwischendarstellungen sein.<\/p>\n<h3>Die Problemumgehung: Profilieren Sie ein repr\u00e4sentatives Slice<\/h3>\n<p>Wenn Sie eine transiente Simulation mit 10.000 Zeitschritten ausf\u00fchren, m\u00fcssen Sie nicht immer den gesamten Lauf profilieren. Stattdessen:<\/p>\n<ul>\n<li>Profil nur die ersten 100 Schritte.<\/li>\n<li>F\u00fchren Sie gen\u00fcgend Iterationen aus, so dass der Profiler-Overhead im Vergleich zur tats\u00e4chlichen Arbeit gering ist.<\/li>\n<li>\u00dcberpr\u00fcfen Sie, ob die Zeitverteilung mit zunehmender Anzahl der Schritte konsistent bleibt.<\/li>\n<\/ul>\n<h2>Auswahl des richtigen Profilers f\u00fcr Ihren Anwendungsfall<\/h2>\n<table class=\"custom-table\">\n<tbody><tr>\n<th>Szenario<\/th>\n<th>Empfohlenes Werkzeug<\/th>\n<th>Warum<\/th>\n<\/tr>\n<tr>\n<td>Schnellpr\u00fcfung, keine Installation<\/td>\n<td><code>cProfile<\/code><\/td>\n<td>Eingebaut, Nullinstallation, immer verf\u00fcgbar<\/td>\n<\/tr>\n<tr>\n<td>Produktionscode, kann nicht neu gestartet werden<\/td>\n<td><code>py-spy<\/code><\/td>\n<td>Kann mit minimalem Overhead an einen laufenden Prozess angeh\u00e4ngt werden<\/td>\n<\/tr>\n<tr>\n<td>GPU, CPU und Speicherprofilierung<\/td>\n<td><code>scalene<\/code><\/td>\n<td>All-in-One-, GPU-bewusste Profilierung auf Linienebene<\/td>\n<\/tr>\n<tr>\n<td>Ergebnisse f\u00fcr Kollaborateure pr\u00e4sentieren<\/td>\n<td><code>cProfile<\/code> + <code>SnakeViz<\/code><\/td>\n<td>Visuell, interaktiv und leichter zu erkl\u00e4ren<\/td>\n<\/tr>\n<tr>\n<td>tief in eine Funktion eintauchen<\/td>\n<td><code>line_profiler<\/code><\/td>\n<td>Zeile-f\u00fcr-Linie-Detail<\/td>\n<\/tr>\n<tr>\n<td>Speicherzuordnungsmuster<\/td>\n<td><code>scalene<\/code> oder <code>tracemalloc<\/code><\/td>\n<td>Verfolgt Zuweisungen, Lecks und Fragmentierung<\/td>\n<\/tr>\n<tr>\n<td>Langlaufsimulation<\/td>\n<td><code>py-spy<\/code> plus verkleinert <code>cProfile<\/code><\/td>\n<td>Geringer Overhead und repr\u00e4sentative Probenahme<\/td>\n<\/tr>\n<\/tbody><\/table>\n<h2>Was Sie vermeiden sollten: h\u00e4ufige Profilierungsfehler<\/h2>\n<p>Fehler 1: Profilieren eines zu kleinen Problems. Ein 10 \u00d7 10-Mesh, das in weniger als einer Sekunde endet, zeigt keine Engp\u00e4sse im Ma\u00dfstab 1000 \u00d7 1000. Profil in repr\u00e4sentativer Gr\u00f6\u00dfe, wenn m\u00f6glich.<\/p>\n<p>Fehler 2: Optimierung vor Profiling. Wenn Sie Solver \u00e4ndern, Parallelit\u00e4t hinzuf\u00fcgen oder Schleifen neu schreiben, bevor Sie Profildaten sammeln, raten Sie.<\/p>\n<p>Fehler 3: Ignorieren der Vorbereitungsphase. Viele Forscher profilieren nur <code>equation.solve()<\/code> , aber die Vorbereitung kann l\u00e4nger dauern als die L\u00f6sung. Profil die vollst\u00e4ndige Pipeline.<\/p>\n<p>Fehler 4: Verwirrung am schnellsten isoliert mit dem schnellsten Overall. Ein Solver mit weniger Iterationen kann immer noch langsamer sein, wenn er eine teure Matrixmontage oder Datenkonvertierung erfordert.<\/p>\n<p>Fehler 5: Profiling nur einmal. Profil vor der Optimierung, \u00e4ndern Sie und dann erneut Profil. Stellen Sie sicher, dass sich der Engpass tats\u00e4chlich bewegt oder verbessert hat.<\/p>\n<h2>Interne Referenzen<\/h2>\n<ul>\n<li><a href=\"https:\/\/matforge.org\/what-is-fipy-and-when-should-you-use-it\/\">Was ist FIPY und wann sollten Sie es verwenden? <\/a> - Verstehen der Architektur und der vektorisierten Operationen von FIPY.<\/li>\n<li><a href=\"https:\/\/matforge.org\/gpu-acceleration-for-fipy-simulations-cupy-and-numba-integration-guide\/\">GPU-Beschleunigung f\u00fcr FIPY-Simulationen: Cupy- und Numba-Integrationshandbuch<\/a> \u2014 Leistungs\u00fcberlegungen F\u00fcr GPU-beschleunigte Workflows.<\/li>\n<li><a href=\"https:\/\/matforge.org\/validation-and-verification-for-pde-simulations-practical-framework\/\">Validierung und Verifizierung von PDE-Simulationen: Ein praktischer Rahmen<\/a> \u2014 Sicherstellen der Ergebnisse der Solver vor der Optimierung ihnen<\/li>\n<\/ul>\n<h2>Zusammenfassung: Die richtige Reihenfolge ist wichtig<\/h2>\n<p>Beim Performance-Profiling geht es nicht darum, den schnellsten Trick zu finden. Es geht um Disziplin.<\/p>\n<ol>\n<li>messen. F\u00fchren Sie <code>cProfile<\/code>, <code>py-spy<\/code> oder <code>scalene<\/code> f\u00fcr repr\u00e4sentative Problemgr\u00f6\u00dfen aus.<\/li>\n<li>diagnostizieren. Lesen Sie die Ergebnisse sorgf\u00e4ltig durch. Die Top-Funktion ist nicht immer der eigentliche Engpass.<\/li>\n<li>behandeln Fix, was du gemessen hast, nicht was du angenommen hast.<\/li>\n<li>wieder messen. Stellen Sie sicher, dass Ihr Fix tats\u00e4chlich geholfen hat.<\/li>\n<\/ol>\n<p>Die wertvollste Erkenntnis aus der Profilerstellung ist einfach: Der langsamste Teil Ihres Codes ist selten der Teil, den Sie f\u00fcr langsam hielten. Sobald Sie Daten haben, h\u00f6rt die Optimierung auf, Vermutungen zu sein, und beginnt zu Engineering.<\/p>\n<h2>Verwandte Anleitungen<\/h2>\n<ul>\n<li><a href=\"https:\/\/pages.nist.gov\/fipy\/en\/latest\/SOLVERS.html\">FIPY-Performance-Profiling- und Solver-Engpass-Identifizierung <\/a> - NISTs FIPY-Dokumentation zu Solver-Auswahl und Leistungsmustern.<\/li>\n<li><a href=\"https:\/\/aaltoscicomp.github.io\/python-for-scicomp\/profiling\/\">Profiling Python-Code <\/a> - Leitfaden zur Messung, Diagnose und Behandlung von Leistungsproblemen.<\/li>\n<li><a href=\"https:\/\/edbennett.github.io\/high-performance-python\/05-profiling\/index.html\">Hochleistungs-Python: Profiling zur Identifizierung von Engp\u00e4ssen<\/a> \u2014 Walkthrough im Workshop-Stil vom Anfang bis zur Flamme Diagramm<\/li>\n<\/ul>\n"},"excerpt":{"rendered":"<p><span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Reading Time: <\/span> <span class=\"rt-time\"> 8<\/span> <span class=\"rt-label rt-postfix\">minutes<\/span><\/span>Schl\u00fcssel zum Mitnehmen Profil vor der Optimierung. Erraten Sie nicht, welcher Teil Ihres PDE-Solvers langsam ist. Messen Sie es zuerst. Der eigentliche Engpass ist oft nicht derjenige, den Sie erwarten. Python-Profiler sind praktisch. Tools wie cProfile, py-spy, scalene und SnakeViz unterst\u00fctzen jeweils unterschiedliche Profilierungsanforderungen. Gew\u00f6hnliche PDE-Solver-Engp\u00e4sse umfassen die Matrix-Assembly, lineare Solver-Iterationen, Overhead auf Python-Ebene im [&hellip;]<\/p>\n","protected":false,"raw":""},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_locale":"de_DE","_original_post":"https:\/\/matforge.org\/?p=388","iawp_total_views":2,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-862","post","type-post","status-publish","format-standard","hentry","category-simulation-modeling-projects","de-DE"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Leistungsprofilierung f\u00fcr Python PDE-Solver<\/title>\n<meta name=\"description\" content=\"Erfahren Sie, wie Sie Python-PDE-Solver profilieren, Engp\u00e4sse identifizieren, Profiling-Tools vergleichen und wissenschaftliche Rechnerworkflows optimieren.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/matforge.org\/de\/scientific-computing-performance-profiling-identifying-bottlenecks\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Leistungsprofilierung f\u00fcr Python PDE-Solver\" \/>\n<meta property=\"og:description\" content=\"Erfahren Sie, wie Sie Python-PDE-Solver profilieren, Engp\u00e4sse identifizieren, Profiling-Tools vergleichen und wissenschaftliche Rechnerworkflows optimieren.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/matforge.org\/de\/scientific-computing-performance-profiling-identifying-bottlenecks\/\" \/>\n<meta property=\"og:site_name\" content=\"matforge.org\" \/>\n<meta property=\"article:published_time\" content=\"2026-07-30T12:23:29+00:00\" \/>\n<meta name=\"author\" content=\"Elena Markovska\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Elena Markovska\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"12\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/matforge.org\\\/de\\\/scientific-computing-performance-profiling-identifying-bottlenecks\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/matforge.org\\\/de\\\/scientific-computing-performance-profiling-identifying-bottlenecks\\\/\"},\"author\":{\"name\":\"Elena Markovska\",\"@id\":\"https:\\\/\\\/matforge.org\\\/#\\\/schema\\\/person\\\/980162bb5de46742daece973661d93da\"},\"headline\":\"Profiling der wissenschaftlichen Rechnerleistung: Identifizierung von Engp\u00e4ssen bei PDE-Solvern\",\"datePublished\":\"2026-07-30T12:23:29+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/matforge.org\\\/de\\\/scientific-computing-performance-profiling-identifying-bottlenecks\\\/\"},\"wordCount\":2061,\"commentCount\":0,\"articleSection\":[\"Simulation & amp; Modellierungsprojekte\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/matforge.org\\\/de\\\/scientific-computing-performance-profiling-identifying-bottlenecks\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/matforge.org\\\/de\\\/scientific-computing-performance-profiling-identifying-bottlenecks\\\/\",\"url\":\"https:\\\/\\\/matforge.org\\\/de\\\/scientific-computing-performance-profiling-identifying-bottlenecks\\\/\",\"name\":\"Leistungsprofilierung f\u00fcr Python PDE-Solver\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/matforge.org\\\/#website\"},\"datePublished\":\"2026-07-30T12:23:29+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/matforge.org\\\/#\\\/schema\\\/person\\\/980162bb5de46742daece973661d93da\"},\"description\":\"Erfahren Sie, wie Sie Python-PDE-Solver profilieren, Engp\u00e4sse identifizieren, Profiling-Tools vergleichen und wissenschaftliche Rechnerworkflows optimieren.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/matforge.org\\\/de\\\/scientific-computing-performance-profiling-identifying-bottlenecks\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/matforge.org\\\/de\\\/scientific-computing-performance-profiling-identifying-bottlenecks\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/matforge.org\\\/de\\\/scientific-computing-performance-profiling-identifying-bottlenecks\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/matforge.org\\\/de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Profiling der wissenschaftlichen Rechnerleistung: Identifizierung von Engp\u00e4ssen bei PDE-Solvern\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/matforge.org\\\/#website\",\"url\":\"https:\\\/\\\/matforge.org\\\/\",\"name\":\"matforge.org\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/matforge.org\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/matforge.org\\\/#\\\/schema\\\/person\\\/980162bb5de46742daece973661d93da\",\"name\":\"Elena Markovska\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2de4e35b6581d7d8a839335156c6b5834cfaa0aef537a1c837e882dc57eea1e7?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2de4e35b6581d7d8a839335156c6b5834cfaa0aef537a1c837e882dc57eea1e7?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2de4e35b6581d7d8a839335156c6b5834cfaa0aef537a1c837e882dc57eea1e7?s=96&d=mm&r=g\",\"caption\":\"Elena Markovska\"},\"sameAs\":[\"http:\\\/\\\/matforge.org\"],\"url\":\"https:\\\/\\\/matforge.org\\\/author\\\/elena-markovska\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Leistungsprofilierung f\u00fcr Python PDE-Solver","description":"Erfahren Sie, wie Sie Python-PDE-Solver profilieren, Engp\u00e4sse identifizieren, Profiling-Tools vergleichen und wissenschaftliche Rechnerworkflows optimieren.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/matforge.org\/de\/scientific-computing-performance-profiling-identifying-bottlenecks\/","og_locale":"de_DE","og_type":"article","og_title":"Leistungsprofilierung f\u00fcr Python PDE-Solver","og_description":"Erfahren Sie, wie Sie Python-PDE-Solver profilieren, Engp\u00e4sse identifizieren, Profiling-Tools vergleichen und wissenschaftliche Rechnerworkflows optimieren.","og_url":"https:\/\/matforge.org\/de\/scientific-computing-performance-profiling-identifying-bottlenecks\/","og_site_name":"matforge.org","article_published_time":"2026-07-30T12:23:29+00:00","author":"Elena Markovska","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Elena Markovska","Gesch\u00e4tzte Lesezeit":"12\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/matforge.org\/de\/scientific-computing-performance-profiling-identifying-bottlenecks\/#article","isPartOf":{"@id":"https:\/\/matforge.org\/de\/scientific-computing-performance-profiling-identifying-bottlenecks\/"},"author":{"name":"Elena Markovska","@id":"https:\/\/matforge.org\/#\/schema\/person\/980162bb5de46742daece973661d93da"},"headline":"Profiling der wissenschaftlichen Rechnerleistung: Identifizierung von Engp\u00e4ssen bei PDE-Solvern","datePublished":"2026-07-30T12:23:29+00:00","mainEntityOfPage":{"@id":"https:\/\/matforge.org\/de\/scientific-computing-performance-profiling-identifying-bottlenecks\/"},"wordCount":2061,"commentCount":0,"articleSection":["Simulation & amp; Modellierungsprojekte"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/matforge.org\/de\/scientific-computing-performance-profiling-identifying-bottlenecks\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/matforge.org\/de\/scientific-computing-performance-profiling-identifying-bottlenecks\/","url":"https:\/\/matforge.org\/de\/scientific-computing-performance-profiling-identifying-bottlenecks\/","name":"Leistungsprofilierung f\u00fcr Python PDE-Solver","isPartOf":{"@id":"https:\/\/matforge.org\/#website"},"datePublished":"2026-07-30T12:23:29+00:00","author":{"@id":"https:\/\/matforge.org\/#\/schema\/person\/980162bb5de46742daece973661d93da"},"description":"Erfahren Sie, wie Sie Python-PDE-Solver profilieren, Engp\u00e4sse identifizieren, Profiling-Tools vergleichen und wissenschaftliche Rechnerworkflows optimieren.","breadcrumb":{"@id":"https:\/\/matforge.org\/de\/scientific-computing-performance-profiling-identifying-bottlenecks\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/matforge.org\/de\/scientific-computing-performance-profiling-identifying-bottlenecks\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/matforge.org\/de\/scientific-computing-performance-profiling-identifying-bottlenecks\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/matforge.org\/de\/"},{"@type":"ListItem","position":2,"name":"Profiling der wissenschaftlichen Rechnerleistung: Identifizierung von Engp\u00e4ssen bei PDE-Solvern"}]},{"@type":"WebSite","@id":"https:\/\/matforge.org\/#website","url":"https:\/\/matforge.org\/","name":"matforge.org","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/matforge.org\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Person","@id":"https:\/\/matforge.org\/#\/schema\/person\/980162bb5de46742daece973661d93da","name":"Elena Markovska","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/2de4e35b6581d7d8a839335156c6b5834cfaa0aef537a1c837e882dc57eea1e7?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/2de4e35b6581d7d8a839335156c6b5834cfaa0aef537a1c837e882dc57eea1e7?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/2de4e35b6581d7d8a839335156c6b5834cfaa0aef537a1c837e882dc57eea1e7?s=96&d=mm&r=g","caption":"Elena Markovska"},"sameAs":["http:\/\/matforge.org"],"url":"https:\/\/matforge.org\/author\/elena-markovska\/"}]}},"_links":{"self":[{"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/posts\/862","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/comments?post=862"}],"version-history":[{"count":1,"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/posts\/862\/revisions"}],"predecessor-version":[{"id":1046,"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/posts\/862\/revisions\/1046"}],"wp:attachment":[{"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/media?parent=862"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/categories?post=862"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/matforge.org\/wp-json\/wp\/v2\/tags?post=862"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}