Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-13 09:31:42

0001 
0002 // Copyright 2020, Jefferson Science Associates, LLC.
0003 // Subject to the terms in the LICENSE file found in the top-level directory.
0004 
0005 
0006 #include "JBenchUtils.h"
0007 #include <chrono>
0008 #include <sys/types.h>
0009 
0010 
0011 void JBenchUtils::set_seed(size_t event_number, std::string caller_name)
0012 {
0013     std::hash<std::string> hasher;
0014     long seed = event_number ^ hasher(caller_name);
0015     m_generator = std::mt19937(seed);
0016 }
0017 
0018 
0019 size_t JBenchUtils::rand_size(size_t avg, double spread) {
0020     auto delta = static_cast<size_t>(avg*spread);
0021     std::uniform_int_distribution<size_t> distribution(avg-delta, avg+delta);
0022     return distribution(m_generator);
0023 }
0024 
0025 
0026 int JBenchUtils::randint(int min, int max) {
0027     std::uniform_int_distribution<int> distribution(min, max);
0028     return distribution(m_generator);
0029 }
0030 
0031 double JBenchUtils::randdouble(double min, double max) {
0032     std::uniform_real_distribution<double> dist(min, max);
0033     return dist(m_generator);
0034 }
0035 
0036 float JBenchUtils::randfloat(float min, float max) {
0037     std::uniform_real_distribution<float> dist(min, max);
0038     return dist(m_generator);
0039 }
0040 
0041 uint64_t JBenchUtils::consume_cpu_ms(uint64_t millisecs, double spread) {
0042 
0043     uint64_t sampled = rand_size(millisecs, spread);
0044     uint64_t result = 0;
0045 
0046     // Perform a variable amount of work in a fixed time
0047     auto duration = std::chrono::milliseconds(sampled);
0048     auto start_time = std::chrono::steady_clock::now();
0049     while ((std::chrono::steady_clock::now() - start_time) < duration) {
0050 
0051         double a = (m_generator)();
0052         double b = sqrt(a * pow(1.23, -a)) / a;
0053         result += long(b);
0054     }
0055     return result;
0056 }
0057 
0058 uint64_t JBenchUtils::read_memory(const std::vector<char>& buffer) {
0059 
0060     auto length = buffer.size();
0061     uint64_t sum = 0;
0062     for (unsigned i=0; i<length; ++i) {
0063         sum += buffer[i];
0064     }
0065     return sum;
0066 }
0067 
0068 uint64_t JBenchUtils::write_memory(std::vector<char>& buffer, uint64_t bytes, double spread) {
0069 
0070     uint64_t sampled = rand_size(bytes, spread);
0071     for (unsigned i=0; i<sampled; ++i) {
0072         buffer.push_back(2);
0073     }
0074     return sampled*2;
0075 }
0076 
0077 
0078 void JBenchUtils::consume_cpu_us(uint64_t microseconds) {
0079 
0080     using clock = std::chrono::steady_clock;
0081     auto deadline = clock::now() + std::chrono::microseconds(microseconds);
0082 
0083     volatile double acc = 1.0;            // volatile: optimizer can't elide
0084     while (clock::now() < deadline) {
0085         // FMA is fast but not trivially free; 8 ops per loop body
0086         // avoids tight branch-dominated loops that mispredict badly
0087         acc = std::fma(acc, 1.0000001, 0.0000001);
0088         acc = std::fma(acc, 1.0000001, 0.0000001);
0089         acc = std::fma(acc, 1.0000001, 0.0000001);
0090         acc = std::fma(acc, 1.0000001, 0.0000001);
0091         acc = std::fma(acc, 1.0000001, 0.0000001);
0092         acc = std::fma(acc, 1.0000001, 0.0000001);
0093         acc = std::fma(acc, 1.0000001, 0.0000001);
0094         acc = std::fma(acc, 1.0000001, 0.0000001);
0095     }
0096     // Prevent dead-store elimination at the call site too
0097     asm volatile("" : : "r,m"(acc) : "memory");
0098 }
0099 
0100