<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>About on IOPS</title><link>https://iops.gitlabpages.inria.fr/about/</link><description>Recent content in About on IOPS</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://iops.gitlabpages.inria.fr/about/index.xml" rel="self" type="application/rss+xml"/><item><title>Design Philosophy</title><link>https://iops.gitlabpages.inria.fr/about/philosophy/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://iops.gitlabpages.inria.fr/about/philosophy/</guid><description>&lt;p>Five design principles guide IOPS development. They explain why IOPS looks the way it does and what trade-offs were chosen.&lt;/p>
&lt;h2 id="1-one-yaml-to-rule-them-all">1. One YAML to Rule Them All&lt;/h2>
&lt;p>A single, self-contained specification captures the complete benchmark lifecycle: workload definition, parameter space, run rules, environment, and validation criteria. You should never need a second file, a sidecar script, or a hidden environment variable to understand what a study does. The YAML is the source of truth.&lt;/p></description></item><item><title>Contributing to IOPS</title><link>https://iops.gitlabpages.inria.fr/about/contributing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://iops.gitlabpages.inria.fr/about/contributing/</guid><description>&lt;p>Guidelines for contributing to IOPS.&lt;/p>
&lt;h2 id="getting-started">Getting Started&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Fork the Repository&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Clone your fork&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git clone https://gitlab.inria.fr/YOUR_USERNAME/iops.git
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cd iops
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;strong>Set Up Development Environment&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Create virtual environment&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>python3 -m venv iops_env
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>source iops_env/bin/activate
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Install in editable mode&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>pip install -e .
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Install development dependencies&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>pip install -r requirements-dev.txt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Verify the setup&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>pytest tests/
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ol>
&lt;h2 id="development-workflow">Development Workflow&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Create a Branch&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>git checkout -b feature/my-new-feature
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># or&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git checkout -b fix/issue-description
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;strong>Make Changes&lt;/strong>&lt;/p></description></item><item><title>Deprecations</title><link>https://iops.gitlabpages.inria.fr/about/deprecations/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://iops.gitlabpages.inria.fr/about/deprecations/</guid><description>&lt;p>This page lists deprecated features and provides migration guidance.&lt;/p>
&lt;h2 id="backwards-compatibility-policy">Backwards Compatibility Policy&lt;/h2>
&lt;p>IOPS follows a &lt;strong>2 minor version deprecation cycle&lt;/strong>:&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Version&lt;/th>
 &lt;th>Behavior&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>N&lt;/td>
 &lt;td>Feature deprecated with warning, old behavior still works&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>N+1&lt;/td>
 &lt;td>Warning remains, old behavior still works&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>N+2&lt;/td>
 &lt;td>Feature removed, error with migration guidance&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>This gives users at least two releases to migrate their configurations.&lt;/p>
&lt;h2 id="current-deprecations">Current Deprecations&lt;/h2>
&lt;h3 id="benchmarkexecutor_options--benchmarkslurm_options">&lt;code>benchmark.executor_options&lt;/code> → &lt;code>benchmark.slurm_options&lt;/code>&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>&lt;/th>
 &lt;th>&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;strong>Deprecated in&lt;/strong>&lt;/td>
 &lt;td>3.5.0&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>Remove after&lt;/strong>&lt;/td>
 &lt;td>3.7.0&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>Reason&lt;/strong>&lt;/td>
 &lt;td>Renamed for clarity (options are SLURM-specific)&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>Before:&lt;/strong>&lt;/p></description></item><item><title>Changelog</title><link>https://iops.gitlabpages.inria.fr/about/changelog/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://iops.gitlabpages.inria.fr/about/changelog/</guid><description>&lt;p>All notable changes to IOPS are documented here.&lt;/p>
&lt;h2 id="3510---2026-10-26">[3.5.10] - 2026-10-26&lt;/h2>
&lt;h3 id="added">Added&lt;/h3>
&lt;ul>
&lt;li>&lt;code>iops deps&lt;/code> lists the optional dependencies, what each one enables, and whether it is installed, so the packages behind Bayesian search, Parquet sinks, watch mode, plot export, gallery downscaling, and Studio can be checked in one place instead of by triggering the feature and reading the error. &lt;code>--missing&lt;/code> narrows the table to what is absent, and &lt;code>--check&lt;/code> exits with status 1 when anything is missing, for use in CI. The same catalog now backs the availability flags inside IOPS: &lt;code>iops/deps.py&lt;/code> holds one entry per extra and the modules that gate on a package call &lt;code>is_available()&lt;/code> instead of carrying their own try/except, so the command and the runtime cannot disagree about what is installed. Detection uses each package&amp;rsquo;s import name rather than its distribution name, which is why Pillow (imported as &lt;code>PIL&lt;/code>) is reported correctly. Every install hint IOPS prints now quotes the package spec (&lt;code>pip install &amp;quot;iops-benchmark[bayesian]&amp;quot;&lt;/code>), because zsh treats the square brackets of an extra as a glob and rejects the unquoted form with &lt;code>no matches found&lt;/code>. A test asserts no source file emits an unquoted hint.&lt;/li>
&lt;li>&lt;code>xaxis_range&lt;/code> and &lt;code>yaxis_range&lt;/code> set explicit limits on a report plot&amp;rsquo;s axes, as &lt;code>[min, max]&lt;/code>, instead of leaving the zoom to Plotly. Both are written in data units even when the axis is logarithmic (&lt;code>yaxis_range: [1e-6, 1e-2]&lt;/code> with &lt;code>log_y: true&lt;/code> shows 10^-6 to 10^-2), since the conversion to powers of ten happens at render time. This makes several plots directly comparable on identical axes, lets a bar chart be pinned to zero, and allows zooming into a band of interest. The bounds must be numbers with min below max, and on a logarithmic axis the lower bound must be positive, because such an axis cannot represent zero. When a range is set, the decade tick rule reads the range rather than the data. The options are also available in the Studio plot editor.&lt;/li>
&lt;li>&lt;strong>Hooks&lt;/strong> run a command of your choice when something happens during a run, which makes a long run on a cluster easy to follow without watching the terminal. A top-level &lt;code>hooks:&lt;/code> list names an &lt;code>event&lt;/code> (&lt;code>start&lt;/code>, &lt;code>progress&lt;/code>, &lt;code>failures&lt;/code>, &lt;code>consecutive_failures&lt;/code>, or &lt;code>finish&lt;/code>), says when it fires with &lt;code>at&lt;/code> (one-shot thresholds) and/or &lt;code>every&lt;/code> (a repeating threshold), and gives a &lt;code>command&lt;/code>. Thresholds are an integer count or a percentage string such as &lt;code>&amp;quot;25%&amp;quot;&lt;/code>, counted in attempts (executions times repetitions). A &lt;code>failures&lt;/code> percentage is the failure rate among tests that ran and is held back until &lt;code>min_tests&lt;/code> have run (default 10, lowered on small runs), &lt;code>consecutive_failures&lt;/code> re-arms after a success, and &lt;code>finish&lt;/code> hooks can be restricted with &lt;code>when&lt;/code> to the outcomes &lt;code>completed&lt;/code>, &lt;code>interrupted&lt;/code>, &lt;code>budget_exceeded&lt;/code>, &lt;code>fail_fast&lt;/code>, or &lt;code>crashed&lt;/code>. The command is a Jinja2 template rendered against the run context (&lt;code>progress&lt;/code>, &lt;code>run&lt;/code>, &lt;code>benchmark.name&lt;/code>, &lt;code>workdir&lt;/code>, &lt;code>report_path&lt;/code>, &lt;code>hostname&lt;/code>, &lt;code>os_env&lt;/code>, and a ready-made &lt;code>message&lt;/code>), with a &lt;code>quote&lt;/code> filter for the shell, and the same values are exported as &lt;code>IOPS_*&lt;/code> environment variables for scripts. Commands run with bash on the host running IOPS, in the background and in order, each in its own session with a &lt;code>timeout&lt;/code> (default 60 seconds), so a slow or failing hook is logged as a warning and never affects the run, and &lt;code>finish&lt;/code> waits for pending hooks before IOPS exits. Output goes to &lt;code>__iops_hooks.log&lt;/code> in the run directory. Hooks are listed but not fired by &lt;code>--dry-run&lt;/code>, &lt;code>iops run --no-hooks&lt;/code> disables them, and &lt;code>hooks&lt;/code> can be overridden per entry under &lt;code>machines&lt;/code>. &lt;code>iops check&lt;/code> renders every hook command against a sample context to catch misspelled names, and &lt;code>iops hooks test config.yaml&lt;/code> (with &lt;code>--hook&lt;/code>, &lt;code>--event&lt;/code>, &lt;code>--render-only&lt;/code>, and &lt;code>--machine&lt;/code>) runs the commands once so a mail command can be tried before a long run. A bare &lt;code>on:&lt;/code> key is rejected with a pointer to &lt;code>event:&lt;/code>, because YAML reads it as a boolean. See the &lt;a href="https://iops.gitlabpages.inria.fr/iops/user-guide/hooks/">Hooks guide&lt;/a> and &lt;code>examples/hooks/hooks.yaml&lt;/code>.&lt;/li>
&lt;/ul>
&lt;h3 id="changed">Changed&lt;/h3>
&lt;ul>
&lt;li>Every IOPS command starts about twice as fast. Deciding whether an optional package was installed was done by importing it, and importing scikit-optimize pulls in scikit-learn and SciPy behind it, which cost roughly 0.8 seconds. That was paid on every invocation to set a boolean, including &lt;code>iops --version&lt;/code> and &lt;code>iops find&lt;/code>, whether or not the run used Bayesian search. The availability gates now locate a module instead of executing it, which measures as no cost at all, taking startup from about 1.0 to about 0.45 seconds; the remainder is pandas, reached through the results writer. &lt;code>iops deps&lt;/code> still performs a real import, since there the answer is the product and a package that is installed but broken should be reported as missing. This became a one-line change because the gates had already moved behind a single catalog.&lt;/li>
&lt;li>A logarithmic axis (&lt;code>log_x&lt;/code>, &lt;code>log_y&lt;/code>) whose data spans two decades or more is now labelled once per decade, as a power of ten. Plotly labels minor log ticks by default, so an axis covering four decades read &lt;code>2, 0.001, 5, 2, 100µ, 5, 2, 10µ&lt;/code>, mixing minor labels in with the decade marks. Data confined to less than two decades keeps the automatic ticks: those labels are ordinary numbers, and a decade rule would leave such an axis with a single label or none at all, since its whole range can sit between two powers of ten.&lt;/li>
&lt;/ul>
&lt;h3 id="fixed">Fixed&lt;/h3>
&lt;ul>
&lt;li>The &lt;code>report_config.yaml&lt;/code> written after a run dropped most plot options: only &lt;code>type&lt;/code>, &lt;code>x_var&lt;/code>, &lt;code>y_var&lt;/code>, &lt;code>group_by&lt;/code>, &lt;code>title&lt;/code>, and &lt;code>colorscale&lt;/code> were kept, so &lt;code>log_x&lt;/code>, &lt;code>log_y&lt;/code>, axis labels, sizes, error-bar and outlier toggles, &lt;code>z_metric&lt;/code>, &lt;code>color_by&lt;/code>, &lt;code>size_by&lt;/code>, and the coverage heatmap options were lost. Because &lt;code>iops report&lt;/code> auto-loads that file in preference to the run metadata, a regenerated report silently ignored them, even though the report produced at the end of the run honored them. Every non-default plot field is now written, for both &lt;code>reporting.metrics&lt;/code> plots and &lt;code>reporting.default_plots&lt;/code>. Runs created with an earlier version keep the truncated file; restore the missing options by hand, or delete the file so &lt;code>iops report&lt;/code> falls back to the configuration stored in the run metadata.&lt;/li>
&lt;li>Bar plot value labels used two decimal places, so metrics below 0.005 were all labeled &lt;code>0.00&lt;/code>. Labels now show three significant digits (&lt;code>0.000956&lt;/code>).&lt;/li>
&lt;li>With &lt;code>fail_fast&lt;/code> enabled, the core-hours of the test that stopped the run were not added to the total, because the run stopped before they were counted. They are now included, so the budget total and hooks see the full cost.&lt;/li>
&lt;li>The automatic HTML report produced at the end of a run now includes resource sampling data. It was generated before the run metadata was finalized and &lt;code>__iops_resource_summary.csv&lt;/code> was written, so custom plots on resource metrics (such as &lt;code>gpu_avg_utilization_pct&lt;/code>) reported &amp;ldquo;not found in results&amp;rdquo;, and the Resource Sampling table, System Environment section, and total runtime were missing until the report was regenerated with &lt;code>iops report&lt;/code>. The report is now built as the last step of a run that completes normally.&lt;/li>
&lt;li>The version probe wrote an &lt;code>__iops_versions.json&lt;/code> that no JSON parser could read whenever a version command printed more than one line on macOS or BSD, or printed a tab on any system. Its escaping relied on a GNU-only &lt;code>sed&lt;/code> idiom and a tab substitution that never took effect. Escaping now uses bash parameter expansion and produces identical, valid output on bash 3.2 and 5.x.&lt;/li>
&lt;li>Studio no longer hangs on targets whose terminal truncates long input lines. Every command was sent as a single line, so one longer than the target tty&amp;rsquo;s input buffer was cut short and the shell waited forever for the missing newline, leaving the session unusable. Environment discovery hit this on clusters such as PLAFRIM, which truncate at 1024 bytes. Commands that would exceed the budget are now streamed to a temporary script on the target and invoked with a short line (sourced, so &lt;code>module load&lt;/code> and &lt;code>export&lt;/code> still persist). Streamed transfers to macOS and BSD targets also work now: they decoded with &lt;code>base64 -d &amp;quot;$file&amp;quot;&lt;/code>, which BSD &lt;code>base64&lt;/code> rejects.&lt;/li>
&lt;/ul>
&lt;h2 id="359---2026-08-19">[3.5.9] - 2026-08-19&lt;/h2>
&lt;h3 id="added-1">Added&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>IOPS Studio&lt;/strong> (experimental): a local web UI for using IOPS end to end, launched with &lt;code>iops studio&lt;/code> (requires the optional &lt;code>nicegui&lt;/code> dependency). See the &lt;a href="https://iops.gitlabpages.inria.fr/iops/getting-started/studio/">Getting Started guide&lt;/a>.&lt;/p></description></item><item><title>License</title><link>https://iops.gitlabpages.inria.fr/about/license/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://iops.gitlabpages.inria.fr/about/license/</guid><description>&lt;p>IOPS is licensed under the BSD 3-Clause License.&lt;/p>
&lt;h2 id="bsd-3-clause-license">BSD 3-Clause License&lt;/h2>
&lt;p>Copyright (c) 2024-2025, TADaaM - INRIA Bordeaux
All rights reserved.&lt;/p>
&lt;p>Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.&lt;/p></description></item></channel></rss>