runtime-distr.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #include <thread>
  2. #include "utility.hpp"
  3. #include "stopwatch.hpp"
  4. #include "../dataset.hpp"
  5. #include "../vm_compiled.hpp"
  6. #include "../blake2/blake2.h"
  7. struct Outlier {
  8. Outlier(int idx, double rtime) : index(idx), runtime(rtime) {}
  9. int index;
  10. double runtime;
  11. };
  12. int main(int argc, char** argv) {
  13. constexpr int distributionSize = 100;
  14. int distribution[distributionSize + 1] = { 0 };
  15. Stopwatch sw;
  16. alignas(16) uint64_t hash[8];
  17. uint64_t checksum = 0;
  18. double totalRuntime = 0;
  19. double maxRuntime = 0;
  20. std::vector<Outlier> outliers;
  21. outliers.reserve(25);
  22. randomx_flags flags = RANDOMX_FLAG_DEFAULT;
  23. bool softAes, largePages, jit, verify;
  24. int totalCount, initThreadCount;
  25. double binSize, offset;
  26. int32_t seed;
  27. readOption("--verify", argc, argv, verify);
  28. readOption("--jit", argc, argv, jit);
  29. readOption("--softAes", argc, argv, softAes);
  30. readIntOption("--nonces", argc, argv, totalCount, 10000);
  31. readIntOption("--init", argc, argv, initThreadCount, 1);
  32. readFloatOption("--binSize", argc, argv, binSize, 1e-3);
  33. readFloatOption("--offset", argc, argv, offset, 0);
  34. readIntOption("--seed", argc, argv, seed, 0);
  35. readOption("--largePages", argc, argv, largePages);
  36. if (!verify) {
  37. flags = (randomx_flags)(flags | RANDOMX_FLAG_FULL_MEM);
  38. std::cout << "Measure program runtime" << std::endl;
  39. }
  40. else {
  41. std::cout << "Measure verification time" << std::endl;
  42. }
  43. std::cout << " - histogram offset: " << offset << std::endl;
  44. std::cout << " - histogram bin size: " << binSize << std::endl;
  45. if (jit) {
  46. flags = (randomx_flags)(flags | RANDOMX_FLAG_JIT);
  47. std::cout << " - JIT compiled mode" << std::endl;
  48. }
  49. else {
  50. std::cout << " - interpreted mode" << std::endl;
  51. }
  52. if (softAes) {
  53. std::cout << " - software AES mode" << std::endl;
  54. }
  55. else {
  56. flags = (randomx_flags)(flags | RANDOMX_FLAG_HARD_AES);
  57. std::cout << " - hardware AES mode" << std::endl;
  58. }
  59. if (largePages) {
  60. flags = (randomx_flags)(flags | RANDOMX_FLAG_LARGE_PAGES);
  61. std::cout << " - large pages mode" << std::endl;
  62. }
  63. else {
  64. std::cout << " - small pages mode" << std::endl;
  65. }
  66. std::cout << "Initializing..." << std::endl;
  67. randomx_cache *cache = randomx_alloc_cache(flags);
  68. randomx_dataset *dataset = nullptr;
  69. if (cache == nullptr) {
  70. std::cout << "Cache allocation failed" << std::endl;
  71. return 1;
  72. }
  73. randomx_init_cache(cache, &seed, sizeof seed);
  74. if (!verify) {
  75. blake2b(&hash, sizeof hash, &seed, sizeof seed, nullptr, 0);
  76. dataset = randomx_alloc_dataset(flags);
  77. if (dataset == nullptr) {
  78. std::cout << "Dataset allocation failed" << std::endl;
  79. return 1;
  80. }
  81. std::vector<std::thread> threads;
  82. uint32_t datasetItemCount = randomx_dataset_item_count();
  83. if (initThreadCount > 1) {
  84. auto perThread = datasetItemCount / initThreadCount;
  85. auto remainder = datasetItemCount % initThreadCount;
  86. uint32_t startItem = 0;
  87. for (int i = 0; i < initThreadCount; ++i) {
  88. auto count = perThread + (i == initThreadCount - 1 ? remainder : 0);
  89. threads.push_back(std::thread(&randomx_init_dataset, dataset, cache, startItem, count));
  90. startItem += count;
  91. }
  92. for (unsigned i = 0; i < threads.size(); ++i) {
  93. threads[i].join();
  94. }
  95. }
  96. else {
  97. randomx_init_dataset(dataset, cache, 0, datasetItemCount);
  98. }
  99. randomx_release_cache(cache);
  100. cache = nullptr;
  101. }
  102. std::cout << "Running " << totalCount << " programs..." << std::endl;
  103. randomx_vm* vm = randomx_create_vm(flags, cache, dataset);
  104. if (!verify) {
  105. vm->initScratchpad(&hash);
  106. vm->resetRoundingMode();
  107. }
  108. for (int i = 0; i < totalCount; ++i) {
  109. sw.restart();
  110. if (verify)
  111. randomx_calculate_hash(vm, &i, sizeof i, &hash);
  112. else
  113. vm->run(&hash);
  114. double elapsed = sw.getElapsed();
  115. //std::cout << "Elapsed: " << elapsed << std::endl;
  116. totalRuntime += elapsed;
  117. if (elapsed > maxRuntime)
  118. maxRuntime = elapsed;
  119. int bin = (elapsed - offset) / binSize;
  120. bool outlier = false;
  121. if (bin < 0) {
  122. bin = 0;
  123. outlier = true;
  124. }
  125. if (bin > distributionSize) {
  126. bin = distributionSize;
  127. outlier = true;
  128. }
  129. if (outlier && outliers.size() < outliers.capacity())
  130. outliers.push_back(Outlier(i, elapsed));
  131. distribution[bin]++;
  132. if(!verify)
  133. blake2b(hash, sizeof(hash), vm->getRegisterFile(), sizeof(randomx::RegisterFile), nullptr, 0);
  134. checksum ^= hash[0];
  135. }
  136. for (int i = 0; i < distributionSize + 1; ++i) {
  137. std::cout << i << " " << distribution[i] << std::endl;
  138. }
  139. std::cout << "Average runtime: " << totalRuntime / totalCount << std::endl;
  140. std::cout << "Maximum runtime: " << maxRuntime << std::endl;
  141. std::cout << "Checksum: " << checksum << std::endl;
  142. std::cout << "Outliers: " << std::endl;
  143. for (Outlier& ol : outliers) {
  144. std::cout << " " << ol.index << ": " << ol.runtime << std::endl;
  145. }
  146. return 0;
  147. }