Skip to main content

cs2381 Notes: 31 Primes

··2 mins

For tomorrow’s lab, we’re going to count the primes up to some limit.

App code:

public class App {
    public static void main(String[] args) {
        int procs = Runtime.getRuntime().availableProcessors();
        System.out.println("We have " + procs + " hardware threads.");

        long t0 = System.nanoTime();
        long count = Primes.countPrimes(10000);
        long t1 = System.nanoTime();
        long ms = ((t1 - t0) / 1000000);

        System.out.printf("found %d primes in %d ms\n", count, ms);
    }
}

Base Primes code:

import java.util.ArrayList;
import java.util.List;

public class Primes {
    static long countPrimes(long nn) {
        var xs = findPrimes(nn);
        return xs.size();
    }

    static List<Long> findPrimes(long nn) {
        var ys = new ArrayList<Long>();
        for (long ii = 2; ii < nn; ++ii) {
            if (isPrime(ii)) {
                ys.add(ii);
            }
        }
        return ys;
    }

    static boolean isPrime(long xx) {
        for (long ii = 2; ii < xx; ++ii) {
            if (xx % ii == 0) {
                return false;
            }
        }
        return true;
    }
}

Optimizations:

  • Threads
  • Limit isPrime search to sqrt(xx)
  • Limit isPrime search to 2 and then odd numbers
  • Build an ArrayList of primes
  • Do the Sieve of Eratosthenes with a BitSet

Can we count all primes up to a billion in less than 10 seconds?

What would it take to go to 10 billion?

Sample Optimizations #

Threads:

        var workers = new WorkerC[P];
        
        for (int ii = 0; ii < P; ++ii) {
            long i0 = Math.max(2, ii*npp);
            long i1 = ii == (P - 1) ? nn : (ii+1) * npp;
            workers[ii] = new WorkerC(i0, i1);
            workers[ii].start();
        }

        long count = 1; // 2
        for (int ii = 0; ii < P; ++ii) {
            try {
                workers[ii].join();
                count += workers[ii].count;
            }
            catch (InterruptedException ee) {
                throw new Error("interrupted");
            }
        }

class WorkerC extends Thread {
    long i0;
    long i1;
    long count;

    WorkerC(long i0, long i1) {
        this.i0 = i0;
        this.i1 = i1;
        this.count = 0;
    }

    @Override
    public void run() {
        this.count = PrimesC.countPrimesRange(i0, i1);
    }
}

ArrayList:

import java.util.ArrayList;
import java.util.List;

public class PrimesAL {
    static ArrayList<Long> primes;
    
    static long countPrimes(long nn) {
        primes = new ArrayList<Long>();
        primes.add(2L);
        primes.add(3L);
        primes.add(5L);

        for (long ii = 7; ii < nn; ii += 2) {
            if (isPrime(ii)) {
                primes.add(ii);
            }
        }
        
        return primes.size();
    }

    static boolean isPrime(long xx) {
        long top = 1 + (long) Math.ceil(Math.sqrt(xx));
        for (long yy : primes) {
            if (yy > top) {
                break;
            }
            if (xx % yy == 0) {
                return false;
            }
        }
        return true;
    }
}