Skip to content

Commit

Permalink
Add stats for distributed app evaluations
Browse files Browse the repository at this point in the history
  • Loading branch information
nicelhc13 committed Apr 14, 2024
1 parent b9a1906 commit f448fdc
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 6 deletions.
162 changes: 162 additions & 0 deletions libgalois/include/galois/stats.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
// SPDX-License-Identifier: BSD-2-Clause
// Copyright (c) 2023. University of Texas at Austin. All rights reserved.

#pragma once

#include <sys/resource.h>
#include <linux/perf_event.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <asm/unistd.h>
#include <cstdint>
#include <chrono>
#include <iostream>
#include <string>
#include <fstream>

class HighResTimer {
private:
std::chrono::high_resolution_clock::time_point start_time;
std::chrono::high_resolution_clock::time_point end_time;

public:
HighResTimer() = default;

void start() { start_time = std::chrono::high_resolution_clock::now(); }

void stop() { end_time = std::chrono::high_resolution_clock::now(); }

uint64_t getDurationNano() const {
return std::chrono::duration_cast<std::chrono::nanoseconds>(end_time -
start_time)
.count();
}
};

class PerfEvent {
private:
int fd;
struct perf_event_attr pe;

uint64_t perf_event_open(struct perf_event_attr* hw_event, pid_t pid, int cpu,
int group_fd, uint64_t flags) {
return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags);
}

public:
PerfEvent(uint64_t type, uint64_t config) {
memset(&pe, 0, sizeof(struct perf_event_attr));
pe.type = type;
pe.size = sizeof(struct perf_event_attr);
pe.config = config;
pe.disabled = 1;
pe.exclude_kernel = 1; // Exclude kernel events
pe.exclude_hv = 1; // Exclude hypervisor events

fd = perf_event_open(&pe, 0, -1, -1, 0);
if (fd == -1) {
std::cerr << "Error opening leader " << std::endl;
}
}

void start() {
if (ioctl(fd, PERF_EVENT_IOC_RESET, 0) == -1) {
std::cerr << "Error in PERF_EVENT_IOC_RESET" << std::endl;
}
if (ioctl(fd, PERF_EVENT_IOC_ENABLE, 0) == -1) {
std::cerr << "Error in PERF_EVENT_IOC_ENABLE" << std::endl;
}
}

void stop() {
if (ioctl(fd, PERF_EVENT_IOC_DISABLE, 0) == -1) {
std::cerr << "Error in PERF_EVENT_IOC_DISABLE" << std::endl;
}
}

uint64_t readValue() {
uint64_t count;
if (read(fd, &count, sizeof(uint64_t)) == -1) {
std::cerr << "Error reading count" << std::endl;
}
return count;
}

~PerfEvent() { close(fd); }
};

class ScopeBenchmarker {
private:
std::string scopeName;
std::string outputName;
HighResTimer timer;
PerfEvent cacheMissesEvent;
PerfEvent cacheReferencesEvent;
PerfEvent instructionsEvent;
PerfEvent minorPageFaultsEvent;
PerfEvent majorPageFaultsEvent;

static uint64_t getMaxRSS() {
struct rusage usage;
getrusage(RUSAGE_SELF, &usage);
#if defined(__linux__)
return usage.ru_maxrss;
#else
return usage.ru_maxrss * (sysconf(_SC_PAGESIZE) / 1024);
#endif
}

public:
explicit ScopeBenchmarker(const std::string& _scopeName, const std::string& _outputName)
: scopeName(_scopeName),
outputName(_outputName),
cacheMissesEvent(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES),
cacheReferencesEvent(PERF_TYPE_HARDWARE,
PERF_COUNT_HW_CACHE_REFERENCES),
instructionsEvent(PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS),
minorPageFaultsEvent(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN),
majorPageFaultsEvent(PERF_TYPE_SOFTWARE,
PERF_COUNT_SW_PAGE_FAULTS_MAJ) {
timer.start();
cacheMissesEvent.start();
cacheReferencesEvent.start();
instructionsEvent.start();
minorPageFaultsEvent.start();
majorPageFaultsEvent.start();
}

~ScopeBenchmarker() {
timer.stop();
cacheMissesEvent.stop();
cacheReferencesEvent.stop();
instructionsEvent.stop();
minorPageFaultsEvent.stop();
majorPageFaultsEvent.stop();

uint64_t cacheMisses = cacheMissesEvent.readValue();
uint64_t cacheReferences = cacheReferencesEvent.readValue();
uint64_t instructions = instructionsEvent.readValue();
uint64_t max_rss = getMaxRSS();
uint64_t minorPageFaults = minorPageFaultsEvent.readValue();
uint64_t majorPageFaults = majorPageFaultsEvent.readValue();


std::string output = "Benchmark results for " + scopeName + ":\n" +
"Duration: " + std::to_string(timer.getDurationNano()) +
" nanoseconds\n" +
"Max RSS: " + std::to_string(max_rss) + " KB\n" +
"Cache Misses: " + std::to_string(cacheMisses) + "\n" +
"Cache References: " + std::to_string(cacheReferences) + "\n" +
"Instructions: " + std::to_string(instructions) + "\n" +
"Minor Page Faults: " + std::to_string(minorPageFaults) + "\n" +
"Major Page Faults: " + std::to_string(majorPageFaults) + "\n";

std::cout << output;

std::ofstream fp(outputName, std::ios::out);
fp << output;
fp.close();
}
};

#define BENCHMARK_SCOPE(name, fname) ScopeBenchmarker benchmarker##__LINE__(name, fname)
19 changes: 13 additions & 6 deletions lonestar/analytics/distributed/bfs/bfs_pull.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "galois/DTerminationDetector.h"
#include "galois/gstl.h"
#include "galois/runtime/Tracer.h"
#include "galois/stats.h"

#include <iostream>
#include <limits>
Expand Down Expand Up @@ -344,13 +345,19 @@ int main(int argc, char** argv) {
std::string timer_str("Timer_" + std::to_string(run));
galois::StatTimer StatTimer_main(timer_str.c_str(), REGION_NAME);

StatTimer_main.start();
if (execution == Async) {
BFS<true>::go(*hg);
} else {
BFS<false>::go(*hg);

{
std::string output_fname =
"bfs-pull-" + std::to_string(net.ID) + "_" + std::to_string(run) + ".out";
BENCHMARK_SCOPE("bfs-pull", output_fname);
StatTimer_main.start();
if (execution == Async) {
BFS<true>::go(*hg);
} else {
BFS<false>::go(*hg);
}
StatTimer_main.stop();
}
StatTimer_main.stop();

// sanity check
BFSSanityCheck::go(*hg, DGAccumulator_sum, m);
Expand Down

0 comments on commit f448fdc

Please sign in to comment.