<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Cuda on Lessons learned</title><link>https://eghuro.cz/tags/cuda/</link><description>Recent content in Cuda on Lessons learned</description><generator>Hugo</generator><language>en-us</language><copyright>© Alexandr Mansurov · Licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/)</copyright><lastBuildDate>Sat, 26 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://eghuro.cz/tags/cuda/index.xml" rel="self" type="application/rss+xml"/><item><title>A failed CUDA build over SSH still launched the old executable</title><link>https://eghuro.cz/posts/remote-failed-build-stale-executable/</link><pubDate>Sat, 26 Sep 2026 00:00:00 +0000</pubDate><guid>https://eghuro.cz/posts/remote-failed-build-stale-executable/</guid><description>&lt;p&gt;A remote command returned a CUDA compilation error followed by a normal simulation startup banner:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;error: calling a __device__ function(&amp;#34;__sinf&amp;#34;) from a __host__ __device__ function(&amp;#34;inflowFluctuation&amp;#34;) is not allowed&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The simulation started, but it ran an older executable. Semicolons let the launch proceed after &lt;code&gt;nvcc&lt;/code&gt; failed. Correcting the source and rebuilding recovered the test; guarding the build-to-launch transition would prevent that misleading result.&lt;/p&gt;&#10;&lt;p&gt;The &lt;a&#10; href="https://eghuro.cz/posts/claude-code-ssh-openpbs-setup"&#10; &#10; data-rel="prefetch"&#10; &#10; &#10;&gt;Claude Code and OpenPBS setup&lt;/a&gt;&#10; explains the local-agent/remote-command boundary. This happened during an early SSH-driven test, before we moved the long-running work into scheduled jobs. The shell mistake also applies inside a PBS script.&lt;/p&gt;&#10;&#10;&lt;h2 id="diagnostics-did-not-control-execution"&gt;Diagnostics did not control execution &lt;/h2&gt;&#10;&lt;p&gt;The command had this structure, with project paths removed:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nvcc -o solver solver.cu &amp;gt; build.log 2&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -A3 error build.log &lt;span class="p"&gt;|&lt;/span&gt; head&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nohup ./solver &lt;span class="k"&gt;case&lt;/span&gt;.cfg &amp;gt; run.log 2&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &amp;lt; /dev/null &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The build wrote to an executable path that already existed. Compilation failed, leaving a runnable earlier build. Printing matching diagnostics didn&amp;rsquo;t stop the next command, and backgrounding the program didn&amp;rsquo;t establish whether the requested source had compiled.&lt;/p&gt;&#10;&lt;p&gt;The failed-build result included an ordinary banner. After replacing &lt;code&gt;__sinf&lt;/code&gt; with &lt;code&gt;sinf&lt;/code&gt; in the host/device function, the rebuilt program&amp;rsquo;s banner contained the newly added &lt;code&gt;inflowTurb=0.08&lt;/code&gt; parameter and subsequent progress lines. The earlier banner lacked that field. That difference provided evidence of which code path actually ran.&lt;/p&gt;&#10;&lt;p&gt;The transcript shows this operational recovery. Its retry still used semicolon-separated build and launch commands, so it did not repair the fail-open shell structure.&lt;/p&gt;&#10;&#10;&lt;h2 id="make-compiler-status-a-launch-prerequisite"&gt;Make compiler status a launch prerequisite &lt;/h2&gt;&#10;&lt;p&gt;For a future build, preserve the compiler&amp;rsquo;s status explicitly. This generalized Bash pattern builds to a temporary path and only publishes it after success:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;set&lt;/span&gt; -euo pipefail&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_DIR&lt;/span&gt;&lt;span class="p"&gt;:?Set PROJECT_DIR to the remote project directory&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;candidate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;mktemp ./solver.build.XXXXXX&lt;span class="k"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;trap&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rm -f &amp;#34;$candidate&amp;#34;&amp;#39;&lt;/span&gt; EXIT&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; nvcc -o &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$candidate&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; solver.cu &amp;gt; build.log 2&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; mv -f &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$candidate&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; ./solver&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;else&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cat build.log &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;exec&lt;/span&gt; ./solver &lt;span class="k"&gt;case&lt;/span&gt;.cfg&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is a recommended guard, not code installed during the incident. The named source and configuration must exist in the remote project. Use a single build owner: concurrent publishers to &lt;code&gt;./solver&lt;/code&gt; require a separate ownership or versioned-artifact design.&lt;/p&gt;&#10;&lt;p&gt;When running remotely, send the whole script through SSH so its directory selection and status checks happen in the same remote shell. Avoid embedding local path expansions accidentally. For batch work, run the payload in the allocated job rather than adding another unscheduled &lt;code&gt;nohup&lt;/code&gt; launch.&lt;/p&gt;&#10;&#10;&lt;h2 id="reproduce-the-shell-failure-without-cuda"&gt;Reproduce the shell failure without CUDA &lt;/h2&gt;&#10;&lt;p&gt;On a local machine with a POSIX shell, this harmless fixture leaves an existing command available after a simulated build failure:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sh -c &lt;span class="s1"&gt;&amp;#39;solver() { printf &amp;#34;old executable ran\n&amp;#34;; }; false; solver&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It prints &lt;code&gt;old executable ran&lt;/code&gt; and exits successfully. The guarded form prevents execution:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sh -c &lt;span class="s1"&gt;&amp;#39;solver() { printf &amp;#34;old executable ran\n&amp;#34;; }; false &amp;amp;&amp;amp; solver&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That form prints nothing and returns a failure status. For a real compiler test, deliberately introduce an error and verify that no new run starts. Also log a build identifier or other deliberate runtime identity; a healthy-looking startup line only proves that some executable ran.&lt;/p&gt;&#10;&lt;p&gt;Check your next remote build command for the exact status dependency between compilation and launch, especially where diagnostic pipelines sit between them.&lt;/p&gt;&#10;</description></item></channel></rss>