Skip to content

Commit

Permalink
Merge branch 'drag-race' into sol2
Browse files Browse the repository at this point in the history
  • Loading branch information
davepl authored Nov 6, 2024
2 parents 76e7e42 + ad33b96 commit df14de3
Show file tree
Hide file tree
Showing 15 changed files with 1,075 additions and 1,032 deletions.
11 changes: 11 additions & 0 deletions BENCHMARK.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Some solutions are not included in the automated benchmark runs, either because
- [Running a benchmark of all solutions for a particular language](#running-a-benchmark-of-all-solutions-for-a-particular-language)
- [Running in unconfined mode](#running-in-unconfined-mode)
- [Output formats](#output-formats)
- [Setting the solution timeout](#setting-the-solution-timeout)

## What operating system to use?

Expand Down Expand Up @@ -375,3 +376,13 @@ The output format can be controlled via the `FORMATTER` variable like this:
make FORMATTER=json
make DIRECTORY=PrimeCrystal/solution_1 FORMATTER=csv
```

## Setting the solution timeout

The run of each solution is limited to a certain duration, which is 10 minutes by default.
You can change this setting through the `TIMEOUT` variable like this:

```shell
make TIMEOUT=15
make DIRECTORY=PrimeCPP/solution_2 TIMEOUT=15
```
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ SHELL := /bin/bash

DIRECTORY := $(shell pwd)
FORMATTER := "table"
TIMEOUT := "10"

.PHONY: all
all: benchmark
Expand All @@ -14,6 +15,7 @@ benchmark: check-env
ARGS=("-d $${REALPATH}" "-f $(FORMATTER)"); \
[ ! -z $${OUTPUT_FILE} ] && ARGS+=( "-o $${OUTPUT_FILE}" ); \
[ ! -z $${UNCONFINED} ] && ARGS+=( "--unconfined" ); \
[ ! -z $${TIMEOUT} ] && ARGS+=( "-t $${TIMEOUT}" ); \
cd ./tools; npm ci --silent && npm start --silent -- benchmark $${ARGS[@]}

.PHONY: check-env
Expand Down
98 changes: 50 additions & 48 deletions PrimeCPP/solution_2/PrimeCPP_PAR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,46 +24,41 @@ using namespace std::chrono;
const uint64_t DEFAULT_UPPER_LIMIT = 10'000'000LLU;

class BitArray {
uint32_t *array;
size_t arrSize;
uint8_t *array;
size_t logicalSize;

inline static size_t arraySize(size_t size)
static constexpr size_t arraySize(size_t size)
{
return (size >> 5) + ((size & 31) > 0);
return (size >> 3) + ((size & 7) > 0);
}

inline static size_t index(size_t n)
static constexpr size_t index(size_t n)
{
return (n >> 5);
}

inline static uint32_t getSubindex(size_t n, uint32_t d)
{
return d & uint32_t(uint32_t(0x01) << (n % 32));
}

inline void setFalseSubindex(size_t n, uint32_t &d)
{
d &= ~uint32_t(uint32_t(0x01) << (n % (8*sizeof(uint32_t))));
return (n >> 3);
}

public:
explicit BitArray(size_t size) : arrSize(size)
explicit BitArray(size_t size) : logicalSize(size)
{
array = new uint32_t[arraySize(size)];
std::memset(array, 0xFF, (size >> 3) + ((size & 7) > 0));
auto arrSize = (size + 1) / 2; // Only store bits for odd numbers
array = new uint8_t[arraySize(arrSize)];
std::memset(array, 0x00, arraySize(arrSize));
}

~BitArray() {delete [] array;}
~BitArray() { delete[] array; }

bool get(size_t n) const
constexpr bool get(size_t n) const
{
return getSubindex(n, array[index(n)]);
if (n % 2 == 0)
return false; // Even numbers > 2 are not prime
n = n / 2; // Map the actual number to the index in the array
return !(array[index(n)] & (uint8_t(1) << (n % 8)));
}

static constexpr uint32_t rol(uint32_t x, uint32_t n)
void set(size_t n)
{
return (x<<n) | (x>>(32-n));
n = n / 2; // Map the actual number to the index in the array
array[index(n)] |= (uint8_t(1) << (n % 8));
}

static constexpr uint32_t buildSkipMask(size_t skip, size_t offset)
Expand Down Expand Up @@ -116,25 +111,25 @@ class BitArray {

inline size_t size() const
{
return arrSize;
return logicalSize;
}
};


// prime_sieve
//
// Represents the data comprising the sieve (an array of N bits, where N is the upper limit prime being tested)
// as well as the code needed to eliminate non-primes from its array, which you perform by calling runSieve.
// Represents the data comprising the sieve (an array of bits representing odd numbers starting from 3)
// and includes the code needed to eliminate non-primes from its array by calling runSieve.

class prime_sieve
{
private:

BitArray Bits; // Sieve data, where 1==prime, 0==not
BitArray Bits; // Sieve data, where 0==prime, 1==not

public:

prime_sieve(uint64_t n) : Bits(n) // Initialize all to true (potential primes)
prime_sieve(uint64_t n) : Bits(n) // Initialize bits to zero default
{
}

Expand All @@ -154,15 +149,21 @@ class prime_sieve

while (factor <= q)
{
for (uint64_t num = factor; num < Bits.size(); num += 2)
// Find the next prime number
for (; factor <= q; factor += 2)
{
if (Bits.get(num))
if (Bits.get(factor))
{
factor = num;
break;
}
}
Bits.setFlagsFalse(factor * factor, factor + factor);

// Mark multiples of the prime number as not prime
uint64_t start = factor * factor;
for (uint64_t num = start; num <= Bits.size(); num += factor * 2)
{
Bits.set(num);
}

factor += 2;
}
Expand All @@ -174,9 +175,9 @@ class prime_sieve

size_t countPrimes() const
{
size_t count = (Bits.size() >= 2); // Count 2 as prime if within range
for (int i = 3; i < Bits.size(); i+=2)
if (Bits.get(i))
size_t count = (Bits.size() >= 2); // Count 2 as prime if within range
for (uint64_t num = 3; num <= Bits.size(); num += 2)
if (Bits.get(num))
count++;
return count;
}
Expand All @@ -187,23 +188,24 @@ class prime_sieve

bool isPrime(uint64_t n) const
{
if (n & 1)
return Bits.get(n);
else
if (n == 2)
return true;
if (n < 2 || n % 2 == 0)
return false;
return Bits.get(n);
}

// validateResults
//
// Checks to see if the number of primes found matches what we should expect. This data isn't used in the
// Checks to see if the number of primes found matches what we should expect. This data isn't used in the
// sieve processing at all, only to sanity check that the results are right when done.

bool validateResults() const
{
const std::map<const uint64_t, const int> resultsDictionary =
{
{ 10LLU, 4 }, // Historical data for validating our results - the number of primes
{ 100LLU, 25 }, // to be found under some limit, such as 168 primes under 1000
{ 10LLU, 4 }, // Historical data for validating our results - the number of primes
{ 100LLU, 25 }, // to be found under some limit, such as 168 primes under 1000
{ 1'000LLU, 168 },
{ 10'000LLU, 1229 },
{ 100'000LLU, 9592 },
Expand All @@ -227,8 +229,8 @@ class prime_sieve
if (showResults)
cout << "2, ";

size_t count = (Bits.size() >= 2); // Count 2 as prime if in range
for (uint64_t num = 3; num <= Bits.size(); num+=2)
size_t count = (Bits.size() >= 2); // Count 2 as prime if in range
for (uint64_t num = 3; num <= Bits.size(); num += 2)
{
if (Bits.get(num))
{
Expand All @@ -247,7 +249,7 @@ class prime_sieve
<< "Average: " << duration/passes << ", "
<< "Limit: " << Bits.size() << ", "
<< "Counts: " << count << "/" << countPrimes() << ", "
<< "Valid : " << (validateResults() ? "Pass" : "FAIL!")
<< "Valid: " << (validateResults() ? "Pass" : "FAIL!")
<< "\n";

// Following 2 lines added by rbergen to conform to drag race output format
Expand Down Expand Up @@ -354,7 +356,7 @@ int main(int argc, char **argv)
}

if (bOneshot)
cout << "Oneshot is on. A single pass will be used to simulate a 5 second run." << endl;
cout << "Oneshot is on. A single pass will be used to simulate a 5 second run." << endl;

if (bOneshot && (cSecondsRequested > 0 || cThreadsRequested > 1))
{
Expand Down Expand Up @@ -389,8 +391,8 @@ int main(int argc, char **argv)
else
{
auto tStart = steady_clock::now();
std::thread threads[cThreads];
uint64_t l_passes[cThreads];
std::vector<std::thread> threads(cThreads);
std::vector<uint64_t> l_passes(cThreads);
for (unsigned int i = 0; i < cThreads; i++)
threads[i] = std::thread([i, &l_passes, &tStart](size_t llUpperLimit)
{
Expand Down
6 changes: 3 additions & 3 deletions PrimeCrystal/solution_1/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
FROM crystallang/crystal:1.0.0-alpine AS build
FROM crystallang/crystal:1.14-alpine AS build

WORKDIR /opt/app
COPY primes.cr .
RUN crystal build primes.cr --release --static --no-debug

FROM alpine:3.13
FROM alpine:3

COPY --from=build /opt/app/primes /usr/local/bin/

ENTRYPOINT [ "primes" ]
ENTRYPOINT [ "primes" ]
2 changes: 1 addition & 1 deletion PrimeCrystal/solution_2/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM debian:11

ENV CRYSTAL_VER="1.1"
ENV CRYSTAL_VER="1.14"

WORKDIR /opt

Expand Down
Loading

0 comments on commit df14de3

Please sign in to comment.