1

I've programmed simple implementation of sieve of Eratosthenes for calculating primes in given range. Initially I planned to use long int as main integer type. Calculating all primes lesser then 10 milion took something between 11-12 seconds. But when I switched type to int, I was getting about 4-5 seconds instead. Therefore I wonder - why is it?

I understand that long int takes more space than int, but I'm running 64-bit CPU - so - if I understand correctly - it has ALU that accepts 64-bit integers i.e. instructions on such numbers can be executed in same number of cycles. My prior research revealed similar questions beeing asked about performance difference between unsigned and signed types ([here][1] or [here][2]), but I'm using signed variables and I still get performence drop for the same (lesser then 2^33-1) input. Below I post my full code.

#include <iostream>
#include <fstream>

int main()
{
    unsigned long int X, i, j;
    bool *prime, *primeFill;
    std::fstream outFile;
    clock_t T;

    /* user interaction */
    std::cout << "This applet will export all prime number from range (0, X). Enter desired X value: "; 
    std::cin >> X;

    primeFill=new bool [X]; 
    for (i=2; i<X; i++) 
        primeFill[i]=false;

    prime = new bool [X]; 

    /* main loop, where all actual computation happens */
    T=clock(); i=2;
    while(i<X) {
        prime[i]=true, primeFill[i]=true;
        for (j=2*i; j<=X; j+=i) prime[j]=false, primeFill[j]=true;
        while (primeFill[i]) 
            i++;
    }

    T=clock()-T;   

    /* outputing results to textfile & standard output */
    outFile.open("primes.txt", std::ios::out);

    for (i=2; i<X; i++)
        if (prime[i]) 
            outFile << i << '\n';

    outFile.close();
    std::cout << "Finished. Computation took " << (1000*float(T)) / CLOCKS_PER_SEC << " ms\n";
    return 0;
}

EDIT New code above doesn't produce such problem. Refer to my answer below.

Matt C
  • 4,470
  • 5
  • 26
  • 44
  • What compiler are you using? Are you sure that you are compiling for a 64bit architecture? – Cyb3rFly3r Apr 23 '16 at 20:53
  • What is the size of the `long int`? – Thomas Matthews Apr 23 '16 at 20:55
  • Look at the disassembly, is the compiler generating 32-bit or 64-bit instructions? – Thomas Matthews Apr 23 '16 at 21:01
  • Measure the time for the `ceil` and `sqrt` functions for both 64 bit and 32-bit. Is the compiler using the 32-bit versions in 64-bit mode? – Thomas Matthews Apr 23 '16 at 21:02
  • 2
    ... **why are you using `isPrime` for Sieve of Eratosthenes?** You missed the point. Also, you're on Unix-like system if `long` and `int` makes a difference, is that right? The algorithm, even if properly implemented requires a lot of memory and is not cache friendly. – LogicStuff Apr 23 '16 at 21:02
  • @Cyb3rFly3r @Thomas Matthews I'm running [Intel i5-4570](http://ark.intel.com/pl/products/75043/Intel-Core-i5-4570-Processor-6M-Cache-up-to-3_60-GHz). Both `uname -a` and `file main` are showing `x86-64`. I use GCC 5.3.0. [Here](http://pastebin.com/raw/1ke7ZnyP) I posted detailed output of these commands. @LogicStuff Yes, I'm running Linux 4.6. – Mateusz Duchalski Apr 23 '16 at 21:03
  • You can speed up your algorithm by having the `for` loop start at 3 and increment by 2. – Thomas Matthews Apr 23 '16 at 21:03
  • Your formatting is amusingly bad. – Lightness Races in Orbit Apr 23 '16 at 21:21
  • `new bool[X]` wastes a colossal amount of space – M.M Apr 24 '16 at 02:03

1 Answers1

0

As @LogicStuff correctly pointed out, I missed the point of Sieve of Eratosthenes by using isPrime() function. I've edited the code (edited original question) and now the same test (calculating primes lesser than 10 milion) takes between 250 and 300 miliseconds despite integer type - I've tested int, long int, unsigned int and unsigned long int.

This means that source of the problem was inside isPrime() function i.e. compilier or CPU lack either optimalization for double conversion or % operator. I'm betting on the first one, because such problem was described here for unsigned int as I mentioned in initial post. Thanks for all comments.