HPMC User Guide v 1.00
© 2022 Bassem W. Jamaleddine


2-5

   Finding Primes Offloading to MIC

This chapter shows how to use your HPMC calculator to find the prime numbers using openMP. The operations will be offloaded to the Intel Xeon Phi MIC.

Consider the program prime3a.c shown in the following listing:

    --  Program Code 2.5.1 :      [LISTING prime3a.c] - [Finding Primes using openMP]
(raw text)
1.     #include <stdio.h>
2.     #include <stdlib.h>
3.     #include <string.h>
4.     #include <math.h>
5.     #include <omp.h>
6.     
7.     // fill p[] with primes up to max plus one more
8.     int
9.     primearray(int max, int p[]) {
10.        p[0] = 3;
11.        int top = 0, n, i;
12.        for (n = 5;; n += 2)
13.            for (i = 0;; i++)
14.                if (n % p[i] == 0)
15.                    break;
16.                else
17.                    if (p[i]*p[i] > n) {
18.                        p[++top] = n;
19.        printf("prime: %d top: %d %d %ld  \n",
20.                 n, top, p[top], (long)p[top]*p[top]);
21.                        if (n > max)
22.                            return top; // last n
23.                        break;
24.                    }
25.    }
26.    // use primes in p[] to check up to max
27.    // 5 is p[1] is the 3rd prime, so start count from 2
28.    int
29.    primecount_omp(long max, int p[]) {
30.        int n, i, sum = 2;
31.        #pragma omp parallel for private(i) schedule(guided) 
      reduction(+:sum) 
32.        for (n = 5; n <= max; n += 2)
33.            for (i = 0;; i++)
34.                if (n % p[i] == 0)
35.                    break;
36.                else
37.                    if (p[i]*p[i] > n) {
38.                        sum++;
39.                        break;
40.                    }
41.        return sum;
42.    }
43.    // call primearray() with SQR and then primecount_omp() with MAX
44.    // PNT (x/logx) to find approx. size of array p[] psize
45.    int
46.    main(int argc, char** argv) {
47.        if (argc < 2) {
48.            printf("You need to supply a limit\n");
49.            return 1;
50.        }
51.        long MAX = strtoul(argv[1], 0, 10);
52.        int SQR = sqrt(MAX);
53.        int psize = 50 + 1.2 * SQR / log(SQR);
54.        int *p = malloc(psize * sizeof*p);
55.        int top = primearray(SQR, p);
56.        printf("psize: %d top: %d %d %ld\n", psize, top, p[top], 
      (long)p[top]*p[top]); 
57.        int sum = primecount_omp(MAX, p);
58.        printf("Count: %d (%.2f%%)\n", sum, (double) 100*sum / MAX) ;
59.        double lnx = MAX / log(MAX);
60.        printf("LnX:   %.2f (%f)\n",  lnx, sum / lnx);
61.        return 0;
62.    }

HPMC 2022


Compile prime3a.c to be executed on the MIC:

icc -O3 -mmic -qopenmp -L /opt/intel/lib/mic -Wno-unknown-pragmas -std=c99 -liomp5 prime3a.c -o prime3a.mic



Running the prime3a.phi by offloading it to the MIC. The upper limit selected is 100000000.

02:28 root@HPMC9: /mm03fs/PHI1/BSR # xphi prime3a.phi -a 100000000

02:28 root@HPMC9: /mm03fs/PHI1/BSR #  xphi prime3a.phi -a 100000000
prime: 5 top: 1 5 25  
prime: 7 top: 2 7 49  
prime: 11 top: 3 11 121  
prime: 13 top: 4 13 169  
prime: 17 top: 5 17 289  
prime: 19 top: 6 19 361  
prime: 23 top: 7 23 529  
prime: 29 top: 8 29 841  
prime: 31 top: 9 31 961  
prime: 37 top: 10 37 1369  
prime: 41 top: 11 41 1681  
prime: 43 top: 12 43 1849  
prime: 47 top: 13 47 2209  
...
prime: 9929 top: 1222 9929 98585041  
prime: 9931 top: 1223 9931 98624761  
prime: 9941 top: 1224 9941 98823481  
prime: 9949 top: 1225 9949 98982601  
prime: 9967 top: 1226 9967 99341089  
prime: 9973 top: 1227 9973 99460729  
prime: 10007 top: 1228 10007 100140049  
psize: 1352 top: 1228 10007 100140049
Count: 5761455 (5.76%)
LnX:   5428681.02 (1.061299)


On the MIC you can see the processes being executed as shown below.

(HPMC9) 02:28 root@mic0: ~ # pstree -up

(HPMC9) 02:28 root@mic0: ~ #  pstree -up 
init(1)-+-coi_daemon(4353,micuser)-+-prime3a.phi(5543)-+-{prime3a.phi}(5549)
        |                          |                   |-{prime3a.phi}(5550)
        |                          |                   |-{prime3a.phi}(5551)
        |                          |                   |-{prime3a.phi}(5552)
        |                          |                   |-{prime3a.phi}(5553)
        |                          |                   |-{prime3a.phi}(5554)
        |                          |                   |-{prime3a.phi}(5555)
        |                          |                   |-{prime3a.phi}(5556)
        |                          |                   |-{prime3a.phi}(5557)
        |                          |                   |-{prime3a.phi}(5558)
        |                          |                   |-{prime3a.phi}(5559)
...
        |                          |                   |-{prime3a.phi}(5769)
        |                          |                   |-{prime3a.phi}(5770)
        |                          |                   |-{prime3a.phi}(5771)
        |                          |                   `-{prime3a.phi}(5772)
        |                          |-{coi_daemon}(4355)
        |                          `-{coi_daemon}(5545)
        |-getty(4369)
        |-klogd(4332)
        |-mpssd(4338)-+-{mpssd}(4340)
        |             `-{mpssd}(4341)
        |-portmap(4290,1)
        |-sshd(4321)---sshd(5306)---bash(5308)---pstree(5773)
        |-syslogd(4329)
        `-udevd(4113)-+-udevd(4335)
                      `-udevd(4362)