11package main
22
33import (
4- "fmt"
4+ "flag"
5+ "math"
56 "math/rand"
67 "runtime"
78 "time"
89
910 "github.com/qcserestipy/gohpc/pkg/workerpool"
11+ "github.com/sirupsen/logrus"
1012)
1113
14+ func init () {
15+ formatter := & logrus.TextFormatter {}
16+ formatter .FullTimestamp = true
17+ formatter .TimestampFormat = time .RFC3339
18+ logrus .SetLevel (logrus .DebugLevel )
19+ logrus .SetFormatter (formatter )
20+ }
21+
1222func main () {
13- const nTests = 10_000_000_000
23+ logrus .Info ("Starting Monte Carlo π approximation" )
24+ numbPtr := flag .Int ("n" , 10000000000 , "Number of Trials" )
25+ flag .Parse ()
26+ nTests := * numbPtr
27+ logrus .Infof ("Number of Trials: %d" , nTests )
1428
1529 // Split work into tasks
1630 numWorkers := runtime .NumCPU ()
31+ logrus .Infof ("System: %d CPU cores available" , numWorkers )
32+
1733 type Task struct { Count int }
1834 tasks := make ([]Task , numWorkers )
1935 chunk := nTests / numWorkers
36+ remainder := nTests % numWorkers
37+
38+ var totalAllocated int
2039 for i := range tasks {
21- tasks [i ] = Task {Count : chunk }
40+ extraPoints := 0
41+ if i < remainder {
42+ extraPoints = 1
43+ }
44+ tasks [i ] = Task {Count : chunk + extraPoints }
45+ totalAllocated += tasks [i ].Count
2246 }
2347
48+ logrus .WithFields (logrus.Fields {
49+ "workers" : numWorkers ,
50+ "points_per_task" : chunk ,
51+ "remainder" : remainder ,
52+ "total_allocated" : totalAllocated ,
53+ }).Info ("Work distribution prepared" )
54+
55+ setupStart := time .Now ()
2456 // Create pool
2557 pool := workerpool.New [Task , float64 ](numWorkers )
58+ logrus .Infof ("Worker pool initialized in %v" , time .Since (setupStart ))
2659
2760 // Define work
2861 work := func (t Task ) float64 {
62+ taskStart := time .Now ()
2963 inCircle := 0
30- r := rand .New (rand .NewSource (time .Now ().UnixNano ()))
64+ seed := time .Now ().UnixNano ()
65+ r := rand .New (rand .NewSource (seed ))
66+ logrus .Debugf ("Worker started with seed %d for %d points" , seed , t .Count )
67+
3168 for i := 0 ; i < t .Count ; i ++ {
3269 x , y := r .Float64 (), r .Float64 ()
3370 if x * x + y * y < 1 {
3471 inCircle ++
3572 }
3673 }
74+
75+ ratio := float64 (inCircle ) / float64 (t .Count )
76+ logrus .WithFields (logrus.Fields {
77+ "points_processed" : t .Count ,
78+ "points_in_circle" : inCircle ,
79+ "local_ratio" : ratio ,
80+ "local_pi_approx" : 4 * ratio ,
81+ "duration" : time .Since (taskStart ),
82+ }).Debug ("Worker completed" )
83+
3784 return float64 (inCircle )
3885 }
3986
4087 // Run
4188 start := time .Now ()
89+ logrus .Info ("Starting computation..." )
4290 results := pool .Run (tasks , work )
4391 elapsed := time .Since (start )
4492
@@ -49,5 +97,13 @@ func main() {
4997 }
5098 piApprox := 4 * (total / float64 (nTests ))
5199
52- fmt .Printf ("π ≈ %0.8f (computed in %s)" , piApprox , elapsed )
100+ logrus .WithFields (logrus.Fields {
101+ "pi_approximation" : piApprox ,
102+ "error" : math .Abs (piApprox - math .Pi ),
103+ "duration" : elapsed ,
104+ "points_per_sec" : float64 (nTests ) / elapsed .Seconds (),
105+ }).Info ("Computation completed" )
106+
107+ logrus .Infof ("π ≈ %0.8f (error: %0.8f, computed in %s)" ,
108+ piApprox , math .Abs (piApprox - math .Pi ), elapsed )
53109}
0 commit comments