Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Frequency Latency Estimation via CPU Clock Modulation (Duty Cycle Modulation) #1

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions FreqGetter.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

close(pMSRFile);
}

return dcm;

}

inline void waitCurFreq(unsigned int coreID, unsigned int targetFreq)
{
assert(coreID < getCoreNumber());
Expand All @@ -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());
Expand Down
12 changes: 12 additions & 0 deletions FreqGetter.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,32 @@ 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
* \param targetFreq
*/
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
* \return
*/
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
Expand Down
69 changes: 69 additions & 0 deletions FreqSetter.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <assert.h>

#include <unistd.h>
Expand All @@ -31,6 +32,7 @@
#include "utils.h"

FILE** pSetFiles = NULL;
int* pSetMSRs = NULL;

char openFreqSetterFiles()
{
Expand All @@ -57,6 +59,33 @@ char openFreqSetterFiles()
return 0;
}

char openDCMSetterMSRs()
{
unsigned int nbCore = getCoreNumber();

pSetMSRs = malloc (sizeof(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);
printf("pSetMSR[%d]=%d\n", i, pSetMSRs[i]);
if ( pSetMSRs[i] < 0 )
{
return -1;
}
}

return 0;

}

inline void setFreq(unsigned int coreID, unsigned int targetFreq)
{
assert(coreID < getCoreNumber());
Expand All @@ -65,6 +94,16 @@ inline void setFreq(unsigned int coreID, unsigned int targetFreq)
fflush(pSetFiles[coreID]);
}


inline void setDCM(unsigned int coreID, uint64_t targetDCM)
{
assert(coreID < getCoreNumber());

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)
{
int nbCore = getCoreNumber();
Expand All @@ -77,6 +116,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));
Expand All @@ -103,6 +153,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();
Expand Down
29 changes: 29 additions & 0 deletions FreqSetter.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,35 +18,61 @@

#ifndef FREQSETTER_H
#define FREQSETTER_H
#include <stdint.h>

/**
* Open and prepare frequency operation
* \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
* \param coreID the id of the core to set
* \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, uint64_t 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();


/**
Expand All @@ -56,4 +82,7 @@ inline void setMinFreqForAll();
*/
char setCPUGovernor(const char* newPolicy);

/**
* No DCM counter-part
*/
#endif
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
CC=gcc
CFLAGS=-O3 -g -march=native -Wall -Wextra
CFLAGS=-O3 -g -march=native -Wall -Wextra
LDFLAGS=

.PHONY: all trace doc clean

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

Expand Down
51 changes: 51 additions & 0 deletions README_DCM.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
ftalat_dcm : Frequency Transition Latency Estimator for Clock Modulation
DCM Point of Contact: Wei Wang <[email protected]>, Allan Porterfield <[email protected]>, John Cavazos <[email protected]>, Sridutt Bhalachandra <[email protected]>

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
52 changes: 52 additions & 0 deletions ftalat_dcm_runner.sh
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.

# 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
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see from where this is coming.

done
done
Loading