Created a specific button to generate plots

This makes possible to generate metrics without waiting for the plots
generation.
This commit is contained in:
Éder F. Zulian
2016-02-26 08:49:44 -03:00
parent 2b99e82cff
commit 5887c4be6a
11 changed files with 183 additions and 97 deletions

View File

@@ -50,7 +50,9 @@ PythonCaller::PythonCaller() :
testFunctionName("runTests"),
metricModuleName("metrics"),
metricFunctionName("calculateMetrics"),
pathToScripts(QApplication::applicationDirPath().toStdString() + "/../../DRAMSys/analyzer/scripts/")
pathToScripts(QApplication::applicationDirPath().toStdString() + "/../../DRAMSys/analyzer/scripts/"),
plotsModuleName("plots"),
plotsFunctionName("generatePlots")
{
Py_Initialize();
PyObject *sysPath = PySys_GetObject((char*)"path");
@@ -59,10 +61,13 @@ PythonCaller::PythonCaller() :
Py_DECREF(path);
qDebug() << testModuleName.c_str() << testFunctionName.c_str();
qDebug() << metricModuleName.c_str() << metricFunctionName.c_str();
qDebug() << plotsModuleName.c_str() << plotsFunctionName.c_str();
qDebug() << "XXX: " << pathToScripts.c_str();
pRunTestsFunction = loadFunctionFromModule(testModuleName, testFunctionName);
pCalculateMetricsFunction = loadFunctionFromModule(metricModuleName, metricFunctionName);
pGenPlotsFunction = loadFunctionFromModule(plotsModuleName, plotsFunctionName);
}
@@ -93,6 +98,7 @@ PythonCaller::~PythonCaller()
{
Py_DECREF(pRunTestsFunction);
Py_DECREF(pCalculateMetricsFunction);
Py_DECREF(pGenPlotsFunction);
Py_Finalize();
}
@@ -149,3 +155,14 @@ TraceCalculatedMetrics PythonCaller::calculateMetricsOnTrace(QString pathToTrace
Py_DECREF(pResult);
return result;
}
void PythonCaller::generatePlotsOnTrace(QString pathToTrace)
{
assert(PyCallable_Check(pGenPlotsFunction));
PyObject *pArgs = PyTuple_New(1);
PyObject *pArgument = PyUnicode_FromString(pathToTrace.toStdString().c_str());
PyTuple_SetItem(pArgs, 0, pArgument);
PyObject_CallObject(pGenPlotsFunction, pArgs);
Py_DECREF(pArgument);
}

View File

@@ -50,11 +50,16 @@ public:
~PythonCaller();
TraceTestResults runTestsOnTrace(QString pathToTrace);
TraceCalculatedMetrics calculateMetricsOnTrace(QString pathToTrace);
void generatePlotsOnTrace(QString pathToTrace);
private:
PyObject *pRunTestsFunction, *pCalculateMetricsFunction;
PyObject *pGenPlotsFunction;
PyObject* loadFunctionFromModule(std::string moduleName, std::string functionName);
std::string testModuleName, testFunctionName, metricModuleName, metricFunctionName, pathToScripts;
std::string plotsModuleName;
std::string plotsFunctionName;
PyObject *callFunctionWithStringArgument(PyObject *function, QString argument);
};

View File

@@ -33,6 +33,7 @@
* Janik Schlemminger
* Robert Gernhardt
* Matthias Jung
* Éder F. Zulian
*/
#include <QFileInfo>
@@ -203,3 +204,23 @@ void EvaluationTool::on_btn_exportCSV_clicked()
}
}
void EvaluationTool::on_btn_genPlots_clicked()
{
genPlots();
}
void EvaluationTool::genPlots()
{
ui->traceMetricTreeWidget->clear();
if(traceFilesModel->rowCount() == 0)
return;
PythonCaller pythonCaller;
for (int row = 0; row < traceFilesModel->rowCount(); ++row) {
TraceFileItem *item = static_cast<TraceFileItem*>(traceFilesModel->item(row));
pythonCaller.generatePlotsOnTrace(item->getPath());
}
ui->traceMetricTreeWidget->expandAll();
}

View File

@@ -33,6 +33,7 @@
* Janik Schlemminger
* Robert Gernhardt
* Matthias Jung
* Éder F. Zulian
*/
#ifndef EVALUATIONTOOL_H
@@ -69,14 +70,16 @@ private Q_SLOTS:
void on_btn_test_clicked();
void setTestMessage(QString message);
void on_btn_calculateMetrics_clicked();
void on_btn_exportCSV_clicked();
void on_btn_genPlots_clicked();
private:
void fillFileList(QList<QString> paths);
void runTests();
void calculateMetrics();
void cleanUpUI();
void genPlots();
Ui::EvaluationTool *ui;

View File

@@ -137,6 +137,13 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_genPlots">
<property name="text">
<string>Generate plots</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_exportCSV">
<property name="text">

14
DRAMSys/analyzer/scripts/memUtil.py Normal file → Executable file
View File

@@ -55,3 +55,17 @@ def getNumberOfBanks(dbconnection):
cursor.execute("SELECT NumberOfBanks FROM generalInfo")
result = cursor.fetchone()
return result[0]
def maximum_data_rate(connection):
memspec = MemSpec(connection)
memoryType = memspec.getValue("memoryType")
if (memoryType.find("DDR") != -1):
width = 64
else:
if (memoryType.find("WIDEIO") != -1):
width = memspec.getValue("width")
clk = memspec.getValue("clkMhz")
rate = memspec.getValue("dataRate")
maxDataRate = float(clk)*float(width)*float(rate)
return maxDataRate

View File

@@ -115,104 +115,14 @@ def memory_utilisation_percent_new(connection):
idle = memory_idle(connection)
return (active/(total-idle))*100
@metric
def memory_utilisation_new(connection):
#This function calculates the memory utilisation in Gbit/s considering the memory_utilisation_percent_new function result.
memory_utilisation_window_new(connection)
def memory_utilisation_in_Gbps(connection):
# This function calculates the memory utilisation in Gbit/s considering the memory_utilisation_percent_new function result.
maxDataRate = maximum_data_rate(connection)
memoryPercent = memory_utilisation_percent_new(connection)
return (memoryPercent/100)*(maxDataRate/1024)
def memory_utilisation_window_new(connection):
#This function determines the average memory bandwidth over time in percentage and in Gbit/s.
#The average bandwidth over time is done dividing the time into windows of the same length and getting the average bandwidth in each window.
#Through the data from the database, DataStrobeEnd and DataStrobeBegin, it is possible to assess when a data transfer begins or ends.
#Hence, it is possible to ckeck when a data transfer happens and if it occupies or is inside a time window. Then, it is possible to determine the average bandwidth in percentage.
#Besides, extracting the data from the memory specs, it is possible to calculate the maximum data rate of the memory and then determine the bandwidth in Gbit/s.
#The bandwidth data are then plotted in two graphics.
windowSize = 1000000
cursor = connection.cursor()
cursor.execute(""" SELECT max(DataStrobeEnd) FROM Transactions """)
total = cursor.fetchone()
steps = ceil(float(total[0])/float(windowSize))
#print(steps)
#All possible cases of data transfers inside a time window
queryFull= """ SELECT sum(DataStrobeEnd - DataStrobeBegin) FROM transactions Where DataStrobeBegin > ? and DataStrobeEnd < ?""" #The data transfer begins and ends inside the time window
queryEnd= """ SELECT sum(DataStrobeEnd - ?) FROM transactions Where DataStrobeBegin < ? and DataStrobeEnd > ? and DataStrobeEnd <=?""" #Only the end of the data transfer is inside the time window
queryBegin= """ SELECT sum(? - DataStrobeBegin) FROM transactions Where DataStrobeBegin >= ? and DataStrobeBegin < ? and DataStrobeEnd > ?""" #Only the beginning of the data transfer is inside the time window
queryPart = """ SELECT DataStrobeBegin FROM transactions Where DataStrobeBegin <= ? and DataStrobeEnd >= ?""" #The data transfer occupies all the time window
maxDataRate = maximum_data_rate(connection)
#print(width)
#print(clk)
#print(rate)
bandwidthPercentage = [0] * steps
bandwidth = [0] * steps
for i in range(steps):
#print(i)
bandwidthPercentage[i] = 0
cursor.execute(queryPart, (i*windowSize, (i+1)*windowSize))
result = cursor.fetchone()
if(result is None):
cursor.execute(queryFull, (i*windowSize, (i+1)*windowSize))
result = cursor.fetchone()
if(result[0] is not None):
bandwidthPercentage[i] += int(result[0])
#print(bandwidthPercentage[i])
cursor.execute(queryEnd, (i*windowSize,i*windowSize,i*windowSize,(i+1)*windowSize))
result = cursor.fetchone()
if(result[0] is not None):
bandwidthPercentage[i] += int(result[0])
#print(bandwidthPercentage[i])
cursor.execute(queryBegin, ((i+1)*windowSize, i*windowSize, (i+1)*windowSize, (i+1)*windowSize))
result = cursor.fetchone()
if(result[0] is not None):
bandwidthPercentage[i] += int(result[0])
#print(bandwidthPercentage[i])
else:
bandwidthPercentage[i] = windowSize
#print(bandwidthPercentage[i])
bandwidthPercentage[i] = float(bandwidthPercentage[i]/windowSize)
bandwidth[i] = float(bandwidthPercentage[i])*float(maxDataRate)/1024
bandwidthPercentage[i] *= 100
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_pdf import PdfPages
time = np.arange(0,steps*windowSize,windowSize)
plt.figure(1)
plt.plot(time/1000,bandwidthPercentage)
plt.xlabel('Time (ns)')
plt.ylabel('Bandwidth (%)')
plt.ylim(0,120)
plt.grid(True)
windowPercentage = PdfPages('windowPercentage.pdf')
windowPercentage.savefig()
windowPercentage.close()
plt.figure(2)
plt.plot(time/1000,bandwidth)
plt.xlabel('Time (ns)')
plt.ylabel('Bandwidth (Gbit/s)')
plt.grid(True)
window = PdfPages('window.pdf')
window.savefig()
window.close()
def maximum_data_rate(connection):
memspec = MemSpec(connection)
memoryType = memspec.getValue("memoryType")
if (memoryType.find("DDR") != -1):
width = 64
else:
if (memoryType.find("WIDEIO") != -1):
width = memspec.getValue("width")
clk = memspec.getValue("clkMhz")
rate = memspec.getValue("dataRate")
maxDataRate = float(clk)*float(width)*float(rate)
return maxDataRate
@metric
def memory_utilisation_percent_old(connection):
@@ -429,6 +339,7 @@ def time_in_power_down_states_percent(connection):
totalTimeAllBanks = trace_length_in_ns(connection) * getNumberOfBanks(connection)
return (time_in_power_down_states_in_ns(connection) * 1.0 / totalTimeAllBanks) * 100
def passRatio(connection):
numberOfPassWins = {}

View File

@@ -0,0 +1,108 @@
import sys
import sqlite3
from memUtil import *
from math import *
plots = []
def plot(function):
plots.append(function)
return function
@plot
def memory_utilisation_window(connection):
# This function determines the average memory bandwidth over time in percentage and in Gbit/s.
# The average bandwidth over time is done dividing the time into windows of the same length and getting the average bandwidth in each window.
# Through the data from the database, DataStrobeEnd and DataStrobeBegin, it is possible to assess when a data transfer begins or ends.
# Hence, it is possible to ckeck when a data transfer happens and if it occupies or is inside a time window. Then, it is possible to determine the average bandwidth in percentage.
# Besides, extracting the data from the memory specs, it is possible to calculate the maximum data rate of the memory and then determine the bandwidth in Gbit/s.
# The bandwidth data are then plotted in two graphics.
windowSize = 1000000
cursor = connection.cursor()
cursor.execute(""" SELECT max(DataStrobeEnd) FROM Transactions """)
total = cursor.fetchone()
steps = ceil(float(total[0])/float(windowSize))
# print(steps)
# All possible cases of data transfers inside a time window
queryFull = """ SELECT sum(DataStrobeEnd - DataStrobeBegin) FROM transactions Where DataStrobeBegin > ? and DataStrobeEnd < ?""" # The data transfer begins and ends inside the time window
queryEnd = """ SELECT sum(DataStrobeEnd - ?) FROM transactions Where DataStrobeBegin < ? and DataStrobeEnd > ? and DataStrobeEnd <=?""" # Only the end of the data transfer is inside the time window
queryBegin = """ SELECT sum(? - DataStrobeBegin) FROM transactions Where DataStrobeBegin >= ? and DataStrobeBegin < ? and DataStrobeEnd > ?""" # Only the beginning of the data transfer is inside the time window
queryPart = """ SELECT DataStrobeBegin FROM transactions Where DataStrobeBegin <= ? and DataStrobeEnd >= ?""" # The data transfer occupies all the time window
maxDataRate = maximum_data_rate(connection)
# print(width)
# print(clk)
# print(rate)
bandwidthPercentage = [0] * steps
bandwidth = [0] * steps
for i in range(steps):
# print(i)
bandwidthPercentage[i] = 0
cursor.execute(queryPart, (i*windowSize, (i+1)*windowSize))
result = cursor.fetchone()
if(result is None):
cursor.execute(queryFull, (i*windowSize, (i+1)*windowSize))
result = cursor.fetchone()
if(result[0] is not None):
bandwidthPercentage[i] += int(result[0])
# print(bandwidthPercentage[i])
cursor.execute(queryEnd, (i*windowSize, i*windowSize, i*windowSize, (i+1)*windowSize))
result = cursor.fetchone()
if(result[0] is not None):
bandwidthPercentage[i] += int(result[0])
# print(bandwidthPercentage[i])
cursor.execute(queryBegin, ((i+1)*windowSize, i*windowSize, (i+1)*windowSize, (i+1)*windowSize))
result = cursor.fetchone()
if(result[0] is not None):
bandwidthPercentage[i] += int(result[0])
# print(bandwidthPercentage[i])
else:
bandwidthPercentage[i] = windowSize
# print(bandwidthPercentage[i])
bandwidthPercentage[i] = float(bandwidthPercentage[i]/windowSize)
bandwidth[i] = float(bandwidthPercentage[i])*float(maxDataRate)/1024
bandwidthPercentage[i] *= 100
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_pdf import PdfPages
time = np.arange(0, steps*windowSize, windowSize)
plt.figure(1)
plt.plot(time/1000, bandwidthPercentage)
plt.xlabel('Time (ns)')
plt.ylabel('Bandwidth (%)')
plt.ylim(0, 120)
plt.grid(True)
windowPercentage = PdfPages('windowPercentage.pdf')
windowPercentage.savefig()
windowPercentage.close()
plt.figure(2)
plt.plot(time/1000, bandwidth)
plt.xlabel('Time (ns)')
plt.ylabel('Bandwidth (Gbit/s)')
plt.grid(True)
window = PdfPages('window.pdf')
window.savefig()
window.close()
def generatePlots(pathToTrace):
connection = sqlite3.connect(pathToTrace)
print("================================")
print("Generating plots for {0}".format(pathToTrace))
for p in plots:
p(connection)
connection.close()
if __name__ == "__main__":
path = sys.argv[1]
generatePlots(path)

0
DRAMSys/analyzer/scripts/tests.py Normal file → Executable file
View File

View File

@@ -100,7 +100,8 @@ FORMS += \
OTHER_FILES += \
common/static/createTraceDB.sql \
scripts/metrics.py \
scripts/tests.py
scripts/tests.py \
scripts/plots.py
QMAKE_CXXFLAGS += -std=c++11
QMAKE_CXXFLAGS += -Xlinker -export-dynamic

View File

@@ -209,4 +209,3 @@ void TraceAnalyzer::on_actionMetrics_triggered()
evaluationTool.activateWindow();
evaluationTool.showAndEvaluateMetrics(openedTraceFiles.toList());
}