File tree 11 files changed +227
-0
lines changed
range_cluster_global_mutex
11 files changed +227
-0
lines changed Original file line number Diff line number Diff line change
1
+ # Counting Primes
2
+
3
+ Various multithreaded implimentations of counting prime numbers upto a given number.
4
+
5
+ # Implimentations
6
+ - Serial
7
+ - Range Cluster Global Mutex
8
+ - Range Cluster Channel
9
+ - Fair Global Mutex
10
+
Original file line number Diff line number Diff line change
1
+ package benchmarks
2
+
3
+ import (
4
+ "testing"
5
+
6
+ "github.com/aynp/counting-primes/config"
7
+ "github.com/aynp/counting-primes/implementations/precompute"
8
+ "github.com/aynp/counting-primes/implementations/range_cluster_channel"
9
+ "github.com/aynp/counting-primes/implementations/range_cluster_global_mutex"
10
+ "github.com/aynp/counting-primes/implementations/serial"
11
+ )
12
+
13
+ func BenchmarkSerial (b * testing.B ) {
14
+ for n := 0 ; n < b .N ; n ++ {
15
+ serial .CountPrimes (config .MAX_TEST )
16
+ }
17
+ }
18
+
19
+ func BenchmarkRangeClusterGlobalMutex (b * testing.B ) {
20
+ for n := 0 ; n < b .N ; n ++ {
21
+ range_cluster_global_mutex .CountPrimes (config .MAX_TEST )
22
+ }
23
+ }
24
+
25
+ func BenchmarkRangeClusterChannel (b * testing.B ) {
26
+ for n := 0 ; n < b .N ; n ++ {
27
+ range_cluster_channel .CountPrimes (config .MAX_TEST )
28
+ }
29
+ }
30
+
31
+ func BenchmarkFairGlobalMutex (b * testing.B ) {
32
+ for n := 0 ; n < b .N ; n ++ {
33
+ range_cluster_global_mutex .CountPrimes (config .MAX_TEST )
34
+ }
35
+ }
36
+
37
+ func BenchmarkPrecompute (b * testing.B ) {
38
+ for n := 0 ; n < b .N ; n ++ {
39
+ precompute .CountPrimes (config .MAX_TEST )
40
+ }
41
+ }
Original file line number Diff line number Diff line change
1
+ package config
2
+
3
+ var NUM_THREADS = 4
4
+ var MAX_TEST = 1_000_000
5
+
Original file line number Diff line number Diff line change
1
+ module github.com/aynp/counting-primes
2
+
3
+ go 1.21.5
Original file line number Diff line number Diff line change
1
+ package range_cluster_channel
2
+
3
+ import (
4
+ "sync"
5
+ "sync/atomic"
6
+
7
+ "github.com/aynp/counting-primes/config"
8
+ "github.com/aynp/counting-primes/lib"
9
+ )
10
+
11
+ var current atomic.Int32
12
+ var totalPrimes atomic.Int32
13
+
14
+ func worker (max_test int , wg * sync.WaitGroup ) {
15
+ defer wg .Done ()
16
+
17
+ for {
18
+ i := current .Add (1 )
19
+ if i > int32 (max_test ) {
20
+ break
21
+ }
22
+
23
+ if lib .IsPrime (int (i )) {
24
+ totalPrimes .Add (1 )
25
+ }
26
+ }
27
+ }
28
+
29
+ func CountPrimes (max_test int ) int {
30
+ thread_count := config .NUM_THREADS
31
+
32
+ var wg sync.WaitGroup
33
+
34
+ current .Store (0 )
35
+ totalPrimes .Store (0 )
36
+
37
+ for i := 0 ; i < thread_count ; i ++ {
38
+ go worker (max_test , & wg )
39
+ }
40
+
41
+ return int (current .Load ())
42
+ }
Original file line number Diff line number Diff line change
1
+ package precompute
2
+
3
+ import (
4
+ "github.com/aynp/counting-primes/config"
5
+ "github.com/aynp/counting-primes/lib"
6
+ )
7
+
8
+ var ans int
9
+
10
+ func init () {
11
+ count := 0
12
+ for i := 0 ; i < config .MAX_TEST ; i ++ {
13
+ if lib .IsPrime (i ) {
14
+ count ++
15
+ }
16
+ }
17
+
18
+ ans = count
19
+ }
20
+
21
+ // This implimentation is a bit of cheating, but I'll allow it
22
+ func CountPrimes (n int ) int {
23
+ return ans
24
+ }
Original file line number Diff line number Diff line change
1
+ package range_cluster_channel
2
+
3
+ import (
4
+ "github.com/aynp/counting-primes/config"
5
+ "github.com/aynp/counting-primes/lib"
6
+ )
7
+
8
+ func countPrimesInRange (start , end int , ch chan int ) {
9
+ count := 0
10
+
11
+ for i := start ; i < end ; i ++ {
12
+ if lib .IsPrime (i ) {
13
+ count ++
14
+ }
15
+ }
16
+
17
+ ch <- count
18
+ }
19
+
20
+ func CountPrimes (n int ) int {
21
+ thread_count := config .NUM_THREADS
22
+
23
+ count := 0
24
+ chunk_size := n / thread_count
25
+
26
+ ch := make (chan int , thread_count )
27
+
28
+ for i := 0 ; i < thread_count ; i ++ {
29
+ go countPrimesInRange (i * chunk_size , (i + 1 )* chunk_size , ch )
30
+ }
31
+
32
+ for i := 0 ; i < thread_count ; i ++ {
33
+ count += <- ch
34
+ }
35
+
36
+ return count
37
+ }
Original file line number Diff line number Diff line change
1
+ package range_cluster_global_mutex
2
+
3
+ import (
4
+ "sync"
5
+ "sync/atomic"
6
+
7
+ "github.com/aynp/counting-primes/config"
8
+ "github.com/aynp/counting-primes/lib"
9
+ )
10
+
11
+ var wg sync.WaitGroup
12
+ var count atomic.Int64
13
+
14
+ func countPrimesInRange (start , end int ) {
15
+ defer wg .Done ()
16
+
17
+ for i := start ; i < end ; i ++ {
18
+ if lib .IsPrime (i ) {
19
+ count .Add (1 )
20
+ }
21
+ }
22
+ }
23
+
24
+ func CountPrimes (n int ) int {
25
+ count .Store (0 )
26
+
27
+ thread_count := config .NUM_THREADS
28
+ chunk_size := n / thread_count
29
+
30
+ for i := 0 ; i < thread_count ; i ++ {
31
+ wg .Add (1 )
32
+ go countPrimesInRange (i * chunk_size , (i + 1 )* chunk_size )
33
+ }
34
+
35
+ wg .Wait ()
36
+
37
+ return int (count .Load ())
38
+ }
Original file line number Diff line number Diff line change
1
+ package serial
2
+
3
+ import (
4
+ "github.com/aynp/counting-primes/lib"
5
+ )
6
+
7
+ func CountPrimes (n int ) int {
8
+ count := 0
9
+ for i := 2 ; i < n ; i ++ {
10
+ if lib .IsPrime (i ) {
11
+ count ++
12
+ }
13
+ }
14
+ return count
15
+ }
Original file line number Diff line number Diff line change
1
+ package lib
2
+
3
+ // IsPrime returns true if n is prime, false otherwise.
4
+ // This takes O(sqrt(n)) time.
5
+ func IsPrime (n int ) bool {
6
+ for i := 2 ; i * i <= n ; i ++ {
7
+ if n % i == 0 {
8
+ return false
9
+ }
10
+ }
11
+ return true
12
+ }
You can’t perform that action at this time.
0 commit comments