Here's the code for the Go (golang.org) version:
package main
import (
"fmt"
)
func main(){
findprimes(10*1000)
}
func isprime(x int) bool {
for i := 2; i < x; i++ {
if x%i == 0 {
return false
}
}
return true
}
func findprimes(m int){
for i := 11; i < m; i++ {
if isprime(i) && isprime(i-6) {
fmt.Printf("%d %d\n", i-6, i)
}
}
}
It ran just as fast as the C version.
Using an Asus u81a
Intel Core 2 Duo T6500 2.1GHz, 2MB L2 cache, 800MHz FSB.
4GB RAM
The 100k version: C: 2.723s
Go: 2.743s
With 1000000 (1M instead of 100K): C: 3m35.458s
Go: 3m36.259s
But I think that it would be fair to use Go's built in multithreading capabilities and compare that version with the regular C version (without multithreading), just because it's almost too easy to do multithreading with Go.
Update: I did a parallel version using Goroutines in Go:
package main
import (
"fmt"
"runtime"
)
func main(){
runtime.GOMAXPROCS(4)
printer := make(chan string)
printer2 := make(chan string)
printer3 := make(chan string)
printer4 := make(chan string)
finished := make(chan int)
var buffer, buffer2, buffer3 string
running := 4
go findprimes(11, 30000, printer, finished)
go findprimes(30001, 60000, printer2, finished)
go findprimes(60001, 85000, printer3, finished)
go findprimes(85001, 100000, printer4, finished)
for {
select {
case i := <-printer:
// batch of sexy primes received from printer channel 1, print them
fmt.Printf(i)
case i := <-printer2:
// sexy prime list received from channel, store it
buffer = i
case i := <-printer3:
// sexy prime list received from channel, store it
buffer2 = i
case i := <-printer4:
// sexy prime list received from channel, store it
buffer3 = i
case <-finished:
running--
if running == 0 {
// all goroutines ended
// dump buffer to stdout
fmt.Printf(buffer)
fmt.Printf(buffer2)
fmt.Printf(buffer3)
return
}
}
}
}
func isprime(x int) bool {
for i := 2; i < x; i++ {
if x%i == 0 {
return false
}
}
return true
}
func findprimes(from int, to int, printer chan string, finished chan int){
str := ""
for i := from; i <= to; i++ {
if isprime(i) && isprime(i-6) {
str = str + fmt.Sprintf("%d %d\n", i-6, i)
}
}
printer <- str
//fmt.Printf("Finished %d to %d\n", from, to)
finished <- 1
}
The parallelized version used in average 2.743 seconds, the exact same time that the regular version used.
The parallelized version completed in 1.706 seconds. It used less than 1.5 Mb RAM.
One odd thing: My dual core kubuntu 64bit never peaked in both cores. It looked like Go was using just one core. Fixed with a call to runtime.GOMAXPROCS(4)
Update: I ran the paralellized version up to 1M numbers. One of My CPU cores was at 100% all the time, while the other wasn't used at all (odd). It took a whole minute more than the C and the regular Go versions. :(
With 1000000 (1M instead of 100K):
C: 3m35.458s
Go: 3m36.259s
Go using goroutines:
3m27.137s2m16.125s
The 100k version:
C: 2.723s
Go: 2.743s
Go using goroutines: 1.706s