desired_resources.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #include <iostream>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include "desired_resources.h"
  6. NTL_CLIENT
  7. // For a given dpfreq, a worker will always transmit a specific
  8. // number of dps per second (this needs to be determined
  9. // experimentally). A dpnode can only accept a specific number
  10. // of dps per second.
  11. // freq_reduction_threshold should be equal to the max number of
  12. // workers that a dpnode can handle when the dpfreq == 4294967
  13. // Input: order, total_workers, total_dpnodes,
  14. // GB_mem_per_node, freq_reduction_threshold
  15. // Output: desired_dpnodes, max_workers, dpfreq
  16. void desired_resources(const ZZ &order, unsigned short total_workers,
  17. unsigned short total_dpnodes, unsigned short GB_mem_per_node,
  18. unsigned short freq_reduction_threshold, unsigned short &desired_dpnodes,
  19. unsigned int &max_workers, unsigned int &dpfreq)
  20. {
  21. // One point in how many is a DP by default?
  22. unsigned int dpscale = 1000;
  23. ZZ sorder = SqrRoot(order);
  24. // How many DPnodes should we use for a problem of this size?
  25. // 338 is bytes per DP in the table. 10 is a safety factor.
  26. ZZ dpnumerator = sorder * 338 * 10;
  27. ZZ dpdenominator;
  28. dpdenominator = GB_mem_per_node;
  29. dpdenominator *= 1000000000UL; // Convert the above line to B
  30. ZZ dpnodes = (dpnumerator / (dpdenominator * dpscale)) + 1;
  31. if (dpnodes > total_dpnodes) {
  32. desired_dpnodes = total_dpnodes;
  33. ZZ zzdpscale = dpnumerator / (dpdenominator * total_dpnodes);
  34. if (NumBits(zzdpscale) > 31) {
  35. dpscale = 4294967295U;
  36. } else {
  37. dpscale = trunc_long(zzdpscale, 31);
  38. }
  39. } else {
  40. desired_dpnodes = total_dpnodes;
  41. }
  42. // How many workers would we like to use?
  43. ZZ sorder23 = sorder >> 23;
  44. if (NumBits(sorder23) > 30) {
  45. // Just use all the workers we can find
  46. max_workers = 4294967295U; // 2^32 - 1
  47. } else {
  48. max_workers = trunc_long(sorder23,31) + 1;
  49. }
  50. if (max_workers > total_workers) {
  51. max_workers = total_workers;
  52. }
  53. // By default, 1 in dpscale points are distinguished points.
  54. dpfreq = 4294967295U / dpscale;
  55. if ((float)max_workers/desired_dpnodes > freq_reduction_threshold) {
  56. // if the ratio of workers to dpnodes is too high
  57. unsigned int max_dpfreq = (4294967295U/1000) / (((float)max_workers/desired_dpnodes)/freq_reduction_threshold);
  58. // max dpfreq for the given ratio of workers to dpnodes
  59. if (dpfreq > max_dpfreq) {
  60. dpfreq = max_dpfreq;
  61. }
  62. }
  63. #ifdef DPFREQ_DIVISOR
  64. // not a nice solution, but gives you the extra control if you need it
  65. dpfreq /= DPFREQ_DIVISOR;
  66. #endif
  67. // Orders smaller than 100*scale^2 behave specially, in order to
  68. // avoid DP-free cycles
  69. ZZ orderlimit;
  70. orderlimit = 100;
  71. orderlimit *= dpscale;
  72. orderlimit *= dpscale;
  73. if (order < 1000) {
  74. // Just make every point a DP
  75. dpfreq = 4294967295U;
  76. } else if (order < orderlimit) {
  77. // The frequency of DPs should be 10/sqrt(order) to avoid
  78. // a DP-free cycle, so dpfreq = (10*2^32)/sqrt(order)
  79. ZZ f = (to_ZZ(10) << 32) / SqrRoot(order);
  80. dpfreq = trunc_long(f, 31);
  81. }
  82. }
  83. #ifdef TEST_DESIRED_RESOURCES
  84. int main(int argc, char **argv)
  85. {
  86. if (argc != 5) {
  87. std::cerr << "Usage: " << argv[0] << " num_workers num_dpnodes GB_mem_per_node freq_reduction_threshold\n";
  88. return 1;
  89. }
  90. unsigned short total_workers = strtoul(argv[1], NULL, 10);
  91. unsigned short total_dpnodes = strtoul(argv[2], NULL, 10);
  92. unsigned short GB_mem_per_node = strtoul(argv[3], NULL, 10);
  93. unsigned short freq_reduction_threshold = strtoul(argv[4], NULL, 10);
  94. cout << "# log_2(order) dpnodes workers dpfreq\n";
  95. for (int i=44; i<=92; ++i) {
  96. unsigned short desired_dpnodes;
  97. unsigned int max_workers;
  98. unsigned int dpfreq;
  99. ZZ order;
  100. order = 1;
  101. order <<= i;
  102. order += 1;
  103. desired_resources(order, total_workers, total_dpnodes, GB_mem_per_node, freq_reduction_threshold, desired_dpnodes, max_workers, dpfreq);
  104. cout << i << " " << desired_dpnodes << " " << max_workers << " "
  105. << dpfreq << "\n";
  106. }
  107. }
  108. #endif