How can i scale only one core's frequency in a multi-core processor?(Monitor through PMU)

How can i scale only one core's frequency in a multi-core processor?(Monitor through PMU)

Songtao.H's picture

Hi,

I am trying to scale only one core's frequency in a multi-core processor with linux 3.8 kernel based on intel i7 3610QM.

I scaled each core's frequency through program A  .And i got a result like this:

    cat  /proc/cpuinfo  | grep MHz

    cpu MHz        : 1200.000
    cpu MHz        : 1200.000    //core 0
    cpu MHz        : 1600.000
    cpu MHz        : 1600.000      //core 1
    cpu MHz        : 2000.000
    cpu MHz        : 2000.000      //core 2
    cpu MHz        : 2300.000
    cpu MHz        : 2300.000      //core 3

Then , i run a openmp test program with 6 threads . (program B)
And monitor the event UNHALTED_CORE_CYCLES of each core using PMU through a Linux module.  

          |    core 0     |        core 1       |        core 2       |       core 3      |
    |thread0 | thread1 |  thread2  | thread3 | thread4  |  thread5 | thread6 | thread7 |
    2294805446 76295634 2294803945 2294804700 2294803738 2294803508 38357212 2294805673
    2294766152 70455048 2294766097 2294766570 2294766156 2294765874 30905408 2294766779
    2294781461 80676090 2294780031 2294780267 2294781153 2294780650 37552709 2294780340
    2294789708 69952866 2294786896 2294786492 2294786812 2294786996 33818385 2294788832
    2294783242 78313422 2294782071 2294782291 2294781417 2294781856 32139270 2294783222
    2294790337 71224453 2294788792 2294789465 2294789916 2294787994 37572423 2294789002
            ^         x         ^          ^          ^           ^        x         ^
   

The problem is that the four cores' frequency are actually the same at 2.3GHz ,instead of 1.2GHz,1.6GHz,2.0GHz and 2.3GHz respectively . I wonder is there a method that can scale each core's frequency at different speeds in a multi-core processor .

/****************************************  program A   *********************************************/

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
const char *convtab[] = {"2301000","2300000","2200000","2100000","2000000","1900000","1800000", "1700000", "1600000", "1500000", "1400000", "1300000", "1200000" };
/***********freq_config**********/
void freq_scale0(int core, int lev)
{
    int fd;
    char file[128];
    sprintf(file, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_setspeed", core);
    fd = open(file, O_RDWR);
    write(fd, convtab[lev], 7);
    close(fd);
}
void freq_scale(int core, int lev)
{
    freq_scale0(core, lev);
}
void freq_mode(int core, const char *mode)
{
    int fd;
    char file[128];
    sprintf(file, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor", core);
    fd = open(file, O_RDWR);
    write(fd, mode, strlen(mode));
    close(fd);
}
int main(int argc, char *argv[])
{
    /* intel i7 3610QM  4 cores  8 threads */
    if(argv[1][0]=='s')
    {
    freq_mode(0, "userspace");
    freq_mode(1, "userspace");
    freq_mode(2, "userspace");
    freq_mode(3, "userspace");
    freq_mode(4, "userspace");
    freq_mode(5, "userspace");
    freq_mode(6, "userspace");
    freq_mode(7, "userspace");
    freq_scale0(0, 12);    //1.2GHz  core 0
    freq_scale0(1, 12);    //1.2GHz  core 0
    freq_scale0(2, 8);    //1.6GHz  core 1
    freq_scale0(3, 8);    //1.6GHz  core 1
    freq_scale0(4, 4);    //2.0GHz  core 2
    freq_scale0(5, 4);    //2.0GHz  core 2
    freq_scale0(6, 1);    //2.3GHz  core 3
    freq_scale0(7, 1);    //2.3GHz  core 3
    }
    else
    {
    freq_mode(0, "ondemand");
    freq_mode(1, "ondemand");
    freq_mode(2, "ondemand");
    freq_mode(3, "ondemand");
    freq_mode(4, "ondemand");
    freq_mode(5, "ondemand");
    freq_mode(6, "ondemand");
    freq_mode(7, "ondemand");
    }
    return 0;
}

/****************************************  program B   *********************************************/

#include <stdio.h>
#include <omp.h>
int main()
{
int i;
int x=1;
omp_set_num_threads(6);//6 of 8 threads 
#pragma    omp parallel for  private(x) schedule(dynamic)
for(i=0;i<1000000000;i++)
    x=x*x+1;
return 0;
}

4 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.
Patrick Fay (Intel)'s picture

Here are the instructions I've used before. I've not tried changing just one core. The instructions look like they require changing all the cpus. That is, if HT is enabled, you probably need to change both cpus on the core.

1.) Is the system capable of software CPU speed control? If the "directory" /sys/devices/system/cpu/cpu0/cpufreq exists, speed is controllable. -- If it does not exist, you need to go to the BIOS and turn on EIST and any other C and P state control and visibility, then reboot

2.) What speed is the box set to now? Do the following:

$ cd /sys/devices/system/cpu
$ cat ./cpu0/cpufreq/cpuinfo_max_freq
3193000
$ cat ./cpu0/cpufreq/cpuinfo_min_freq
1596000

3.) What speeds can I set to? Do
$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies
It will list highest settable to lowest; example from my NHM "Smackover" DX58SO HEDT board, I see:
3193000 3192000 3059000 2926000 2793000 2660000 2527000 2394000 2261000 2128000 1995000 1862000 1729000 159600
You can choose from among those numbers to set the "high water" mark and "low water" mark for speed. If you set "high" and "low" to the same thing, it will run only at that speed.

4.) Show me how to set all to highest settable speed! Use the following little sh/ksh/bash script:
$ cd /sys/devices/system/cpu # a virtual directory made visible by device drivers
$ newSpeedTop=`awk '{print $1}' ./cpu0/cpufreq/scaling_available_frequencies`
$ newSpeedLow=$newSpeedTop  # make them the same in this example
$ for c in ./cpu[0-9]* ; do
>   echo $newSpeedTop > ${c}/cpufreq/scaling_max_freq
>   echo $newSpeedLow >${c}/cpufreq/scaling_min_freq
> done
$

5.) How do I return to the default - i.e. allow machine to vary from highest to lowest? Edit line # 3 of the script above, and re-run it.  Change the line:
$ newSpeedLow=$newSpeedTop  # make them the same in this example
To read
$ newSpeedLow=`awk '{print $NF}' ./cpu0/cpufreq/scaling_available_frequencies`
And then re-run the script.

 Hopefully these instructions give you enough info to resolve your questions.

Pat

Songtao.H's picture

Hi pat,
 Thank you for your reply !

I have tried your method,but the same problem still happens.In fact,every core scales to the same frequency when i scale any one of the eight cores' frequency.

So,i wonder does my processor have the hardware characteristic to scale each core to different frequencies .

Songtao

iliyapolak's picture

could  that be done by writing to this MSR_TURBO_RATIO_LIMIT MSR register?

Login to leave a comment.