From 0cd0cd4acbf674c910b4310ca5940199ceab4495 Mon Sep 17 00:00:00 2001 From: weiwang Date: Tue, 7 Jul 2015 21:42:12 -0700 Subject: [PATCH 1/4] Clock Modulation transition latency estimator [draft commit] --- FreqGetter.c | 21 +++++++++++++++++ FreqGetter.h | 12 ++++++++++ FreqSetter.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ FreqSetter.h | 28 ++++++++++++++++++++++ utils.c | 17 ++++++++++++++ utils.h | 11 +++++++++ 6 files changed, 155 insertions(+) diff --git a/FreqGetter.c b/FreqGetter.c index dc5e344..4d0cf5e 100644 --- a/FreqGetter.c +++ b/FreqGetter.c @@ -149,6 +149,25 @@ unsigned int getCurFreq(unsigned int coreID) return freq; } +unsigned int getCurDCM(unsigned int coreID) +{ + assert(coreID < getCoreNumber()); + + unsigned int dcm = 0; + + int pMSRFile = openCPUMSR(coreID); + if ( pMSRFile > 0 ) + { + /* IA32_CLOCK_MODULATION = 0x19a */ + pread(pMSRFile, &dcm, sizeof dcm, 0x19a); + + pclose(pFreqFile); + } + + return dcm; + +} + inline void waitCurFreq(unsigned int coreID, unsigned int targetFreq) { assert(coreID < getCoreNumber()); @@ -169,6 +188,8 @@ inline void waitCurFreq(unsigned int coreID, unsigned int targetFreq) }while(freq != targetFreq); } +/* not sure if we need waitCurDCM */ + unsigned int getMinAvailableFreq(unsigned int coreID) { assert(coreID < getCoreNumber()); diff --git a/FreqGetter.h b/FreqGetter.h index 9ec58bc..f3787d7 100644 --- a/FreqGetter.h +++ b/FreqGetter.h @@ -41,6 +41,8 @@ void freeFreqInfo(); */ unsigned int getCurFreq(unsigned int coreID); +unsigned int getCurDCM(unsigned int coreID); + /** * Wait the core identified by \a coreID to be at \a targetFreq frequency * \param coreID core identifier @@ -48,6 +50,8 @@ unsigned int getCurFreq(unsigned int coreID); */ inline void waitCurFreq(unsigned int coreID, unsigned int targetFreq); +inline void waitCurDCM(unsigned int coreID, unsigned int targetFreq); + /** * Get the minimum frequency available for the core identified by \a coreID * \param coreID core identifier @@ -55,6 +59,14 @@ inline void waitCurFreq(unsigned int coreID, unsigned int targetFreq); */ unsigned int getMinAvailableFreq(unsigned int coreID); +/** + * Get the minimum frequency available for the core identified by \a coreID + * \param coreID core identifier + * \return Depends on whether CPU Clock Modulation Extended or not + * + */ +unsigned int getMinAvailableDCM(unsigned int coreID); + /** * Get the maximum frequency available for the core identified by \a coreID * \param coreID core identifier diff --git a/FreqSetter.c b/FreqSetter.c index 26b0622..00af4a0 100644 --- a/FreqSetter.c +++ b/FreqSetter.c @@ -31,6 +31,7 @@ #include "utils.h" FILE** pSetFiles = NULL; +unsigned int* pSetMSRs = -1; char openFreqSetterFiles() { @@ -57,6 +58,32 @@ char openFreqSetterFiles() return 0; } +char openDCMSetterMSRs() +{ + unsigned int nbCore = getCoreNumber(); + + pSetMSRs = malloc (sizeof(unsigned int) * nbCore); + + if (pSetMSRs == NULL) + { + fprintf(stdout,"Fail to allocate memory for file descriptors\n"); + return -1; + } + + unsigned int i = 0; + for ( i = 0 ; i < nbCore ; i++ ) + { + pSetMSRs[i] = openCPUMSR(i); + if ( pSetMSRs[i] < 0 ) + { + return -1; + } + } + + return 0; + +} + inline void setFreq(unsigned int coreID, unsigned int targetFreq) { assert(coreID < getCoreNumber()); @@ -65,6 +92,15 @@ inline void setFreq(unsigned int coreID, unsigned int targetFreq) fflush(pSetFiles[coreID]); } + +inline void setDCM(unsigned int coreID, unsigned int targetDCM) +{ + assert(coreID < getCoreNumber()); + + pwrite(pSetMSRs[coreID], &targetDCM, sizeof targetDCM, 0x19a); + +} + inline void setAllFreq(unsigned int targetFreq) { int nbCore = getCoreNumber(); @@ -77,6 +113,17 @@ inline void setAllFreq(unsigned int targetFreq) } } +inline void setAllDCM(unsigned int targetDCM) +{ + int nbCore = getCoreNumber(); + int i; + + for (i = 0; i < nbCore ; i++ ) + { + pwrite(pSetMSRs[i], &targetDCM, sizeof targetDCM, 0x19a); + } +} + inline void setMinFreqForAll() { setAllFreq(getMinAvailableFreq(0)); @@ -103,6 +150,25 @@ void closeFreqSetterFiles(void) } } +void closeDCMSetterMSRs(void) +{ + int nbCore = getCoreNumber(); + int i = 0; + + if ( pSetMSRs ) + { + for ( i = 0 ; i < nbCore ; i++ ) + { + if ( pSetMSRs[i] >= 0 ) + { + close(pSetMSRs[i]); + } + } + + free(pSetMSRs); + } +} + char setCPUGovernor(const char* newPolicy) { int nbCore = getCoreNumber(); diff --git a/FreqSetter.h b/FreqSetter.h index 3732920..e4eda40 100644 --- a/FreqSetter.h +++ b/FreqSetter.h @@ -24,11 +24,20 @@ * \return 0 is everything gone fine */ char openFreqSetterFiles(); +/** + * Open and prepare DCM operation + * \return 0 is everything gone fine + */ +char openDCMSetterMSRs(); /** * Close the opened file to change frequencies */ void closeFreqSetterFiles(void); +/** + * Close the opened MSR to change DCM + */ +void closeDCMSetterMSRs(void); /** * Set a new frequency for a specific core determined by \a coreID @@ -36,17 +45,33 @@ void closeFreqSetterFiles(void); * \param targetFreq the new freq */ inline void setFreq(unsigned int coreID, unsigned int targetFreq); +/** + * Set a new DCM frequency for a specific core determined by \a coreID + * \param coreID the id of the core to set + * \param targetDCM the new DCM + */ +inline void setDCM(unsigned int coreID, unsigned int targetDCM); /** * Set a new frequency for all cores * \param targetFreq the new freq */ inline void setAllFreq(unsigned int targetFreq); +/** + * Set a new DCM frequency for all cores + * \param targetDCM the new DCM + */ +inline void setAllDCM(unsigned int targetDCM); + /** * Set the minimal available frequency for all cores */ inline void setMinFreqForAll(); +/** + * Set the minimal available DCM for all cores (actually 1) + */ +inline void setMinDCMForAll(); /** @@ -56,4 +81,7 @@ inline void setMinFreqForAll(); */ char setCPUGovernor(const char* newPolicy); +/** + * No DCM counter-part + */ #endif diff --git a/utils.c b/utils.c index e21fad5..63a840f 100644 --- a/utils.c +++ b/utils.c @@ -41,6 +41,23 @@ FILE* openCPUFreqFile(unsigned int coreID, const char* fileName, const char* mod return pFile; } +int openCPUMSR(unsigned int coreID) +{ + char msrPathBuffer[BUFFER_PATH_SIZE]= {'\0'}; + snprintf(msrPathBuffer,BUFFER_PATH_SIZE,MSR_PATH_FORMAT,coreID); + + + int pMSR = open(msrPathBuffer, O_RDWR); + if ( pMSR < 0) + { + fprintf(stderr,"Fail to open %s\n",msrPathBuffer); + } + + return pMSR; +} + + + void pinCPU(int cpu) { cpu_set_t cpuset; diff --git a/utils.h b/utils.h index 101b457..7404b2a 100644 --- a/utils.h +++ b/utils.h @@ -24,6 +24,7 @@ #define BUFFER_PATH_SIZE 100 #define CPU_PATH_FORMAT "/sys/devices/system/cpu/cpu%d/cpufreq/%s" +#define MSR_PATH_FORMAT "/dev/cpu/cpu%d/msr" /** * Easy to use function to open any file related to a CPU core @@ -36,6 +37,16 @@ */ FILE* openCPUFreqFile(unsigned int coreID, const char* fileName, const char* mode); +/** + * Easy to use function to open any MSR file related to a CPU core + * (files are located in /dev/cpu/cpu[coreID]/msr) + * \param coreID the id of the core to look at + * \return the file descriptor + * \warning don't forget to close the descriptor returned with close + */ +int openCPUMSR(unsigned int coreID, int mode); + + /** * Pin the current program to a specific core using CPU_SET and * sched_setaffinity From 59b377ccef35ee82b7a963c9c480585becb782f0 Mon Sep 17 00:00:00 2001 From: W Wang Date: Wed, 8 Jul 2015 03:13:35 -0400 Subject: [PATCH 2/4] draft commit. The model exited complaining about confidency overlap. Need to figure out why. Cannot estimate latency of clock modulation. --- FreqGetter.c | 2 +- FreqSetter.c | 8 +++++--- Makefile | 2 +- main.c | 48 +++++++++++++++++++++++++++++++++++++++++------- utils.c | 2 ++ utils.h | 4 ++-- 6 files changed, 52 insertions(+), 14 deletions(-) diff --git a/FreqGetter.c b/FreqGetter.c index 4d0cf5e..14174db 100644 --- a/FreqGetter.c +++ b/FreqGetter.c @@ -161,7 +161,7 @@ unsigned int getCurDCM(unsigned int coreID) /* IA32_CLOCK_MODULATION = 0x19a */ pread(pMSRFile, &dcm, sizeof dcm, 0x19a); - pclose(pFreqFile); + close(pMSRFile); } return dcm; diff --git a/FreqSetter.c b/FreqSetter.c index 00af4a0..c1fce87 100644 --- a/FreqSetter.c +++ b/FreqSetter.c @@ -31,7 +31,7 @@ #include "utils.h" FILE** pSetFiles = NULL; -unsigned int* pSetMSRs = -1; +int* pSetMSRs = NULL; char openFreqSetterFiles() { @@ -62,7 +62,7 @@ char openDCMSetterMSRs() { unsigned int nbCore = getCoreNumber(); - pSetMSRs = malloc (sizeof(unsigned int) * nbCore); + pSetMSRs = malloc (sizeof(int) * nbCore); if (pSetMSRs == NULL) { @@ -74,6 +74,7 @@ char openDCMSetterMSRs() for ( i = 0 ; i < nbCore ; i++ ) { pSetMSRs[i] = openCPUMSR(i); + printf("pSetMSR[%d]=%d\n", i, pSetMSRs[i]); if ( pSetMSRs[i] < 0 ) { return -1; @@ -97,8 +98,9 @@ inline void setDCM(unsigned int coreID, unsigned int targetDCM) { assert(coreID < getCoreNumber()); + printf("Before........................\n"); pwrite(pSetMSRs[coreID], &targetDCM, sizeof targetDCM, 0x19a); - + printf("WeiWeiWei........................\n"); } inline void setAllFreq(unsigned int targetFreq) diff --git a/Makefile b/Makefile index dc7a2ab..6f48e90 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC=gcc -CFLAGS=-O3 -g -march=native -Wall -Wextra +CFLAGS=-O3 -g -march=native -Wall -Wextra -DDVFS LDFLAGS= .PHONY: all trace doc clean diff --git a/main.c b/main.c index dd1278d..f2de4c9 100644 --- a/main.c +++ b/main.c @@ -50,6 +50,10 @@ const float DIFF_OFFSET_PERCENTAGE = 25.0f; unsigned long times[NB_BENCH_META_REPET] ; +/* easier impelemntation */ +int msrValues[]= +{0, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0}; + void usage() { fprintf(stdout,"./ftalat [-c coreID] startFreq targetFreq\n"); @@ -99,8 +103,13 @@ void runTest(unsigned int startFreq, unsigned int targetFreq, unsigned int coreI unsigned long targetQ1=0; unsigned long targetQ3=0; +#ifdef DVFS setFreq(coreID,targetFreq); waitCurFreq(coreID,targetFreq); +#else + setDCM(coreID, targetFreq); + /* do I need to waitCurDCM? */ +#endif targetBenchTime = measureLoop(NB_BENCH_META_REPET); fprintf(stdout,"Bench %d %.2f\n",targetFreq, targetBenchTime); targetBenchSD = sd(NB_BENCH_META_REPET, targetBenchTime, times); @@ -108,9 +117,12 @@ void runTest(unsigned int startFreq, unsigned int targetFreq, unsigned int coreI // Build the inter-quartile range for the target frequency interQuartileRange(NB_BENCH_META_REPET, times, &targetQ1, &targetQ3); - +#ifdef DVFS setFreq(coreID,startFreq); waitCurFreq(coreID,startFreq); +#else + setDCM(coreID, startFreq); +#endif startBenchTime = measureLoop(NB_BENCH_META_REPET); fprintf(stdout,"Bench %d %.2f\n",startFreq, startBenchTime); startBenchSD = sd(NB_BENCH_META_REPET, startBenchTime, times); @@ -183,7 +195,11 @@ void runTest(unsigned int startFreq, unsigned int targetFreq, unsigned int coreI #endif sync_rdtsc1(startLoopTime); +#ifdef DVFS setFreq(coreID,targetFreq); +#else + setDCM(coreID, targetFreq); +#endif sync_rdtsc1(lateStartLoopTime); do { @@ -215,8 +231,12 @@ void runTest(unsigned int startFreq, unsigned int targetFreq, unsigned int coreI if ( validateHighBoundTime < targetLowBoundTime || validateLowBoundTime > targetHighBoundTime ) { validated = 0; +#ifdef DVFS setFreq(coreID,startFreq); waitCurFreq(coreID,startFreq); +#else + setDCM(coreID, startFreq); +#endif } }while(!validated && ++j < NB_TRY_REPET); @@ -326,9 +346,10 @@ int main(int argc, char** argv) fprintf(stdout,"Core ID is set to 0\n"); coreID = 0; } - +#ifdef DVFS initFreqInfo(); - +#endif +#ifdef DVFS if ( isFreqAvailable(coreID,startFreq) == 0 ) { fprintf(stdout,"The starting frequency that you have entered (%d) is not available for the core %d\n",startFreq,coreID); @@ -346,7 +367,7 @@ int main(int argc, char** argv) } initCoreRelations(); - +#endif #ifdef _DUMP openDump("./results.dump",NB_TRY_REPET_LOOP*NB_VALIDATION_REPET); @@ -365,27 +386,40 @@ int main(int argc, char** argv) { perror("setscheduler background"); } - +#ifdef DVFS if ( setCPUGovernor("userspace") != 0 ) { fprintf(stderr,"We are unable to set \"userspace\" governor. Do you have cpufreq and permissions ?\n"); cleanup(); return -5; } - +#endif +#ifdef DVFS // Set the minimal frequency if ( openFreqSetterFiles() != 0 ) { cleanup(); return -3; } +#else + if ( openDCMSetterMSRs() != 0) { + /* cleanup(); ? */ + return -3; + } +#endif +#ifdef DVFS setFreqForAllRelatedCore(coreID,getMinAvailableFreq(coreID)); runTest(startFreq, targetFreq, coreID); +#else + setDCM(coreID, msrValues[1]); + runTest(msrValues[startFreq], msrValues[targetFreq], coreID); +#endif // kill bg thread pthread_cancel(bgth); - +#ifdef DVFS cleanup(); +#endif return 0; } diff --git a/utils.c b/utils.c index 63a840f..533158c 100644 --- a/utils.c +++ b/utils.c @@ -27,6 +27,8 @@ #include #include +#include + FILE* openCPUFreqFile(unsigned int coreID, const char* fileName, const char* mode) { char filePathBuffer[BUFFER_PATH_SIZE]= {'\0'}; diff --git a/utils.h b/utils.h index 7404b2a..1cde956 100644 --- a/utils.h +++ b/utils.h @@ -24,7 +24,7 @@ #define BUFFER_PATH_SIZE 100 #define CPU_PATH_FORMAT "/sys/devices/system/cpu/cpu%d/cpufreq/%s" -#define MSR_PATH_FORMAT "/dev/cpu/cpu%d/msr" +#define MSR_PATH_FORMAT "/dev/cpu/%d/msr" /** * Easy to use function to open any file related to a CPU core @@ -44,7 +44,7 @@ FILE* openCPUFreqFile(unsigned int coreID, const char* fileName, const char* mod * \return the file descriptor * \warning don't forget to close the descriptor returned with close */ -int openCPUMSR(unsigned int coreID, int mode); +int openCPUMSR(unsigned int coreID); /** From 4add9a0b98a9fae738e96ca5e38091df746d8ccb Mon Sep 17 00:00:00 2001 From: Wei Wang Date: Wed, 8 Jul 2015 04:50:07 -0400 Subject: [PATCH 3/4] Can estimate DCM transition overhead now. Use uint64_t is somehow important for MSRWRITE to 0x19a. --- FreqSetter.c | 9 +++++---- FreqSetter.h | 3 ++- Makefile | 2 +- main.c | 2 +- utils.c | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/FreqSetter.c b/FreqSetter.c index c1fce87..66cca4a 100644 --- a/FreqSetter.c +++ b/FreqSetter.c @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -94,13 +95,13 @@ inline void setFreq(unsigned int coreID, unsigned int targetFreq) } -inline void setDCM(unsigned int coreID, unsigned int targetDCM) +inline void setDCM(unsigned int coreID, uint64_t targetDCM) { assert(coreID < getCoreNumber()); - printf("Before........................\n"); - pwrite(pSetMSRs[coreID], &targetDCM, sizeof targetDCM, 0x19a); - printf("WeiWeiWei........................\n"); + printf("Begin Setting Core %d to %x", coreID, targetDCM); + pwrite(pSetMSRs[coreID], &targetDCM, sizeof targetDCM, 0x19A); + printf("Finish Setting Core %d to %x", coreID, targetDCM); } inline void setAllFreq(unsigned int targetFreq) diff --git a/FreqSetter.h b/FreqSetter.h index e4eda40..9bde9fa 100644 --- a/FreqSetter.h +++ b/FreqSetter.h @@ -18,6 +18,7 @@ #ifndef FREQSETTER_H #define FREQSETTER_H +#include /** * Open and prepare frequency operation @@ -50,7 +51,7 @@ inline void setFreq(unsigned int coreID, unsigned int targetFreq); * \param coreID the id of the core to set * \param targetDCM the new DCM */ -inline void setDCM(unsigned int coreID, unsigned int targetDCM); +inline void setDCM(unsigned int coreID, uint64_t targetDCM); /** * Set a new frequency for all cores diff --git a/Makefile b/Makefile index 6f48e90..bc68383 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC=gcc -CFLAGS=-O3 -g -march=native -Wall -Wextra -DDVFS +CFLAGS=-O3 -g -march=native -Wall -Wextra LDFLAGS= .PHONY: all trace doc clean diff --git a/main.c b/main.c index f2de4c9..f0aaa3e 100644 --- a/main.c +++ b/main.c @@ -51,7 +51,7 @@ const float DIFF_OFFSET_PERCENTAGE = 25.0f; unsigned long times[NB_BENCH_META_REPET] ; /* easier impelemntation */ -int msrValues[]= +unsigned int msrValues[]= {0, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0}; void usage() diff --git a/utils.c b/utils.c index 533158c..bcd2242 100644 --- a/utils.c +++ b/utils.c @@ -49,7 +49,7 @@ int openCPUMSR(unsigned int coreID) snprintf(msrPathBuffer,BUFFER_PATH_SIZE,MSR_PATH_FORMAT,coreID); - int pMSR = open(msrPathBuffer, O_RDWR); + int pMSR = open(msrPathBuffer, O_WRONLY); if ( pMSR < 0) { fprintf(stderr,"Fail to open %s\n",msrPathBuffer); From 4466586180b0591e2a1407a5b69d10c4814ebea0 Mon Sep 17 00:00:00 2001 From: Wei Wang Date: Wed, 5 Aug 2015 19:09:03 -0400 Subject: [PATCH 4/4] Added Readme for FTALAT_DCM PULL Request --- Makefile | 5 +- README_DCM.md | 51 +++++++++++++ ftalat_dcm_runner.sh | 52 +++++++++++++ main.c | 22 +++--- script/generateGraph_DCM.py | 143 ++++++++++++++++++++++++++++++++++++ 5 files changed, 262 insertions(+), 11 deletions(-) create mode 100644 README_DCM.md create mode 100755 ftalat_dcm_runner.sh create mode 100644 script/generateGraph_DCM.py diff --git a/Makefile b/Makefile index bc68383..dce7630 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC=gcc -CFLAGS=-O3 -g -march=native -Wall -Wextra +CFLAGS=-O3 -g -march=native -Wall -Wextra LDFLAGS= .PHONY: all trace doc clean @@ -7,6 +7,9 @@ LDFLAGS= all: $(CC) $(CFLAGS) $(LDFLAGS) main.c loop.c CoreRelation.c FreqGetter.c FreqSetter.c measure.c utils.c ConfInterval.c -o ftalat -lm -pthread +dcm: + $(CC) $(CFLAGS) -DDCM $(LDFLAGS) main.c loop.c CoreRelation.c FreqGetter.c FreqSetter.c measure.c utils.c ConfInterval.c -o ftalat_dcm -lm -pthread + trace: $(CC) $(CFLAGS) $(LDFLAGS) -D_DUMP main.c loop.c dumpResults.c CoreRelation.c FreqGetter.c FreqSetter.c measure.c utils.c ConfInterval.c -o ftalat -lm -pthread diff --git a/README_DCM.md b/README_DCM.md new file mode 100644 index 0000000..189e968 --- /dev/null +++ b/README_DCM.md @@ -0,0 +1,51 @@ +ftalat_dcm : Frequency Transition Latency Estimator for Clock Modulation +DCM Point of Contact: Wei Wang , Allan Porterfield , John Cavazos , Sridutt Bhalachandra + +ftalat allows you to determine the time taken by your CPU to switch from one frequency to another one. +Here, the frequency change is supported by *software clock modulation* (see Intel System Programmers Guide) + +#Prerequisites +1) The machine must be an Intel processor, better chance of working with SandyBridge and Ivybridge. +2) In general, non-extended software controlled clock modulation supports eight frequencies, with an interval of 12.5% and +extended version supports sixteen frequencies, with an interval of 6.25%. Extension to software controlled clock modulation is supported only if CPUID.06H:EAX[Bit 5] = 1. Also the CPU must have ACPI feature to support both extended and non-extended software controlled clock modulation, i.e. CPUID.01H:EDX[Bit 22]=1. +3) If any of the CPUID output is not 1, code modification is required. + + +# Compilation +``` + make dcm +``` +or +``` + make trace +``` +to compile a second version of ftalat writing latency for each run of the kernel. A graph of this data can be displayed using the GNUPlot script `traceViewer.gnuplot` + +# Usage +``` + ./ftalat_dcm startFreq targetFreq + where startFreq is the frequency at the beginning of the test and targetFreq the frequency to switch to + The program will output the time taken by your CPU to swtich from startFreq to targetFreq + ftalat_dcm must be run with ***root*** to set clock modulation (write to a msr) +``` + +The script `ftalat_dcm_runner.sh` allows you to run the test for all frequencies couple (in the realm of software clock modulation) for your CPU. The script will write the output in a folder `Results` +From the files written in the `Results` folder, you can generate graphs. To do this, you need to use the python scripts from the `script` folder. +``` + ./extract.py data_folder output_folder + data_folder should be 'Results' folder + output_folder is a new folder (which has to be created before) where the proceed files will be stored. +``` + +Then, you have to run +``` + ./generateGraph_DCM.py input_folder file + where input_folder is the folder where the files generated by extract.py are located + and file, the name of the file (without extension) for graph output (PDF) and latency table (a GNUPlot script is also generated) +``` + +# Depencies +You must have python (2.7) and GNUPlot installed + +# Licence +The program is licenced under GPLv3. Please read [COPYRIGHT](https://github.com/LittleWhite-tb/ftalat/blob/master/COPYRIGHT) file for more information diff --git a/ftalat_dcm_runner.sh b/ftalat_dcm_runner.sh new file mode 100755 index 0000000..7cc0fa0 --- /dev/null +++ b/ftalat_dcm_runner.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# ftalat - Frequency Transition Latency Estimator +# Copyright (C) 2013 Universite de Versailles +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Script to bench all the frequencies couple with ftalat + +OUTPUT_FILE=results +OUTPUT_EXT=.txt +OUTPUT_DIR=Results +FREQUENCIES=`seq 1 1 16` +ITER=31 + +mkdir -p $OUTPUT_DIR + +for startFreq in ${FREQUENCIES} +do + # Avoid turbo as starting seq + for testFreq in ${FREQUENCIES} + do + if [ $startFreq -eq $testFreq ] + then + echo "Skip $startFreq -> $testFreq (same frequency)" + continue + fi + + echo "$startFreq -> $testFreq" + # Test if the result file already exists + if ( ! (test -e "${OUTPUT_DIR}/${OUTPUT_FILE}"_"${startFreq}"-"${testFreq}${OUTPUT_EXT}" ) ) + then + for i in `seq $ITER` + do + ./ftalat $startFreq $testFreq >> ${OUTPUT_DIR}/${OUTPUT_FILE}"_"${startFreq}"-"${testFreq}${OUTPUT_EXT} + echo "############################" >> ${OUTPUT_DIR}/${OUTPUT_FILE}"_"${startFreq}"-"${testFreq}${OUTPUT_EXT} + done + fi + setDutyCycle-16.exe + done +done diff --git a/main.c b/main.c index f0aaa3e..8df4c66 100644 --- a/main.c +++ b/main.c @@ -53,6 +53,8 @@ unsigned long times[NB_BENCH_META_REPET] ; /* easier impelemntation */ unsigned int msrValues[]= {0, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0}; +/* 0: default/original DCM; 17 (0x11): 1/16 Freq; 18 (0x12):2/16 Freq */ +/* 19(0x13) :3/16 Freq; ...; 31(0x1f):15/16 Freq; 0: 16/16 Freq */ void usage() { @@ -103,7 +105,7 @@ void runTest(unsigned int startFreq, unsigned int targetFreq, unsigned int coreI unsigned long targetQ1=0; unsigned long targetQ3=0; -#ifdef DVFS +#ifndef DCM setFreq(coreID,targetFreq); waitCurFreq(coreID,targetFreq); #else @@ -117,7 +119,7 @@ void runTest(unsigned int startFreq, unsigned int targetFreq, unsigned int coreI // Build the inter-quartile range for the target frequency interQuartileRange(NB_BENCH_META_REPET, times, &targetQ1, &targetQ3); -#ifdef DVFS +#ifndef DCM setFreq(coreID,startFreq); waitCurFreq(coreID,startFreq); #else @@ -195,7 +197,7 @@ void runTest(unsigned int startFreq, unsigned int targetFreq, unsigned int coreI #endif sync_rdtsc1(startLoopTime); -#ifdef DVFS +#ifndef DCM setFreq(coreID,targetFreq); #else setDCM(coreID, targetFreq); @@ -231,7 +233,7 @@ void runTest(unsigned int startFreq, unsigned int targetFreq, unsigned int coreI if ( validateHighBoundTime < targetLowBoundTime || validateLowBoundTime > targetHighBoundTime ) { validated = 0; -#ifdef DVFS +#ifndef DCM setFreq(coreID,startFreq); waitCurFreq(coreID,startFreq); #else @@ -346,10 +348,10 @@ int main(int argc, char** argv) fprintf(stdout,"Core ID is set to 0\n"); coreID = 0; } -#ifdef DVFS +#ifndef DCM initFreqInfo(); #endif -#ifdef DVFS +#ifndef DCM if ( isFreqAvailable(coreID,startFreq) == 0 ) { fprintf(stdout,"The starting frequency that you have entered (%d) is not available for the core %d\n",startFreq,coreID); @@ -386,7 +388,7 @@ int main(int argc, char** argv) { perror("setscheduler background"); } -#ifdef DVFS +#ifndef DCM if ( setCPUGovernor("userspace") != 0 ) { fprintf(stderr,"We are unable to set \"userspace\" governor. Do you have cpufreq and permissions ?\n"); @@ -394,7 +396,7 @@ int main(int argc, char** argv) return -5; } #endif -#ifdef DVFS +#ifndef DCM // Set the minimal frequency if ( openFreqSetterFiles() != 0 ) { @@ -408,7 +410,7 @@ int main(int argc, char** argv) } #endif -#ifdef DVFS +#ifndef DCM setFreqForAllRelatedCore(coreID,getMinAvailableFreq(coreID)); runTest(startFreq, targetFreq, coreID); #else @@ -418,7 +420,7 @@ int main(int argc, char** argv) // kill bg thread pthread_cancel(bgth); -#ifdef DVFS +#ifndef DVFS cleanup(); #endif return 0; diff --git a/script/generateGraph_DCM.py b/script/generateGraph_DCM.py new file mode 100644 index 0000000..bea9d11 --- /dev/null +++ b/script/generateGraph_DCM.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python + +# ftalat - Frequency Transition Latency Estimator +# Copyright (C) 2013 Universite de Versailles +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +# Script to proceed the results generated by extract.py and to generate +# the graph with GNUPlot + +import sys, os +import glob + +import mathutils +import cpuutils + +# Usual argument checking +if len(sys.argv) != 3: + print './extract.py input_folder output_file' + sys.exit() + +if not os.path.isdir(sys.argv[1]): + print sys.argv[1] + " is not a directory" + sys.exit() + +if os.path.isdir(sys.argv[2]): + print sys.argv[2] + " is a directory ! Please specify a file" + sys.exit() + +# Check turbo freq +turboFreq=0 +try: + turboFile = open(sys.argv[1] + "/turbo","r") + turboFreq = int(turboFile.read().strip()) + turboFile.close() +except IOError: + print "turbo file not found in " + sys.argv[1] + sys.exit() + +if os.path.exists(sys.argv[2]): + var = raw_input(sys.argv[2] + " exists ! Do you want to overwrite it ? [Y/n] ") + + if var != "y" and var != "Y": + print "Aborted" + sys.exit() + +# Get the files to proceed +resultsFiles = glob.glob(sys.argv[1]+"/*.csv") +sortedResultsFiles = sorted(resultsFiles) + +results = {} +for f in sortedResultsFiles: + # Extract the freq from the file name + simplifiedName, fileExtension = os.path.splitext(os.path.basename(f)) + + freqsString = simplifiedName.split("_")[1] # At this point we have "startFreq-targetFreq" + freq = int(freqsString) + + # Read the file + inFile = open(f) + dataFile = inFile.readlines() + inFile.close() + + medians = [] + for line in dataFile: + line = line.rstrip() + if len(line) == 0: + continue + + # Read values in line + values = [] + valuesString = line.split(" ") + for value in valuesString: + values.append(int(value)) + + medians.append(mathutils.median(values)) + results[freq]=medians + +# Write data output +outFile = open(sys.argv[2],"w") + +sortedKeys = sorted(results.keys()) +size = len(sortedKeys) +if sortedKeys[size-1] == turboFreq: # Check turbo freq + size = size-1 + +# The loop is as follow since we have to transpose the table for GNUPlot +i = 0 +for key in sortedKeys: + if str(key)[-4:] == "1000": # Check to avoid turbo + continue + + outFile.write("{0}".format(key)) + for k in sortedKeys: + outFile.write(" {0}".format((results[k][i]/float(sortedKeys[size-1]))*1000)) + outFile.write("\n") + i+=1 +outFile.close() + +# write the gnuplot script +scriptFile = open(sys.argv[2] + ".script","w") +scriptFile.write("set title \"Frequencies transition latency estimation\"\n") + +scriptFile.write("set autoscale x\n") +scriptFile.write("set autoscale y\n") + +scriptFile.write("set ylabel \"Latency (micro-seconds)\"\n") + +scriptFile.write("set term pdfcairo enhanced color\n") +scriptFile.write("set output \"" + sys.argv[2] + ".pdf\"\n") + +scriptFile.write("set key out vert\n") +scriptFile.write("set key cent\n") +scriptFile.write("set key right\n") + +scriptFile.write("set palette model HSV rgbformulae 3,2,2\n") +scriptFile.write("unset colorbox\n") + +scriptFile.write("plot ") + +# plot all freqs +for i in range(size): + # scriptFile.write("\"" + sys.argv[2] + "\" using ($1/1000000):(${0} != 0 ? ((${0}/{2})*1000) : 1/0) axes x1y1 title \"{1} Ghz\" with linespoints".format(i+2,sortedKeys[i]/1000000.0,float(sortedKeys[size-1]))) + scriptFile.write("\"" + sys.argv[2] + "\" using (2.7/(16/$1)):(${0} != 0 ? ((${0})) : 1/0) axes x1y1 title \"{1} Ghz\" with linespoints palette frac {3}".format(i+2,(2.7/(16/sortedKeys[i]))/1000000.0,float(sortedKeys[size-1]),(1.0/(len(sortedKeys)))*i)) + if i != size-1: + scriptFile.write(", \\\n") + +scriptFile.close() + +# Finally, call gnuplot +os.system("gnuplot " + sys.argv[2] + ".script")