[fpc-pascal] How does FPC perform in the FASTEST Computer Language Race
Ryan Joseph
genericptr at gmail.com
Sat Jul 10 18:46:21 CEST 2021
> On Jul 10, 2021, at 4:16 AM, Guillermo via fpc-pascal <fpc-pascal at lists.freepascal.org> wrote:
>
> Hi,
>
> I remember years ago a similar test in a web page. Pascal was way low
> in the list, even below Java and Python! but we (in a forum) found that
> it wasn't Pascal fault: most versons program were optimised in code
> while Pascal used brute force (also compiling using -O3 made it way
> faster than the web proclaimed so we suspect they used -O- or even
> worse a relic compiler [Turbo Pascal 1?]). Once fixed it was almost
> unoticeably behind C in both FPC and Delphi (Delphi result was a bit
> faster).
Here's the C++ version that won. Looks like the magic comes from constexpr, which I don't understand very well in C++ except that it's a constant expression. Can anyone explain how constexpr works here?
// ---------------------------------------------------------------------------
// PrimeCPP_CONSTEXPR.cpp : Taking advantage of compiler optimizing constants
// ---------------------------------------------------------------------------
#include <chrono>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <thread>
#include <vector>
#include "Sieve.h"
using namespace std;
using namespace std::chrono;
struct RESULTS
{
unsigned long long upTo;
int count;
};
constexpr RESULTS resultsDictionary[] = {
{10LL, 4}, // Historical data for validating our results - the number of primes
{100LL, 25}, // to be found under some limit, such as 168 primes under 1000
{1000LL, 168},
{10000LL, 1229},
{100000LL, 9592},
{1000000LL, 78498},
{10000000LL, 664579},
};
constexpr int find(const unsigned long long val)
{
for (const auto d : resultsDictionary)
{
if (d.upTo == val)
return d.count;
}
return -1;
}
constexpr int countPrimes(const Sieve &sieve)
{
return sieve.count();
}
constexpr bool validateResults(const Sieve &sieve)
{
const auto sieveSize = sieve.size();
const auto result = find(sieveSize);
if (-1 == result)
return false;
return result == countPrimes(sieve);
}
void printResults(const Sieve &sieve, bool showResults, double duration, int passes, int threads)
{
const auto sieveSize = sieve.size();
if (showResults)
printf("2, ");
int count = (sieveSize >= 2); // Starting count (2 is prime)
for (int num = 3; num <= sieveSize; num += 2)
{
if (sieve.contains(num))
{
if (showResults)
printf("%d, ", num);
count++;
}
}
if (showResults)
printf("\n");
printf("Passes: %d, Time: %lf, Avg: %lf, Limit: %llu, Count1: %d, Count2: %d, Valid: %d\n",
passes,
duration,
duration / passes,
sieveSize,
count,
countPrimes(sieve),
validateResults(sieve));
printf("\n");
printf("flo80_constexpr;%d;%f;%d;algorithm=base,faithful=no,bits=1\n", passes, duration, threads);
}
void run(uint64_t upperLimit, const Sieve &checkSieve, int numberOfThreads = 1, int runtimeSeconds = 5)
{
unsigned int passes = 0;
printf("Computing primes to %llu on %d thread%s for %d second%s.\n", upperLimit,
numberOfThreads,
numberOfThreads == 1 ? "" : "s",
runtimeSeconds,
runtimeSeconds == 1 ? "" : "s");
const auto tStart = steady_clock::now();
while (duration_cast<seconds>(steady_clock::now() - tStart).count() < runtimeSeconds)
{
vector<thread> threadPool;
for (unsigned int i = 0; i < numberOfThreads; i++)
{
threadPool.push_back(thread([upperLimit]
{
auto sieve = Sieve(upperLimit);
sieve.runSieve();
}));
}
for (auto &th : threadPool)
th.join();
passes += numberOfThreads;
}
const auto tEnd = steady_clock::now();
printResults(checkSieve, false, duration_cast<microseconds>(tEnd - tStart).count() / 1000000.0, passes, numberOfThreads);
}
int main(int argc, char **argv)
{
uint64_t upperLimit = 1'000'000L;
constexpr int runtimeSeconds = 5;
if (argc > 1)
{
upperLimit = std::max((uint64_t)atoll(argv[argc - 1]), (uint64_t)1);
assert(upperLimit < Sieve::maxSize);
}
auto checkSieve = Sieve(upperLimit);
checkSieve.runSieve();
const auto result = validateResults(checkSieve) ? checkSieve.count() : 0;
const auto numberOfThreads = thread::hardware_concurrency();
thread::hardware_concurrency();
run(upperLimit, checkSieve, numberOfThreads, runtimeSeconds);
run(upperLimit, checkSieve, 1, runtimeSeconds);
return result;
}
Regards,
Ryan Joseph
More information about the fpc-pascal
mailing list