Last active
November 5, 2016 04:26
-
-
Save marioroy/e785bdb94742633b67e1138a21085013 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
# Parallel demonstration for Monte Carlo Pi Calculation | |
# https://gist.github.com/dmr3/f435e84fb26f4de2e0c8e1f2d2e74f9b | |
# | |
# Original source by Demian Riccardi | |
# Parallel demonstration by Mario Roy | |
use Mojolicious::Lite; | |
use MCE::Hobo; | |
use MCE::Shared; | |
any '/' => sub { | |
my $self = shift; | |
$self->render( 'index', rows => [ [] ] ); | |
}; | |
# setup websocket message handler | |
websocket '/more_pi' => sub { | |
my $self = shift; | |
$self->inactivity_timeout(3000); | |
$self->on( | |
json => sub { | |
my $ws = shift; | |
my $args = shift; | |
my ( $pi, $total_runs, $new_runs ) = @$args; | |
# my $cnt_pi = -1 * ( ( $pi * $total_runs ) / 4 - $total_runs ); | |
# my ( $x, $y ); | |
# | |
# foreach ( 1 .. $new_runs ) { | |
# $x = rand(1); | |
# $y = rand(1); | |
# $cnt_pi++ if $x * $x + $y * $y > 1; | |
# } | |
my $cnt_pi = MCE::Shared->scalar( | |
-1 * ( ( $pi * $total_runs ) / 4 - $total_runs ) | |
); | |
my $seq = MCE::Shared->sequence( | |
{ chunk_size => 5000, bounds_only => 1 }, | |
1, $new_runs | |
); | |
my $task = sub { | |
my ( $cnt, $x, $y ) = ( 0 ); | |
while ( my ( $beg, $end ) = $seq->next ) { | |
foreach ( $beg .. $end ) { | |
$x = rand(1); | |
$y = rand(1); | |
$cnt++ if $x * $x + $y * $y > 1; | |
} | |
} | |
$cnt_pi->incrby( $cnt ); | |
}; | |
MCE::Hobo->create( { posix_exit => 1 }, $task ) for 1 .. 4; | |
MCE::Hobo->waitall; | |
$total_runs += $new_runs; | |
$pi = 4 * ( $total_runs - $cnt_pi->get ) / $total_runs; | |
my $html = $ws->render_to_string( 'table', | |
rows => [ [ $pi, $total_runs ] ] ); | |
$ws->send( | |
{ | |
json => { | |
row => $html, | |
vals => [ $pi, $total_runs, $new_runs ], | |
target => '#table', #for fun | |
} | |
} | |
); | |
} | |
); | |
}; | |
app->start; | |
__DATA__ | |
@@ index.html.ep | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Monte Carlo pi</title> | |
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet"> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script> | |
</head> | |
<body> | |
<div class=container> | |
%= include 'mcpiform' | |
<div class="row"><div class="col-md-6"> | |
<table class="table table-bordered table-condensed"> | |
<thead> | |
<tr><th>Calculated π</th><th> Total runs</th></tr> | |
</thead> | |
<tbody id="table"> | |
%= include 'table' | |
</tbody> | |
</table> | |
</div></div> | |
</div> | |
%= javascript 'js/ws.js' | |
</body> | |
</html> | |
@@ mcpiform.html.ep | |
<div class="form-inline" role="form"> | |
<div class="form-group"> | |
<label for="mcpi">Starting π</label> | |
<input type="text" class="form-control" id="mcpif" value="0"> | |
</div> | |
<div class="form-group"> | |
<label for="truns"> Total runs</label> | |
<input type="text" class="form-control" id="trunsf" value="0"> | |
</div> | |
<div class="form-group"> | |
<label for="nruns"> New runs</label> | |
<input type="text" class="form-control" id="nrunsf" value="10000"> | |
</div> | |
<div class="form-group"> | |
<label for="nitrs"> Repeats </label> | |
<input type="text" class="form-control" id="nitrsf" value="1"> | |
</div> | |
<input type="submit" value="Add" id="pibutton" onclick="update_pi( '<%= url_for('more_pi')->to_abs %>')" > | |
</div> | |
@@ table.html.ep | |
% foreach my $row (@$rows) { | |
<tr> | |
% foreach my $text (@$row) { | |
<td><%= $text %></td> | |
% } | |
</tr> | |
% } | |
@@ js/ws.js | |
function update_pi (url) { | |
if (!("WebSocket" in window)) { | |
alert('Your browser does not support WebSockets!'); | |
return; | |
} | |
$('#pibutton').prop("disabled",true); | |
var ws = new WebSocket(url); | |
var counter = $('#nitrsf').val(); | |
var save_cnt = $('#nitrsf').val(); | |
ws.onopen = function () { | |
var mcpi = $('#mcpif'); | |
var trun = $('#trunsf'); | |
var nrun = $('#nrunsf'); | |
ws.send(JSON.stringify([mcpi.val(),trun.val(),nrun.val()])); | |
counter--; | |
}; | |
console.log(counter); | |
ws.onmessage = function (evt) { | |
var data = JSON.parse(evt.data); | |
$(data.target).append(data.row); | |
if(counter > 0){ | |
ws.send(JSON.stringify( [data.vals[0],data.vals[1],data.vals[2]])); | |
counter--; | |
if (counter === 0) { | |
$('#pibutton').prop("disabled",false); | |
} | |
} | |
//$('#table').append(data.row); | |
//insert values into form for convenience | |
$('#mcpif').val(data.vals[0]); | |
$('#trunsf').val(data.vals[1]); | |
$('#nrunsf').val(data.vals[2]); | |
$('#nitrsf').val(save_cnt); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment