mpi.cc 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #include <stdio.h>
  2. #include <mpi.h>
  3. #include <NTL/ZZ.h>
  4. #include "controller.h"
  5. #include "worker.h"
  6. #include "dpnode.h"
  7. NTL_CLIENT
  8. static int mpi_size;
  9. static int controllerfds[2];
  10. static void boundcb(const char *boundaddr, unsigned short boundport)
  11. {
  12. // Write the port and addr to the pipe
  13. write(controllerfds[1], &boundport, 2);
  14. write(controllerfds[1], boundaddr, strlen(boundaddr));
  15. close(controllerfds[1]);
  16. }
  17. void desired_resources(const ZZ &order, unsigned short &desired_dpnodes,
  18. unsigned int &max_workers, unsigned int &dpfreq)
  19. {
  20. // How many DPnodes should we use for a problem of this size?
  21. desired_dpnodes = 2;
  22. // How many workers would we like to use?
  23. ZZ sorder = SqrRoot(order >> 46);
  24. if (NumBits(sorder) > 30) {
  25. // Just use all the workers we can find
  26. max_workers = 4294967295U; // 2^32 - 1
  27. } else {
  28. max_workers = trunc_long(sorder,31) + 1;
  29. }
  30. // By default, 1 in 1000 points are distinguihed points. The
  31. // number in the next line is 2^32/1000
  32. dpfreq = 4294967;
  33. if (order < 1000) {
  34. // Just make every point a DP
  35. dpfreq = 4294967295U;
  36. } else if (NumBits(order) < 27) {
  37. // The frequency of DPs should be 10/sqrt(order) to avoid
  38. // a DP-free cycle, so dpfreq = (10*2^32)/sqrt(order)
  39. ZZ f = (to_ZZ(10) << 32) / SqrRoot(order);
  40. dpfreq = trunc_long(f, 31);
  41. }
  42. }
  43. int main(int argc, char **argv)
  44. {
  45. // Init MPI
  46. MPI_Init(&argc, &argv);
  47. char hostname[257];
  48. gethostname(hostname, 256);
  49. int rank;
  50. int ret = 0;
  51. MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  52. MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
  53. if (rank == 0) {
  54. // Start the controller
  55. pipe(controllerfds);
  56. if (fork() == 0) {
  57. // Child; close the write half of the pipe
  58. close(controllerfds[1]);
  59. unsigned short boundport;
  60. char boundaddr[257];
  61. int res;
  62. res = read(controllerfds[0], &boundport, 2);
  63. if (res < 2) return 1;
  64. res = read(controllerfds[0], boundaddr, 256);
  65. if (res < 1) return 1;
  66. close(controllerfds[0]);
  67. boundaddr[res] = '\0';
  68. std::cerr << "Child bound to " << boundaddr << ":" << boundport << "\n";
  69. // The child will spawn two of its own children to be the
  70. // workers
  71. if (fork() == 0) {
  72. return worker_main(boundaddr, boundport);
  73. } else if (fork() == 0) {
  74. return worker_main(boundaddr, boundport);
  75. }
  76. // And now become the dpnode
  77. return dpnode_main(boundaddr, boundport);
  78. } else {
  79. // Parent; close the read half of the pipe
  80. close(controllerfds[0]);
  81. unsigned short bindport;
  82. Worklist worklist;
  83. if (controller_parse_args(argc, argv, bindport, worklist)) {
  84. std::cerr << "Usage: " << argv[0] << " [-p listenport] N1 iter1 N2 iter2 ...\n";
  85. return 1;
  86. }
  87. ret = controller_main(worklist, bindport, boundcb);
  88. }
  89. }
  90. MPI_Finalize();
  91. return ret;
  92. }