{"id":154,"date":"2024-11-24T12:00:04","date_gmt":"2024-11-24T10:00:04","guid":{"rendered":"https:\/\/tel-zur.net\/blog\/?p=154"},"modified":"2024-11-24T12:03:00","modified_gmt":"2024-11-24T10:03:00","slug":"embarrassingly-parallel-computations-with-ray","status":"publish","type":"post","link":"https:\/\/tel-zur.net\/blog\/2024\/11\/24\/embarrassingly-parallel-computations-with-ray\/","title":{"rendered":"Embarrassingly Parallel Computations with Ray"},"content":{"rendered":"\n<p><a href=\"https:\/\/www.ray.io\/\" data-type=\"link\" data-id=\"https:\/\/www.ray.io\/\">Ray<\/a> is an excellent framework for large-scale distributed computations in <a href=\"https:\/\/www.python.org\/\" data-type=\"link\" data-id=\"https:\/\/www.python.org\/\">Python<\/a>. In this blog post, I demonstrate a simple example of Ray&#8217;s capability to perform <strong>Embarrassingly Parallel Computation<\/strong> with minimal and straightforward source code. It is well known that if we <a href=\"https:\/\/en.wikipedia.org\/wiki\/Random_number\" data-type=\"link\" data-id=\"https:\/\/en.wikipedia.org\/wiki\/Random_number\">randomly<\/a> throw dots inside a square enclosing a circle, the ratio of the number of dots that fall inside the circle to the total number of dots approaches \u03c0\/4 (where \u03c0 \u2248 3.1415926&#8230;), as the total number of dots approaches infinity. Figure 1 illustrates this concept. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"474\" height=\"355\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2024\/11\/pi_mc.jpeg\" alt=\"\" class=\"wp-image-155\" style=\"width:817px;height:auto\" srcset=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2024\/11\/pi_mc.jpeg 474w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2024\/11\/pi_mc-300x225.jpeg 300w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><figcaption class=\"wp-element-caption\">Figure 1: Estimating Pi using a Monte Carlo computation.<\/figcaption><\/figure>\n\n\n\n<p>Numerical methods that are based on random numbers are call <a href=\"https:\/\/en.wikipedia.org\/wiki\/Monte_Carlo_method\" data-type=\"link\" data-id=\"https:\/\/en.wikipedia.org\/wiki\/Monte_Carlo_method\">Monte-Carlo computations<\/a>. The accuracy of this method depends on the sample size. However, achieving higher accuracy requires a larger sample, which in turn increases computation time. Fortunately, this algorithm, which relies on random numbers, can be easily parallelized. Since random numbers are, by definition, uncorrelated, parallel tasks can execute the same algorithm simultaneously without interference. The only step remaining is to combine the partial results of these independent computations into a single final result using a reduction operation.<\/p>\n\n\n\n<p>The simple Python code that implements this using Ray, along with the computation result executed in <a href=\"https:\/\/code.visualstudio.com\/\" data-type=\"link\" data-id=\"https:\/\/code.visualstudio.com\/\">VS Code<\/a>, is shown in Figure 2.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"579\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2024\/11\/ray_pi_mc_vscode-1024x579.png\" alt=\"\" class=\"wp-image-156\" srcset=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2024\/11\/ray_pi_mc_vscode-1024x579.png 1024w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2024\/11\/ray_pi_mc_vscode-300x170.png 300w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2024\/11\/ray_pi_mc_vscode-768x434.png 768w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2024\/11\/ray_pi_mc_vscode-1536x868.png 1536w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2024\/11\/ray_pi_mc_vscode-1568x886.png 1568w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2024\/11\/ray_pi_mc_vscode.png 1854w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Figure 2: Python code using Ray in VS-Code.<\/figcaption><\/figure>\n\n\n\n<p>The full code is enclosed below:<\/p>\n\n\n<pre class=\"wp-block-code synano\" data-theme=\"default\"><code class=\"language-auto\">import ray\nimport random\n\n# Initialize Ray\nray.init(ignore_reinit_error=True)\n\n@ray.remote\ndef sample_pi(num_samples):\n    count = 0\n    for _ in range(num_samples):\n        x, y = random.random(), random.random()\n        if x*x + y*y &lt;= 1.0:\n            count += 1\n    return count\n\n# Number of samples for each task\nnum_samples = 10000000\n# Number of tasks\nnum_tasks = 100\n\n# Submit tasks to Ray\ncounts = ray.get([sample_pi.remote(num_samples) for _ in range(num_tasks)])\n\n# Calculate the estimated value of pi\ntotal_samples = num_samples * num_tasks\npi_estimate = 4 * sum(counts) \/ total_samples\n\nprint(f&quot;Estimated value of pi: {pi_estimate}&quot;)\n\n# Shutdown Ray\nray.shutdown()<\/code><\/pre>\n\n\n<p>It is recommended to verify the parallel execution of this code by monitoring your computer&#8217;s resource usage. For this purpose, you can use your system&#8217;s task manager. On Linux systems, tools like <code><a href=\"https:\/\/www.man7.org\/linux\/man-pages\/man1\/top.1.html\" data-type=\"link\" data-id=\"https:\/\/www.man7.org\/linux\/man-pages\/man1\/top.1.html\">top<\/a><\/code> or <code><a href=\"https:\/\/htop.dev\/\" data-type=\"link\" data-id=\"https:\/\/htop.dev\/\">htop<\/a><\/code> are particularly useful for observing CPU utilization in real time. Figure 3 provides an example of this process.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2024\/11\/ray_pi_mc_top-1024x576.png\" alt=\"\" class=\"wp-image-160\" srcset=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2024\/11\/ray_pi_mc_top-1024x576.png 1024w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2024\/11\/ray_pi_mc_top-300x169.png 300w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2024\/11\/ray_pi_mc_top-768x432.png 768w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2024\/11\/ray_pi_mc_top-1536x864.png 1536w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2024\/11\/ray_pi_mc_top-1568x882.png 1568w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2024\/11\/ray_pi_mc_top.png 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Figure 3: Verification of the parallel execution of the code by looking simultaneously at &#8216;htop&#8217;.<\/figcaption><\/figure>\n\n\n\n<p>You are welcome to try this short example yourself and leave me a comment below.<\/p>\n\n\n\n<p>Guy<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ray is an excellent framework for large-scale distributed computations in Python. In this blog post, I demonstrate a simple example of Ray&#8217;s capability to perform Embarrassingly Parallel Computation with minimal and straightforward source code. It is well known that if we randomly throw dots inside a square enclosing a circle, the ratio of the number &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/tel-zur.net\/blog\/2024\/11\/24\/embarrassingly-parallel-computations-with-ray\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Embarrassingly Parallel Computations with Ray&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-154","post","type-post","status-publish","format-standard","hentry","category-uncategorized","entry"],"_links":{"self":[{"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/posts\/154","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/comments?post=154"}],"version-history":[{"count":6,"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/posts\/154\/revisions"}],"predecessor-version":[{"id":165,"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/posts\/154\/revisions\/165"}],"wp:attachment":[{"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/media?parent=154"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/categories?post=154"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/tags?post=154"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}