From 71179ecf7957a2f390fa9b7bee476e5ebb01ce4e Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 23 May 2021 01:38:32 -0600 Subject: [PATCH 1/3] Added Nim solution 2 --- PrimeNim/solution_2/.gitignore | 1 + PrimeNim/solution_2/Dockerfile | 7 +++ PrimeNim/solution_2/README.md | 31 +++++++++++ PrimeNim/solution_2/primes.nim | 99 ++++++++++++++++++++++++++++++++++ 4 files changed, 138 insertions(+) create mode 100644 PrimeNim/solution_2/.gitignore create mode 100644 PrimeNim/solution_2/Dockerfile create mode 100644 PrimeNim/solution_2/README.md create mode 100644 PrimeNim/solution_2/primes.nim diff --git a/PrimeNim/solution_2/.gitignore b/PrimeNim/solution_2/.gitignore new file mode 100644 index 000000000..094987456 --- /dev/null +++ b/PrimeNim/solution_2/.gitignore @@ -0,0 +1 @@ +primes \ No newline at end of file diff --git a/PrimeNim/solution_2/Dockerfile b/PrimeNim/solution_2/Dockerfile new file mode 100644 index 000000000..44c56d072 --- /dev/null +++ b/PrimeNim/solution_2/Dockerfile @@ -0,0 +1,7 @@ +FROM nimlang/nim:alpine + +WORKDIR /opt/app +COPY primes.nim . +RUN nim c -d:danger primes.nim + +ENTRYPOINT [ "/opt/app/primes" ] diff --git a/PrimeNim/solution_2/README.md b/PrimeNim/solution_2/README.md new file mode 100644 index 000000000..a72e1fcc5 --- /dev/null +++ b/PrimeNim/solution_2/README.md @@ -0,0 +1,31 @@ +# Nim implementation #2 + +![Category](https://img.shields.io/badge/Category-faithful-green) + +## Run + +### Run locally + +Nim is available via package manager under the popular systems. The following command should get you started: + +``` +nim c -d:danger -r primes.nim +``` + +### Docker + +As per usual minimal just a minimal set of commands: + +``` +docker build -t primes . +docker run --rm primes +``` + +## Benchmarks +Gains around 10% performance from `solution_1` with just `-d:release`, doing `-d:danger` it becomes ~135% faster here. + +## Output +``` +beef331;5398;5.00043797492981;1 +``` + diff --git a/PrimeNim/solution_2/primes.nim b/PrimeNim/solution_2/primes.nim new file mode 100644 index 000000000..297eed3a1 --- /dev/null +++ b/PrimeNim/solution_2/primes.nim @@ -0,0 +1,99 @@ +import std/[times, math, strformat, tables, bitops] + +const DICT = { + 10'u64: 4, + 100'u64: 25, + 1000'u64: 168, + 10000'u64: 1229, + 100000'u64: 9592, + 1000000'u64: 78498, + 10000000'u64: 664579, + 100000000'u64: 5761455, + 1000000000'u64: 50847534, + 10000000000'u64: 455052511, +}.toTable() + +type + BitList = seq[uint8] + PrimeSieve = ref object of RootObj + sieveSize: uint64 + bits: BitList + +proc `{}`(a: BitList, i: SomeInteger): bool {.inline.} = + let + byteIndex = i div 8 + bitInd = i mod 8 + a[byteIndex].testBit(bitInd) + +proc `{}=`(a: var BitList, i: SomeInteger, val: bool) {.inline.}= + let + byteIndex = i div 8 + bitInd = i mod 8 + if val: + a[byteIndex].setBit(bitInd) + else: + a[byteIndex].clearBit(bitInd) + +method runSieve(this: PrimeSieve) {.base.} = + var factor = 3'u64 + let q = uint64(math.sqrt(float64(this.sieveSize))) + + while factor <= q: + for num in countup(factor, this.sieveSize, 2'u64): + if not this.bits{num}: + factor = num + break + + var num2 = factor * factor + while num2 < this.sieveSize: + this.bits{num2} = true + num2 += (factor * 2'u64) + + factor += 2'u64 + +method countPrimes(this: PrimeSieve): uint64 {.base.} = + var count = 1'u64 + + for num in countup(3'u64, this.sieveSize, 2'u64): + if not this.bits{num}: + count += 1'u64 + + return count + +method printResults(this: PrimeSieve, showResults: bool, duration: float64, passes: int) {.base.} = + if showResults: + stdout.write("2, ") + + var count = 1'u64 + for num in countup(3'u64, this.sieveSize, 2'u64): + if not this.bits{num}: + if showResults: + stdout.write(&"{num}") + count += 1'u64 + + if showResults: + echo "" + + let + countPrimes = this.countPrimes() + isValid = (countPrimes == uint64(DICT[this.sieveSize])) + + stderr.writeLine(&"Passes: {passes}, Time: {duration}, Avg: {(duration / float64(passes))}, Limit: {this.sieveSize}, Count1: {count}, Count2: {countPrimes}, Valid: {isValid}") + echo &"beef331;{passes};{duration};1" + +proc newPrimeSieve(sieveSize: uint64): PrimeSieve = + PrimeSieve(sieveSize: sieveSize, bits: newSeq[uint8](sieveSize div 8)) + +# --- Main block +var passes = 0 +let startTime = times.epochTime() + +while true: + var sieve = newPrimeSieve(1000000'u64) + sieve.runSieve() + + passes += 1 + var duration = times.epochTime() - startTime + if duration >= 5: + sieve.printResults(false, duration, passes) + break From 6d2ae98090bda784e7819cde69470180dc9c5a77 Mon Sep 17 00:00:00 2001 From: Jason Beetham Date: Sun, 23 May 2021 14:05:51 -0600 Subject: [PATCH 2/3] Update README.md --- PrimeNim/solution_2/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PrimeNim/solution_2/README.md b/PrimeNim/solution_2/README.md index a72e1fcc5..bb9288d0a 100644 --- a/PrimeNim/solution_2/README.md +++ b/PrimeNim/solution_2/README.md @@ -22,7 +22,7 @@ docker run --rm primes ``` ## Benchmarks -Gains around 10% performance from `solution_1` with just `-d:release`, doing `-d:danger` it becomes ~135% faster here. +Gains around 10% performance from `solution_1` with just `-d:release`, doing `-d:danger` it becomes ~35% faster here. ## Output ``` From 9728b4878340939fbeecca05dcba1ff1c690c8f4 Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 23 May 2021 14:53:47 -0600 Subject: [PATCH 3/3] Added more flags for more speed --- PrimeNim/solution_2/Dockerfile | 2 +- PrimeNim/solution_2/README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/PrimeNim/solution_2/Dockerfile b/PrimeNim/solution_2/Dockerfile index 44c56d072..e9bfe737c 100644 --- a/PrimeNim/solution_2/Dockerfile +++ b/PrimeNim/solution_2/Dockerfile @@ -2,6 +2,6 @@ FROM nimlang/nim:alpine WORKDIR /opt/app COPY primes.nim . -RUN nim c -d:danger primes.nim +RUN nim c -d:danger --passC:"-march=native" -d:lto primes.nim ENTRYPOINT [ "/opt/app/primes" ] diff --git a/PrimeNim/solution_2/README.md b/PrimeNim/solution_2/README.md index bb9288d0a..d3933829c 100644 --- a/PrimeNim/solution_2/README.md +++ b/PrimeNim/solution_2/README.md @@ -9,7 +9,7 @@ Nim is available via package manager under the popular systems. The following command should get you started: ``` -nim c -d:danger -r primes.nim +nim c -d:danger --passC:"-march=native" -d:lto -r primes.nim ``` ### Docker @@ -22,7 +22,7 @@ docker run --rm primes ``` ## Benchmarks -Gains around 10% performance from `solution_1` with just `-d:release`, doing `-d:danger` it becomes ~35% faster here. +Gains around 10% performance from `solution_1` with just `-d:release`. With added flags around 50% faster. ## Output ```