desired_resources.cc 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #include <iostream>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include "desired_resources.h"
  6. NTL_CLIENT
  7. // Input: order, total_nodes, GB_mem_per_node
  8. // Output: desired_dpnodes, max_workers, dpfreq
  9. void desired_resources(const ZZ &order, unsigned short total_nodes,
  10. unsigned short GB_mem_per_node, unsigned short &desired_dpnodes,
  11. unsigned int &max_workers, unsigned int &dpfreq)
  12. {
  13. // One point in how many is a DP by default?
  14. unsigned int dpscale = 1000;
  15. ZZ sorder = SqrRoot(order);
  16. // How many DPnodes should we use for a problem of this size?
  17. // 338 is bytes per DP in the table. 10 is a safety factor.
  18. ZZ dpnumerator = sorder * 338 * 10;
  19. ZZ dpdenominator;
  20. dpdenominator = GB_mem_per_node;
  21. dpdenominator *= 1000000000UL; // Convert the above line to GB
  22. ZZ dpnodes = (dpnumerator / (dpdenominator * dpscale)) + 1;
  23. if (dpnodes > total_nodes) {
  24. desired_dpnodes = total_nodes;
  25. ZZ zzdpscale = dpnumerator / (dpdenominator * total_nodes);
  26. if (NumBits(zzdpscale) > 31) {
  27. dpscale = 4294967295U;
  28. } else {
  29. dpscale = trunc_long(zzdpscale, 31);
  30. }
  31. } else {
  32. desired_dpnodes = trunc_long(dpnodes, 31);
  33. }
  34. // How many workers would we like to use?
  35. ZZ sorder23 = sorder >> 23;
  36. if (NumBits(sorder23) > 30) {
  37. // Just use all the workers we can find
  38. max_workers = 4294967295U; // 2^32 - 1
  39. } else {
  40. max_workers = trunc_long(sorder23,31) + 1;
  41. }
  42. // By default, 1 in dpscale points are distinguished points.
  43. dpfreq = 4294967295U / dpscale;
  44. // Orders smaller than 100*scale^2 behave specially, in order to
  45. // avoid DP-free cycles
  46. ZZ orderlimit;
  47. orderlimit = 100;
  48. orderlimit *= dpscale;
  49. orderlimit *= dpscale;
  50. if (order < 1000) {
  51. // Just make every point a DP
  52. dpfreq = 4294967295U;
  53. } else if (order < orderlimit) {
  54. // The frequency of DPs should be 10/sqrt(order) to avoid
  55. // a DP-free cycle, so dpfreq = (10*2^32)/sqrt(order)
  56. ZZ f = (to_ZZ(10) << 32) / SqrRoot(order);
  57. dpfreq = trunc_long(f, 31);
  58. }
  59. }
  60. #ifdef TEST_DESIRED_RESOURCES
  61. int main(int argc, char **argv)
  62. {
  63. if (argc != 3) {
  64. std::cerr << "Usage: " << argv[0] << " num_nodes GB_mem_per_node\n";
  65. return 1;
  66. }
  67. unsigned short total_nodes = strtoul(argv[1], NULL, 10);
  68. unsigned short GB_mem_per_node = strtoul(argv[2], NULL, 10);
  69. cout << "# log_2(order) dpnodes workers dpfreq\n";
  70. for (int i=44; i<=92; ++i) {
  71. unsigned short desired_dpnodes;
  72. unsigned int max_workers;
  73. unsigned int dpfreq;
  74. ZZ order;
  75. order = 1;
  76. order <<= i;
  77. order += 1;
  78. desired_resources(order, total_nodes, GB_mem_per_node, desired_dpnodes, max_workers, dpfreq);
  79. cout << i << " " << desired_dpnodes << " " << max_workers << " "
  80. << dpfreq << "\n";
  81. }
  82. }
  83. #endif