HPMC User Guide v 1.00
© 2022 Bassem W. Jamaleddine
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:
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. }
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)