<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://www.arunkant.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.arunkant.com/" rel="alternate" type="text/html" hreflang="en" /><updated>2026-07-10T19:26:54+05:30</updated><id>https://www.arunkant.com/feed.xml</id><title type="html">From first principles</title><subtitle>Personal blog of Arun Kant Sharma — essays on programming, web development, and learning by going back to first principles.</subtitle><author><name>Arun Kant Sharma</name><email>mail@arunkant.com</email></author><entry><title type="html">CUDA from the Ground Up</title><link href="https://www.arunkant.com/posts/cuda-from-ground-up/" rel="alternate" type="text/html" title="CUDA from the Ground Up" /><published>2026-07-01T00:00:00+05:30</published><updated>2026-07-01T00:00:00+05:30</updated><id>https://www.arunkant.com/posts/cuda-from-ground-up</id><content type="html" xml:base="https://www.arunkant.com/posts/cuda-from-ground-up/"><![CDATA[<nav class="post-toc">
  <p><strong>Contents</strong></p>
<ul id="markdown-toc">
  <li><a href="#introduction" id="markdown-toc-introduction">Introduction</a></li>
  <li><a href="#anatomy-of-a-kernel" id="markdown-toc-anatomy-of-a-kernel">Anatomy of a Kernel</a></li>
  <li><a href="#threads-blocks-and-grids" id="markdown-toc-threads-blocks-and-grids">Threads, Blocks, and Grids</a></li>
  <li><a href="#the-memory-model" id="markdown-toc-the-memory-model">The Memory Model</a></li>
  <li><a href="#two-dimensional-grids" id="markdown-toc-two-dimensional-grids">Two-Dimensional Grids</a>    <ul>
      <li><a href="#the-halo-problem" id="markdown-toc-the-halo-problem">The halo problem</a></li>
    </ul>
  </li>
  <li><a href="#checking-for-errors" id="markdown-toc-checking-for-errors">Checking for Errors</a></li>
  <li><a href="#matrix-multiplication-with-tiling" id="markdown-toc-matrix-multiplication-with-tiling">Matrix Multiplication with Tiling</a></li>
  <li><a href="#memory-coalescing-and-bank-conflicts" id="markdown-toc-memory-coalescing-and-bank-conflicts">Memory Coalescing and Bank Conflicts</a>    <ul>
      <li><a href="#global-memory-coalescing" id="markdown-toc-global-memory-coalescing">Global memory coalescing</a></li>
      <li><a href="#shared-memory-bank-conflicts" id="markdown-toc-shared-memory-bank-conflicts">Shared memory bank conflicts</a></li>
      <li><a href="#padding" id="markdown-toc-padding">Padding</a></li>
    </ul>
  </li>
  <li><a href="#parallel-reduction" id="markdown-toc-parallel-reduction">Parallel Reduction</a>    <ul>
      <li><a href="#warp-divergence" id="markdown-toc-warp-divergence">Warp divergence</a></li>
      <li><a href="#the-modern-fix-warp-shuffle" id="markdown-toc-the-modern-fix-warp-shuffle">The modern fix: warp shuffle</a></li>
    </ul>
  </li>
  <li><a href="#asynchronous-execution-and-streams" id="markdown-toc-asynchronous-execution-and-streams">Asynchronous Execution and Streams</a></li>
  <li><a href="#conclusion--where-to-go-next" id="markdown-toc-conclusion--where-to-go-next">Conclusion / Where to Go Next</a></li>
</ul>

</nav>

<h1 class="no_toc" id="cuda-from-the-ground-up">CUDA from the Ground Up</h1>

<h2 id="introduction">Introduction</h2>

<p>If you have written C++ before, CUDA is going to look strangely familiar. Functions are functions, pointers are pointers, and loops still loop. The difference is scale: instead of running one thing at a time, you will run thousands of copies of the same function at once, each one handed a different slice of data.</p>

<p>That scale comes from how GPUs are built. A CPU has a handful of powerful cores designed to finish one task quickly. A GPU has thousands of simpler cores designed to chew through a huge pile of similar tasks. You do not move your whole program to the GPU. You move the parts that look like “do the same operation on a huge pile of data”: image filters, matrix math, simulations, reductions, and most of the heavy lifting inside modern machine learning.</p>

<p>The mental shift is from “how do I solve this step by step?” to “how do I split this into many independent pieces?” Once you make that switch, CUDA stops feeling foreign and starts feeling obvious.</p>

<p>In this tutorial we will walk through a few classic kernels together: a vector add, a 2D matrix add, a smoothing filter with shared memory, a tiled matrix multiplication, a parallel reduction, and a multi-stream pipeline. By the end you will understand the execution model, the memory model, and the handful of optimization ideas that make CUDA fast.</p>

<p>You need to be comfortable with C++ pointers, arrays, and memory allocation. You also need access to a CUDA-capable GPU or a free Google Colab instance, which gives you a Tesla T4 and <code class="language-plaintext highlighter-rouge">nvcc</code> already installed.</p>

<h2 id="anatomy-of-a-kernel">Anatomy of a Kernel</h2>

<p>The best way to understand CUDA is to start with the smallest useful program and watch how it grows. So here is a vector add: it takes two arrays, adds them element by element, and writes the result into a third array. This example contains almost every pattern you will use in CUDA, so we will spend some time with it.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;cuda_runtime.h&gt;</span><span class="cp">
</span>
<span class="n">__global__</span> <span class="kt">void</span> <span class="nf">addVectors</span><span class="p">(</span><span class="k">const</span> <span class="kt">int</span><span class="o">*</span> <span class="n">A</span><span class="p">,</span> <span class="k">const</span> <span class="kt">int</span><span class="o">*</span> <span class="n">B</span><span class="p">,</span> <span class="kt">int</span><span class="o">*</span> <span class="n">C</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">blockIdx</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">blockDim</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">threadIdx</span><span class="p">.</span><span class="n">x</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">C</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">A</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">B</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">const</span> <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1000</span><span class="p">;</span>
    <span class="kt">size_t</span> <span class="n">bytes</span> <span class="o">=</span> <span class="n">n</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span>

    <span class="c1">// 1. Host allocation</span>
    <span class="kt">int</span><span class="o">*</span> <span class="n">h_A</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">[</span><span class="n">n</span><span class="p">];</span>
    <span class="kt">int</span><span class="o">*</span> <span class="n">h_B</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">[</span><span class="n">n</span><span class="p">];</span>
    <span class="kt">int</span><span class="o">*</span> <span class="n">h_C</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">[</span><span class="n">n</span><span class="p">];</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">h_A</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
        <span class="n">h_B</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span> <span class="o">*</span> <span class="mi">2</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// 2. Device allocation</span>
    <span class="kt">int</span> <span class="o">*</span><span class="n">d_A</span><span class="p">,</span> <span class="o">*</span><span class="n">d_B</span><span class="p">,</span> <span class="o">*</span><span class="n">d_C</span><span class="p">;</span>
    <span class="n">cudaMalloc</span><span class="p">((</span><span class="kt">void</span><span class="o">**</span><span class="p">)</span><span class="o">&amp;</span><span class="n">d_A</span><span class="p">,</span> <span class="n">bytes</span><span class="p">);</span>
    <span class="n">cudaMalloc</span><span class="p">((</span><span class="kt">void</span><span class="o">**</span><span class="p">)</span><span class="o">&amp;</span><span class="n">d_B</span><span class="p">,</span> <span class="n">bytes</span><span class="p">);</span>
    <span class="n">cudaMalloc</span><span class="p">((</span><span class="kt">void</span><span class="o">**</span><span class="p">)</span><span class="o">&amp;</span><span class="n">d_C</span><span class="p">,</span> <span class="n">bytes</span><span class="p">);</span>

    <span class="c1">// 3. Copy host -&gt; device</span>
    <span class="n">cudaMemcpy</span><span class="p">(</span><span class="n">d_A</span><span class="p">,</span> <span class="n">h_A</span><span class="p">,</span> <span class="n">bytes</span><span class="p">,</span> <span class="n">cudaMemcpyHostToDevice</span><span class="p">);</span>
    <span class="n">cudaMemcpy</span><span class="p">(</span><span class="n">d_B</span><span class="p">,</span> <span class="n">h_B</span><span class="p">,</span> <span class="n">bytes</span><span class="p">,</span> <span class="n">cudaMemcpyHostToDevice</span><span class="p">);</span>

    <span class="c1">// 4. Launch configuration</span>
    <span class="kt">int</span> <span class="n">threadsPerBlock</span> <span class="o">=</span> <span class="mi">256</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">blocksPerGrid</span> <span class="o">=</span> <span class="p">(</span><span class="n">n</span> <span class="o">+</span> <span class="n">threadsPerBlock</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">/</span> <span class="n">threadsPerBlock</span><span class="p">;</span>

    <span class="c1">// 5. Kernel launch</span>
    <span class="n">addVectors</span><span class="o">&lt;&lt;&lt;</span><span class="n">blocksPerGrid</span><span class="p">,</span> <span class="n">threadsPerBlock</span><span class="o">&gt;&gt;&gt;</span><span class="p">(</span><span class="n">d_A</span><span class="p">,</span> <span class="n">d_B</span><span class="p">,</span> <span class="n">d_C</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span>

    <span class="c1">// 6. Copy device -&gt; host</span>
    <span class="n">cudaMemcpy</span><span class="p">(</span><span class="n">h_C</span><span class="p">,</span> <span class="n">d_C</span><span class="p">,</span> <span class="n">bytes</span><span class="p">,</span> <span class="n">cudaMemcpyDeviceToHost</span><span class="p">);</span>

    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">h_C</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">" "</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"...</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>

    <span class="c1">// 7. Cleanup</span>
    <span class="n">cudaFree</span><span class="p">(</span><span class="n">d_A</span><span class="p">);</span>
    <span class="n">cudaFree</span><span class="p">(</span><span class="n">d_B</span><span class="p">);</span>
    <span class="n">cudaFree</span><span class="p">(</span><span class="n">d_C</span><span class="p">);</span>
    <span class="k">delete</span><span class="p">[]</span> <span class="n">h_A</span><span class="p">;</span>
    <span class="k">delete</span><span class="p">[]</span> <span class="n">h_B</span><span class="p">;</span>
    <span class="k">delete</span><span class="p">[]</span> <span class="n">h_C</span><span class="p">;</span>

    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The shape of this program is the same shape as almost every CUDA program you will write. We allocate memory on the CPU (the host), allocate memory on the GPU (the device), copy the input data over, launch a kernel, copy the result back, and clean up both sides. I have left out error checking here so the structure is easy to see; the next section adds the macro you should use in real code.</p>

<p>A kernel is just a C++ function with the <code class="language-plaintext highlighter-rouge">__global__</code> specifier. It runs on the GPU but is called from the CPU. Kernels must return <code class="language-plaintext highlighter-rouge">void</code>, so results go back through pointer arguments. Inside <code class="language-plaintext highlighter-rouge">addVectors</code>, every thread computes a global index <code class="language-plaintext highlighter-rouge">i</code> and writes one element of <code class="language-plaintext highlighter-rouge">C</code>. The <code class="language-plaintext highlighter-rouge">if (i &lt; n)</code> guard is important: kernels are launched in fixed-size blocks, so there are usually extra threads that do not correspond to real data. The guard keeps them from reading or writing out of bounds.</p>

<p>The launch syntax <code class="language-plaintext highlighter-rouge">&lt;&lt;&lt;blocksPerGrid, threadsPerBlock&gt;&gt;&gt;</code> tells CUDA how many threads to create. Here we launch 4 blocks of 256 threads, for 1,024 threads total. Only the first 1,000 have real work; the rest stay idle because of the guard. The expression <code class="language-plaintext highlighter-rouge">(n + threadsPerBlock - 1) / threadsPerBlock</code> is integer ceiling division: it rounds <code class="language-plaintext highlighter-rouge">n / threadsPerBlock</code> up so we always have enough threads.</p>

<p>The kernel call itself is asynchronous. The CPU queues the work and returns immediately. The next <code class="language-plaintext highlighter-rouge">cudaMemcpy</code> from device to host blocks until the kernel is done, so in this tiny program we get synchronization for free.</p>

<p>CUDA uses three function specifiers to decide where code runs and where it can be called from:</p>

<table>
  <thead>
    <tr>
      <th>Specifier</th>
      <th>Runs on</th>
      <th>Callable from</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">__global__</code></td>
      <td>GPU</td>
      <td>CPU</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">__device__</code></td>
      <td>GPU</td>
      <td>GPU</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">__host__</code></td>
      <td>CPU</td>
      <td>CPU (this is the default)</td>
    </tr>
  </tbody>
</table>

<p><code class="language-plaintext highlighter-rouge">__global__</code> functions are your kernel entry points. <code class="language-plaintext highlighter-rouge">__device__</code> functions are helpers that other GPU code can call. <code class="language-plaintext highlighter-rouge">__host__</code> is what ordinary C++ already does. A function can even be both <code class="language-plaintext highlighter-rouge">__host__ __device__</code> if you want the compiler to generate two versions.</p>

<p>Every thread gets a set of built-in coordinates. For a 1D launch, the ones that matter are:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">threadIdx.x</code> — position inside the block</li>
  <li><code class="language-plaintext highlighter-rouge">blockIdx.x</code> — position of the block inside the grid</li>
  <li><code class="language-plaintext highlighter-rouge">blockDim.x</code> — number of threads in the block</li>
  <li><code class="language-plaintext highlighter-rouge">gridDim.x</code> — number of blocks in the grid</li>
</ul>

<p>The global index for a 1D launch is:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">blockIdx</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">blockDim</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">threadIdx</span><span class="p">.</span><span class="n">x</span><span class="p">;</span>
</code></pre></div></div>

<p>Think of it as: skip all the threads in earlier blocks, then count forward to your seat inside this block. This little formula is the key to almost every 1D kernel.</p>

<blockquote>
  <p><strong>Try it yourself.</strong> If <code class="language-plaintext highlighter-rouge">n</code> is 1,000 and we launch 4 blocks of 256 threads, which threads do real work and which stay idle? Write down the global index range for each block and confirm the guard condition handles the boundary.</p>
</blockquote>

<h2 id="threads-blocks-and-grids">Threads, Blocks, and Grids</h2>

<p>Now that we can launch a kernel, we need to understand how CUDA decides which thread handles which array index. CUDA organizes threads into a hierarchy, and getting comfortable with that hierarchy is the key to writing correct and fast kernels.</p>

<p>A <strong>thread</strong> is one invocation of the kernel. Threads are extremely lightweight; the GPU can switch between them with almost no cost. A <strong>block</strong> is a group of threads that run on the same streaming multiprocessor (SM). Threads in a block can share memory and synchronize with each other, and a block is limited to 1,024 threads on most hardware. A <strong>grid</strong> is the collection of all blocks launched by a single kernel call. Blocks in a grid run independently; you cannot synchronize across blocks.</p>

<p>A 1D launch with 4 blocks of 256 threads looks like this:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Grid
├── Block 0  → threads 0..255
├── Block 1  → threads 256..511
├── Block 2  → threads 512..767
└── Block 3  → threads 768..1023

Each thread computes: i = blockIdx.x * 256 + threadIdx.x
</code></pre></div></div>

<p>The launch configuration <code class="language-plaintext highlighter-rouge">(n + 255) / 256</code> is the standard way to round up. Without it, <code class="language-plaintext highlighter-rouge">1000 / 256</code> would truncate to 3 blocks, giving only 768 threads and silently ignoring the last 232 elements. The trick is to add <code class="language-plaintext highlighter-rouge">threadsPerBlock - 1</code> to the numerator before the integer divide. If there is any remainder, the sum pushes the quotient up by one.</p>

<p>When you round up, you create threads that have no data to process. The kernel must guard those threads:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">C</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">A</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">B</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The extra threads are still launched, still consume registers, and still run through the code. They just do not touch memory. This is normal, and the guard is the standard way to handle it.</p>

<p>There is one more unit hiding inside this hierarchy: a <strong>warp</strong> is a group of 32 threads that the hardware executes together. You do not explicitly launch warps; the GPU bundles threads automatically. Warps matter for performance, especially when threads in the same warp take different branches or access memory in a scattered pattern. We will come back to both ideas, first when we look at memory coalescing and again when we parallelize a reduction.</p>

<h2 id="the-memory-model">The Memory Model</h2>

<p>With thread coordinates under our belt, we hit the next obstacle: the GPU has its own memory, completely separate from the CPU’s. The host pointer you get from <code class="language-plaintext highlighter-rouge">new</code> points into system RAM. The device pointer you get from <code class="language-plaintext highlighter-rouge">cudaMalloc</code> points into GPU VRAM. Kernels can only read and write device memory.</p>

<p>The reason we care is that the PCIe bus between CPU and GPU is fast by everyday standards but glacial by GPU standards. Every transfer is a round trip, so the goal is to move data over once, do as much work as possible on the GPU, and move it back once. The vector add we just wrote is too small for this to matter, but it is the same pattern we will use for every larger kernel.</p>

<p>The full data journey for our vector add looks like this:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>     Host (CPU)                         Device (GPU)
   ┌─────────────┐                     ┌─────────────┐
   │   h_A       │ ── cudaMemcpy H→D ─→│   d_A       │
   │   h_B       │ ── cudaMemcpy H→D ─→│   d_B       │
   │   h_C       │ ←── cudaMemcpy D→H ─│   d_C       │
   └─────────────┘                     └─────────────┘
                                              │
                                         addVectors&lt;&lt;&lt; &gt;&gt;&gt;
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">cudaMalloc</code> works like <code class="language-plaintext highlighter-rouge">malloc</code> but allocates in GPU memory. It takes a <code class="language-plaintext highlighter-rouge">void**</code> and returns a <code class="language-plaintext highlighter-rouge">cudaError_t</code>. We will wrap it in a macro soon, but the raw call looks like this:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span><span class="o">*</span> <span class="n">d_A</span><span class="p">;</span>
<span class="n">cudaMalloc</span><span class="p">((</span><span class="kt">void</span><span class="o">**</span><span class="p">)</span><span class="o">&amp;</span><span class="n">d_A</span><span class="p">,</span> <span class="n">bytes</span><span class="p">);</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">cudaMemcpy</code> is the workhorse for moving data between host and device. Its four modes are <code class="language-plaintext highlighter-rouge">cudaMemcpyHostToDevice</code>, <code class="language-plaintext highlighter-rouge">cudaMemcpyDeviceToHost</code>, <code class="language-plaintext highlighter-rouge">cudaMemcpyDeviceToDevice</code>, and <code class="language-plaintext highlighter-rouge">cudaMemcpyHostToHost</code>. The direction argument matters, and mixing it up is a common source of crashes. You can also copy from one device pointer to another with <code class="language-plaintext highlighter-rouge">cudaMemcpyDeviceToDevice</code>, which is useful when you want to avoid a round trip through the CPU.</p>

<p><code class="language-plaintext highlighter-rouge">cudaFree</code> releases device memory. It is safe to call <code class="language-plaintext highlighter-rouge">cudaFree</code> on a null pointer. Forgetting to call it leaks GPU memory, which is usually scarcer than host memory. Device memory and host memory are managed separately: every <code class="language-plaintext highlighter-rouge">cudaMalloc</code> needs a <code class="language-plaintext highlighter-rouge">cudaFree</code>, and every <code class="language-plaintext highlighter-rouge">new[]</code> needs a <code class="language-plaintext highlighter-rouge">delete[]</code>.</p>

<p>CUDA also supports Unified Memory, where a single pointer is valid on both host and device and the runtime migrates data automatically. It is convenient for prototyping, but for performance you usually want explicit control. We will stick to explicit copies in this tutorial and revisit Unified Memory another time.</p>

<h2 id="two-dimensional-grids">Two-Dimensional Grids</h2>

<p>One-dimensional arrays are fine, but most interesting GPU problems are two-dimensional. Images, matrices, and physical grids all map naturally to a 2D layout, and CUDA supports up to three-dimensional grids and blocks through a struct called <code class="language-plaintext highlighter-rouge">dim3</code>.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">dim3</span> <span class="nf">threadsPerBlock</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span> <span class="mi">16</span><span class="p">);</span>              <span class="c1">// 256 threads in a 16x16 block</span>
<span class="n">dim3</span> <span class="nf">blocksPerGrid</span><span class="p">(</span><span class="n">width</span> <span class="o">/</span> <span class="mi">16</span><span class="p">,</span> <span class="n">height</span> <span class="o">/</span> <span class="mi">16</span><span class="p">);</span> <span class="c1">// enough blocks to cover the image</span>

<span class="n">processImage</span><span class="o">&lt;&lt;&lt;</span><span class="n">blocksPerGrid</span><span class="p">,</span> <span class="n">threadsPerBlock</span><span class="o">&gt;&gt;&gt;</span><span class="p">(</span><span class="n">d_image</span><span class="p">,</span> <span class="n">width</span><span class="p">,</span> <span class="n">height</span><span class="p">);</span>
</code></pre></div></div>

<p>Inside the kernel, threads have <code class="language-plaintext highlighter-rouge">.x</code>, <code class="language-plaintext highlighter-rouge">.y</code>, and <code class="language-plaintext highlighter-rouge">.z</code> coordinates:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">x</span> <span class="o">=</span> <span class="n">blockIdx</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">blockDim</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">threadIdx</span><span class="p">.</span><span class="n">x</span><span class="p">;</span> <span class="c1">// column</span>
<span class="kt">int</span> <span class="n">y</span> <span class="o">=</span> <span class="n">blockIdx</span><span class="p">.</span><span class="n">y</span> <span class="o">*</span> <span class="n">blockDim</span><span class="p">.</span><span class="n">y</span> <span class="o">+</span> <span class="n">threadIdx</span><span class="p">.</span><span class="n">y</span><span class="p">;</span> <span class="c1">// row</span>
</code></pre></div></div>

<p>The device memory is still one flat array, so a 2D coordinate has to be flattened. Row-major order means each row is <code class="language-plaintext highlighter-rouge">width</code> elements wide, so row <code class="language-plaintext highlighter-rouge">y</code> starts at <code class="language-plaintext highlighter-rouge">y * width</code>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">index</span> <span class="o">=</span> <span class="n">y</span> <span class="o">*</span> <span class="n">width</span> <span class="o">+</span> <span class="n">x</span><span class="p">;</span>
</code></pre></div></div>

<p>Here is a 2D kernel that adds two matrices. It guards both the width and height boundaries because 2D launches also create extra threads along the edges:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">__global__</span> <span class="kt">void</span> <span class="nf">addMatrix</span><span class="p">(</span><span class="k">const</span> <span class="kt">int</span><span class="o">*</span> <span class="n">A</span><span class="p">,</span> <span class="k">const</span> <span class="kt">int</span><span class="o">*</span> <span class="n">B</span><span class="p">,</span> <span class="kt">int</span><span class="o">*</span> <span class="n">C</span><span class="p">,</span>
                          <span class="kt">int</span> <span class="n">width</span><span class="p">,</span> <span class="kt">int</span> <span class="n">height</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">x</span> <span class="o">=</span> <span class="n">blockIdx</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">blockDim</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">threadIdx</span><span class="p">.</span><span class="n">x</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">y</span> <span class="o">=</span> <span class="n">blockIdx</span><span class="p">.</span><span class="n">y</span> <span class="o">*</span> <span class="n">blockDim</span><span class="p">.</span><span class="n">y</span> <span class="o">+</span> <span class="n">threadIdx</span><span class="p">.</span><span class="n">y</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">x</span> <span class="o">&lt;</span> <span class="n">width</span> <span class="o">&amp;&amp;</span> <span class="n">y</span> <span class="o">&lt;</span> <span class="n">height</span><span class="p">)</span> <span class="p">{</span>
        <span class="kt">int</span> <span class="n">idx</span> <span class="o">=</span> <span class="n">y</span> <span class="o">*</span> <span class="n">width</span> <span class="o">+</span> <span class="n">x</span><span class="p">;</span>
        <span class="n">C</span><span class="p">[</span><span class="n">idx</span><span class="p">]</span> <span class="o">=</span> <span class="n">A</span><span class="p">[</span><span class="n">idx</span><span class="p">]</span> <span class="o">+</span> <span class="n">B</span><span class="p">[</span><span class="n">idx</span><span class="p">];</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>A 1,024x1,024 matrix with 16x16 blocks needs a 64x64 grid:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">dim3</span> <span class="nf">block</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span> <span class="mi">16</span><span class="p">);</span>
<span class="n">dim3</span> <span class="nf">grid</span><span class="p">(</span><span class="mi">1024</span> <span class="o">/</span> <span class="mi">16</span><span class="p">,</span> <span class="mi">1024</span> <span class="o">/</span> <span class="mi">16</span><span class="p">);</span>
<span class="n">addMatrix</span><span class="o">&lt;&lt;&lt;</span><span class="n">grid</span><span class="p">,</span> <span class="n">block</span><span class="o">&gt;&gt;&gt;</span><span class="p">(</span><span class="n">d_A</span><span class="p">,</span> <span class="n">d_B</span><span class="p">,</span> <span class="n">d_C</span><span class="p">,</span> <span class="mi">1024</span><span class="p">,</span> <span class="mi">1024</span><span class="p">);</span>
</code></pre></div></div>

<p>This is the same coordinate pattern we will use for the image blur and the tiled matrix multiply later, so it is worth getting comfortable with it now.</p>

<blockquote>
  <p><strong>Try it yourself.</strong> For a matrix with <code class="language-plaintext highlighter-rouge">width = 10</code>, what is the flat index of the cell at column 5, row 2? What is the flat index of the cell immediately to its right?</p>
</blockquote>

<h3 id="the-halo-problem">The halo problem</h3>

<p>Many 2D kernels read neighboring pixels. An image blur, for example, needs the pixel to the left and right of each output pixel. If every thread fetches its neighbors directly from global memory, the same pixels are loaded many times. Shared memory fixes that.</p>

<p>Shared memory is a small, fast scratchpad attached to each SM. Threads in the same block can read and write it, and it is roughly two orders of magnitude faster than global memory. You declare it with <code class="language-plaintext highlighter-rouge">__shared__</code>. The pattern is always the same: load data from global memory into shared memory, call <code class="language-plaintext highlighter-rouge">__syncthreads()</code> so no thread starts computing before the data is ready, and then compute using the fast shared copy.</p>

<p>Here is a 1D smoothing filter that averages a pixel with its left and right neighbors. This is the same stencil pattern used in image blurs, just collapsed to one dimension so we can focus on the memory mechanics:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define BLOCK_SIZE 256
</span>
<span class="n">__global__</span> <span class="kt">void</span> <span class="nf">smooth1D</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span> <span class="n">input</span><span class="p">,</span> <span class="kt">int</span><span class="o">*</span> <span class="n">output</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">__shared__</span> <span class="kt">int</span> <span class="n">cache</span><span class="p">[</span><span class="n">BLOCK_SIZE</span> <span class="o">+</span> <span class="mi">2</span><span class="p">];</span> <span class="c1">// room for left and right halo</span>

    <span class="kt">int</span> <span class="n">tid</span> <span class="o">=</span> <span class="n">threadIdx</span><span class="p">.</span><span class="n">x</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">blockIdx</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">blockDim</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">tid</span><span class="p">;</span>

    <span class="c1">// Load center value, offset by one to leave room for halos</span>
    <span class="n">cache</span><span class="p">[</span><span class="n">tid</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">)</span> <span class="o">?</span> <span class="n">input</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">:</span> <span class="mi">0</span><span class="p">;</span>

    <span class="c1">// Load halos: edge threads fetch one extra value from global memory</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">tid</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">cache</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="o">?</span> <span class="n">input</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">tid</span> <span class="o">==</span> <span class="n">blockDim</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">cache</span><span class="p">[</span><span class="n">BLOCK_SIZE</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">?</span> <span class="n">input</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">__syncthreads</span><span class="p">();</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
        <span class="kt">int</span> <span class="n">left</span>   <span class="o">=</span> <span class="n">cache</span><span class="p">[</span><span class="n">tid</span><span class="p">];</span>
        <span class="kt">int</span> <span class="n">center</span> <span class="o">=</span> <span class="n">cache</span><span class="p">[</span><span class="n">tid</span> <span class="o">+</span> <span class="mi">1</span><span class="p">];</span>
        <span class="kt">int</span> <span class="n">right</span>  <span class="o">=</span> <span class="n">cache</span><span class="p">[</span><span class="n">tid</span> <span class="o">+</span> <span class="mi">2</span><span class="p">];</span>
        <span class="n">output</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">left</span> <span class="o">+</span> <span class="n">center</span> <span class="o">+</span> <span class="n">right</span><span class="p">)</span> <span class="o">/</span> <span class="mi">3</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The extra slots on each side of the shared array are called <strong>halos</strong> or <strong>ghost cells</strong>. They hold the values just outside the block’s territory, which are needed by the edge threads. The reason we care is that each halo value is fetched from global memory only once per block, even though multiple threads in the block might need it.</p>

<p>Notice that <code class="language-plaintext highlighter-rouge">__syncthreads()</code> is called outside the <code class="language-plaintext highlighter-rouge">if (i &lt; n)</code> guard. If any thread in the block skipped the barrier, the rest would wait forever and the kernel would hang. This is one of the most common ways to deadlock a CUDA kernel, so it is worth remembering.</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Block 0 shared cache:
┌────────┬────────────────┬────────┐
│ halo 0 │  values 0..255 │ halo 1 │
└────────┴────────────────┴────────┘
         ↑                ↑
     input[-1]?       input[256]
</code></pre></div></div>

<p>The left halo for the first block has no neighbor, so we pad with 0. The right halo is fetched from the next block’s first element. In a real image blur you would pad the image edges in the same way.</p>

<h2 id="checking-for-errors">Checking for Errors</h2>

<p>CUDA errors are easy to miss. <code class="language-plaintext highlighter-rouge">cudaMalloc</code> returns an error code, but the <code class="language-plaintext highlighter-rouge">&lt;&lt;&lt;...&gt;&gt;&gt;</code> kernel launch syntax does not. Kernels run asynchronously, so a crash inside a kernel may not surface until much later. Your CPU code keeps running, and the only symptom is wrong data.</p>

<p>The fix is a small macro and two habits. Here is the macro:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define CUDA_CHECK(call) \
    do { \
        cudaError_t err = call; \
        if (err != cudaSuccess) { \
            std::cerr &lt;&lt; "CUDA Error: " &lt;&lt; cudaGetErrorString(err) \
                      &lt;&lt; " at " &lt;&lt; __FILE__ &lt;&lt; ":" &lt;&lt; __LINE__ &lt;&lt; std::endl; \
            exit(EXIT_FAILURE); \
        } \
    } while (0)
</span></code></pre></div></div>

<p>Wrap every CUDA API call:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaMalloc</span><span class="p">((</span><span class="kt">void</span><span class="o">**</span><span class="p">)</span><span class="o">&amp;</span><span class="n">d_A</span><span class="p">,</span> <span class="n">bytes</span><span class="p">));</span>
<span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaMemcpy</span><span class="p">(</span><span class="n">d_A</span><span class="p">,</span> <span class="n">h_A</span><span class="p">,</span> <span class="n">bytes</span><span class="p">,</span> <span class="n">cudaMemcpyHostToDevice</span><span class="p">));</span>
</code></pre></div></div>

<p>After a kernel launch, check for launch configuration errors with <code class="language-plaintext highlighter-rouge">cudaGetLastError</code> and then wait for completion with <code class="language-plaintext highlighter-rouge">cudaDeviceSynchronize</code>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">addVectors</span><span class="o">&lt;&lt;&lt;</span><span class="n">blocks</span><span class="p">,</span> <span class="n">threads</span><span class="o">&gt;&gt;&gt;</span><span class="p">(</span><span class="n">d_A</span><span class="p">,</span> <span class="n">d_B</span><span class="p">,</span> <span class="n">d_C</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span>
<span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaGetLastError</span><span class="p">());</span>      <span class="c1">// catches invalid launch config</span>
<span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaDeviceSynchronize</span><span class="p">());</span> <span class="c1">// catches runtime errors in the kernel</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">cudaGetLastError</code> tells you if the launch itself was illegal, such as asking for too many threads per block. <code class="language-plaintext highlighter-rouge">cudaDeviceSynchronize</code> waits for the kernel to finish and returns any error that happened while it was running, such as an out-of-bounds memory access. The complete examples from here on all use <code class="language-plaintext highlighter-rouge">CUDA_CHECK</code>. In small snippets we may leave it out to keep the focus on the algorithm, but in real code you should always check.</p>

<h2 id="matrix-multiplication-with-tiling">Matrix Multiplication with Tiling</h2>

<p>Matrix multiplication is the classic GPU workload. A naive kernel computes each output element as the dot product of a row of <code class="language-plaintext highlighter-rouge">A</code> and a column of <code class="language-plaintext highlighter-rouge">B</code>. The problem is memory traffic: every row and every column is read many times by different threads. For large matrices, the GPU spends most of its time waiting for data instead of multiplying.</p>

<p>Tiling uses shared memory as a user-managed cache. A block of threads loads a small square tile of <code class="language-plaintext highlighter-rouge">A</code> and a tile of <code class="language-plaintext highlighter-rouge">B</code> into shared memory, computes a partial dot product from those tiles, then loads the next pair of tiles. Each element of global memory is read only once per tile traversal instead of once per output element.</p>

<p>The idea in phases, for a 16x16 tile, looks like this:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Phase 0: load A[0:15][0:15] and B[0:15][0:15] into shared memory
         compute partial sums
Phase 1: load A[0:15][16:31] and B[16:31][0:15]
         compute partial sums
... until the full row/column is covered
</code></pre></div></div>

<p>Here is the tiled kernel. It assumes square matrices and that <code class="language-plaintext highlighter-rouge">width</code> is a multiple of <code class="language-plaintext highlighter-rouge">TILE_SIZE</code>.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;cuda_runtime.h&gt;</span><span class="cp">
</span>
<span class="cp">#define CUDA_CHECK(call) \
    do { \
        cudaError_t err = call; \
        if (err != cudaSuccess) { \
            std::cerr &lt;&lt; "CUDA Error: " &lt;&lt; cudaGetErrorString(err) \
                      &lt;&lt; " at " &lt;&lt; __FILE__ &lt;&lt; ":" &lt;&lt; __LINE__ &lt;&lt; std::endl; \
            exit(EXIT_FAILURE); \
        } \
    } while (0)
</span>
<span class="cp">#define TILE_SIZE 16
</span>
<span class="c1">// Square matrices only; width must be divisible by TILE_SIZE.</span>
<span class="n">__global__</span> <span class="kt">void</span> <span class="nf">tiledMatMul</span><span class="p">(</span><span class="k">const</span> <span class="kt">int</span><span class="o">*</span> <span class="n">A</span><span class="p">,</span> <span class="k">const</span> <span class="kt">int</span><span class="o">*</span> <span class="n">B</span><span class="p">,</span> <span class="kt">int</span><span class="o">*</span> <span class="n">C</span><span class="p">,</span> <span class="kt">int</span> <span class="n">width</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">__shared__</span> <span class="kt">int</span> <span class="n">tileA</span><span class="p">[</span><span class="n">TILE_SIZE</span><span class="p">][</span><span class="n">TILE_SIZE</span><span class="p">];</span>
    <span class="n">__shared__</span> <span class="kt">int</span> <span class="n">tileB</span><span class="p">[</span><span class="n">TILE_SIZE</span><span class="p">][</span><span class="n">TILE_SIZE</span><span class="p">];</span>

    <span class="kt">int</span> <span class="n">tx</span> <span class="o">=</span> <span class="n">threadIdx</span><span class="p">.</span><span class="n">x</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">ty</span> <span class="o">=</span> <span class="n">threadIdx</span><span class="p">.</span><span class="n">y</span><span class="p">;</span>

    <span class="kt">int</span> <span class="n">row</span> <span class="o">=</span> <span class="n">blockIdx</span><span class="p">.</span><span class="n">y</span> <span class="o">*</span> <span class="n">TILE_SIZE</span> <span class="o">+</span> <span class="n">ty</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">col</span> <span class="o">=</span> <span class="n">blockIdx</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">TILE_SIZE</span> <span class="o">+</span> <span class="n">tx</span><span class="p">;</span>

    <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">numPhases</span> <span class="o">=</span> <span class="n">width</span> <span class="o">/</span> <span class="n">TILE_SIZE</span><span class="p">;</span>

    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">phase</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">phase</span> <span class="o">&lt;</span> <span class="n">numPhases</span><span class="p">;</span> <span class="o">++</span><span class="n">phase</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// Each thread loads one element of each tile</span>
        <span class="n">tileA</span><span class="p">[</span><span class="n">ty</span><span class="p">][</span><span class="n">tx</span><span class="p">]</span> <span class="o">=</span> <span class="n">A</span><span class="p">[</span><span class="n">row</span> <span class="o">*</span> <span class="n">width</span> <span class="o">+</span> <span class="p">(</span><span class="n">phase</span> <span class="o">*</span> <span class="n">TILE_SIZE</span> <span class="o">+</span> <span class="n">tx</span><span class="p">)];</span>
        <span class="n">tileB</span><span class="p">[</span><span class="n">ty</span><span class="p">][</span><span class="n">tx</span><span class="p">]</span> <span class="o">=</span> <span class="n">B</span><span class="p">[(</span><span class="n">phase</span> <span class="o">*</span> <span class="n">TILE_SIZE</span> <span class="o">+</span> <span class="n">ty</span><span class="p">)</span> <span class="o">*</span> <span class="n">width</span> <span class="o">+</span> <span class="n">col</span><span class="p">];</span>

        <span class="n">__syncthreads</span><span class="p">();</span>

        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">TILE_SIZE</span><span class="p">;</span> <span class="o">++</span><span class="n">k</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">sum</span> <span class="o">+=</span> <span class="n">tileA</span><span class="p">[</span><span class="n">ty</span><span class="p">][</span><span class="n">k</span><span class="p">]</span> <span class="o">*</span> <span class="n">tileB</span><span class="p">[</span><span class="n">k</span><span class="p">][</span><span class="n">tx</span><span class="p">];</span>
        <span class="p">}</span>

        <span class="n">__syncthreads</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="n">C</span><span class="p">[</span><span class="n">row</span> <span class="o">*</span> <span class="n">width</span> <span class="o">+</span> <span class="n">col</span><span class="p">]</span> <span class="o">=</span> <span class="n">sum</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">const</span> <span class="kt">int</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">1024</span><span class="p">;</span>
    <span class="k">const</span> <span class="kt">size_t</span> <span class="n">bytes</span> <span class="o">=</span> <span class="n">width</span> <span class="o">*</span> <span class="n">width</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span>

    <span class="kt">int</span><span class="o">*</span> <span class="n">h_A</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">[</span><span class="n">width</span> <span class="o">*</span> <span class="n">width</span><span class="p">];</span>
    <span class="kt">int</span><span class="o">*</span> <span class="n">h_B</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">[</span><span class="n">width</span> <span class="o">*</span> <span class="n">width</span><span class="p">];</span>
    <span class="kt">int</span><span class="o">*</span> <span class="n">h_C</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">[</span><span class="n">width</span> <span class="o">*</span> <span class="n">width</span><span class="p">];</span>

    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">width</span> <span class="o">*</span> <span class="n">width</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">h_A</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
        <span class="n">h_B</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="kt">int</span> <span class="o">*</span><span class="n">d_A</span><span class="p">,</span> <span class="o">*</span><span class="n">d_B</span><span class="p">,</span> <span class="o">*</span><span class="n">d_C</span><span class="p">;</span>
    <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaMalloc</span><span class="p">((</span><span class="kt">void</span><span class="o">**</span><span class="p">)</span><span class="o">&amp;</span><span class="n">d_A</span><span class="p">,</span> <span class="n">bytes</span><span class="p">));</span>
    <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaMalloc</span><span class="p">((</span><span class="kt">void</span><span class="o">**</span><span class="p">)</span><span class="o">&amp;</span><span class="n">d_B</span><span class="p">,</span> <span class="n">bytes</span><span class="p">));</span>
    <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaMalloc</span><span class="p">((</span><span class="kt">void</span><span class="o">**</span><span class="p">)</span><span class="o">&amp;</span><span class="n">d_C</span><span class="p">,</span> <span class="n">bytes</span><span class="p">));</span>

    <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaMemcpy</span><span class="p">(</span><span class="n">d_A</span><span class="p">,</span> <span class="n">h_A</span><span class="p">,</span> <span class="n">bytes</span><span class="p">,</span> <span class="n">cudaMemcpyHostToDevice</span><span class="p">));</span>
    <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaMemcpy</span><span class="p">(</span><span class="n">d_B</span><span class="p">,</span> <span class="n">h_B</span><span class="p">,</span> <span class="n">bytes</span><span class="p">,</span> <span class="n">cudaMemcpyHostToDevice</span><span class="p">));</span>

    <span class="n">dim3</span> <span class="nf">threads</span><span class="p">(</span><span class="n">TILE_SIZE</span><span class="p">,</span> <span class="n">TILE_SIZE</span><span class="p">);</span>
    <span class="n">dim3</span> <span class="nf">blocks</span><span class="p">(</span><span class="n">width</span> <span class="o">/</span> <span class="n">TILE_SIZE</span><span class="p">,</span> <span class="n">width</span> <span class="o">/</span> <span class="n">TILE_SIZE</span><span class="p">);</span>

    <span class="n">tiledMatMul</span><span class="o">&lt;&lt;&lt;</span><span class="n">blocks</span><span class="p">,</span> <span class="n">threads</span><span class="o">&gt;&gt;&gt;</span><span class="p">(</span><span class="n">d_A</span><span class="p">,</span> <span class="n">d_B</span><span class="p">,</span> <span class="n">d_C</span><span class="p">,</span> <span class="n">width</span><span class="p">);</span>
    <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaGetLastError</span><span class="p">());</span>
    <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaDeviceSynchronize</span><span class="p">());</span>

    <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaMemcpy</span><span class="p">(</span><span class="n">h_C</span><span class="p">,</span> <span class="n">d_C</span><span class="p">,</span> <span class="n">bytes</span><span class="p">,</span> <span class="n">cudaMemcpyDeviceToHost</span><span class="p">));</span>

    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"C[0][0] = "</span> <span class="o">&lt;&lt;</span> <span class="n">h_C</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"C[1023][1023] = "</span> <span class="o">&lt;&lt;</span> <span class="n">h_C</span><span class="p">[</span><span class="n">width</span> <span class="o">*</span> <span class="n">width</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>

    <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaFree</span><span class="p">(</span><span class="n">d_A</span><span class="p">));</span>
    <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaFree</span><span class="p">(</span><span class="n">d_B</span><span class="p">));</span>
    <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaFree</span><span class="p">(</span><span class="n">d_C</span><span class="p">));</span>
    <span class="k">delete</span><span class="p">[]</span> <span class="n">h_A</span><span class="p">;</span>
    <span class="k">delete</span><span class="p">[]</span> <span class="n">h_B</span><span class="p">;</span>
    <span class="k">delete</span><span class="p">[]</span> <span class="n">h_C</span><span class="p">;</span>

    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The second <code class="language-plaintext highlighter-rouge">__syncthreads()</code> inside the phase loop is not optional. Without it, a fast warp could start loading the next phase into <code class="language-plaintext highlighter-rouge">tileA</code> and <code class="language-plaintext highlighter-rouge">tileB</code> while a slower warp is still reading the previous phase, producing garbage. This is the same synchronization idea we used in the smoothing filter, just inside a loop now.</p>

<blockquote>
  <p><strong>Try it yourself.</strong> Trace through the indices when <code class="language-plaintext highlighter-rouge">TILE_SIZE = 2</code> and <code class="language-plaintext highlighter-rouge">width = 4</code>. Which threads load which elements of <code class="language-plaintext highlighter-rouge">A</code> and <code class="language-plaintext highlighter-rouge">B</code> in each phase?</p>
</blockquote>

<h2 id="memory-coalescing-and-bank-conflicts">Memory Coalescing and Bank Conflicts</h2>

<p>Getting data to the GPU is only half the battle; the other half is making sure the memory system can serve that data efficiently. If the threads in a warp ask for memory in a scattered way, the hardware has to run many separate transactions, and the kernel slows down for no good reason.</p>

<h3 id="global-memory-coalescing">Global memory coalescing</h3>

<p>When a warp of 32 threads reads global memory, the hardware does not fetch 32 individual values. It fetches aligned 128-byte chunks. If the 32 threads request 32 consecutive 4-byte integers starting at a 128-byte boundary, the whole request is satisfied in one transaction. That is a <strong>coalesced</strong> access.</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Coalesced read:
Thread 0 → addr 0     Thread 1 → addr 4     ... Thread 31 → addr 124
All 32 values fit in one 128-byte transaction.

Uncoalesced read:
Thread 0 → addr 0     Thread 1 → addr 4096  Thread 2 → addr 8192 ...
Each thread needs a separate transaction.
</code></pre></div></div>

<p>In our tiled matrix multiplication, the loads</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">tileA</span><span class="p">[</span><span class="n">ty</span><span class="p">][</span><span class="n">tx</span><span class="p">]</span> <span class="o">=</span> <span class="n">A</span><span class="p">[</span><span class="n">row</span> <span class="o">*</span> <span class="n">width</span> <span class="o">+</span> <span class="p">(</span><span class="n">phase</span> <span class="o">*</span> <span class="n">TILE_SIZE</span> <span class="o">+</span> <span class="n">tx</span><span class="p">)];</span>
<span class="n">tileB</span><span class="p">[</span><span class="n">ty</span><span class="p">][</span><span class="n">tx</span><span class="p">]</span> <span class="o">=</span> <span class="n">B</span><span class="p">[(</span><span class="n">phase</span> <span class="o">*</span> <span class="n">TILE_SIZE</span> <span class="o">+</span> <span class="n">ty</span><span class="p">)</span> <span class="o">*</span> <span class="n">width</span> <span class="o">+</span> <span class="n">col</span><span class="p">];</span>
</code></pre></div></div>

<p>are coalesced because adjacent threads have adjacent <code class="language-plaintext highlighter-rouge">tx</code> and <code class="language-plaintext highlighter-rouge">col</code> values, so they read adjacent memory locations. This is one reason tiling is faster than the naive approach: it turns scattered accesses into consecutive ones.</p>

<h3 id="shared-memory-bank-conflicts">Shared memory bank conflicts</h3>

<p>Shared memory is divided into 32 banks. Consecutive 4-byte words belong to consecutive banks, wrapping around after bank 31. If 32 threads in a warp access 32 different banks, the accesses happen in parallel. If multiple threads access different words in the same bank, the hardware serializes them. That is a <strong>bank conflict</strong>.</p>

<p>The compute loop in our tiled matrix multiply is a nice example of how the hardware helps:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">TILE_SIZE</span><span class="p">;</span> <span class="o">++</span><span class="n">k</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">sum</span> <span class="o">+=</span> <span class="n">tileA</span><span class="p">[</span><span class="n">ty</span><span class="p">][</span><span class="n">k</span><span class="p">]</span> <span class="o">*</span> <span class="n">tileB</span><span class="p">[</span><span class="n">k</span><span class="p">][</span><span class="n">tx</span><span class="p">];</span>
<span class="p">}</span>
</code></pre></div></div>

<p>For <code class="language-plaintext highlighter-rouge">tileA[ty][k]</code>, every thread in a warp reads the same address at the same time. The hardware detects this and broadcasts the value to all threads at once, so there is no conflict. For <code class="language-plaintext highlighter-rouge">tileB[k][tx]</code>, adjacent threads read adjacent columns, so they hit different banks. Again, no conflict.</p>

<h3 id="padding">Padding</h3>

<p>If your access pattern forces threads to read down a column instead of across a row, you can get a conflict. The classic fix is to add an unused column to the shared array:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">__shared__</span> <span class="kt">int</span> <span class="n">tile</span><span class="p">[</span><span class="mi">16</span><span class="p">][</span><span class="mi">17</span><span class="p">];</span> <span class="c1">// padding shifts bank assignments</span>
</code></pre></div></div>

<p>That extra column changes which bank each row starts in, breaking up the conflict pattern. The math does not change; only the memory layout does.</p>

<h2 id="parallel-reduction">Parallel Reduction</h2>

<p>Suppose you want to sum a million numbers. On a CPU you would loop and accumulate. On a GPU, if a million threads all try to update one shared total, they overwrite each other. You could use <code class="language-plaintext highlighter-rouge">atomicAdd</code>, but forcing a million threads into a single line destroys the parallelism that makes the GPU fast.</p>

<p>The better approach is a tree reduction in shared memory. Each block reduces its own chunk to a single value, then adds that value to the global total with one <code class="language-plaintext highlighter-rouge">atomicAdd</code> per block. The reason we care is that this pattern shows up everywhere: sums, maxima, minima, dot products, and any operation that collapses a large array into one number.</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Tree reduction inside a block of 8 threads:

sdata: [a0 a1 a2 a3 a4 a5 a6 a7]
stride 4: [a0+a4 a1+a5 a2+a6 a3+a7 a4 a5 a6 a7]
stride 2: [a0+a4+a2+a6 a1+a5+a3+a7 ...]
stride 1: [sum of all 8 ...]
</code></pre></div></div>

<p>Here is the shared-memory reduction kernel:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define BLOCK_SIZE 256
</span>
<span class="n">__global__</span> <span class="kt">void</span> <span class="nf">sumReduction</span><span class="p">(</span><span class="k">const</span> <span class="kt">int</span><span class="o">*</span> <span class="n">input</span><span class="p">,</span> <span class="kt">int</span><span class="o">*</span> <span class="n">total</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">__shared__</span> <span class="kt">int</span> <span class="n">sdata</span><span class="p">[</span><span class="n">BLOCK_SIZE</span><span class="p">];</span>

    <span class="kt">int</span> <span class="n">tid</span> <span class="o">=</span> <span class="n">threadIdx</span><span class="p">.</span><span class="n">x</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">blockIdx</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">blockDim</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">tid</span><span class="p">;</span>

    <span class="n">sdata</span><span class="p">[</span><span class="n">tid</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">)</span> <span class="o">?</span> <span class="n">input</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
    <span class="n">__syncthreads</span><span class="p">();</span>

    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">stride</span> <span class="o">=</span> <span class="n">blockDim</span><span class="p">.</span><span class="n">x</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="n">stride</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">;</span> <span class="n">stride</span> <span class="o">&gt;&gt;=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">tid</span> <span class="o">&lt;</span> <span class="n">stride</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">sdata</span><span class="p">[</span><span class="n">tid</span><span class="p">]</span> <span class="o">+=</span> <span class="n">sdata</span><span class="p">[</span><span class="n">tid</span> <span class="o">+</span> <span class="n">stride</span><span class="p">];</span>
        <span class="p">}</span>
        <span class="n">__syncthreads</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">tid</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">atomicAdd</span><span class="p">(</span><span class="n">total</span><span class="p">,</span> <span class="n">sdata</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="warp-divergence">Warp divergence</h3>

<p>The loop above has a subtle problem. In the first round, threads 0..127 are active and threads 128..255 are idle. In the next round, threads 64..127 become idle, and so on. Because a warp executes 32 threads in lockstep, once the active set drops below 32 threads, the warp has both active and inactive lanes. The inactive lanes do not do useful work, but the warp still takes the full time to execute the instruction. This is <strong>warp divergence</strong>.</p>

<p>For the final few rounds the divergence is severe: only one thread is active in the last round, so 31 threads are masked off and waiting. It is not wrong, but it is wasteful.</p>

<h3 id="the-modern-fix-warp-shuffle">The modern fix: warp shuffle</h3>

<p>Modern CUDA lets threads in the same warp read each other’s registers directly with <strong>shuffle</strong> instructions. The reduction becomes branch-free inside the warp, which eliminates divergence. The idea is to reduce in shared memory down to 32 values, then hand those 32 values to warp 0 and finish with <code class="language-plaintext highlighter-rouge">__shfl_down_sync</code>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">__global__</span> <span class="kt">void</span> <span class="nf">sumReductionShuffle</span><span class="p">(</span><span class="k">const</span> <span class="kt">int</span><span class="o">*</span> <span class="n">input</span><span class="p">,</span> <span class="kt">int</span><span class="o">*</span> <span class="n">total</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">__shared__</span> <span class="kt">int</span> <span class="n">sdata</span><span class="p">[</span><span class="n">BLOCK_SIZE</span><span class="p">];</span>

    <span class="kt">int</span> <span class="n">tid</span> <span class="o">=</span> <span class="n">threadIdx</span><span class="p">.</span><span class="n">x</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">blockIdx</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">blockDim</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">tid</span><span class="p">;</span>

    <span class="n">sdata</span><span class="p">[</span><span class="n">tid</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">)</span> <span class="o">?</span> <span class="n">input</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
    <span class="n">__syncthreads</span><span class="p">();</span>

    <span class="c1">// Reduce in shared memory down to 32 partial sums</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">stride</span> <span class="o">=</span> <span class="n">blockDim</span><span class="p">.</span><span class="n">x</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="n">stride</span> <span class="o">&gt;</span> <span class="mi">16</span><span class="p">;</span> <span class="n">stride</span> <span class="o">&gt;&gt;=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">tid</span> <span class="o">&lt;</span> <span class="n">stride</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">sdata</span><span class="p">[</span><span class="n">tid</span><span class="p">]</span> <span class="o">+=</span> <span class="n">sdata</span><span class="p">[</span><span class="n">tid</span> <span class="o">+</span> <span class="n">stride</span><span class="p">];</span>
        <span class="p">}</span>
        <span class="n">__syncthreads</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="c1">// The first warp now holds 32 partial sums. Finish with shuffles.</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">tid</span> <span class="o">&lt;</span> <span class="mi">32</span><span class="p">)</span> <span class="p">{</span>
        <span class="kt">int</span> <span class="n">warpVal</span> <span class="o">=</span> <span class="n">sdata</span><span class="p">[</span><span class="n">tid</span><span class="p">];</span>

        <span class="n">warpVal</span> <span class="o">+=</span> <span class="n">__shfl_down_sync</span><span class="p">(</span><span class="mh">0xffffffff</span><span class="p">,</span> <span class="n">warpVal</span><span class="p">,</span> <span class="mi">16</span><span class="p">);</span>
        <span class="n">warpVal</span> <span class="o">+=</span> <span class="n">__shfl_down_sync</span><span class="p">(</span><span class="mh">0xffffffff</span><span class="p">,</span> <span class="n">warpVal</span><span class="p">,</span> <span class="mi">8</span><span class="p">);</span>
        <span class="n">warpVal</span> <span class="o">+=</span> <span class="n">__shfl_down_sync</span><span class="p">(</span><span class="mh">0xffffffff</span><span class="p">,</span> <span class="n">warpVal</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span>
        <span class="n">warpVal</span> <span class="o">+=</span> <span class="n">__shfl_down_sync</span><span class="p">(</span><span class="mh">0xffffffff</span><span class="p">,</span> <span class="n">warpVal</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
        <span class="n">warpVal</span> <span class="o">+=</span> <span class="n">__shfl_down_sync</span><span class="p">(</span><span class="mh">0xffffffff</span><span class="p">,</span> <span class="n">warpVal</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>

        <span class="k">if</span> <span class="p">(</span><span class="n">tid</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">atomicAdd</span><span class="p">(</span><span class="n">total</span><span class="p">,</span> <span class="n">warpVal</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The mask <code class="language-plaintext highlighter-rouge">0xffffffff</code> says all 32 threads participate. Every thread performs the <code class="language-plaintext highlighter-rouge">+=</code>, so there is no divergence. Some threads compute values we discard, but that is cheaper than branch serialization. Shuffle is also faster than shared memory because it uses registers and avoids bank conflicts.</p>

<h2 id="asynchronous-execution-and-streams">Asynchronous Execution and Streams</h2>

<p>Up to this point, everything has gone through CUDA’s default stream, which synchronizes with the CPU at every copy and kernel launch. That is fine for small programs, but it leaves the GPU idle while data is being copied and the CPU idle while the GPU computes.</p>

<p>CUDA streams fix this. A stream is an ordered queue of operations. Operations in different streams can run concurrently: one stream can copy data while another runs a kernel. To copy asynchronously, the memory must be pinned with <code class="language-plaintext highlighter-rouge">cudaMallocHost</code>, because the OS is not allowed to page it out during a DMA transfer.</p>

<p>Here is a pipeline that splits an array into four chunks and processes them in four streams:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;cuda_runtime.h&gt;</span><span class="cp">
</span>
<span class="cp">#define CUDA_CHECK(call) \
    do { \
        cudaError_t err = call; \
        if (err != cudaSuccess) { \
            std::cerr &lt;&lt; "CUDA Error: " &lt;&lt; cudaGetErrorString(err) \
                      &lt;&lt; " at " &lt;&lt; __FILE__ &lt;&lt; ":" &lt;&lt; __LINE__ &lt;&lt; std::endl; \
            exit(EXIT_FAILURE); \
        } \
    } while (0)
</span>
<span class="n">__global__</span> <span class="kt">void</span> <span class="nf">scaleArray</span><span class="p">(</span><span class="kt">float</span><span class="o">*</span> <span class="n">data</span><span class="p">,</span> <span class="kt">float</span> <span class="n">scale</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">blockIdx</span><span class="p">.</span><span class="n">x</span> <span class="o">*</span> <span class="n">blockDim</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">threadIdx</span><span class="p">.</span><span class="n">x</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="mi">50</span><span class="p">;</span> <span class="o">++</span><span class="n">j</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">scale</span> <span class="o">+</span> <span class="mf">0.001f</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">const</span> <span class="kt">int</span> <span class="n">numElements</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="mi">20</span><span class="p">;</span> <span class="c1">// 1,048,576</span>
    <span class="k">const</span> <span class="kt">int</span> <span class="n">numStreams</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
    <span class="k">const</span> <span class="kt">int</span> <span class="n">chunkSize</span> <span class="o">=</span> <span class="n">numElements</span> <span class="o">/</span> <span class="n">numStreams</span><span class="p">;</span>
    <span class="k">const</span> <span class="kt">int</span> <span class="n">chunkBytes</span> <span class="o">=</span> <span class="n">chunkSize</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">float</span><span class="p">);</span>

    <span class="c1">// Pinned host memory is required for async copies</span>
    <span class="kt">float</span><span class="o">*</span> <span class="n">h_data</span><span class="p">;</span>
    <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaMallocHost</span><span class="p">((</span><span class="kt">void</span><span class="o">**</span><span class="p">)</span><span class="o">&amp;</span><span class="n">h_data</span><span class="p">,</span> <span class="n">numElements</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">float</span><span class="p">)));</span>

    <span class="kt">float</span><span class="o">*</span> <span class="n">d_data</span><span class="p">;</span>
    <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaMalloc</span><span class="p">((</span><span class="kt">void</span><span class="o">**</span><span class="p">)</span><span class="o">&amp;</span><span class="n">d_data</span><span class="p">,</span> <span class="n">numElements</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">float</span><span class="p">)));</span>

    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">numElements</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">h_data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="mf">1.0f</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">cudaStream_t</span> <span class="n">streams</span><span class="p">[</span><span class="n">numStreams</span><span class="p">];</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">numStreams</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaStreamCreate</span><span class="p">(</span><span class="o">&amp;</span><span class="n">streams</span><span class="p">[</span><span class="n">i</span><span class="p">]));</span>
    <span class="p">}</span>

    <span class="kt">int</span> <span class="n">threadsPerBlock</span> <span class="o">=</span> <span class="mi">256</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">blocksPerGrid</span> <span class="o">=</span> <span class="p">(</span><span class="n">chunkSize</span> <span class="o">+</span> <span class="n">threadsPerBlock</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">/</span> <span class="n">threadsPerBlock</span><span class="p">;</span>

    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">numStreams</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
        <span class="kt">int</span> <span class="n">offset</span> <span class="o">=</span> <span class="n">i</span> <span class="o">*</span> <span class="n">chunkSize</span><span class="p">;</span>

        <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaMemcpyAsync</span><span class="p">(</span><span class="o">&amp;</span><span class="n">d_data</span><span class="p">[</span><span class="n">offset</span><span class="p">],</span> <span class="o">&amp;</span><span class="n">h_data</span><span class="p">[</span><span class="n">offset</span><span class="p">],</span>
                                   <span class="n">chunkBytes</span><span class="p">,</span> <span class="n">cudaMemcpyHostToDevice</span><span class="p">,</span>
                                   <span class="n">streams</span><span class="p">[</span><span class="n">i</span><span class="p">]));</span>

        <span class="n">scaleArray</span><span class="o">&lt;&lt;&lt;</span><span class="n">blocksPerGrid</span><span class="p">,</span> <span class="n">threadsPerBlock</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">streams</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">&gt;&gt;&gt;</span>
            <span class="p">(</span><span class="o">&amp;</span><span class="n">d_data</span><span class="p">[</span><span class="n">offset</span><span class="p">],</span> <span class="mf">2.0f</span><span class="p">,</span> <span class="n">chunkSize</span><span class="p">);</span>

        <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaMemcpyAsync</span><span class="p">(</span><span class="o">&amp;</span><span class="n">h_data</span><span class="p">[</span><span class="n">offset</span><span class="p">],</span> <span class="o">&amp;</span><span class="n">d_data</span><span class="p">[</span><span class="n">offset</span><span class="p">],</span>
                                   <span class="n">chunkBytes</span><span class="p">,</span> <span class="n">cudaMemcpyDeviceToHost</span><span class="p">,</span>
                                   <span class="n">streams</span><span class="p">[</span><span class="n">i</span><span class="p">]));</span>
    <span class="p">}</span>

    <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaDeviceSynchronize</span><span class="p">());</span>

    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"First value: "</span> <span class="o">&lt;&lt;</span> <span class="n">h_data</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Last value:  "</span> <span class="o">&lt;&lt;</span> <span class="n">h_data</span><span class="p">[</span><span class="n">numElements</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>

    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">numStreams</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaStreamDestroy</span><span class="p">(</span><span class="n">streams</span><span class="p">[</span><span class="n">i</span><span class="p">]));</span>
    <span class="p">}</span>

    <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaFreeHost</span><span class="p">(</span><span class="n">h_data</span><span class="p">));</span>
    <span class="n">CUDA_CHECK</span><span class="p">(</span><span class="n">cudaFree</span><span class="p">(</span><span class="n">d_data</span><span class="p">));</span>

    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The kernel launch syntax now has a fourth argument: the stream. The third argument is dynamic shared memory size, which we do not need here.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">scaleArray</span><span class="o">&lt;&lt;&lt;</span><span class="n">blocks</span><span class="p">,</span> <span class="n">threads</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">stream</span><span class="o">&gt;&gt;&gt;</span><span class="p">(...);</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">cudaMemcpyAsync</code>, the kernel launch, and the next <code class="language-plaintext highlighter-rouge">cudaMemcpyAsync</code> all return immediately. The CPU queues work for each stream and then waits once at the end. In practice, the GPU’s copy engine and compute units can overlap, so the total time is closer to the longest single chunk than to the sum of all chunks.</p>

<p>A word of caution about pinned memory: because it is page-locked, the OS cannot swap it out. If you allocate too much, you starve the rest of the system. Use pinned memory as a staging area, not as your primary storage.</p>

<h2 id="conclusion--where-to-go-next">Conclusion / Where to Go Next</h2>

<p>You now have the building blocks of CUDA programming: kernels, threads, blocks, grids, device memory, shared memory, tiling, coalescing, reduction, and streams. The pattern is almost always the same: move data to the GPU, launch enough threads to cover the problem, keep memory access patterns regular, and overlap work where you can.</p>

<p>What comes next depends on what you are building:</p>

<ul>
  <li><strong>cuBLAS</strong> and <strong>cuDNN</strong> provide highly tuned implementations of linear algebra and deep-learning primitives. Use them before writing your own matrix kernels.</li>
  <li><strong>Nsight Compute</strong> and <strong>Nsight Systems</strong> are NVIDIA’s profilers. They show memory throughput, occupancy, warp divergence, and where your kernel actually spends its time.</li>
  <li><strong>Cooperative Groups</strong> is a newer API for synchronizing and shuffling at warp, block, and grid levels with cleaner abstractions than raw <code class="language-plaintext highlighter-rouge">__syncthreads</code>.</li>
</ul>

<p>The best way to learn CUDA is to write kernels that solve real problems and then profile them. Start simple, measure, and optimize only the parts the profiler tells you are slow. Good luck.</p>]]></content><author><name>Arun Kant Sharma</name><email>mail@arunkant.com</email></author><category term="Programming" /><category term="cuda" /><category term="c++" /><category term="gpu" /><category term="parallel-computing" /><category term="machine-learning" /><summary type="html"><![CDATA[A practical, from-zero guide to writing your first CUDA kernels, understanding the GPU execution model, and optimizing with shared memory, tiling, and streams.]]></summary></entry><entry><title type="html">How to Stop Claude from Ghostwriting Your Git History (And Fix It If It Already Did)</title><link href="https://www.arunkant.com/posts/co-authored-by-claude/" rel="alternate" type="text/html" title="How to Stop Claude from Ghostwriting Your Git History (And Fix It If It Already Did)" /><published>2026-06-02T00:00:00+05:30</published><updated>2026-06-02T00:00:00+05:30</updated><id>https://www.arunkant.com/posts/Co-Authored-by-Claude</id><content type="html" xml:base="https://www.arunkant.com/posts/co-authored-by-claude/"><![CDATA[<nav class="post-toc">
  <p><strong>Contents</strong></p>
<ul id="markdown-toc">
  <li><a href="#the-almost-solutions" id="markdown-toc-the-almost-solutions">The “Almost” Solutions</a></li>
  <li><a href="#the-ultimate-fix-git-filter-repo" id="markdown-toc-the-ultimate-fix-git-filter-repo">The Ultimate Fix: <code class="language-plaintext highlighter-rouge">git filter-repo</code></a>    <ul>
      <li><a href="#step-1-install-git-filter-repo" id="markdown-toc-step-1-install-git-filter-repo">Step 1: Install <code class="language-plaintext highlighter-rouge">git filter-repo</code></a></li>
      <li><a href="#step-2-the-magic-one-liner" id="markdown-toc-step-2-the-magic-one-liner">Step 2: The Magic One-Liner</a></li>
      <li><a href="#step-3-re-link-and-force-push" id="markdown-toc-step-3-re-link-and-force-push">Step 3: Re-link and Force Push</a></li>
    </ul>
  </li>
  <li><a href="#preventing-future-attributions" id="markdown-toc-preventing-future-attributions">Preventing Future Attributions</a></li>
  <li><a href="#a-quick-warning-on-rewriting-history" id="markdown-toc-a-quick-warning-on-rewriting-history">A Quick Warning on Rewriting History</a></li>
</ul>

</nav>

<p>If you’ve been using AI coding assistants lately, you’ve probably experienced that moment of magic where the AI writes a perfect block of code, structures your boilerplate, and even writes a neat commit message for you.</p>

<p>But recently, I looked at my repository’s commit history and noticed a highly annoying stowaway:</p>

<p><code class="language-plaintext highlighter-rouge">Co-Authored-By: Claude &lt;noreply@anthropic.com&gt;</code></p>

<p><img src="/assets/images/2026-06-02-co-authored-by-claude/git-commit-claude.png" alt="A git commit message showing Claude listed as a co-author" /></p>

<p>Suddenly, my clean git history was littered with co-author tags. While I appreciate the help, I don’t need my version control looking like a joint venture with a large language model. Not only does it clutter up the <code class="language-plaintext highlighter-rouge">git log</code>, it also surfaces in the GitHub UI on every commit:</p>

<p><img src="/assets/images/2026-06-02-co-authored-by-claude/claude-in-github-ui.png" alt="GitHub's commit view showing Claude credited alongside the author" /></p>

<p>And worse — it messes with repository contributor stats, adding Claude to the contributors list as if it were a teammate:</p>

<p><img src="/assets/images/2026-06-02-co-authored-by-claude/claude-added-to-contributors.png" alt="GitHub contributors page listing Claude as a project contributor" /></p>

<p>I wanted them gone. But if you know anything about Git, you know that changing old commit messages isn’t as simple as hitting “Edit.”</p>

<p>Here is how I navigated the rabbit hole of Git history rewriting, what failed, and the ultimate solution that finally cleaned up my repo.</p>

<h3 id="the-almost-solutions">The “Almost” Solutions</h3>

<p>My first instinct was to use a bash script. A quick search usually points to <strong><code class="language-plaintext highlighter-rouge">git filter-branch</code></strong>. I threw a <code class="language-plaintext highlighter-rouge">sed</code> command at it, only to be greeted by a massive Git warning telling me that <code class="language-plaintext highlighter-rouge">filter-branch</code> is deprecated, dangerous, and known to mangle histories. No thanks.</p>

<p>Next, I tried an interactive rebase:</p>

<p><code class="language-plaintext highlighter-rouge">git rebase --root --exec "..."</code></p>

<p>This actually worked beautifully for my main branch! But it had a fatal flaw: <strong>rebase is a single-branch tool.</strong> When the rebase finished, my <code class="language-plaintext highlighter-rouge">main</code> branch was clean, but my other branches were untouched. Worse, all my Git tags were left behind, still pointing to the old, contaminated commit hashes.</p>

<p>I needed a way to nuke these messages across <em>every</em> branch and <em>every</em> tag simultaneously.</p>

<h3 id="the-ultimate-fix-git-filter-repo">The Ultimate Fix: <code class="language-plaintext highlighter-rouge">git filter-repo</code></h3>

<p>Git’s official recommendation for this kind of heavy lifting is a tool called <code class="language-plaintext highlighter-rouge">git filter-repo</code>. It is blisteringly fast, handles tags and branches automatically, and is designed specifically to not corrupt your repo.</p>

<p>Here is the exact step-by-step process to scrub Claude (or any other AI) from your entire repository.</p>

<h4 id="step-1-install-git-filter-repo">Step 1: Install <code class="language-plaintext highlighter-rouge">git filter-repo</code></h4>

<p>It’s a Python-based tool, so installation is incredibly easy.</p>

<p>If you’re on a Mac:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>brew <span class="nb">install </span>git-filter-repo
</code></pre></div></div>

<p>Or via Python/pip (works anywhere):</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip <span class="nb">install </span>git-filter-repo
</code></pre></div></div>

<h4 id="step-2-the-magic-one-liner">Step 2: The Magic One-Liner</h4>

<p>Before doing this, ensure you have a clean working directory.</p>

<p><code class="language-plaintext highlighter-rouge">git filter-repo</code> allows you to pass a small Python callback directly in the terminal to modify commit messages on the fly. Open your terminal in the root of your project and run this:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git filter-repo <span class="nt">--message-callback</span> <span class="s1">'
import re
return re.sub(b"(?m)^.*Co-Authored.*Claude.*\n?", b"", message)
'</span>
</code></pre></div></div>

<p><strong>What is this doing?</strong>
It iterates through every single commit, branch, and tag in your repository. It looks for any line containing “Co-Authored” and “Claude” and replaces it with nothing. Because it rewrites the commits, your tags are automatically updated to point to the new, clean commit hashes.</p>

<h4 id="step-3-re-link-and-force-push">Step 3: Re-link and Force Push</h4>

<p>Because rewriting history changes all your commit hashes, <code class="language-plaintext highlighter-rouge">git filter-repo</code> has a built-in safety mechanism: it automatically removes your remote tracking branches (like <code class="language-plaintext highlighter-rouge">origin</code>) so you don’t accidentally push before verifying.</p>

<p>Once you’ve checked your git log and confirmed Claude is gone, re-add your remote:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git remote add origin https://github.com/your-username/your-repo.git
</code></pre></div></div>

<p>Finally, push your new, clean history back to your remote. You must push branches and tags explicitly:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push origin <span class="nt">--force</span> <span class="nt">--all</span>
git push origin <span class="nt">--force</span> <span class="nt">--tags</span>
</code></pre></div></div>

<h3 id="preventing-future-attributions">Preventing Future Attributions</h3>

<p>Cleaning up history is only half the battle. If you don’t change anything, Claude will happily start adding <code class="language-plaintext highlighter-rouge">Co-Authored-By</code> lines back on your very next commit. The fix is a one-time tweak to your Claude Code settings.</p>

<p>Open (or create) <code class="language-plaintext highlighter-rouge">~/.claude/settings.json</code> and set the <code class="language-plaintext highlighter-rouge">attribution</code> fields to empty strings:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"attribution"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"commit"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w">
    </span><span class="nl">"pr"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>This tells Claude Code to skip the commit trailer <em>and</em> the PR description footer that normally credit it as a co-author. Save the file and you’re done — no restart needed. Every future commit and PR Claude creates on your behalf will be free of attribution noise.</p>

<h3 id="a-quick-warning-on-rewriting-history">A Quick Warning on Rewriting History</h3>

<p>Rewriting Git history is the nuclear option. Because the commit hashes change, anyone else working on this repository with you will have a broken local environment. If you are working on a solo project, fire away. If you are working on a team, make sure everyone pushes their changes, run this script, and then have your teammates delete their local folders and re-clone the repository from scratch.</p>

<p>AI assistants are amazing tools, but our commit history belongs to us. Hopefully, this saves you the headache of dealing with unwanted AI co-authors!</p>]]></content><author><name>Arun Kant Sharma</name><email>mail@arunkant.com</email></author><category term="Git" /><category term="git" /><category term="ai" /><category term="claude" /><category term="filter-repo" /><category term="productivity" /><summary type="html"><![CDATA[Claude was silently adding itself as a co-author on every commit. Here's how I scrubbed it from my entire repo — branches, tags, and all — using git filter-repo.]]></summary></entry><entry><title type="html">Why I’m Building SaaS in 2026</title><link href="https://www.arunkant.com/posts/building-saas-in-2026/" rel="alternate" type="text/html" title="Why I’m Building SaaS in 2026" /><published>2026-04-29T00:00:00+05:30</published><updated>2026-04-29T00:00:00+05:30</updated><id>https://www.arunkant.com/posts/building-saas-in-2026</id><content type="html" xml:base="https://www.arunkant.com/posts/building-saas-in-2026/"><![CDATA[<nav class="post-toc">
  <p><strong>Contents</strong></p>
<ul id="markdown-toc">
  <li><a href="#saas-isnt-dying-but-the-conversation-is-shifting" id="markdown-toc-saas-isnt-dying-but-the-conversation-is-shifting">SaaS Isn’t Dying, But the Conversation Is Shifting</a></li>
  <li><a href="#the-agent-trap-swiss-army-knives-made-of-jelly" id="markdown-toc-the-agent-trap-swiss-army-knives-made-of-jelly">The Agent Trap: Swiss Army Knives Made of Jelly</a></li>
  <li><a href="#the-framework-agent-first-workflow-second" id="markdown-toc-the-framework-agent-first-workflow-second">The Framework: Agent First, Workflow Second</a></li>
  <li><a href="#build-vs-buy-the-hidden-maintenance-tax" id="markdown-toc-build-vs-buy-the-hidden-maintenance-tax">Build vs. Buy: The Hidden Maintenance Tax</a></li>
  <li><a href="#what-this-looks-like-in-practice" id="markdown-toc-what-this-looks-like-in-practice">What This Looks Like in Practice</a></li>
  <li><a href="#saas-in-2026-is-the-plumbing-not-the-hype" id="markdown-toc-saas-in-2026-is-the-plumbing-not-the-hype">SaaS in 2026 Is the Plumbing, Not the Hype</a></li>
</ul>

</nav>

<p>Every few months, someone declares SaaS dead. The argument has gotten louder in 2026: why pay for vertical tools when an LLM and a GitHub Action can do the same job in an afternoon?</p>

<p>I’ve heard this pitch enough times - and built enough of those afternoon GitHub Actions myself - to know where it breaks. The demo always works. The Tuesday morning two months later, when the upstream API changes its response shape and your “AI agent” silently ships nonsense to customers, is where the wheels come off.</p>

<p>I think SaaS in 2026 is healthier than the obituaries suggest, but the conversation around it is shifting in ways worth paying attention to.</p>

<h2 id="saas-isnt-dying-but-the-conversation-is-shifting">SaaS Isn’t Dying, But the Conversation Is Shifting</h2>

<p>You’ve seen the takes. <em>“SaaS is dead.”</em> <em>“AI agents will replace every vertical tool.”</em> <em>“Why buy software when you can just prompt an LLM to do it in-house?”</em></p>

<p>I don’t buy it.</p>

<p>Those takes confuse the <strong>interface</strong> with the <strong>infrastructure</strong>. Yes, AI changes how we interact with software. But the need for shared, maintained, specialized tools doesn’t vanish just because you can spin up an Autogen crew in ten minutes.</p>

<p>If anything, the more AI floods the market, the more valuable it becomes to have a <em>concrete workflow</em> that actually works while you sleep.</p>

<h2 id="the-agent-trap-swiss-army-knives-made-of-jelly">The Agent Trap: Swiss Army Knives Made of Jelly</h2>

<p>In-house AI agents are seductive because they’re infinitely flexible. The same agent can summarize tickets, draft emails, assign blame for bugs, and probably order pizza if you give it a DoorDash API key.</p>

<p>But that flexibility comes at a hidden cost: <strong>reliability</strong>.</p>

<p>An agent is essentially a reasoning layer wrapped around hope. It guesses at priorities. It hallucinates whether a PR description is customer-facing or internal. It breaks when an upstream tool sneezes. And every time a new model drops, you’re back to prompt-engineering a Friday afternoon away.</p>

<p>The real cost isn’t the OpenAI bill. It’s you, at 11 PM, debugging why your changelog included <em>“fix typo in admin panel”</em> in the email that just went to 10,000 users.</p>

<h2 id="the-framework-agent-first-workflow-second">The Framework: Agent First, Workflow Second</h2>

<p>This isn’t an argument against agents. It’s an argument for knowing <em>when</em> to use them.</p>

<p>The pattern I keep coming back to:</p>

<p><strong>1. Use agents to figure out the workflow.</strong>
What do internal teams actually want - raw ticket lists grouped by squad, or plain-English summaries? Should security patches get a red border? Should refactors be auto-filtered? Agents are great for exploration. You can ask, iterate, and throw away.</p>

<p><strong>2. Convert the agent into a concrete workflow.</strong>
Once you know the shape of the work, stop treating it like a conversation. Hard-code the rules. Build the validation layer. Lock the integration. Turn the fuzzy agent into reliable software that does the same correct thing every Tuesday at 9 AM.</p>

<p><strong>3. Mix intelligence and consistency where each belongs.</strong>
Use AI for the parts that benefit from intelligence - reading unstructured tickets, understanding context, writing human prose. Use software for the parts that require consistency - formatting, routing, permissions, delivery.</p>

<p>The mistake most teams make is stopping at step one and shipping the agent.</p>

<h2 id="build-vs-buy-the-hidden-maintenance-tax">Build vs. Buy: The Hidden Maintenance Tax</h2>

<p>There’s another argument I keep hearing: <em>“We’ll just build our own AI tools internally. It’s cheaper, and our data stays in-house.”</em></p>

<p>Sure. But agents are <strong>not</strong> set-and-forget.</p>

<p>You still need people to maintain them. New API version from JIRA? Fix the parser. New model release? Retest all your prompts. Linear changed their webhook format again? Back to the logs. You’ve built a fragile ETL pipeline dressed up as a chatbot, and now you’re the on-call engineer for a paragraph generator.</p>

<p>There’s also a quieter cost most teams don’t price in: <strong>external tools learn faster.</strong></p>

<p>If every company builds its own changelog bot, you’ve got 500 engineering teams each solving the same edge cases in isolation. One team figures out how to handle JIRA sub-tasks. Another figures out GitHub co-author attribution. Nobody shares notes. A shared tool learns from all of them. Your internal agent only learns from you. Over time, that compounds.</p>

<h2 id="what-this-looks-like-in-practice">What This Looks Like in Practice</h2>

<p>Imagine the work of generating release notes done right.</p>

<p>You connect to your JIRA board (or GitHub, or Linear). You define your audiences - maybe an internal Slack channel for the engineering team and a public page for users. From your earlier exploration, you already know the rules:</p>

<ul>
  <li>Internal changelogs need ticket IDs and squad assignments.</li>
  <li>External changelogs need human-readable context, no jargon.</li>
  <li>Security patches always get highlighted.</li>
  <li>“WIP” and “refactor” tickets get filtered out unless manually overridden.</li>
</ul>

<p>Those rules become a workflow. Every release, it reads your tickets, applies the logic, generates the prose, and delivers it to the right place. It doesn’t get creative. It doesn’t forget the rules because it’s Tuesday. It just works.</p>

<p>You get the intelligence of AI - it understands your messy tickets - wrapped in the reliability of actual software. That’s the shape of the SaaS I want to use, and it’s the shape of the SaaS I’m building with <a href="https://releasedog.com">Releasedog</a>.</p>

<h2 id="saas-in-2026-is-the-plumbing-not-the-hype">SaaS in 2026 Is the Plumbing, Not the Hype</h2>

<p>I’m not skeptical of AI. I’m skeptical of <em>where</em> people are pointing it.</p>

<p>Agents are incredible demos. They’re terrible infrastructure.</p>

<p>The future belongs to tools that take AI’s flexibility and trap it inside software’s reliability. Use agents to explore. Use workflows to run your business. And for the love of your future self, stop maintaining that Friday-night GitHub Action that generates your changelog.</p>

<p>Your 11 PM self will thank you.</p>]]></content><author><name>Arun Kant Sharma</name><email>mail@arunkant.com</email></author><category term="SaaS" /><category term="saas" /><category term="ai" /><category term="agents" /><category term="workflows" /><summary type="html"><![CDATA[In-house AI agents are seductive but fragile. Here's the case for using agents to explore and concrete workflows to ship.]]></summary></entry><entry><title type="html">The Un-Abstracted Frontend</title><link href="https://www.arunkant.com/posts/the-un-abstracted-frontend/" rel="alternate" type="text/html" title="The Un-Abstracted Frontend" /><published>2025-10-01T00:00:00+05:30</published><updated>2025-10-01T00:00:00+05:30</updated><id>https://www.arunkant.com/posts/The-Un-Abstracted-Frontend</id><content type="html" xml:base="https://www.arunkant.com/posts/the-un-abstracted-frontend/"><![CDATA[<nav class="post-toc">
  <p><strong>Contents</strong></p>
<ul id="markdown-toc">
  <li><a href="#building-a-modern-react-app-from-scratch-no-vite-no-nextjs" id="markdown-toc-building-a-modern-react-app-from-scratch-no-vite-no-nextjs">Building a Modern React App from Scratch (No Vite, No Next.js!)</a></li>
  <li><a href="#phase-1-the-vanilla-js-core-handling-modern-javascript" id="markdown-toc-phase-1-the-vanilla-js-core-handling-modern-javascript">Phase 1: The Vanilla JS Core (Handling Modern JavaScript)</a>    <ul>
      <li><a href="#1-project-initialization-and-structure" id="markdown-toc-1-project-initialization-and-structure">1. Project Initialization and Structure</a></li>
      <li><a href="#2-the-core-tools-webpack-and-babel" id="markdown-toc-2-the-core-tools-webpack-and-babel">2. The Core Tools: webpack and Babel</a></li>
      <li><a href="#3-the-code-modern-js" id="markdown-toc-3-the-code-modern-js">3. The Code: Modern JS</a></li>
    </ul>
  </li>
  <li><a href="#phase-2-handling-assets-css-and-images" id="markdown-toc-phase-2-handling-assets-css-and-images">Phase 2: Handling Assets (CSS and Images)</a>    <ul>
      <li><a href="#5-adding-assets-and-loaders" id="markdown-toc-5-adding-assets-and-loaders">5. Adding Assets and Loaders</a></li>
      <li><a href="#6-configuration-for-html-and-css" id="markdown-toc-6-configuration-for-html-and-css">6. Configuration for HTML and CSS</a></li>
      <li><a href="#7-the-final-npm-scripts" id="markdown-toc-7-the-final-npm-scripts">7. The Final npm Scripts</a></li>
    </ul>
  </li>
  <li><a href="#phase-3-layering-react-jsx-transformation" id="markdown-toc-phase-3-layering-react-jsx-transformation">Phase 3: Layering React (JSX Transformation)</a>    <ul>
      <li><a href="#8-installing-react-and-the-jsx-preset" id="markdown-toc-8-installing-react-and-the-jsx-preset">8. Installing React and the JSX Preset</a></li>
      <li><a href="#9-configure-babel-and-webpack-for-jsx" id="markdown-toc-9-configure-babel-and-webpack-for-jsx">9. Configure Babel and webpack for JSX</a></li>
      <li><a href="#10-write-your-react-code" id="markdown-toc-10-write-your-react-code">10. Write Your React Code</a></li>
    </ul>
  </li>
</ul>

</nav>

<h2 id="building-a-modern-react-app-from-scratch-no-vite-no-nextjs">Building a Modern React App from Scratch (No Vite, No Next.js!)</h2>
<p>Grounded Development: Why the “Magic” Needs to Stop
If you’re new to modern JavaScript, running npx create-react-app or npx create-vite feels like pure magic. In seconds, you have a working app!</p>

<p>But what actually converts your cool ES6 consts and your funky JSX into browser-friendly code?</p>

<p>We’re going to strip away the abstractions and build a clean, predictable development environment using just npm, webpack (the Bundler), and Babel (the Transpiler). We will build the pipeline in three phases, adding a new capability in each step.</p>

<h2 id="phase-1-the-vanilla-js-core-handling-modern-javascript">Phase 1: The Vanilla JS Core (Handling Modern JavaScript)</h2>
<p>Our first goal is simple: Get a modern JS file to run in the browser.</p>

<h3 id="1-project-initialization-and-structure">1. Project Initialization and Structure</h3>
<p>Every modern project starts here.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Create the folder and start npm</span>
<span class="nb">mkdir </span>grounded-app
<span class="nb">cd </span>grounded-app
npm init <span class="nt">-y</span>

<span class="c"># Create the source and output directories</span>
<span class="nb">mkdir </span>src dist
</code></pre></div></div>
<h3 id="2-the-core-tools-webpack-and-babel">2. The Core Tools: webpack and Babel</h3>
<p>We need a bundler to combine files and a transpiler to convert modern JS.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Install bundler/server tools and Babel core</span>
npm <span class="nb">install</span> <span class="nt">--save-dev</span> <span class="se">\</span>
  webpack webpack-cli webpack-dev-server <span class="se">\</span>
  @babel/core babel-loader @babel/preset-env
</code></pre></div></div>
<h3 id="3-the-code-modern-js">3. The Code: Modern JS</h3>
<p>Let’s use an arrow function that older browsers might not understand.</p>

<p>src/index.js</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">greet</span> <span class="o">=</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="s2">`Hello, </span><span class="p">${</span><span class="nx">name</span><span class="p">}</span><span class="s2">! This is modern JS.`</span><span class="p">);</span>
<span class="p">};</span>

<span class="nb">document</span><span class="p">.</span><span class="nf">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">DOMContentLoaded</span><span class="dl">'</span><span class="p">,</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nf">greet</span><span class="p">(</span><span class="dl">'</span><span class="s1">Grounded Developer</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<ol>
  <li>Configuration for Transpilation
We tell Babel what transformations to apply, and we tell webpack how to use Babel.</li>
</ol>

<p>.babelrc (In the project root)</p>

<pre><code class="language-JSON">{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": "defaults"
      }
    ]
  ]
}
</code></pre>

<p>webpack.config.js (Minimal Setup)</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">path</span> <span class="o">=</span> <span class="nf">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">path</span><span class="dl">'</span><span class="p">);</span>

<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="p">{</span>
  <span class="na">entry</span><span class="p">:</span> <span class="dl">'</span><span class="s1">./src/index.js</span><span class="dl">'</span><span class="p">,</span>
  <span class="na">output</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">filename</span><span class="p">:</span> <span class="dl">'</span><span class="s1">bundle.js</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">path</span><span class="p">:</span> <span class="nx">path</span><span class="p">.</span><span class="nf">resolve</span><span class="p">(</span><span class="nx">__dirname</span><span class="p">,</span> <span class="dl">'</span><span class="s1">dist</span><span class="dl">'</span><span class="p">),</span>
    <span class="na">clean</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
  <span class="p">},</span>
  <span class="na">module</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">rules</span><span class="p">:</span> <span class="p">[</span>
      <span class="c1">// THE BABEL RULE: Apply babel-loader to all .js files outside node_modules</span>
      <span class="p">{</span>
        <span class="na">test</span><span class="p">:</span> <span class="sr">/</span><span class="se">\.</span><span class="sr">js$/</span><span class="p">,</span> 
        <span class="na">exclude</span><span class="p">:</span> <span class="sr">/node_modules/</span><span class="p">,</span>
        <span class="na">use</span><span class="p">:</span> <span class="p">{</span> <span class="na">loader</span><span class="p">:</span> <span class="dl">'</span><span class="s1">babel-loader</span><span class="dl">'</span> <span class="p">},</span>
      <span class="p">},</span>
    <span class="p">],</span>
  <span class="p">},</span>
  <span class="na">mode</span><span class="p">:</span> <span class="dl">'</span><span class="s1">development</span><span class="dl">'</span>
<span class="p">};</span>
</code></pre></div></div>
<p>What happens: webpack bundles the file, and the babel-loader ensures the arrow function is converted to a browser-safe function() {} along the way.</p>

<h2 id="phase-2-handling-assets-css-and-images">Phase 2: Handling Assets (CSS and Images)</h2>
<p>A frontend app isn’t just JavaScript. Now we teach webpack to handle other file types using Loaders and Plugins.</p>

<h3 id="5-adding-assets-and-loaders">5. Adding Assets and Loaders</h3>
<p>We need loaders for CSS and a plugin to manage our HTML file.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Install asset loaders and the HTML plugin</span>
npm <span class="nb">install</span> <span class="nt">--save-dev</span> style-loader css-loader html-webpack-plugin
</code></pre></div></div>
<h3 id="6-configuration-for-html-and-css">6. Configuration for HTML and CSS</h3>
<p>A. HTML Plugin: We use html-webpack-plugin to generate the output HTML and inject the script tag automatically.
index.html (Update the entry point to be served as the template)</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...
<span class="nt">&lt;body&gt;</span>
    <span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">"app"</span><span class="nt">&gt;&lt;/div&gt;</span>
    <span class="nt">&lt;/body&gt;</span>
...
</code></pre></div></div>
<p>B. webpack.config.js (Adding the asset rules)</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">path</span> <span class="o">=</span> <span class="nf">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">path</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">HtmlWebpackPlugin</span> <span class="o">=</span> <span class="nf">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">html-webpack-plugin</span><span class="dl">'</span><span class="p">);</span> 

<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="p">{</span>
  <span class="c1">// ... (entry, output, devServer, mode remain the same)</span>

  <span class="na">module</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">rules</span><span class="p">:</span> <span class="p">[</span>
      <span class="c1">// ... (Babel rule remains)</span>
      
      <span class="c1">// NEW CSS RULE</span>
      <span class="p">{</span>
        <span class="na">test</span><span class="p">:</span> <span class="sr">/</span><span class="se">\.</span><span class="sr">css$/</span><span class="p">,</span>
        <span class="c1">// Loaders run R-L: css-loader resolves imports, style-loader injects into DOM</span>
        <span class="na">use</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">style-loader</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">css-loader</span><span class="dl">'</span><span class="p">],</span>
      <span class="p">},</span>
      <span class="c1">// NEW IMAGE/ASSET RULE (using webpack 5's built-in Asset Module)</span>
      <span class="p">{</span>
        <span class="na">test</span><span class="p">:</span> <span class="sr">/</span><span class="se">\.(</span><span class="sr">png|svg|jpg|jpeg|gif</span><span class="se">)</span><span class="sr">$/i</span><span class="p">,</span>
        <span class="na">type</span><span class="p">:</span> <span class="dl">'</span><span class="s1">asset/resource</span><span class="dl">'</span><span class="p">,</span> <span class="c1">// Copies the file to 'dist' and provides the URL</span>
      <span class="p">},</span>
    <span class="p">],</span>
  <span class="p">},</span>
  
  <span class="c1">// NEW PLUGIN SECTION</span>
  <span class="na">plugins</span><span class="p">:</span> <span class="p">[</span>
    <span class="k">new</span> <span class="nc">HtmlWebpackPlugin</span><span class="p">({</span>
      <span class="na">template</span><span class="p">:</span> <span class="nx">path</span><span class="p">.</span><span class="nf">resolve</span><span class="p">(</span><span class="nx">__dirname</span><span class="p">,</span> <span class="dl">'</span><span class="s1">index.html</span><span class="dl">'</span><span class="p">),</span> 
      <span class="na">filename</span><span class="p">:</span> <span class="dl">'</span><span class="s1">index.html</span><span class="dl">'</span><span class="p">,</span>
    <span class="p">}),</span>
  <span class="p">],</span>

  <span class="c1">// ... (devServer remains the same)</span>
<span class="p">};</span>
</code></pre></div></div>
<h3 id="7-the-final-npm-scripts">7. The Final npm Scripts</h3>
<p>We create our convenient scripts to start the server and run the final production build.</p>

<p>package.json (Scripts section)</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">"scripts"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
  </span><span class="nl">"build"</span><span class="p">:</span><span class="w"> </span><span class="s2">"webpack --mode production"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"start"</span><span class="p">:</span><span class="w"> </span><span class="s2">"webpack serve --open --mode development"</span><span class="w">
</span><span class="p">}</span><span class="err">,</span><span class="w">
</span></code></pre></div></div>
<h2 id="phase-3-layering-react-jsx-transformation">Phase 3: Layering React (JSX Transformation)</h2>
<p>Finally, we introduce React and its primary feature, JSX.</p>

<h3 id="8-installing-react-and-the-jsx-preset">8. Installing React and the JSX Preset</h3>
<p>We need the actual React libraries and the special Babel preset to handle JSX.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Install React core libraries</span>
npm <span class="nb">install </span>react react-dom

<span class="c"># Install the Babel preset for JSX</span>
npm <span class="nb">install</span> <span class="nt">--save-dev</span> @babel/preset-react
</code></pre></div></div>
<h3 id="9-configure-babel-and-webpack-for-jsx">9. Configure Babel and webpack for JSX</h3>
<p>We update the configs to recognize JSX files and syntax.</p>

<p>.babelrc (Add the React preset)</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"presets"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
    </span><span class="s2">"@babel/preset-react"</span><span class="p">,</span><span class="w"> </span><span class="err">//</span><span class="w"> </span><span class="err">&lt;--</span><span class="w"> </span><span class="err">Now</span><span class="w"> </span><span class="err">handles</span><span class="w"> </span><span class="err">JSX</span><span class="w"> </span><span class="err">syntax!</span><span class="w">
    </span><span class="p">[</span><span class="s2">"@babel/preset-env"</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"targets"</span><span class="p">:</span><span class="w"> </span><span class="s2">"defaults"</span><span class="w"> </span><span class="p">}]</span><span class="w">
  </span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>webpack.config.js (Update to include the .jsx extension)</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// ...</span>
  <span class="nx">module</span><span class="p">:</span> <span class="p">{</span>
    <span class="nl">rules</span><span class="p">:</span> <span class="p">[</span>
      <span class="c1">// Updated test regex to include .jsx files</span>
      <span class="p">{</span>
        <span class="na">test</span><span class="p">:</span> <span class="sr">/</span><span class="se">\.(</span><span class="sr">js|jsx</span><span class="se">)</span><span class="sr">$/</span><span class="p">,</span> 
        <span class="na">exclude</span><span class="p">:</span> <span class="sr">/node_modules/</span><span class="p">,</span>
        <span class="na">use</span><span class="p">:</span> <span class="p">{</span> <span class="na">loader</span><span class="p">:</span> <span class="dl">'</span><span class="s1">babel-loader</span><span class="dl">'</span> <span class="p">},</span>
      <span class="p">},</span>
      <span class="c1">// ... (asset rules remain)</span>
    <span class="p">],</span>
  <span class="p">},</span>
  
  <span class="nx">resolve</span><span class="p">:</span> <span class="p">{</span>
    <span class="c1">// Allows importing files with .js or .jsx extensions without specifying them</span>
    <span class="nl">extensions</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">.js</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">.jsx</span><span class="dl">'</span><span class="p">],</span> 
  <span class="p">},</span>
<span class="c1">// ...</span>
</code></pre></div></div>
<h3 id="10-write-your-react-code">10. Write Your React Code</h3>
<p>Our code is now built on the new standard.</p>

<p>src/App.js</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">react</span><span class="dl">'</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">App</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">title</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="c1">// JSX in action!</span>
  <span class="k">return</span> <span class="o">&lt;</span><span class="nx">h1</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">title</span><span class="p">}</span><span class="o">&lt;</span><span class="sr">/h1&gt;</span><span class="err">;
</span><span class="p">};</span>

<span class="k">export</span> <span class="k">default</span> <span class="nx">App</span><span class="p">;</span>
</code></pre></div></div>
<p>src/index.js</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">react</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="nx">ReactDOM</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">react-dom/client</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="nx">App</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">./App</span><span class="dl">'</span><span class="p">;</span>

<span class="nb">document</span><span class="p">.</span><span class="nf">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">DOMContentLoaded</span><span class="dl">'</span><span class="p">,</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">container</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nf">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">app</span><span class="dl">'</span><span class="p">);</span>
    <span class="kd">const</span> <span class="nx">root</span> <span class="o">=</span> <span class="nx">ReactDOM</span><span class="p">.</span><span class="nf">createRoot</span><span class="p">(</span><span class="nx">container</span><span class="p">);</span>
    
    <span class="nx">root</span><span class="p">.</span><span class="nf">render</span><span class="p">(</span>
        <span class="o">&lt;</span><span class="nx">App</span> <span class="nx">title</span><span class="o">=</span><span class="dl">"</span><span class="s2">Final Grounded Setup Complete!</span><span class="dl">"</span> <span class="o">/&gt;</span>
    <span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<p><strong>Final Thoughts</strong>: The End of the Magic
What you have now is the entire build pipeline for a modern single-page application.</p>

<p>The “magic” of frameworks like Vite and Next.js is simply that they pre-configure these 10 steps for you in a highly optimized way. By building it yourself, you now understand exactly what is happening under the hood. It’s good to have a predictable development environment.</p>]]></content><author><name>Arun Kant Sharma</name><email>mail@arunkant.com</email></author><category term="Web" /><category term="react" /><category term="javascript" /><category term="webpack" /><category term="frontend" /><summary type="html"><![CDATA[Building a modern React app from scratch - no Vite, no Next.js - to demystify the magic of `create-react-app` and its friends.]]></summary></entry><entry><title type="html">My bookmarks over the years (part 5)</title><link href="https://www.arunkant.com/posts/bookmarks-i-collected-part-5/" rel="alternate" type="text/html" title="My bookmarks over the years (part 5)" /><published>2022-10-23T00:00:00+05:30</published><updated>2022-10-23T00:00:00+05:30</updated><id>https://www.arunkant.com/posts/bookmarks-i-collected-part-5</id><content type="html" xml:base="https://www.arunkant.com/posts/bookmarks-i-collected-part-5/"><![CDATA[<p>I have bookmarked lots of articles over the years. I hardly visit them but I don’t want to delete them either. I want to clean up my browser and start fresh…</p>

<p>So here is the dump from my browser bookmarks in some order and some brief notes</p>

<hr />

<p><a href="https://nullprogram.com/blog/2020/05/24/">Latency in Asynchronous Python</a> - Async is still single threaded and can block for long time</p>

<p><a href="http://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf">Slide 1 - dean-keynote-ladis2009.pdf</a> - Designs, Lessons and Advice from Building Large Distributed Systems by Jeff Dean, Google Fellow</p>

<p><a href="https://www.somethingsimilar.com/2013/01/14/notes-on-distributed-systems-for-young-bloods/">Notes on Distributed Systems for Young Bloods – Something Similar</a></p>

<p><a href="https://nanxiao.me/en/beware-of-openmps-thread-pool/">Beware of OpenMP’s thread pool | Nan Xiao’s Blog</a> - Issues with onnxruntime. lots of headaches</p>

<p><a href="https://realpython.com/python-microservices-grpc/">Python Microservices With gRPC – Real Python</a> - Real Python tutorial are comprehensive compare to other tutorial on web</p>

<p><a href="https://osmocom.org/">Open Source Mobile Communications</a></p>

<p><a href="https://docs.python.org/3/howto/instrumentation.html">Instrumenting CPython with DTrace and SystemTap - Python 3.9.5 documentation</a></p>

<p><a href="https://ahima.org/">AHIMA Home</a> - The American Health Information Management Association</p>

<p><a href="https://shape-of-code.coding-guidelines.com/2010/06/18/network-protocols-also-evolve-into-a-tangle-of-dependencies/">The Shape of Code » Network protocols also evolve into a tangle of dependencies</a> - Create lots of complicate protocol to create a moat. The MS way</p>

<p><a href="https://realpython.com/async-io-python/#the-asyncawait-syntax-and-native-coroutines">Async IO in Python: A Complete Walkthrough – Real Python</a></p>

<p><a href="https://snarky.ca/how-the-heck-does-async-await-work-in-python-3-5/">How the heck does async/await work in Python 3.5?</a></p>

<p><a href="https://nips.cc/virtual/2020/public/invited_16166.html">NeurIPS 2020 : You Can’t Escape Hyperparameters and Latent Variables: Machine Learning as a Software Engineering Enterprise</a></p>

<p><a href="http://www.43folders.com/izero">43 Folders Series: Inbox Zero | 43 Folders</a> - How to keep inbox clean</p>

<p><a href="https://cp-algorithms.com/">Main Page - Competitive Programming Algorithms</a></p>

<p><a href="https://litestream.io/">Litestream - Streaming SQLite Replication</a> - from fly.io</p>

<p><a href="https://mjg59.dreamwidth.org/57199.html">mjg59 | Producing a trustworthy x86-based Linux appliance</a></p>

<p><a href="https://www.yoctoproject.org/">Yocto Project – It’s not an embedded Linux distribution – it creates a custom one for you</a></p>

<p><a href="https://snyk.io/">Snyk | Developer security | Develop fast. Stay secure.</a></p>

<p><a href="https://www.python.org/dev/peps/pep-0621/#abstract">PEP 621 – Storing project metadata in pyproject.toml | Python.org</a></p>

<p><a href="https://jmmv.dev/2021/04/always-be-quitting.html">Always be quitting - jmmv.dev</a> - How to not stuck in your job. learn to delegate</p>

<p><a href="https://tailscale.com/">Best VPN Service for Secure Networks - Tailscale</a> - One of best company with wireguard networkign</p>

<p><a href="https://openid.net/certification/">OpenID Certification | OpenID</a></p>

<p><a href="https://stackoverflow.com/questions/46184787/gluu-vs-keycloack-vs-wso2-identity-management">compare - Gluu vs keycloack vs wso2 identity management - Stack Overflow</a></p>

<p><a href="https://paper.li/">Build your digital presence with Paper.li</a> - Paper.li is your personal marketing assistant</p>

<p><a href="https://cloudlad.io/multi-region-kubernetes-EKS-and-terraform-012">Multi-Region Kubernetes - EKS and Terraform 0.12 | cloudlad.io</a></p>

<p><a href="https://gluu.org/docs/gluu-server/latest/installation-guide/install-kubernetes/">Kubernetes - Gluu Server 4.2 Docs</a></p>

<p><a href="https://www.pluralith.com/">Pluralith - Proper Terraform State Visualization</a></p>

<p><a href="https://www.ory.sh/">Ory - Open Source Identity Solutions For Everyone - ory.sh</a></p>

<p><a href="https://sosedoff.com/2021/02/21/wireguard-vpn-on-aws.html">Wireguard VPN on AWS</a></p>

<p><a href="https://dev.to/netikras/iptables-a-beast-worth-training-a-firewall-a-nat-router-a-port-forwarder-an-lb-anti-dos-a-logger-for-free-5157">Iptables - a beast worth training: a firewall, a (NAT) router, a port-forwarder, an LB, anti-DoS, a logger,… for free! - DEV Community</a></p>

<p><a href="https://blog.gruntwork.io/a-comprehensive-guide-to-managing-secrets-in-your-terraform-code-1d586955ace1">A comprehensive guide to managing secrets in your Terraform code | by Yevgeniy Brikman | Gruntwork</a></p>

<p>Terragrunt articles are comprehensive
<a href="https://gruntwork.io/guides/kubernetes/how-to-deploy-production-grade-kubernetes-cluster-aws/#kubernetes-architecture">How to deploy a production-grade Kubernetes cluster on AWS</a></p>

<p><a href="https://gruntwork.io/guides/kubernetes/how-to-deploy-production-grade-kubernetes-cluster-aws/#worker-nodes-2">How to deploy a production-grade Kubernetes cluster on AWS</a></p>

<p><a href="https://gruntwork.io/guides/networking/how-to-deploy-production-grade-vpc-aws">How to deploy a production-grade VPC on AWS</a></p>

<p><a href="https://gruntwork.io/guides/automations/how-to-configure-a-production-grade-ci-cd-setup-for-apps-and-infrastructure-code/#cicd_workflows">How to configure a production-grade CI-CD workflow for infrastructure code</a></p>

<p><a href="https://www.runatlantis.io/">Terraform Pull Request Automation | Atlantis</a></p>

<p><a href="https://pages.cs.wisc.edu/~remzi/OSTEP/">Operating Systems: Three Easy Pieces</a> - Duplicate?</p>

<p><a href="https://gruntwork.io/devops-checklist/#server-side">Production Readiness Checklist</a></p>

<p><a href="https://k6.io/">Load testing for engineering teams | k6</a></p>

<p><a href="https://blog.gruntwork.io/terragrunt-how-to-keep-your-terraform-code-dry-and-maintainable-f61ae06959d8">Terragrunt: how to keep your Terraform code DRY and maintainable | by Yevgeniy Brikman | Gruntwork</a></p>

<p><a href="https://aws.amazon.com/blogs/networking-and-content-delivery/centralized-dns-management-of-hybrid-cloud-with-amazon-route-53-and-aws-transit-gateway/">Centralized DNS management of hybrid cloud with Amazon Route 53 and AWS Transit Gateway | Networking &amp; Content Delivery</a></p>

<p><a href="https://slatestarcodex.com/2014/12/17/the-toxoplasma-of-rage/">The Toxoplasma Of Rage | Slate Star Codex</a></p>

<p><a href="https://fortelabs.co/blog/basboverview/">Building a Second Brain: An Overview - Forte Labs</a></p>

<p><a href="https://every.to/almanack/personal-leverage-how-to-truly-10x-your-productivity-2450">Personal Leverage: How to Truly 10x Your Productivity - Almanack - Every</a></p>

<p><a href="https://tailscale.com/blog/how-nat-traversal-works/">How NAT traversal works · Tailscale</a></p>

<p><a href="https://hashnode.com/">Hashnode: Everything you need to start blogging as a developer!</a> - Will check this out</p>

<p><a href="https://brandur.org/idempotency-keys">Implementing Stripe-like Idempotency Keys in Postgres - brandur.org</a></p>

<p><a href="https://sidequestjobs.com/">SideQuest - Short Term Tech Jobs</a></p>

<p><a href="https://erikbern.com/2021/07/07/the-data-team-a-short-story.html">Building a data team at a mid-stage startup: a short story · Erik Bernhardsson</a></p>

<p><a href="https://goomics.net/">Goomics</a> - Comics about life at Google</p>

<p><a href="https://getaether.net/">Aether</a> -  Peer-to-peer ephemeral public communities</p>

<p><a href="https://anagora.org/index">[[index]]</a> - This Agora is a wiki like experimental social network and distributed knowledge graph</p>

<p><a href="https://www.knowledgefutures.org/">Knowledge Futures Group</a> - Knowledge Futures Group is a 501c3 nonprofit building open source technology and collaborating with communities of practice to design and build the public digital infrastructure needed for effective, equitable, and sustainable knowledge futures.</p>

<p><a href="https://typesense.org/blog/the-unreasonable-effectiveness-of-just-showing-up-everyday/">The unreasonable effectiveness of just showing up everyday | Typesense</a> - Showing up is half of the work</p>

<p><a href="https://ungleich.ch/u/products/viirb-ipv6-box/">The VPN IPv6 IoT Router Box (VIIRB) - ungleich.ch</a></p>

<p><a href="https://johnnydecimal.com/">Home | Johnny•Decimal</a> - Digital organisation</p>

<p><a href="https://cheapskatesguide.org/articles/war-on-gp-computing.html">Taking a Stand in the War on General-Purpose Computing</a> - “We must control the client”</p>

<p><a href="https://michaelfeathers.silvrback.com/10-papers-every-developer-should-read-at-least-twice">Michael Feathers - 10 Papers Every Developer Should Read</a></p>

<p><a href="https://www.quantamagazine.org/how-bells-theorem-proved-spooky-action-at-a-distance-is-real-20210720/">How Bell’s Theorem Proved ‘Spooky Action at a Distance’ Is Real | Quanta Magazine</a></p>

<p><a href="https://infrequently.org/2021/07/hobsons-browser/">Hobson’s Browser - Infrequently Noted</a> - In apps browser bad</p>

<p><a href="https://training.galaxyproject.org/training-material/topics/admin/tutorials/ansible/tutorial.html#what-is-ansible">Ansible</a></p>

<p><a href="https://sites.google.com/site/yartikhiy/home/ipv6book">yartikhiy - IPv6 for IPv4 Experts (draft)</a></p>

<p><a href="https://en.wikipedia.org/wiki/Equanimity">Equanimity - Wikipedia</a> - Equanimity (Latin: æquanimitas, having an even mind; aequus even; animus mind/soul) is a state of psychological stability and composure which is undisturbed by experience of or exposure to emotions, pain, or other phenomena that may cause others to lose the balance of their mind. The virtue and value of equanimity is extolled and advocated by a number of major religions and ancient philosophies.</p>

<p><a href="https://www.wired.com/story/to-do-apps-failed-productivity-tools/">Hundreds of Ways to Get S#!+ Done-and We Still Don’t | WIRED</a> - stop reading productivity how-do. pick a system and stick with it</p>]]></content><author><name>Arun Kant Sharma</name><email>mail@arunkant.com</email></author><category term="Bookmarks" /><category term="bookmarks" /><category term="links" /><summary type="html"><![CDATA[A dump of articles and links I've collected in my browser, with brief notes - part 5 of 5.]]></summary></entry><entry><title type="html">My bookmarks over the years (part 4)</title><link href="https://www.arunkant.com/posts/bookmarks-i-collected-part-4/" rel="alternate" type="text/html" title="My bookmarks over the years (part 4)" /><published>2022-10-22T00:00:00+05:30</published><updated>2022-10-22T00:00:00+05:30</updated><id>https://www.arunkant.com/posts/bookmarks-i-collected-part-4</id><content type="html" xml:base="https://www.arunkant.com/posts/bookmarks-i-collected-part-4/"><![CDATA[<p>I have bookmarked lots of articles over the years. I hardly visit them but I don’t want to delete them either. I want to clean up my browser and start fresh…</p>

<p>So here is the dump from my browser bookmarks in some order and some brief notes</p>

<hr />

<p><a href="https://www.iqt.org/bewear-python-typosquatting-is-about-more-than-typos/">Bewear! Python Typosquatting Is About More Than Typos – In-Q-Tel</a> - supply chain attacks</p>

<p><a href="https://graphitemaster.github.io/fibers/">Fibers, Oh My!</a> - python, fiber and green threads etc</p>

<p><a href="https://secretgeek.github.io/html_wysiwyg/html.html">This page is a truly naked, brutalist html quine.</a> - HTML quine</p>

<p><a href="https://docs.microsoft.com/en-us/azure/architecture/patterns/">Cloud design patterns - Azure Architecture Center | Microsoft Docs</a></p>

<p><a href="https://moultano.wordpress.com/2020/10/18/why-deep-learning-works-even-though-it-shouldnt/">Why Deep Learning Works Even Though It Shouldn’t – Ryan Moulton’s Articles</a> - Don’t understand Second Descent Regime</p>

<p><a href="https://joindeleteme.com/">Remove Personal Info from Google - DeleteMe</a></p>

<p><a href="https://www.mathventurepartners.com/blog/2016/9/15/startup-financial-modeling-part-1-what-is-a-financial-model">Startup Financial Modeling, Part 1: What is a Financial Model? - MATH Venture Partners</a></p>

<p><a href="https://chsasank.github.io/writing-maketh-man.html">Writing Maketh a Man - Sasank’s Blog</a> - Start writing regularly</p>

<p><a href="https://0xax.gitbooks.io/linux-insides/content/Cgroups/linux-cgroups-1.html">Introduction to Control Groups · Linux Inside</a></p>

<p><a href="https://v2.grommet.io/">Grommet</a> - PWA and native app desiner</p>

<p><a href="https://tailwindcss.com/">Tailwind CSS - A Utility-First CSS Framework for Rapidly Building Custom Designs</a> - I like it</p>

<p><a href="https://www.dendron.so/">Dendron - Dendron</a> - Like obsidian/roam research</p>

<p><a href="https://fortelabs.co/blog/para/">The PARA Method: A Universal System for Organizing Digital Information - Forte Labs</a></p>

<p><a href="https://web.mit.edu/kerberos/www/dialogue.html">Designing an Authentication System: a Dialogue in Four Scenes</a> - Kerberos design</p>

<p><a href="https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/">What Color is Your Function? – journal.stuffwithstuff.com</a> - Problem when stacking async functionality is tagged on top of a mature language. I feel JS got lucky in this regard as there was no io as such and no OS access earlier and event base system was perfect for UI apps</p>

<p><a href="http://www.paulgraham.com/avg.html">Beating the Averages</a> - Learn lisp to expand your mind</p>

<p><a href="http://www.repec.org/">RePEc: Research Papers in Economics</a> - Economics is social science</p>

<p><a href="https://inspirehep.net/">Home - INSPIRE</a> - Discover High-Energy Physics Content</p>

<p><a href="https://github.com/erebe/personal-server/blob/master/README.md#background">personal-server/README.md at master · erebe/personal-server · GitHub</a> - - personal server with DNS and email management</p>

<p><a href="https://natanyellin.com/posts/tracking-running-processes-on-linux/">The Difficulties of Tracking Running Processes on Linux :: Tech Notes by Natan Yellin</a> - PID gets recycled</p>

<p><a href="https://www.redhat.com/sysadmin/cgroups-part-one">A Linux sysadmin’s introduction to cgroups | Enable Sysadmin</a></p>

<p><a href="https://microconf.com/">MicroConf - The Most Trusted Community for Non-Venture Track SaaS Founders</a></p>

<p><a href="https://pgstats.dev/">Postgres Observability</a></p>

<p><a href="http://osv.io/">OSv - the operating system designed for the cloud</a></p>

<p><a href="https://msportals.xyz/">Administrator Portals | Microsoft Portals</a> - list of MS portals</p>

<p><a href="https://pablasso.com/high-performance-individuals-and-teams/">High performance individuals and teams | Pablasso</a> - avoid bad engineer</p>

<p><a href="https://www.confluent.io/blog/turning-the-database-inside-out-with-apache-samza/">Turning the database inside-out with Apache Samza - Confluent</a> - Also check out dbt</p>

<p><a href="http://pages.stern.nyu.edu/~adamodar/New_Home_Page/webcastvalonline.htm">Valuation Online Class</a> - Aswath Damodaran class</p>

<p><a href="https://jonathan.bergknoff.com/journal/terraform-pain-points/">Jonathan Bergknoff: Terraform Pain Points</a></p>

<p><a href="https://www.eater.com/2018/7/3/17531192/vertical-farming-agriculture-hydroponic-greens">Can Vertical Farming Disrupt the Agriculture Industry? - Eater</a> - Probably no</p>

<p><a href="https://www.pianodreamers.com/ways-to-learn-piano/">What’s the Best Way to Learn Piano in 2021? (In-Depth Guide)</a></p>

<p><a href="https://gtoolkit.com/">Glamorous Toolkit</a> - Pitch: 
The Moldable Development Environment. Glamorous Toolkit is a multi-language notebook. A fancy code editor. A software analysis platform. A visualization engine. A knowledge management system. All programmable. Free and open-source.</p>

<p><a href="https://xtermjs.org/">Xterm.js</a></p>

<p><a href="https://venam.nixers.net/blog/unix/2021/02/07/audio-stack.html">Making Sense of The Audio Stack On Unix</a></p>

<p><a href="https://computing.llnl.gov/tutorials/pthreads/">POSIX Threads Programming</a></p>

<p><a href="https://blog.detectify.com/2020/11/10/common-nginx-misconfigurations/">Common Nginx misconfigurations that leave your web server open to attack | Detectify Blog</a></p>

<p><a href="http://www.lighterra.com/papers/modernmicroprocessors/">Modern Microprocessors - A 90-Minute Guide!</a></p>

<p><a href="https://www.shibboleth.net/products/">Products - Shibboleth Consortium</a></p>

<p><a href="https://www.focalboard.com/">Focalboard: Open source alternative to Trello, Asana, and Notion</a></p>

<p><a href="https://davidsekar.com/misc/block-bsnl-ads-using-ipsec">Block BSNL ADs using IPSec - Davidsekar.com</a></p>

<p><a href="https://www.armscontrolwonk.com/">Arms Control Wonk – an arms control blog network</a></p>

<p><a href="https://boris-marinov.github.io/category-theory-illustrated/04_order/">Category Theory Illustrated - Orders</a></p>

<p><a href="https://www.lesswrong.com/posts/JZZENevaLzLLeC3zn/predictive-coding-has-been-unified-with-backpropagation">Predictive Coding has been Unified with Backpropagation - LessWrong</a> - artificial intelligence and neuroscience</p>

<p><a href="https://news.ycombinator.com/item?id=21850155">Monica: Open-source personal CRM | Hacker News</a> - personal CRM, didn’t work out</p>

<p><a href="https://www.etesync.com/">EteSync - Secure Data Sync</a> - Secure, end-to-end encrypted, and privacy respecting sync for your contacts, calendars, tasks and notes.</p>

<p><a href="https://www.drorpoleg.com/the-ponzi-career/">The Ponzi Career</a> - The Ponzi Career. The future of work is a pyramid scheme, where every person sells his favorite person to the next person.</p>

<p><a href="https://bitclout.com/">Welcome to BitClout</a> - It just keep giving</p>

<p><a href="https://darknetdiaries.com/">Darknet Diaries – True stories from the dark side of the Internet.</a> - a podcast</p>

<p><a href="https://beepb00p.xyz/sad-infra.html#data_is_trapped">The sad state of personal data and infrastructure | beepb00p</a> - This is a sad state of tech</p>

<p><a href="https://indieweb.org/">IndieWeb</a></p>

<p><a href="https://computationalthinking.mit.edu/Fall20/">18.S191 Introduction to Computational Thinking</a></p>

<p><a href="https://en.wikipedia.org/wiki/Rattleback">Rattleback - Wikipedia</a> - rotate on its axis in a preferred direction. If spun in the opposite direction, it becomes unstable, “rattles” to a stop and reverses its spin to the preferred direction.</p>

<p><a href="https://stackoverflow.com/questions/22677070/additional-field-while-serializing-django-rest-framework">Additional field while serializing django rest framework - Stack Overflow</a></p>

<p><a href="https://calyxos.org/">CalyxOS</a> - privacy oriented android fork</p>

<p><a href="https://k3tan.com/starting-a-new-digital-identity">Starting a new digital identity - k3tan</a> - Read like a movie script</p>

<p><a href="https://news.ycombinator.com/item?id=27017041">Request for comments regarding topics to be discussed at Dark Patterns workshop | Hacker News</a></p>

<p><a href="https://til.simonwillison.net/">Simon Willison: TIL</a> - short writings I can replicate</p>

<p><a href="https://medium.com/nerd-for-tech/nlp-zero-to-one-full-course-4f8e1902c379">NLP Zero to One: Full Course. Simple, Clear and Precise Explanations… | by Kowshik chilamkurthy | Nerd For Tech | Mar, 2021 | Medium</a></p>

<p><a href="https://tomayko.com/blog/2009/unicorn-is-unix">I like Unicorn because it’s Unix</a> - best unicorn internal tutorial</p>

<p><a href="https://researchcylera.wpcomstaging.com/2019/04/16/pe-dicom-medical-malware/">HIPAA-Protected Malware? Exploiting DICOM Flaw to Embed Malware in CT/MRI Imagery – Cylera Labs</a></p>

<p><a href="https://www.dvtk.org/">DVTk · DVTk, a must have for anybody working with DICOM!</a></p>

<p><a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2039858/">Mastering DICOM with DVTk</a></p>

<p><a href="https://learn-anything.xyz/">Learn Anything</a> - High promising, not good execution</p>

<p><a href="https://stratechery.com/">Stratechery by Ben Thompson – On the business, strategy, and impact of technology.</a></p>

<p><a href="https://www.integralist.co.uk/posts/python-asyncio/">Guide to Concurrency in Python with Asyncio ⋆ Mark McDonnell</a></p>

<hr />
<p>To be continued…</p>]]></content><author><name>Arun Kant Sharma</name><email>mail@arunkant.com</email></author><category term="Bookmarks" /><category term="bookmarks" /><category term="links" /><summary type="html"><![CDATA[A dump of articles and links I've collected in my browser, with brief notes - part 4 of 5.]]></summary></entry><entry><title type="html">My bookmarks over the years (part 3)</title><link href="https://www.arunkant.com/posts/bookmarks-i-collected-part-3/" rel="alternate" type="text/html" title="My bookmarks over the years (part 3)" /><published>2022-10-21T00:00:00+05:30</published><updated>2022-10-21T00:00:00+05:30</updated><id>https://www.arunkant.com/posts/bookmarks-i-collected-part-3</id><content type="html" xml:base="https://www.arunkant.com/posts/bookmarks-i-collected-part-3/"><![CDATA[<p>I have bookmarked lots of articles over the years. I hardly visit them but I don’t want to delete them either. I want to clean up my browser and start fresh…</p>

<p>So here is the dump from my browser bookmarks in some order and some brief notes</p>

<hr />

<p><a href="https://gist.github.com/XVilka/8346728">True Colour (16 million colours) support in various terminal applications and terminals</a></p>

<p><a href="https://github.com/alexmojaki/snoop">alexmojaki/snoop: A powerful set of Python debugging tools, based on PySnooper</a> - promising stuff, never tried it</p>

<p><a href="https://stackoverflow.com/questions/4628122/how-to-construct-a-timedelta-object-from-a-simple-string">python - How to construct a timedelta object from a simple string - Stack Overflow</a></p>

<p><a href="https://deparkes.co.uk/2018/06/04/use-tox-with-anaconda/">Use Tox With Anaconda - deparkes</a> - Good tool for library devs, for application Bazel would be fine</p>

<p><a href="https://jareddillard.com/blog/continuous-deployment-of-a-sphinx-website-with-using-jenkins-and-docker.html">Continuous deployment of a Sphinx website using Jenkins and Docker | Jared Dillard</a></p>

<p><a href="https://pythonhosted.org/an_example_pypi_project/sphinx.html">Documenting Your Project Using Sphinx - an_example_pypi_project v0.0.5 documentation</a></p>

<p><a href="https://support.dcmtk.org/redmine/projects/dcmtk/wiki/DICOM_NetworkingIntroduction">DICOM NetworkingIntroduction - DCMTK - OFFIS DCMTK and DICOM Projects</a></p>

<p><a href="https://dev.to/emmawedekind/top-3-tools-for-boosting-your-productivity-1lh">Top 3 Tools For Boosting Your Productivity - DEV Community 👩‍💻👨‍💻</a> Notion, spark mail and Fantastical 2 calandar app</p>

<p><a href="https://dev.to/jamesmh/what-are-the-highest-paying-software-developer-jobs-how-can-i-land-one-3dj">What Are The Highest Paying Software Developer Jobs &amp; How Can I Land One? - DEV Community 👩‍💻👨‍💻</a> - Become remarkable in your area</p>

<p><a href="https://www.snoyman.com/blog/2018/10/introducing-rust-crash-course">Introducing the Rust crash course</a> - Doesn’t seem active anymore</p>

<p><a href="https://www.gnu.org/software/libc/manual/html_node/Blocking-Signals.html#Blocking-Signals">Blocking Signals (The GNU C Library)</a> - I get to know it while making a fork server like unicorn</p>

<p><a href="https://exercism.io/">Exercism</a> - Did some rust track. Should restart this</p>

<p><a href="https://kubernetes.io/docs/reference/kubectl/docker-cli-to-kubectl/">kubectl for Docker Users - Kubernetes</a></p>

<p><a href="https://github.com/ahmetb/kubectx">ahmetb/kubectx: Switch faster between clusters and namespaces in kubectl</a> - Never tried it</p>

<p><a href="https://www.amazon.in/Phoenix-Project-DevOps-Helping-Business/dp/0988262592">Buy The Phoenix Project: A Novel About IT, DevOps, and Helping Your Business Win Book Online at Low Prices in India | The Phoenix Project: A Novel About IT, DevOps, and Helping Your Business Win Reviews &amp; Ratings - Amazon.in</a> - Books to read</p>

<p><a href="https://itnext.io/argo-workflow-engine-for-kubernetes-7ae81eda1cc5">Argo: Workflow Engine for Kubernetes - ITNEXT</a> - CRDs was all the hype then. Everyone got CRDs</p>

<p><a href="https://medium.com/@thms.hmm/docker-for-mac-with-kubernetes-enable-k8s-dashboard-62fe036b7480">Docker for Mac with Kubernetes - Enable K8S Dashboard</a></p>

<p><a href="https://medium.com/@thms.hmm/docker-for-mac-with-kubernetes-ingress-controller-with-traefik-e194919591bb">Docker for Mac with Kubernetes - Ingress Controller with Traefik</a></p>

<p><a href="https://blog.getambassador.io/kubernetes-ingress-nodeport-load-balancers-and-ingress-controllers-6e29f1c44f2d">Kubernetes Ingress 101: NodePort, Load Balancers, and Ingress Controllers</a></p>

<p><a href="https://eprint.iacr.org/2016/071">Cryptology ePrint Archive: Report 2016/071 - Reverse-Engineering the S-Box of Streebog, Kuznyechik and STRIBOBr1 (Full Version)</a></p>

<p><a href="https://vim-adventures.com/">VIM Adventures</a> - gamified vim learning</p>

<p><a href="https://brettterpstra.com/">BrettTerpstra.com</a> - Not sure why I bookmarked it</p>

<p><a href="https://en.wikipedia.org/wiki/List_of_eponymous_laws">List of eponymous laws - Wikipedia</a> - Learn word ‘eponymous’</p>

<p><a href="https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/#cpu-management-policies">Control CPU Management Policies on the Node - Kubernetes</a> - to move from docker-compose to k8s</p>

<p><a href="https://godbolt.org/">Compiler Explorer</a> - internet is beautiful</p>

<p><a href="https://medium.com/faun/the-missing-introduction-to-containerization-de1fbb73efc5">The Missing Introduction To Containerization - Faun - Medium</a> - container history</p>

<p><a href="https://puppetlabs.github.io/showoff/quickstart.html">showoff</a> - interacive ppts</p>

<p><a href="http://pages.cs.wisc.edu/%7Eremzi/OSTEP/">Operating Systems: Three Easy Pieces</a> - book on OS. virtualization, concurrency, and persistence</p>

<p><a href="https://apenwarr.ca/log/20181113">mtime comparison considered harmful - apenwarr</a> - mtime nuances</p>

<p><a href="https://rete.js.org/#/docs">Rete.js</a> - visual programming (maybe like sketch, haven’t tried)</p>

<p><a href="https://www.youtube.com/watch?v=MBnnXbOM5S4">(11) The more general uncertainty principle, beyond quantum - YouTube</a> - Duality of partical and waves is more general then just physics</p>

<p><a href="https://timr.co/server-side-rendering-is-a-thiel-truth">Server-Side Rendering is a Thiel Truth</a></p>

<p><a href="https://oneraynyday.github.io/dev/2020/05/03/Analyzing-The-Simplest-C++-Program/">Analyzing The Simplest C++ Program · Ray</a> - ELF stuff</p>

<p><a href="https://www.tomdalling.com/toms-data-onion/">Tom’s Data Onion - A Programming Puzzle In A Text File</a></p>

<p><a href="https://medium.com/faun/opensource-single-sign-on-sso-e52d39e1927">OpenSource Single Sign-On(SSO) - FAUN - Medium</a> - Keycloak stuff</p>

<p><a href="https://blog.shichao.io/2015/04/17/setup_openldap_server_with_openssh_lpk_on_ubuntu.html">Setting up OpenLDAP server with OpenSSH-LPK on Ubuntu 14.04 - Shichao’s Blog</a></p>

<p><a href="https://corecursive.com/054-software-that-doesnt-suck/">Building Subversion - CoRecursive Podcast</a> - some interview, not going to read</p>

<p><a href="https://www.jeffgeerling.com/blog/2020/ansible-101-jeff-geerling-youtube-streaming-series">Ansible 101 by Jeff Geerling - YouTube streaming series | Jeff Geerling</a> - Ansible stuff. Official docs are better</p>

<p><a href="https://cooperpress.com/">Cooperpress: Email Newsletters for Developers</a> - all weakly newsletters</p>

<p><a href="https://latacora.singles/2019/07/16/the-pgp-problem.html">Latacora - The PGP Problem</a> - PGP UX sucks</p>

<p><a href="https://community.letsencrypt.org/t/trying-to-get-a-freeipa-csr-signed-by-letsencrypt/129264/3">Trying to get a freeipa CSR signed by LetsEncrypt - Help - Let’s Encrypt Community Support</a></p>

<p><a href="https://support.simpledns.plus/kb/a63/how-to-delegate-a-sub-domain-to-other-dns-servers.aspx">How to delegate a sub-domain to other DNS servers - Simple DNS Plus</a></p>

<p><a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-centralized-linux-authentication-with-freeipa-on-centos-7#step-5-%E2%80%94-verifying-the-freeipa-server-functions">How To Set Up Centralized Linux Authentication with FreeIPA on CentOS 7 | DigitalOcean</a></p>

<p><a href="https://fiercesw.com/blog/well-well-rhel-a-look-at-the-rhel-8-beta">Well, well, RHEL - A look at the RHEL 8 Beta - Fierce Software</a></p>

<p><a href="https://pagure.io/freeipa/issue/2648">Issue #2648: ipa will not install on amazon ec2 - freeipa - Pagure.io</a></p>

<p><a href="https://chamathb.wordpress.com/2019/06/21/setting-up-rhel-idm-with-integrated-dns-on-aws/">Setting up RHEL IdM with integrated DNS on AWS – Chamath’s Blog</a></p>

<p><a href="https://medium.com/@securityshenaningans/why-you-should-always-scan-udp-part-2-2-42050fb136d8">Why you should always scan UDP ports (part 2/2) | by Security Shenanigans | Aug, 2020 | Medium</a></p>

<p><a href="https://en.wikipedia.org/wiki/United_States_v._Paramount_Pictures,_Inc.">United States v. Paramount Pictures, Inc. - Wikipedia</a> - Hollywood antitrust case</p>

<p><a href="https://tilde.town/">tilde.town</a> - shared linux computer</p>

<p><a href="https://towardsdatascience.com/books-for-quants-1b0f51dd7745">Books for Quants. Book list for mathematical finance… | by Luke Posey | Towards Data Science</a></p>

<p><a href="https://natethesnake.com/">Nate the Snake</a> - long story, decent return</p>

<p><a href="https://slurm.schedmd.com/overview.html">Slurm Workload Manager - Overview</a> - cluster management and job scheduling system</p>

<p><a href="http://bofh.bjash.com/">The Bastard Operator From Hell Complete</a> - Stories and Rants</p>

<p><a href="https://noyaml.com/">🚨🚨 That’s a lot of YAML 🚨🚨</a> - Satire like mocking of yaml</p>

<p><a href="https://twitter.com/hodapp/status/1304478215197593600">Eli Hodapp on Twitter: “Here’s what’s TRULY unbelievable about today’s App Store policy update to “"”allow””” xCloud and Stadia, that you can really only appreciate if you’ve been following the wacky decisions of Apple on how to awkwardly handle everything to do with games… a 🥁*drumroll*🥁 THREAD” / Twitter</a> - Tweet deleted</p>

<p><a href="http://cdar.berkeley.edu/wp-content/uploads/2017/04/Lisa-Goldberg-reviews-The-Book-of-Why.pdf">Lisa-Goldberg-reviews-The-Book-of-Why.pdf</a> - Dead link</p>

<p><a href="https://www.youtube.com/watch?v=v2tExSUSt8o">Multicloud Networking - An Overview - YouTube</a> -</p>

<p><a href="https://wiki.openstack.org/wiki/XenServer/VirtualBox">XenServer/VirtualBox - OpenStack</a></p>

<p><a href="https://trumporbot.com/">Trump Or Bot?</a></p>

<p><a href="https://www.vice.com/en_us/article/bjvjd3/apple-doesnt-trust-you">Apple Doesn’t Trust You</a></p>

<p><a href="https://fasterthanli.me/articles/so-you-want-to-live-reload-rust">So you want to live-reload Rust - fasterthanli.me</a></p>

<p><a href="https://i.redd.it/lktudl5uuip51.jpg">I don’t want solution. I want to be mad</a></p>

<hr />
<p>To be continued…</p>]]></content><author><name>Arun Kant Sharma</name><email>mail@arunkant.com</email></author><category term="Bookmarks" /><category term="bookmarks" /><category term="links" /><summary type="html"><![CDATA[A dump of articles and links I've collected in my browser, with brief notes - part 3 of 5.]]></summary></entry><entry><title type="html">My bookmarks over the years (part 2)</title><link href="https://www.arunkant.com/posts/bookmarks-i-collected-part-2/" rel="alternate" type="text/html" title="My bookmarks over the years (part 2)" /><published>2022-10-19T00:00:00+05:30</published><updated>2022-10-19T00:00:00+05:30</updated><id>https://www.arunkant.com/posts/bookmarks-i-collected-part-2</id><content type="html" xml:base="https://www.arunkant.com/posts/bookmarks-i-collected-part-2/"><![CDATA[<p>I have bookmarked lots of articles over the years. I hardly visit them but I don’t want to delete them either. I want to clean up my browser and start fresh…</p>

<p>So here is the dump from my browser bookmarks in some order and some brief notes</p>

<hr />
<p><a href="https://gauriatiq.medium.com/c-native-addon-independent-of-node-js-version-using-napi-node-addon-api-and-cmake-53315582cbd1">C++ Native Addon independent of Node.js version using Napi/node-addon-api and Cmake | by Atiq Gauri | Medium</a> - Some tutorials</p>

<p><a href="https://gauriatiq.medium.com/electron-app-with-c-back-end-as-native-addon-napi-c67867f4058">Electron App with C++ backend as Native Addon (Napi) | by Atiq Gauri | Medium</a> - More tutorials</p>

<p><a href="https://unikube.io/blog/how-does-kubernetes-development-work/#k3dk3s-lightweight-kubernetes-in-docker">How does local Kubernetes development work? | Unikube Blog | UNIKUBE</a> - tried k3d but k3s is better</p>

<p><a href="https://github.com/Microsoft/nodejs-guidelines/blob/master/windows-environment.md#compiling-native-addon-modules">nodejs-guidelines/windows-environment.md at master · microsoft/nodejs-guidelines</a> - node.js resources</p>

<p><a href="https://www.wix.engineering/post/virtual-monorepo-for-bazel">Too Much Code for Bazel Monorepo? Try Going Virtual</a> - bazel resources</p>

<p><a href="https://www.microsoft.com/en-us/research/uploads/prod/2018/03/build-systems.pdf">Build Systems à la Carte - build-systems.pdf</a> - classifications of build systems</p>

<p><a href="https://betterprogramming.pub/2020-021-javascript-omni-packages-bae42d446d6c">JavaScript Omni-Packages. How to package JavaScript libraries for… | by Joe Honton | Better Programming</a> - JS resource</p>

<p><a href="https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/">ES modules: A cartoon deep-dive - Mozilla Hacks - the Web developer blog</a> - Best explaination of how JS modules works so far. It show how much thought goes into evolving a language and also keep existing codebase maintained</p>

<p><a href="https://www.freecodecamp.org/news/modules-in-javascript/">Modules in JavaScript – CommonJS and ESmodules Explained</a></p>

<p><a href="https://cloud.google.com/blog/products/management-tools/sre-principles-and-flashcards-to-design-nalsd">SRE principles and flashcards to design NALSD | Google Cloud Blog</a> - Flashcards for SRE stuff</p>

<p><a href="https://www.stevenengelhardt.com/2021/09/22/practical-bazel-depending-on-a-system-provided-c-cpp-library/">Practical Bazel: Depending on a System-Provided C/C++ Library | Steven Engelhardt</a> -</p>

<p><a href="https://stackoverflow.com/questions/41553609/what-is-the-right-way-to-refer-bazel-data-files-in-python">What is the right way to refer bazel data files in python? - Stack Overflow</a> - Runfiles and stuff</p>

<p><a href="https://bazelbuild.github.io/rules_nodejs/examples#react">Examples | rules_nodejs</a></p>

<p><a href="https://about.gitlab.com/handbook/">Handbook | GitLab</a> - Every company should have handbook like that</p>

<p><a href="https://guzey.com/personal/what-should-you-do-with-your-life/">What Should You Do with Your Life? Directions and Advice - Alexey Guzey</a></p>

<p><a href="https://publishing-project.rivendellweb.net/bazel-build-system-frontend-styling/">Bazel build system: Frontend Styling – The Publishing Project</a></p>

<p><a href="https://adamwathan.me/2019/10/17/persistent-layout-patterns-in-nextjs/">Persistent Layout Patterns in Next.js – Adam Wathan</a></p>

<p><a href="https://superfastpython.com/python-concurrency-choose-api/">Choose the Right Python Concurrency API</a></p>

<p><a href="https://www.collaborativefund.com/blog/little-ways-the-world-works/">Little Ways The World Works · Collaborative Fund</a></p>

<p><a href="https://festivus.dev/kubernetes/">Kubernetes</a> - I enjoy gifs</p>

<p><a href="https://www.feeonlyindia.com/">HOME | Fee-Only India</a> - Claim to be most ethical</p>

<p><a href="https://training.kalzumeus.com/lifecycle-emails">Hacking Lifecycle Emails for Software Companies</a></p>

<p><a href="https://www.kalzumeus.com/2012/01/23/salary-negotiation/">Salary Negotiation: Make More Money, Be More Valued | Kalzumeus Software</a> - Best guide on salary negotiation so far</p>

<p><a href="https://signalvnoise.com/archives2/dont_scar_on_the_first_cut.php">Don’t scar on the first cut - Signal vs. Noise (by 37signals)</a> - Policies are codified overreactions to unlikely-to-happen-again situations. A collective punishment for the wrong-doings of a one-off. And unless you want to treat the people in your environment as five year-olds, “Because The Policy Said So” is not a valid answer.</p>

<p><a href="https://mycelial.com/">Mycelial - The Best Platform for Synchronized Apps | Mycelial</a> - sync sqlite peer-to-peer</p>

<p><a href="https://slofile.com/">Slofile - Public Slack groups to join</a> - list of public slack channel to join</p>

<h2 id="how-to-crowdsource-and-curate-a-team-newsletter-in-slack--slack"><a href="https://slack.com/intl/en-in/blog/productivity/how-to-crowdsource-and-curate-a-team-newsletter-in-slack">How to crowdsource and curate a team newsletter in Slack | Slack</a></h2>
<p>To be continued…</p>]]></content><author><name>Arun Kant Sharma</name><email>mail@arunkant.com</email></author><category term="Bookmarks" /><category term="bookmarks" /><category term="links" /><summary type="html"><![CDATA[A dump of articles and links I've collected in my browser, with brief notes - part 2 of 5.]]></summary></entry><entry><title type="html">My bookmarks over the years (part 1)</title><link href="https://www.arunkant.com/posts/bookmarks-i-collected-part-1/" rel="alternate" type="text/html" title="My bookmarks over the years (part 1)" /><published>2022-10-10T00:00:00+05:30</published><updated>2022-10-10T00:00:00+05:30</updated><id>https://www.arunkant.com/posts/bookmarks-i-collected-part-1</id><content type="html" xml:base="https://www.arunkant.com/posts/bookmarks-i-collected-part-1/"><![CDATA[<p>I have bookmarked lots of articles over the years. I hardly visit them but I don’t want to delete them either. I want to clean up my browser and start fresh…</p>

<p>So here is the dump from my browser bookmarks in some order and some brief notes</p>

<hr />
<p><a href="https://lwn.net/Articles/630727/">How programs get run [LWN.net]</a> - Explain how exec works in linux. Detailed explaination in book <a href="https://man7.org/tlpi/index.html">The Linux Programming Interface</a></p>

<p><a href="https://tailscale.com/blog/absolute-scale/">Absolute scale corrupts absolutely · Tailscale</a> - Large scale invites bigger currptions :shrugs:</p>

<p><a href="https://www.gkogan.co/blog/big-cloud/">When AWS, Azure, or GCP Becomes the Competition | Greg Kogan</a> - Everyone startup should fear “trillion pound” gorillas and prepare accordingly</p>

<p><a href="https://www.cnbc.com/2018/04/11/goldman-asks-is-curing-patients-a-sustainable-business-model.html">Goldman asks: ‘Is curing patients a sustainable business model?’</a> - The potential to deliver ‘one shot cures’ is one of the most attractive aspects of gene therapy but it could represent a challenge for genome medicine developers looking for sustained cash flow.</p>

<p><a href="https://www.theguardian.com/society/2021/sep/09/transport-noise-linked-to-increased-risk-of-dementia-study-finds">Transport noise linked to increased risk of dementia, study finds | Dementia | The Guardian</a> - I wanted to follow up on this study but I haven’t found anything after this</p>

<p><a href="https://gafferongames.com/post/what_every_programmer_needs_to_know_about_game_networking/">What Every Programmer Needs To Know About Game Networking | Gaffer On Games</a> - Some history and brief on multiplayer game networking</p>

<p><a href="https://xahteiwi.eu/resources/presentations/no-we-wont-have-a-video-call-for-that/">No, We Won’t Have a Video Call for That! - xahteiwi.eu</a> - Async communication, “ChatOps”, avoid/less (sync) meetings, write. things. down</p>

<p><a href="https://kevinmunger.substack.com/p/facebook-is-other-people">Facebook is Other People - by Kevin Munger - Never Met a Science</a></p>
<ul>
  <li>At the door of every contented, happy man somebody should stand with a little hammer, constantly tapping, to remind him that unhappy people exist, that however happy he may be, sooner or later life will show him its claws, some calamity will befall him-illness, poverty, loss-and nobody will hear or see, just as he doesn’t hear or see others now. But there is nobody with a little hammer, the happy man lives on, and the petty cares of life stir him only slightly, as wind stirs an aspen-and everything is fine.</li>
</ul>

<p><a href="https://medium.com/@sixacegames/how-google-destroyed-our-startup-by-terminating-our-google-play-developer-account-6a8cca09ea88">How Google destroyed our startup by terminating our Google Play Developer Account | by 6Ace Games | Oct, 2021 | Medium</a> - Big Tech horrer story</p>

<p><a href="https://fqxi.org/community/forum/topic/3345">FQXi Community</a> - Counterfactual quantum computation is a method of inferring the result of a computation without actually running a quantum computer otherwise capable of actively performing that computation. I-know-some-of-these-words.gif</p>

<p><a href="http://math.andrej.com/2007/09/28/seemingly-impossible-functional-programs/">Mathematics and Computation | Seemingly impossible functional programs</a> - some functional programming wizardry</p>

<p><a href="https://axisofordinary.substack.com/p/the-most-counterintuitive-facts-in">The most counterintuitive facts in all of mathematics, computer science, and physics - by Alexander Kruel - Axis of Ordinary</a></p>

<p><a href="https://www.youtube.com/watch?v=g4-EyNJhcQ8">Analysis: Playing, Fast and Slow - YouTube flow, thinking fast and slow</a></p>

<p><a href="https://byrnehobart.medium.com/writing-is-networking-for-introverts-5cac14ad4c77">Writing is Networking for Introverts | by Byrne Hobart | Medium</a> - Introduced new concept: “microfamous”</p>

<p><a href="https://mathoverflow.net/questions/358/examples-of-great-mathematical-writing/116427#116427">soft question - Examples of great mathematical writing - MathOverflow</a> - Praise for John Milnor</p>

<p><a href="https://runyourown.social/">How to run a small social network site for your friends</a> - One of my bucket list. Connect with me if you want to help</p>

<p><a href="http://www.hpmor.com/">Harry Potter and the Methods of Rationality | Petunia married a professor, and Harry grew up reading science and science fiction.</a></p>

<p><a href="https://www.theguardian.com/science/2022/jan/02/attention-span-focus-screens-apps-smartphones-social-media">Your attention didn’t collapse. It was stolen | Psychology | The Guardian</a> - “Attention economy”, “Eyeballs” whatever. In the age of meterial abundance and robotic revolution, only human attention will be scarce. Social media and many other facets of modern life are destroying our ability to concentrate. We need to reclaim our minds while we still can</p>

<p><a href="https://www.chrisbehan.ca/posts/atomic-habits">The Thinner Book: Atomic Habits by James Clear</a> - Self help book on how to build good habits</p>

<p><a href="https://healthid.ndhm.gov.in/">Home | ABHA</a> - Digital identification for health data in India</p>

<p><a href="https://medevel.com/tag/radiology/">Open-source Radiology software: DICOM &amp; PACS</a></p>

<p><a href="https://servarica.com/">ServaRICA – Customizable Infrastructure provider</a> - Some cheap compute and storage</p>

<p><a href="https://en.wikipedia.org/wiki/Michael_Freeden">Michael Freeden - Wikipedia</a> - I forgot why I bookmarked him</p>

<p><a href="https://explain.dalibo.com/">explain.dalibo.com</a> -  Visualizing and understanding PostgreSQL EXPLAIN plans made easy</p>

<p><a href="https://hoppy.network/">Hoppy</a> - I love these wiregaurd networks, I’ll buy some when I build homelab I guess, hit me up if you are interested</p>

<p><a href="https://untools.co/ishikawa-diagram">Ishikawa Diagram | Untools</a> - Problem solving using diagrams</p>

<p><a href="https://untools.co/?ref=producthunt">Tools for better thinking | Untools</a> - See above</p>

<p><a href="https://www.producthunt.com/topics/side-projects">The Best Side Projects Apps and Products of 2022 | Product Hunt</a> - Inspirations for side projects</p>

<p><a href="https://nx.dev/">Nx: Smart, Fast and Extensible Build System</a> - seemed restricted to javascript. I chose bazel.build over this and happy so far</p>

<p><a href="https://alexchesser.medium.com/professional-development-is-a-choice-e90fb8719259">Professional Development is a Choice | by Alex Chesser | Medium</a> - Professional development must be deliberate and it must be what YOU want for YOUR career</p>

<p><a href="https://blog.dave.tf/post/new-kubernetes/">A better Kubernetes, from the ground up · blog.dave.tf</a> - Some idea to improve k8s</p>

<p><a href="https://chown.me/blog/getting-my-own-asn">Why and how I got my own ASN!</a> - I want to get my own ASN sometime and run it, BGP and all that. Don’t want to spend too much though</p>

<p><a href="http://carl.flax.ie/dothingstellpeople.html">Do Things, Tell People.</a> - Best advice so far</p>

<p><a href="https://asatarin.github.io/testing-distributed-systems/">Testing Distributed Systems | Curated list of resources on testing distributed systems</a> Big list of links on distributed systems</p>

<p><a href="https://internet.nat.moe/">nato internet service</a> - Got to know this from chown.me</p>

<p><a href="https://jakobgreenfeld.com/stay-in-touch">The simple system I’m using to stay in touch with hundreds of people – Jakob Greenfeld – Experiments in Entrepreneurship and Learning</a> - Airtable System to stay in touch with hundreds of people</p>

<p><a href="https://storyset.com/">Storyset | Customize, animate and download illustration for free</a> - Free illustrations for your side projects</p>

<p><a href="https://undraw.co/illustrations">Illustrations | unDraw</a> - Free illustrations for your side projects</p>

<p><a href="https://reproof.app/blog/notes-apps-help-us-forget">Notes apps are where ideas go to die. And that’s good. · reproof</a> - And bookmark bar is where TO-READ goes to die</p>

<p><a href="https://bellmar.medium.com/the-death-of-process-cdb0151a41fe">The Death of Process. To write great policies, arm those in… | by Marianne Bellotti | Feb, 2022 | Medium</a> - Every policy or process doc I write now has a section called “Reasons to Revisit.” It is essentially a reverse success criteria. Rather than a short list of things I would expect to see if the policy was successful - which I do but in a different section - I write about things I would expect to see if the policy needed substantial revisions or to just be killed off altogether. I think laws should have this too</p>

<p><a href="https://www.samjulien.com/shy-dev-networking">The Painfully Shy Developer’s Guide to Networking for a Better Job (Without Being Creepy)</a> - Networking is painful, can introverts get a pronoun for this?</p>

<p><a href="https://elest.io/">Elestio: Fully Managed Open source</a> - Open source software packaged and ready to be deployed. Hope they are successful</p>

<p><a href="https://news.ycombinator.com/item?id=30497703">Ask HN: Books you should read when you transform from SWE into SWE-Management | Hacker News</a></p>

<p><a href="https://www.songsforteaching.com/folk/theresaholeinthebucket.php">There’s a Hole In the Bucket: Traditional Children’s Song Lyrics and Sound Clip</a> - Not sure why I bookmarked it :shrug: (I remember now, it references yak shaving)</p>

<p><a href="https://www.mindprod.com/jgloss/yakshaving.html">yak shaving : Java Glossary</a> - Something seemingly simple grows without bounds</p>

<p><a href="https://causalinf.substack.com/p/how-can-we-know-if-paid-search-advertising?s=r">How can we know if paid search advertising works?</a></p>

<p><a href="https://blog.scaleway.com/40-open-source-projects/">40+ of the best open-source tools to build your startup, from project management to infrastructure</a> - Another list of hyperlinks</p>

<p><a href="https://adoptoposs.org/">Adoptoposs · Keep open source software maintained</a> Looked many time there but didn’t found anything intersting</p>

<p><a href="https://www.gwern.net/docs/ai/gpt/inner-monologue/index">inner monologue (AI) Directory Listing · Gwern.net</a> List of links on one-shot, few-shot learning</p>

<p><a href="https://www.kalzumeus.com/2017/09/09/identity-theft-credit-reports/">Identity Theft, Credit Reports, and You | Kalzumeus Software</a> - How to fix identity theft and credit reports. US specific but general learning are good. Hope I don’t have to use this in my lifetime though</p>

<p><a href="http://www.madore.org/~david/computers/quine.html">Quines (self-replicating programs)</a> Quines what and how tutorial</p>

<p><a href="https://nickdrozd.github.io/2021/03/30/signed-char-lotte.html">signed char lotte | Something Something Programming</a> - Art x Programming</p>

<p><a href="https://freakingrectangle.wordpress.com/2022/04/15/how-to-freaking-hire-great-developers/">How to Freaking Find Great Developers By Having Them Read Code | Freaking Rectangle</a> - New way to hire people. Let me know if it worked for you</p>

<p><a href="https://news.slashdot.org/story/22/04/16/2154203/richard-stallman-speaks-on-the-state-of-free-software-and-answers-questions">Richard Stallman Speaks on the State of Free Software, and Answers Questions - Slashdot</a> RMS interview</p>

<p><a href="https://ronjeffries.com/xprog/articles/jatbaseball/">We Tried Baseball and It Didn’t Work</a> - Why agile doesn’t work, humorus</p>

<hr />
<p>To be continued…</p>]]></content><author><name>Arun Kant Sharma</name><email>mail@arunkant.com</email></author><category term="Bookmarks" /><category term="bookmarks" /><category term="links" /><summary type="html"><![CDATA[A dump of articles and links I've collected in my browser, with brief notes - part 1 of 5.]]></summary></entry><entry><title type="html">CommonJS vs ES Modules in JavaScript</title><link href="https://www.arunkant.com/posts/commonjs-vs-es-modules/" rel="alternate" type="text/html" title="CommonJS vs ES Modules in JavaScript" /><published>2022-07-20T00:00:00+05:30</published><updated>2022-07-20T00:00:00+05:30</updated><id>https://www.arunkant.com/posts/commonjs-vs-es-modules</id><content type="html" xml:base="https://www.arunkant.com/posts/commonjs-vs-es-modules/"><![CDATA[<p>Recently I started learning javascript. we are removing difference between frontend vs backend programmer. I believe most people can do both.</p>

<p>Node JS started and used CommonJS (previously called ServerJS) module system. It loads modules sync. It was fine when reading from file is predictable and long running process on server. Browser cannot load modules and dependencies sync as it would block the UI. So ES Modules were born. they work with both Node (v13.2.0) and browser (script type=”module” attribute)</p>

<h2 id="commonjs-module">CommonJS module</h2>
<p>Let’s create a CommonJS module for calculating fibonanchi (why not?) and use it in an application.</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// fib.js</span>
<span class="kd">function</span> <span class="nf">fib</span><span class="p">(</span><span class="nx">n</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if </span><span class="p">(</span><span class="nx">n</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">||</span> <span class="nx">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="k">return</span> <span class="nx">n</span><span class="p">;</span>
    <span class="k">return</span> <span class="nf">fib</span><span class="p">(</span><span class="nx">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="nf">fib</span><span class="p">(</span><span class="nx">n</span> <span class="o">-</span> <span class="mi">2</span><span class="p">);</span>
<span class="p">}</span>

<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">fib</span> <span class="p">}</span> 
<span class="c1">// Using Shorthand property names</span>
<span class="c1">// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer</span>
</code></pre></div></div>

<p>And let’s use it our app</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// app.js</span>

<span class="kd">const</span> <span class="p">{</span> <span class="nx">fib</span> <span class="p">}</span> <span class="o">=</span> <span class="nf">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">./fib.js</span><span class="dl">'</span><span class="p">);</span> 
<span class="c1">// ".js" is unnecessory using destructuring assignment</span>
<span class="c1">// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment</span>
<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nf">fib</span><span class="p">(</span><span class="mi">10</span><span class="p">));</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ node app.js
55
</code></pre></div></div>

<p>Here we notice use of <code class="language-plaintext highlighter-rouge">module.exports</code> Indicating CommmonJS module</p>

<h2 id="es-modules">ES Modules</h2>
<p>let’s write same with ES modules, we only need to change <code class="language-plaintext highlighter-rouge">modules.export</code> to <code class="language-plaintext highlighter-rouge">expoert ...</code> and <code class="language-plaintext highlighter-rouge">require</code> to <code class="language-plaintext highlighter-rouge">import</code> statements.</p>
<pre><code class="language-mjs">// fib.mjs
function fib(n) {
    if (n == 0 || n == 1) return n;
    return fib(n - 1) + fib(n - 2);
}

export { fib } 
// Shorthand property names
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer
</code></pre>

<p>And let’s use it in our app</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// app.mjs</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">fib</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">./fib.mjs</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nf">fib</span><span class="p">(</span><span class="mi">10</span><span class="p">));</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ node app.mjs 
55
</code></pre></div></div>

<p>See how we are using extension <code class="language-plaintext highlighter-rouge">.mjs</code>. Node give SyntaxError if we try to use ES Modules marking them as such.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(node:26455) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
...
SyntaxError: Cannot use import statement outside a module
</code></pre></div></div>
<p>So we can either use <code class="language-plaintext highlighter-rouge">.mjs</code> extension or we can set type as module in package.json file.</p>

<p>There we have it. CommonJS and ES modules. ES Modules are future but there is lots of existing code written and CommonJS will be here for long time.</p>]]></content><author><name>Arun Kant Sharma</name><email>mail@arunkant.com</email></author><category term="Programming" /><category term="javascript" /><category term="nodejs" /><category term="modules" /><summary type="html"><![CDATA[Why JavaScript has two module systems, how they differ in practice, and when each one shows up in your code.]]></summary></entry></feed>