<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Suyash Dhakal</title>
    <description>The latest articles on DEV Community by Suyash Dhakal (@suyash_dhakal).</description>
    <link>https://dev.to/suyash_dhakal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4080078%2F7e605a9f-2fea-4a3b-9806-f2c3ddc74546.jpg</url>
      <title>DEV Community: Suyash Dhakal</title>
      <link>https://dev.to/suyash_dhakal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/suyash_dhakal"/>
    <language>en</language>
    <item>
      <title>Same Request Sent Twice: How Idempotency Prevents Duplicate Payments</title>
      <dc:creator>Suyash Dhakal</dc:creator>
      <pubDate>Sun, 16 Aug 2026 19:51:05 +0000</pubDate>
      <link>https://dev.to/suyash_dhakal/same-request-sent-twice-how-idempotency-prevents-duplicate-payments-3g8i</link>
      <guid>https://dev.to/suyash_dhakal/same-request-sent-twice-how-idempotency-prevents-duplicate-payments-3g8i</guid>
      <description>&lt;p&gt;A user opens a payment app, types in an amount, and taps "Pay." The spinner shows up. Then nothing — no success screen, no error, just a frozen loader.&lt;/p&gt;

&lt;p&gt;So they tap "Pay" again. Or the app quietly retries in the background because it never got a response.&lt;/p&gt;

&lt;p&gt;But here's the actual problem: what if the first request actually reached the server and the payment already went through, and only the &lt;em&gt;response&lt;/em&gt; got lost on the way back? The second tap now sends the same payment again. Does the user get charged twice?&lt;/p&gt;

&lt;p&gt;This isn't a rare edge case. Mobile connections drop, servers get slow under load, requests time out. Any system that moves money over a network runs into this.&lt;/p&gt;

&lt;h2&gt;
  
  
  The idea that fixes it
&lt;/h2&gt;

&lt;p&gt;The concept here is &lt;strong&gt;idempotency&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;An operation is idempotent if running it twice has the same effect as running it once. Send the same request again, retry, double tap, whatever, and the outcome shouldn't change.&lt;/p&gt;

&lt;p&gt;Pressing an elevator button five times doesn't call five elevators. The building registers your request once. A payment should work the same way: the button might get tapped repeatedly, but the money should move once.&lt;/p&gt;

&lt;p&gt;The server doesn't ignore the repeat request. It just recognizes it as a repeat instead of treating it as something new.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why payments care about this more than most systems
&lt;/h2&gt;

&lt;p&gt;If a retried request reloads a page or re-fetches some data, nobody gets hurt. Payments are different, because the thing being repeated moves real money.&lt;/p&gt;

&lt;p&gt;A typical failure looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
  ↓
Payment API
  ↓
Payment processed
  ↓
Response is lost
  ↓
User/app retries
  ↓
Same payment request reaches the server again
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look at where it breaks. The payment &lt;em&gt;succeeded&lt;/em&gt;. The server did its job. The failure happened after that, somewhere between the server and the user's phone. From the server's side everything is fine. From the user's side, nothing happened — so retrying feels like the obvious move.&lt;/p&gt;

&lt;p&gt;That's why the backend can't assume every incoming request is a brand-new payment. A slow network plus one retry, and someone's account gets debited twice for something they bought once. In fintech that's not a glitch, it's a refund, a support ticket, and a user who stops trusting the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  The idempotency key
&lt;/h2&gt;

&lt;p&gt;So how does the server tell "I already did this" apart from "this is new"?&lt;/p&gt;

&lt;p&gt;With an &lt;strong&gt;idempotency key&lt;/strong&gt; — a unique value the client generates and attaches to that specific payment attempt. Usually it's sent as an HTTP header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /payments
Idempotency-Key: abc123
Content-Type: application/json

{
  "amount": 100,
  "currency": "NPR"
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key itself is just a unique string. The important rule is that a retry reuses the &lt;em&gt;same&lt;/em&gt; key instead of generating a fresh one.&lt;/p&gt;

&lt;p&gt;First attempt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Idempotency-Key: abc123
        ↓
Server receives request
        ↓
Server processes payment
        ↓
Server stores the result associated with abc123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server now has a record saying "abc123 was handled, and here's what happened."&lt;/p&gt;

&lt;p&gt;Response gets lost, app retries with the same key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Idempotency-Key: abc123
        ↓
Server receives request
        ↓
Server recognizes the key
        ↓
Does not create another payment
        ↓
Returns the previous result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No new charge, just a slightly late confirmation for the user. The key is the thing that lets the server link the retry back to the original attempt.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few things worth knowing about the key
&lt;/h2&gt;

&lt;p&gt;Same key plus same operation means retry. A different key means a different operation — which is what lets someone genuinely pay the same amount twice on purpose. They'd just be sending two different keys.&lt;/p&gt;

&lt;p&gt;But same key with a different payload isn't a retry — that's a bug. Say abc123 is used for a Rs. 100 payment, then shows up again with a Rs. 500 request. The server shouldn't just return whatever it stored the first time. Stripe, for example, checks for this: same key with matching parameters returns the original response, but a mismatch returns an error instead of processing it.&lt;/p&gt;

&lt;p&gt;The server also has to store and check these keys reliably. This is usually a database, often with a unique constraint on the key, so two identical requests arriving at nearly the same time can't both slip through.&lt;/p&gt;

&lt;p&gt;There's a timing gap hiding in that too. What if a second request with abc123 lands while the first one is still being processed, before there's even a stored result yet? Most systems handle this with a lock on the key — the second request waits, or gets bounced with a 409 telling the client to try again shortly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two situations side by side
&lt;/h2&gt;

&lt;p&gt;Without idempotency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User sends payment
      ↓
Payment succeeds
      ↓
Response is lost
      ↓
User retries
      ↓
Server processes it again
      ↓
Possible duplicate payment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With idempotency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User sends payment with key ABC
      ↓
Payment succeeds
      ↓
Response is lost
      ↓
User retries with key ABC
      ↓
Server recognizes ABC
      ↓
Previous result is returned
      ↓
No duplicate payment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The trigger is identical in both — a lost response and a retry. The only difference is whether the server blindly repeats the work or notices the repeat.&lt;/p&gt;

&lt;h2&gt;
  
  
  How you'd actually test this
&lt;/h2&gt;

&lt;p&gt;You can read about idempotency all day. Testing it is different. Here's where to start if you're testing a payment flow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Double-tap it.&lt;/strong&gt; Send the same request twice, back to back, same key. Only one charge should go through.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cut the response, not the request.&lt;/strong&gt; Let the server finish processing, but kill the connection before the response comes back. Retry with the same key. Do you get the old result, or does it run again?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reuse the key, change the amount.&lt;/strong&gt; Send &lt;code&gt;abc123&lt;/code&gt; for Rs. 100, then &lt;code&gt;abc123&lt;/code&gt; again for Rs. 500. Does it error out, return the first result anyway, or actually process Rs. 500?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fire both at once.&lt;/strong&gt; Send two identical requests with the same key at the same time. See if both slip through before either one finishes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skip the header.&lt;/strong&gt; Send the request without &lt;code&gt;Idempotency-Key&lt;/code&gt; at all. Check if the API rejects it, or just runs it like normal.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;A request being sent twice doesn't mean the operation should happen twice. Networks are unreliable, users retry, apps retry automatically. None of that is avoidable, and none of it is unusual.&lt;/p&gt;

&lt;p&gt;In payments, this matters even more. Sending the same payment twice can mean charging someone twice. Idempotency is simply a way to make those retries safe.&lt;/p&gt;

&lt;p&gt;In the end, idempotency is about one simple thing: making sure a retry doesn't turn into a duplicate operation.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>idempotency</category>
      <category>backend</category>
      <category>api</category>
    </item>
    <item>
      <title>Estimating Pi: A Monte Carlo Approach Enhanced by OpenMP Parallelism</title>
      <dc:creator>Suyash Dhakal</dc:creator>
      <pubDate>Tue, 15 Oct 2024 11:10:32 +0000</pubDate>
      <link>https://dev.to/suyash_dhakal/estimating-pi-a-monte-carlo-approach-enhanced-by-openmp-parallelism-37g4</link>
      <guid>https://dev.to/suyash_dhakal/estimating-pi-a-monte-carlo-approach-enhanced-by-openmp-parallelism-37g4</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F949t7fgm5e5borq3eeu9.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F949t7fgm5e5borq3eeu9.jpeg" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
Image credit: domin_domin via iStock&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What if I told you that the seemingly random nature of points can be harnessed to calculate one of mathematics’ most famous constants — π? In this blog, we will explore how the Monte Carlo method can be used to estimate the value of π, an essential constant in mathematics and physics. We will also examine how OpenMP parallelism enhances the efficiency of the Monte Carlo approach.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Understanding the Monte Carlo Method
&lt;/h3&gt;

&lt;p&gt;Monte Carlo methods are a broad class of computational algorithms that rely on repeated random sampling to obtain numerical results. They are widely used in various fields, including statistics, finance, physics, and engineering, to solve problems that may be deterministic in nature but are difficult to solve analytically.&lt;/p&gt;

&lt;p&gt;One interesting application of the Monte Carlo method is the estimation of π. By randomly generating points within a unit square and determining how many of those points fall within a quarter circle inscribed in that square, we can derive an estimate for π.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Algorithm for Estimating π&lt;/strong&gt;
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Draw a unit square and inscribe a quarter circle within it.&lt;/li&gt;
&lt;li&gt;Randomly generate points within the square.&lt;/li&gt;
&lt;li&gt;Count the number of points that fall within the quarter circle by checking whether x²+y²≤1.&lt;/li&gt;
&lt;li&gt;Calculate the ratio of points inside the circle to the total points, which approximates π/4.&lt;/li&gt;
&lt;li&gt;Estimate π by multiplying the ratio by 4.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0zcuj5y27dg5o3wfkepe.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0zcuj5y27dg5o3wfkepe.gif" width="480" height="568"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Monte Carlo method applied to approximating the value of π&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Parallel Implementation of Monte Carlo Method
&lt;/h3&gt;

&lt;p&gt;By distributing the workload across multiple threads, the parallel implementation of the Monte Carlo method using OpenMP significantly reduces computation time, especially when handling large datasets. This approach allows for scaling the number of points generated, achieving a more accurate approximation of π. Below is the implementation of the parallel Monte Carlo method for estimating π using OpenMP.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;omp.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wall_clock_time&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;n = "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;scanf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%ld"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;omp_set_num_threads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Set the number of threads&lt;/span&gt;

    &lt;span class="c1"&gt;// True random numbers from random.org (based on atmospheric noise)&lt;/span&gt;
    &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;true_random_numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;74&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;54&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;89&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;54&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;omp_get_wtime&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Record the start time&lt;/span&gt;

    &lt;span class="cp"&gt;#pragma omp parallel
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Seed each thread once&lt;/span&gt;
        &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;true_random_numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;omp_get_thread_num&lt;/span&gt;&lt;span class="p"&gt;()];&lt;/span&gt; 
        &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;local_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="cp"&gt;#pragma omp for private(x, y, z)
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;rand_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;RAND_MAX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Generate random x in [0, 1]&lt;/span&gt;
            &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;rand_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;RAND_MAX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Generate random y in [0, 1]&lt;/span&gt;
            &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Check if inside the unit circle&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;local_count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Count points inside the circle&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="cp"&gt;#pragma omp atomic
&lt;/span&gt;        &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;local_count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;omp_get_wtime&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Record the end time&lt;/span&gt;

    &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;pi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Estimate of Pi&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Approximate PI = %.9Lf&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pi&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;wall_clock_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Elapsed Wall Clock Time: %f seconds&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wall_clock_time&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The provided C program estimates the value of π using the Monte Carlo method, enhanced with parallel processing via OpenMP. It uses true random numbers sourced from random.org, generated using atmospheric noise to ensure high-quality randomness. Each thread is seeded once using the true_random_numbers[] array, allowing for independent and thread-safe random number generation with rand_r().&lt;/p&gt;

&lt;p&gt;The workload is effectively distributed among threads using the#pragma omp for directive, enabling each thread to execute the Monte Carlo algorithm on its assigned set of iterations. Each thread maintains a private copy of the local count of points that fall within the quarter circle. After all threads complete their assigned tasks, the local counts are combined using an atomic operation to prevent race conditions. Finally, the estimated value of π is calculated by multiplying the ratio of points inside the circle by 4.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Experimental Results: Estimating π with 80 Billion Points&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;In the experiment conducted to estimate the value of π using a substantial sample size of &lt;strong&gt;80 billion points&lt;/strong&gt; , the Monte Carlo method was executed with n=80,000,000,000 (80 billion), yielding an approximation of π=3.141592614, &lt;strong&gt;accurate up to 7 decimal places&lt;/strong&gt; , and took an elapsed wall clock time of approximately 235.32 seconds ( &lt;strong&gt;about 3.92 minutes&lt;/strong&gt; ) to approximate π.&lt;/p&gt;

&lt;p&gt;For comparison, the serial version of the algorithm was run with n=8,000,000,000 ( &lt;strong&gt;8 billion&lt;/strong&gt; ), resulting in an approximation of π=3.14160, accurate up to 3 decimal places, and took an elapsed time of 147.69 seconds ( &lt;strong&gt;about 2.46 minutes&lt;/strong&gt; ).&lt;/p&gt;

&lt;p&gt;This showcases a significant efficiency gain with the parallel implementation; the serial version would require approximately &lt;strong&gt;24 to 25 minutes&lt;/strong&gt; to approximate π for a sample size of &lt;strong&gt;80 billion&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experiment Setup:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Device:&lt;/strong&gt; Apple MacBook Air&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chip:&lt;/strong&gt; M2&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RAM:&lt;/strong&gt; 16GB&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CPU:&lt;/strong&gt; 8-core (4 efficiency cores, 4 performance cores)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operating System:&lt;/strong&gt; macOS Sonoma Version 14.6.1&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compiler:&lt;/strong&gt; GCC 14 with OpenMP support&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Convergence of the Monte Carlo Estimation of Pi
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftgcogdunn12t842vu0ug.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftgcogdunn12t842vu0ug.png" width="800" height="595"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The convergence graph shows how the sample size affects the estimated value of π using the Monte Carlo method. As the sample size increases, the estimated value of π stabilizes around the true value of π, which is indicated by a red dashed line. For instance, with a sample size of 10, the estimate is 3.6, while at 1,000,000 samples, it improves to about 3.139. This trend highlights that larger sample sizes yield more accurate estimates, confirming the effectiveness of the Monte Carlo method for approximating the value of Pi.&lt;/p&gt;

&lt;h3&gt;
  
  
  Absolute Error vs. Sample Size
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwcgkg2avp3q5wnng0jmz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwcgkg2avp3q5wnng0jmz.png" width="800" height="594"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The absolute error graph illustrates how the sample size impacts the accuracy of the π estimation using the Monte Carlo method. As the sample size increases, the absolute error decreases significantly, indicating that larger sample sizes lead to more precise approximations. For example, with a sample size of 10, the absolute error is 0.458407, whereas, at a sample size of 1,000,000, the error drops to just 0.002537. This trend demonstrates the reliability of the Monte Carlo method in achieving high accuracy with sufficient sample sizes, confirming its effectiveness for approximating the value of π.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In this study, we applied the Monte Carlo method to estimate π using a sample size of 80 billion points, yielding an approximation of 3.141592614, accurate up to 7 decimal places. The results demonstrated the effectiveness of parallel computing in reducing computation time compared to serial implementation. Additionally, the analysis of convergence and absolute error confirmed that larger sample sizes improve accuracy, demonstrating the robustness of the Monte Carlo method for π approximation.&lt;/p&gt;

</description>
      <category>parallelcomputing</category>
      <category>montecarlosimulation</category>
      <category>pi</category>
      <category>openmp</category>
    </item>
  </channel>
</rss>
