alsk/lib/celero/Distribution.cpp

166 lines
5.3 KiB
C++

///
/// \author John Farrier
///
/// \copyright Copyright 2015, 2016, 2017, 2018. 2019 John Farrier
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
#include <celero/Distribution.h>
#include <celero/Print.h>
#include <celero/Utilities.h>
#include <algorithm>
#include <array>
#include <cmath>
#include <fstream>
#include <iostream>
#include <map>
using namespace celero;
std::vector<uint64_t> celero::BuildDistribution(uint64_t numberOfSamples, uint64_t iterationsPerSample)
{
std::vector<uint64_t> measurements;
while(numberOfSamples--)
{
// Dummy variable
auto dummy = uint64_t(0);
auto cps = iterationsPerSample;
// Get the starting time.
const auto startTime = celero::timer::GetSystemTime();
while(cps--)
{
celero::DoNotOptimizeAway(dummy++);
}
const auto endTime = celero::timer::GetSystemTime();
measurements.push_back(endTime - startTime);
}
return measurements;
}
void celero::RunDistribution(uint64_t intArgument)
{
std::vector<double> series1Normalized(intArgument);
std::vector<double> series2Normalized(intArgument);
std::vector<double> series3Normalized(intArgument);
std::vector<double> series4Normalized(intArgument);
const auto series1 = celero::BuildDistribution(intArgument, uint64_t(64));
const auto series2 = celero::BuildDistribution(intArgument, uint64_t(256));
const auto series3 = celero::BuildDistribution(intArgument, uint64_t(1024));
const auto series4 = celero::BuildDistribution(intArgument, uint64_t(4096));
if(series1.empty() == true || series2.empty() == true || series3.empty() == true || series4.empty() == true)
{
return;
}
std::array<std::map<double, uint64_t>, 4> histograms;
// Find the global max for all tests:
auto maxVal = std::max(*(std::max_element(std::begin(series1), std::end(series1))), *(std::max_element(std::begin(series2), std::end(series2))));
maxVal = std::max(maxVal, *(std::max_element(std::begin(series3), std::end(series3))));
maxVal = std::max(maxVal, *(std::max_element(std::begin(series4), std::end(series4))));
// Find the global min for all tests:
auto minVal = std::min(*(std::min_element(std::begin(series1), std::end(series1))), *(std::min_element(std::begin(series2), std::end(series2))));
minVal = std::min(minVal, *(std::min_element(std::begin(series3), std::end(series3))));
minVal = std::min(minVal, *(std::min_element(std::begin(series4), std::end(series4))));
// Normalize all vectors:
auto normalize = [minVal, maxVal](uint64_t val) -> double {
if(val >= minVal)
{
if(val <= maxVal)
{
const auto delta = maxVal - minVal;
val -= minVal;
return static_cast<double>(val) / static_cast<double>(delta);
}
return static_cast<double>(maxVal);
}
return static_cast<double>(minVal);
};
std::transform(std::begin(series1), std::end(series1), std::begin(series1Normalized),
[normalize](const uint64_t val) -> double { return normalize(val); });
std::transform(std::begin(series2), std::end(series2), std::begin(series2Normalized),
[normalize](const uint64_t val) -> double { return normalize(val); });
std::transform(std::begin(series3), std::end(series3), std::begin(series3Normalized),
[normalize](const uint64_t val) -> double { return normalize(val); });
std::transform(std::begin(series4), std::end(series4), std::begin(series4Normalized),
[normalize](const uint64_t val) -> double { return normalize(val); });
// Build histograms of each of the series:
std::for_each(std::begin(series1Normalized), std::end(series1Normalized),
[&histograms](const double val) { histograms[0][static_cast<int>(val * 1024)]++; });
std::for_each(std::begin(series2Normalized), std::end(series2Normalized),
[&histograms](const double val) { histograms[1][static_cast<int>(val * 1024)]++; });
std::for_each(std::begin(series3Normalized), std::end(series3Normalized),
[&histograms](const double val) { histograms[2][static_cast<int>(val * 1024)]++; });
std::for_each(std::begin(series4Normalized), std::end(series4Normalized),
[&histograms](const double val) { histograms[3][static_cast<int>(val * 1024)]++; });
// Find the maximum length of all histograms:
auto maxLen = size_t(0);
maxLen = std::max(maxLen, histograms[0].size());
maxLen = std::max(maxLen, histograms[1].size());
maxLen = std::max(maxLen, histograms[2].size());
maxLen = std::max(maxLen, histograms[3].size());
// Write out a CSV file that contains all four series:
std::ofstream os;
os.open("celeroDistribution.csv");
os << "64,,256,,1024,,4096,," << std::endl;
for(size_t i = 0; i < maxLen; ++i)
{
for(size_t j = 0; j < histograms.size(); j++)
{
if(i < histograms[j].size())
{
auto element = std::begin(histograms[j]);
for(size_t k = 0; k < i; k++)
{
++element;
}
os << element->first << "," << element->second << ",";
}
else
{
os << ",,";
}
}
os << std::endl;
}
os.close();
}