Advertisement
Guest User

Untitled

a guest
Sep 20th, 2017
440
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 21.70 KB | None | 0 0
  1. /* Read the RAPL registers on recent (>sandybridge) Intel processors    */
  2. /*                                  */
  3. /* There are currently three ways to do this:               */
  4. /*  1. Read the MSRs directly with /dev/cpu/??/msr          */
  5. /*  2. Use the perf_event_open() interface              */
  6. /*  3. Read the values from the sysfs powercap interface        */
  7. /*                                  */
  8. /* MSR Code originally based on a (never made it upstream) linux-kernel */
  9. /*  RAPL driver by Zhang Rui <rui.zhang@intel.com>          */
  10. /*  https://lkml.org/lkml/2011/5/26/93              */
  11. /* Additional contributions by:                     */
  12. /*  Romain Dolbeau -- romain @ dolbeau.org              */
  13. /*                                  */
  14. /* For raw MSR access the /dev/cpu/??/msr driver must be enabled and    */
  15. /*  permissions set to allow read access.               */
  16. /*  You might need to "modprobe msr" before it will work.       */
  17. /*                                  */
  18. /* perf_event_open() support requires at least Linux 3.14 and to have   */
  19. /*  /proc/sys/kernel/perf_event_paranoid < 1            */
  20. /*                                  */
  21. /* the sysfs powercap interface got into the kernel in          */
  22. /*  2d281d8196e38dd (3.13)                      */
  23. /*                                  */
  24. /* Compile with:   gcc -O2 -Wall -o rapl-read rapl-read.c -lm       */
  25. /*                                  */
  26. /* Vince Weaver -- vincent.weaver @ maine.edu -- 11 September 2015  */
  27. /*                                  */
  28.  
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <sys/types.h>
  32. #include <sys/stat.h>
  33. #include <fcntl.h>
  34. #include <errno.h>
  35. #include <inttypes.h>
  36. #include <unistd.h>
  37. #include <math.h>
  38. #include <string.h>
  39.  
  40. #include <sys/syscall.h>
  41. #include <linux/perf_event.h>
  42.  
  43. #define MSR_RAPL_POWER_UNIT     0x606
  44.  
  45. /*
  46.  * Platform specific RAPL Domains.
  47.  * Note that PP1 RAPL Domain is supported on 062A only
  48.  * And DRAM RAPL Domain is supported on 062D only
  49.  */
  50. /* Package RAPL Domain */
  51. #define MSR_PKG_RAPL_POWER_LIMIT    0x610
  52. #define MSR_PKG_ENERGY_STATUS       0x611
  53. #define MSR_PKG_PERF_STATUS     0x613
  54. #define MSR_PKG_POWER_INFO      0x614
  55.  
  56. /* PP0 RAPL Domain */
  57. #define MSR_PP0_POWER_LIMIT     0x638
  58. #define MSR_PP0_ENERGY_STATUS       0x639
  59. #define MSR_PP0_POLICY          0x63A
  60. #define MSR_PP0_PERF_STATUS     0x63B
  61.  
  62. /* PP1 RAPL Domain, may reflect to uncore devices */
  63. #define MSR_PP1_POWER_LIMIT     0x640
  64. #define MSR_PP1_ENERGY_STATUS       0x641
  65. #define MSR_PP1_POLICY          0x642
  66.  
  67. /* DRAM RAPL Domain */
  68. #define MSR_DRAM_POWER_LIMIT        0x618
  69. #define MSR_DRAM_ENERGY_STATUS      0x619
  70. #define MSR_DRAM_PERF_STATUS        0x61B
  71. #define MSR_DRAM_POWER_INFO     0x61C
  72.  
  73. /* PSYS RAPL Domain */
  74. #define MSR_PLATFORM_ENERGY_STATUS  0x64d
  75.  
  76. /* RAPL UNIT BITMASK */
  77. #define POWER_UNIT_OFFSET   0
  78. #define POWER_UNIT_MASK     0x0F
  79.  
  80. #define ENERGY_UNIT_OFFSET  0x08
  81. #define ENERGY_UNIT_MASK    0x1F00
  82.  
  83. #define TIME_UNIT_OFFSET    0x10
  84. #define TIME_UNIT_MASK      0xF000
  85.  
  86. static int open_msr(int core) {
  87.  
  88.     char msr_filename[BUFSIZ];
  89.     int fd;
  90.  
  91.     sprintf(msr_filename, "/dev/cpu/%d/msr", core);
  92.     fd = open(msr_filename, O_RDONLY);
  93.     if ( fd < 0 ) {
  94.         if ( errno == ENXIO ) {
  95.             fprintf(stderr, "rdmsr: No CPU %d\n", core);
  96.             exit(2);
  97.         } else if ( errno == EIO ) {
  98.             fprintf(stderr, "rdmsr: CPU %d doesn't support MSRs\n",
  99.                     core);
  100.             exit(3);
  101.         } else {
  102.             perror("rdmsr:open");
  103.             fprintf(stderr,"Trying to open %s\n",msr_filename);
  104.             exit(127);
  105.         }
  106.     }
  107.  
  108.     return fd;
  109. }
  110.  
  111. static long long read_msr(int fd, int which) {
  112.  
  113.     uint64_t data;
  114.  
  115.     if ( pread(fd, &data, sizeof data, which) != sizeof data ) {
  116.         perror("rdmsr:pread");
  117.         exit(127);
  118.     }
  119.  
  120.     return (long long)data;
  121. }
  122.  
  123. #define CPU_SANDYBRIDGE     42
  124. #define CPU_SANDYBRIDGE_EP  45
  125. #define CPU_IVYBRIDGE       58
  126. #define CPU_IVYBRIDGE_EP    62
  127. #define CPU_HASWELL     60  // 69,70 too?
  128. #define CPU_HASWELL_EP      63
  129. #define CPU_BROADWELL       61  // 71 too?
  130. #define CPU_BROADWELL_EP    79
  131. #define CPU_BROADWELL_DE    86
  132. #define CPU_SKYLAKE     78
  133. #define CPU_SKYLAKE_HS      94
  134. #define CPU_KNIGHTS_LANDING 87
  135. #define CPU_KABYLAKE        142
  136. #define CPU_KABYLAKE_2      158
  137.  
  138.  
  139. /* TODO: on Skylake, also may support  PSys "platform" domain,  */
  140. /* the whole SoC not just the package.              */
  141. /* see dcee75b3b7f025cc6765e6c92ba0a4e59a4d25f4         */
  142.  
  143. static int detect_cpu(void) {
  144.  
  145.     FILE *fff;
  146.  
  147.     int family,model=-1;
  148.     char buffer[BUFSIZ],*result;
  149.     char vendor[BUFSIZ];
  150.  
  151.     fff=fopen("/proc/cpuinfo","r");
  152.     if (fff==NULL) return -1;
  153.  
  154.     while(1) {
  155.         result=fgets(buffer,BUFSIZ,fff);
  156.         if (result==NULL) break;
  157.  
  158.         if (!strncmp(result,"vendor_id",8)) {
  159.             sscanf(result,"%*s%*s%s",vendor);
  160.  
  161.             if (strncmp(vendor,"GenuineIntel",12)) {
  162.                 printf("%s not an Intel chip\n",vendor);
  163.                 return -1;
  164.             }
  165.         }
  166.  
  167.         if (!strncmp(result,"cpu family",10)) {
  168.             sscanf(result,"%*s%*s%*s%d",&family);
  169.             if (family!=6) {
  170.                 printf("Wrong CPU family %d\n",family);
  171.                 return -1;
  172.             }
  173.         }
  174.  
  175.         if (!strncmp(result,"model",5)) {
  176.             sscanf(result,"%*s%*s%d",&model);
  177.         }
  178.  
  179.     }
  180.  
  181.     fclose(fff);
  182.  
  183.     printf("Found ");
  184.  
  185.     switch(model) {
  186.         case CPU_SANDYBRIDGE:
  187.             printf("Sandybridge");
  188.             break;
  189.         case CPU_SANDYBRIDGE_EP:
  190.             printf("Sandybridge-EP");
  191.             break;
  192.         case CPU_IVYBRIDGE:
  193.             printf("Ivybridge");
  194.             break;
  195.         case CPU_IVYBRIDGE_EP:
  196.             printf("Ivybridge-EP");
  197.             break;
  198.         case CPU_HASWELL:
  199.             printf("Haswell");
  200.             break;
  201.         case CPU_HASWELL_EP:
  202.             printf("Haswell-EP");
  203.             break;
  204.         case CPU_BROADWELL:
  205.             printf("Broadwell");
  206.             break;
  207.         case CPU_SKYLAKE:
  208.         case CPU_SKYLAKE_HS:
  209.             printf("Skylake");
  210.             break;
  211.         case CPU_KABYLAKE:
  212.         case CPU_KABYLAKE_2:
  213.             printf("Kaby Lake");
  214.             break;
  215.         case CPU_KNIGHTS_LANDING:
  216.             printf("Knight's Landing");
  217.             break;
  218.         default:
  219.             printf("Unsupported model %d\n",model);
  220.             model=-1;
  221.             break;
  222.     }
  223.  
  224.     printf(" Processor type\n");
  225.  
  226.     return model;
  227. }
  228.  
  229. #define MAX_CPUS    1024
  230. #define MAX_PACKAGES    16
  231.  
  232. static int total_cores=0,total_packages=0;
  233. static int package_map[MAX_PACKAGES];
  234.  
  235. static int detect_packages(void) {
  236.  
  237.     char filename[BUFSIZ];
  238.     FILE *fff;
  239.     int package;
  240.     int i;
  241.  
  242.     for(i=0;i<MAX_PACKAGES;i++) package_map[i]=-1;
  243.  
  244.     printf("\t");
  245.     for(i=0;i<MAX_CPUS;i++) {
  246.         sprintf(filename,"/sys/devices/system/cpu/cpu%d/topology/physical_package_id",i);
  247.         fff=fopen(filename,"r");
  248.         if (fff==NULL) break;
  249.         fscanf(fff,"%d",&package);
  250.         printf("%d (%d)",i,package);
  251.         if (i%8==7) printf("\n\t"); else printf(", ");
  252.         fclose(fff);
  253.  
  254.         if (package_map[package]==-1) {
  255.             total_packages++;
  256.             package_map[package]=i;
  257.         }
  258.  
  259.     }
  260.  
  261.     printf("\n");
  262.  
  263.     total_cores=i;
  264.  
  265.     printf("\tDetected %d cores in %d packages\n\n",
  266.         total_cores,total_packages);
  267.  
  268.     return 0;
  269. }
  270.  
  271.  
  272. /*******************************/
  273. /* MSR code                    */
  274. /*******************************/
  275. static int rapl_msr(int core, int cpu_model) {
  276.  
  277.     int fd;
  278.     long long result;
  279.     double power_units,time_units;
  280.     double cpu_energy_units[MAX_PACKAGES],dram_energy_units[MAX_PACKAGES];
  281.     double package_before[MAX_PACKAGES],package_after[MAX_PACKAGES];
  282.     double pp0_before[MAX_PACKAGES],pp0_after[MAX_PACKAGES];
  283.     double pp1_before[MAX_PACKAGES],pp1_after[MAX_PACKAGES];
  284.     double dram_before[MAX_PACKAGES],dram_after[MAX_PACKAGES];
  285.     double psys_before[MAX_PACKAGES],psys_after[MAX_PACKAGES];
  286.     double thermal_spec_power,minimum_power,maximum_power,time_window;
  287.     int j;
  288.  
  289.     printf("\nTrying /dev/msr interface to gather results\n\n");
  290.  
  291.     if (cpu_model<0) {
  292.         printf("\tUnsupported CPU model %d\n",cpu_model);
  293.         return -1;
  294.     }
  295.  
  296.     for(j=0;j<total_packages;j++) {
  297.         printf("\tListing paramaters for package #%d\n",j);
  298.  
  299.         fd=open_msr(package_map[j]);
  300.  
  301.         /* Calculate the units used */
  302.         result=read_msr(fd,MSR_RAPL_POWER_UNIT);
  303.  
  304.         power_units=pow(0.5,(double)(result&0xf));
  305.         cpu_energy_units[j]=pow(0.5,(double)((result>>8)&0x1f));
  306.         time_units=pow(0.5,(double)((result>>16)&0xf));
  307.  
  308.         /* On Haswell EP and Knights Landing */
  309.         /* The DRAM units differ from the CPU ones */
  310.         if ((cpu_model==CPU_HASWELL_EP) ||
  311.                     (cpu_model==CPU_KNIGHTS_LANDING)) {
  312.             dram_energy_units[j]=pow(0.5,(double)16);
  313.         }
  314.         else {
  315.             dram_energy_units[j]=cpu_energy_units[j];
  316.         }
  317.  
  318.         printf("\t\tPower units = %.3fW\n",power_units);
  319.         printf("\t\tCPU Energy units = %.8fJ\n",cpu_energy_units[j]);
  320.         printf("\t\tDRAM Energy units = %.8fJ\n",dram_energy_units[j]);
  321.         printf("\t\tTime units = %.8fs\n",time_units);
  322.         printf("\n");
  323.  
  324.         /* Show package power info */
  325.         result=read_msr(fd,MSR_PKG_POWER_INFO);
  326.         thermal_spec_power=power_units*(double)(result&0x7fff);
  327.         printf("\t\tPackage thermal spec: %.3fW\n",thermal_spec_power);
  328.         minimum_power=power_units*(double)((result>>16)&0x7fff);
  329.         printf("\t\tPackage minimum power: %.3fW\n",minimum_power);
  330.         maximum_power=power_units*(double)((result>>32)&0x7fff);
  331.         printf("\t\tPackage maximum power: %.3fW\n",maximum_power);
  332.         time_window=time_units*(double)((result>>48)&0x7fff);
  333.         printf("\t\tPackage maximum time window: %.6fs\n",time_window);
  334.  
  335.         /* Show package power limit */
  336.         result=read_msr(fd,MSR_PKG_RAPL_POWER_LIMIT);
  337.         printf("\t\tPackage power limits are %s\n", (result >> 63) ? "locked" : "unlocked");
  338.         double pkg_power_limit_1 = power_units*(double)((result>>0)&0x7FFF);
  339.         double pkg_time_window_1 = time_units*(double)((result>>17)&0x007F);
  340.         printf("\t\tPackage power limit #1: %.3fW for %.6fs (%s, %s)\n",
  341.             pkg_power_limit_1, pkg_time_window_1,
  342.             (result & (1LL<<15)) ? "enabled" : "disabled",
  343.             (result & (1LL<<16)) ? "clamped" : "not_clamped");
  344.         double pkg_power_limit_2 = power_units*(double)((result>>32)&0x7FFF);
  345.         double pkg_time_window_2 = time_units*(double)((result>>49)&0x007F);
  346.         printf("\t\tPackage power limit #2: %.3fW for %.6fs (%s, %s)\n",
  347.             pkg_power_limit_2, pkg_time_window_2,
  348.             (result & (1LL<<47)) ? "enabled" : "disabled",
  349.             (result & (1LL<<48)) ? "clamped" : "not_clamped");
  350.  
  351.         /* only available on *Bridge-EP */
  352.         if ((cpu_model==CPU_SANDYBRIDGE_EP) || (cpu_model==CPU_IVYBRIDGE_EP)) {
  353.             result=read_msr(fd,MSR_PKG_PERF_STATUS);
  354.             double acc_pkg_throttled_time=(double)result*time_units;
  355.             printf("\tAccumulated Package Throttled Time : %.6fs\n",
  356.                 acc_pkg_throttled_time);
  357.         }
  358.  
  359.         /* only available on *Bridge-EP */
  360.         if ((cpu_model==CPU_SANDYBRIDGE_EP) || (cpu_model==CPU_IVYBRIDGE_EP)) {
  361.             result=read_msr(fd,MSR_PP0_PERF_STATUS);
  362.             double acc_pp0_throttled_time=(double)result*time_units;
  363.             printf("\tPowerPlane0 (core) Accumulated Throttled Time "
  364.                 ": %.6fs\n",acc_pp0_throttled_time);
  365.  
  366.             result=read_msr(fd,MSR_PP0_POLICY);
  367.             int pp0_policy=(int)result&0x001f;
  368.             printf("\tPowerPlane0 (core) for core %d policy: %d\n",core,pp0_policy);
  369.  
  370.         }
  371.  
  372.  
  373.         if ((cpu_model==CPU_SANDYBRIDGE) || (cpu_model==CPU_IVYBRIDGE) ||
  374.             (cpu_model==CPU_HASWELL) || (cpu_model==CPU_BROADWELL)) {
  375.  
  376.             result=read_msr(fd,MSR_PP1_POLICY);
  377.             int pp1_policy=(int)result&0x001f;
  378.             printf("\tPowerPlane1 (on-core GPU if avail) %d policy: %d\n",
  379.                 core,pp1_policy);
  380.         }
  381.         close(fd);
  382.  
  383.     }
  384.     printf("\n");
  385.  
  386.     for(j=0;j<total_packages;j++) {
  387.  
  388.         fd=open_msr(package_map[j]);
  389.  
  390.         /* Package Energy */
  391.         result=read_msr(fd,MSR_PKG_ENERGY_STATUS);
  392.         package_before[j]=(double)result*cpu_energy_units[j];
  393.  
  394.         /* PP0 energy */
  395.         /* Not available on Haswell-EP? */
  396.         result=read_msr(fd,MSR_PP0_ENERGY_STATUS);
  397.         pp0_before[j]=(double)result*cpu_energy_units[j];
  398.  
  399.         /* PP1 energy */
  400.         /* not available on *Bridge-EP */
  401.         if ((cpu_model==CPU_SANDYBRIDGE) || (cpu_model==CPU_IVYBRIDGE) ||
  402.             (cpu_model==CPU_HASWELL) || (cpu_model==CPU_BROADWELL) ||
  403.             (cpu_model==CPU_SKYLAKE) || (cpu_model==CPU_SKYLAKE_HS) ||
  404.             (cpu_model==CPU_KABYLAKE) || (cpu_model==CPU_KABYLAKE_2)) {
  405.  
  406.             result=read_msr(fd,MSR_PP1_ENERGY_STATUS);
  407.             pp1_before[j]=(double)result*cpu_energy_units[j];
  408.         }
  409.  
  410.  
  411.         /* Updated documentation (but not the Vol3B) says Haswell and   */
  412.         /* Broadwell have DRAM support too              */
  413.         if ((cpu_model==CPU_SANDYBRIDGE_EP) || (cpu_model==CPU_IVYBRIDGE_EP) ||
  414.             (cpu_model==CPU_HASWELL_EP) ||
  415.             (cpu_model==CPU_HASWELL) || (cpu_model==CPU_BROADWELL) ||
  416.             (cpu_model==CPU_SKYLAKE) || (cpu_model==CPU_SKYLAKE_HS) ||
  417.             (cpu_model==CPU_KABYLAKE) || (cpu_model==CPU_KABYLAKE_2)) {
  418.  
  419.             result=read_msr(fd,MSR_DRAM_ENERGY_STATUS);
  420.             dram_before[j]=(double)result*dram_energy_units[j];
  421.         }
  422.  
  423.  
  424.         /* Skylake and newer for Psys               */
  425.         if ((cpu_model==CPU_SKYLAKE) || (cpu_model==CPU_SKYLAKE_HS) ||
  426.             (cpu_model==CPU_KABYLAKE) || (cpu_model==CPU_KABYLAKE_2)) {
  427.  
  428.             result=read_msr(fd,MSR_PLATFORM_ENERGY_STATUS);
  429.             psys_before[j]=(double)result*cpu_energy_units[j];
  430.         }
  431.  
  432.         close(fd);
  433.     }
  434.  
  435.     printf("\n\tSleeping 1 second\n\n");
  436.     sleep(1);
  437.  
  438.     for(j=0;j<total_packages;j++) {
  439.  
  440.         fd=open_msr(package_map[j]);
  441.  
  442.         printf("\tPackage %d:\n",j);
  443.  
  444.         result=read_msr(fd,MSR_PKG_ENERGY_STATUS);
  445.         package_after[j]=(double)result*cpu_energy_units[j];
  446.         printf("\t\tPackage energy: %.6fJ\n",
  447.             package_after[j]-package_before[j]);
  448.  
  449.         result=read_msr(fd,MSR_PP0_ENERGY_STATUS);
  450.         pp0_after[j]=(double)result*cpu_energy_units[j];
  451.         printf("\t\tPowerPlane0 (cores): %.6fJ\n",
  452.             pp0_after[j]-pp0_before[j]);
  453.  
  454.         /* not available on SandyBridge-EP */
  455.         if ((cpu_model==CPU_SANDYBRIDGE) || (cpu_model==CPU_IVYBRIDGE) ||
  456.             (cpu_model==CPU_HASWELL) || (cpu_model==CPU_BROADWELL) ||
  457.             (cpu_model==CPU_SKYLAKE) || (cpu_model==CPU_SKYLAKE_HS) ||
  458.             (cpu_model==CPU_KABYLAKE) || (cpu_model==CPU_KABYLAKE_2)) {
  459.  
  460.  
  461.             result=read_msr(fd,MSR_PP1_ENERGY_STATUS);
  462.             pp1_after[j]=(double)result*cpu_energy_units[j];
  463.             printf("\t\tPowerPlane1 (on-core GPU if avail): %.6f J\n",
  464.                 pp1_after[j]-pp1_before[j]);
  465.         }
  466.  
  467.         if ((cpu_model==CPU_SANDYBRIDGE_EP) || (cpu_model==CPU_IVYBRIDGE_EP) ||
  468.             (cpu_model==CPU_HASWELL_EP) ||
  469.             (cpu_model==CPU_HASWELL) || (cpu_model==CPU_BROADWELL) ||
  470.             (cpu_model==CPU_SKYLAKE) || (cpu_model==CPU_SKYLAKE_HS) ||
  471.             (cpu_model==CPU_KABYLAKE) || (cpu_model==CPU_KABYLAKE_2)) {
  472.  
  473.  
  474.             result=read_msr(fd,MSR_DRAM_ENERGY_STATUS);
  475.             dram_after[j]=(double)result*dram_energy_units[j];
  476.             printf("\t\tDRAM: %.6fJ\n",
  477.                 dram_after[j]-dram_before[j]);
  478.         }
  479.  
  480.         if ((cpu_model==CPU_SKYLAKE) || (cpu_model==CPU_SKYLAKE_HS) ||
  481.             (cpu_model==CPU_KABYLAKE) || (cpu_model==CPU_KABYLAKE_2)) {
  482.  
  483.  
  484.             result=read_msr(fd,MSR_PLATFORM_ENERGY_STATUS);
  485.             psys_after[j]=(double)result*cpu_energy_units[j];
  486.             printf("\t\tPSYS: %.6fJ\n",
  487.                 psys_after[j]-psys_before[j]);
  488.         }
  489.  
  490.         close(fd);
  491.     }
  492.     printf("\n");
  493.     printf("Note: the energy measurements can overflow in 60s or so\n");
  494.     printf("      so try to sample the counters more often than that.\n\n");
  495.  
  496.     return 0;
  497. }
  498.  
  499. static int perf_event_open(struct perf_event_attr *hw_event_uptr,
  500.                     pid_t pid, int cpu, int group_fd, unsigned long flags) {
  501.  
  502.         return syscall(__NR_perf_event_open,hw_event_uptr, pid, cpu,
  503.                         group_fd, flags);
  504. }
  505.  
  506. #define NUM_RAPL_DOMAINS    5
  507.  
  508. char rapl_domain_names[NUM_RAPL_DOMAINS][30]= {
  509.     "energy-cores",
  510.     "energy-gpu",
  511.     "energy-pkg",
  512.     "energy-ram",
  513.     "energy-psys",
  514. };
  515.  
  516.  
  517. static int check_paranoid(void) {
  518.  
  519.     int paranoid_value;
  520.     FILE *fff;
  521.  
  522.     fff=fopen("/proc/sys/kernel/perf_event_paranoid","r");
  523.     if (fff==NULL) {
  524.         fprintf(stderr,"Error! could not open /proc/sys/kernel/perf_event_paranoid %s\n",
  525.             strerror(errno));
  526.  
  527.         /* We can't return a negative value as that implies no paranoia */
  528.         return 500;
  529.     }
  530.  
  531.     fscanf(fff,"%d",&paranoid_value);
  532.     fclose(fff);
  533.  
  534.     return paranoid_value;
  535.  
  536. }
  537.  
  538. static int rapl_perf(int core) {
  539.  
  540.     FILE *fff;
  541.     int type;
  542.     int config[NUM_RAPL_DOMAINS];
  543.     char units[NUM_RAPL_DOMAINS][BUFSIZ];
  544.     char filename[BUFSIZ];
  545.     int fd[NUM_RAPL_DOMAINS][MAX_PACKAGES];
  546.     double scale[NUM_RAPL_DOMAINS];
  547.     struct perf_event_attr attr;
  548.     long long value;
  549.     int i,j;
  550.     int paranoid_value;
  551.  
  552.     printf("\nTrying perf_event interface to gather results\n\n");
  553.  
  554.     fff=fopen("/sys/bus/event_source/devices/power/type","r");
  555.     if (fff==NULL) {
  556.         printf("\tNo perf_event rapl support found (requires Linux 3.14)\n");
  557.         printf("\tFalling back to raw msr support\n\n");
  558.         return -1;
  559.     }
  560.     fscanf(fff,"%d",&type);
  561.     fclose(fff);
  562.  
  563.     for(i=0;i<NUM_RAPL_DOMAINS;i++) {
  564.  
  565.         sprintf(filename,"/sys/bus/event_source/devices/power/events/%s",
  566.             rapl_domain_names[i]);
  567.  
  568.         fff=fopen(filename,"r");
  569.  
  570.         if (fff!=NULL) {
  571.             fscanf(fff,"event=%x",&config[i]);
  572.             printf("\tEvent=%s Config=%d ",rapl_domain_names[i],config[i]);
  573.             fclose(fff);
  574.         } else {
  575.             continue;
  576.         }
  577.  
  578.         sprintf(filename,"/sys/bus/event_source/devices/power/events/%s.scale",
  579.             rapl_domain_names[i]);
  580.         fff=fopen(filename,"r");
  581.  
  582.         if (fff!=NULL) {
  583.             fscanf(fff,"%lf",&scale[i]);
  584.             printf("scale=%g ",scale[i]);
  585.             fclose(fff);
  586.         }
  587.  
  588.         sprintf(filename,"/sys/bus/event_source/devices/power/events/%s.unit",
  589.             rapl_domain_names[i]);
  590.         fff=fopen(filename,"r");
  591.  
  592.         if (fff!=NULL) {
  593.             fscanf(fff,"%s",units[i]);
  594.             printf("units=%s ",units[i]);
  595.             fclose(fff);
  596.         }
  597.  
  598.         printf("\n");
  599.     }
  600.  
  601.     for(j=0;j<total_packages;j++) {
  602.  
  603.         for(i=0;i<NUM_RAPL_DOMAINS;i++) {
  604.  
  605.             fd[i][j]=-1;
  606.  
  607.             memset(&attr,0x0,sizeof(attr));
  608.             attr.type=type;
  609.             attr.config=config[i];
  610.             if (config[i]==0) continue;
  611.  
  612.             fd[i][j]=perf_event_open(&attr,-1, package_map[j],-1,0);
  613.             if (fd[i][j]<0) {
  614.                 if (errno==EACCES) {
  615.                     paranoid_value=check_paranoid();
  616.                     if (paranoid_value>0) {
  617.                         printf("\t/proc/sys/kernel/perf_event_paranoid is %d\n",paranoid_value);
  618.                         printf("\tThe value must be 0 or lower to read system-wide RAPL values\n");
  619.                     }
  620.  
  621.                     printf("\tPermission denied; run as root or adjust paranoid value\n\n");
  622.                     return -1;
  623.                 }
  624.                 else {
  625.                     printf("\terror opening core %d config %d: %s\n\n",
  626.                         package_map[j], config[i], strerror(errno));
  627.                     return -1;
  628.                 }
  629.             }
  630.         }
  631.     }
  632.  
  633.     printf("\n\tSleeping 1 second\n\n");
  634.     sleep(1);
  635.  
  636.     for(j=0;j<total_packages;j++) {
  637.         printf("\tPackage %d:\n",j);
  638.  
  639.         for(i=0;i<NUM_RAPL_DOMAINS;i++) {
  640.  
  641.             if (fd[i][j]!=-1) {
  642.                 read(fd[i][j],&value,8);
  643.                 close(fd[i][j]);
  644.  
  645.                 printf("\t\t%s Energy Consumed: %lf %s\n",
  646.                     rapl_domain_names[i],
  647.                     (double)value*scale[i],
  648.                     units[i]);
  649.  
  650.             }
  651.  
  652.         }
  653.  
  654.     }
  655.     printf("\n");
  656.  
  657.     return 0;
  658. }
  659.  
  660. static int rapl_sysfs(int core) {
  661.  
  662.     char event_names[MAX_PACKAGES][NUM_RAPL_DOMAINS][256];
  663.     char filenames[MAX_PACKAGES][NUM_RAPL_DOMAINS][256];
  664.     char basename[MAX_PACKAGES][256];
  665.     char tempfile[256];
  666.     long long before[MAX_PACKAGES][NUM_RAPL_DOMAINS];
  667.     long long after[MAX_PACKAGES][NUM_RAPL_DOMAINS];
  668.     int valid[MAX_PACKAGES][NUM_RAPL_DOMAINS];
  669.     int i,j;
  670.     FILE *fff;
  671.  
  672.     printf("\nTrying sysfs powercap interface to gather results\n\n");
  673.  
  674.     /* /sys/class/powercap/intel-rapl/intel-rapl:0/ */
  675.     /* name has name */
  676.     /* energy_uj has energy */
  677.     /* subdirectories intel-rapl:0:0 intel-rapl:0:1 intel-rapl:0:2 */
  678.  
  679.     for(j=0;j<total_packages;j++) {
  680.         i=0;
  681.         sprintf(basename[j],"/sys/class/powercap/intel-rapl/intel-rapl:%d",
  682.             j);
  683.         sprintf(tempfile,"%s/name",basename[j]);
  684.         fff=fopen(tempfile,"r");
  685.         if (fff==NULL) {
  686.             fprintf(stderr,"\tCould not open %s\n",tempfile);
  687.             return -1;
  688.         }
  689.         fscanf(fff,"%s",event_names[j][i]);
  690.         valid[j][i]=1;
  691.         fclose(fff);
  692.         sprintf(filenames[j][i],"%s/energy_uj",basename[j]);
  693.  
  694.         /* Handle subdomains */
  695.         for(i=1;i<NUM_RAPL_DOMAINS;i++) {
  696.             sprintf(tempfile,"%s/intel-rapl:%d:%d/name",
  697.                 basename[j],j,i-1);
  698.             fff=fopen(tempfile,"r");
  699.             if (fff==NULL) {
  700.                 //fprintf(stderr,"\tCould not open %s\n",tempfile);
  701.                 valid[j][i]=0;
  702.                 continue;
  703.             }
  704.             valid[j][i]=1;
  705.             fscanf(fff,"%s",event_names[j][i]);
  706.             fclose(fff);
  707.             sprintf(filenames[j][i],"%s/intel-rapl:%d:%d/energy_uj",
  708.                 basename[j],j,i-1);
  709.  
  710.         }
  711.     }
  712.  
  713.     /* Gather before values */
  714.     for(j=0;j<total_packages;j++) {
  715.         for(i=0;i<NUM_RAPL_DOMAINS;i++) {
  716.             if (valid[j][i]) {
  717.                 fff=fopen(filenames[j][i],"r");
  718.                 if (fff==NULL) {
  719.                     fprintf(stderr,"\tError opening %s!\n",filenames[j][i]);
  720.                 }
  721.                 else {
  722.                     fscanf(fff,"%lld",&before[j][i]);
  723.                     fclose(fff);
  724.                 }
  725.             }
  726.         }
  727.     }
  728.  
  729.     printf("\tSleeping 1 second\n\n");
  730.     sleep(1);
  731.  
  732.     /* Gather after values */
  733.     for(j=0;j<total_packages;j++) {
  734.         for(i=0;i<NUM_RAPL_DOMAINS;i++) {
  735.             if (valid[j][i]) {
  736.                 fff=fopen(filenames[j][i],"r");
  737.                 if (fff==NULL) {
  738.                     fprintf(stderr,"\tError opening %s!\n",filenames[j][i]);
  739.                 }
  740.                 else {
  741.                     fscanf(fff,"%lld",&after[j][i]);
  742.                     fclose(fff);
  743.                 }
  744.             }
  745.         }
  746.     }
  747.  
  748.     for(j=0;j<total_packages;j++) {
  749.         printf("\tPackage %d\n",j);
  750.         for(i=0;i<NUM_RAPL_DOMAINS;i++) {
  751.             if (valid[j][i]) {
  752.                 printf("\t\t%s\t: %lfJ\n",event_names[j][i],
  753.                     ((double)after[j][i]-(double)before[j][i])/1000000.0);
  754.             }
  755.         }
  756.     }
  757.     printf("\n");
  758.  
  759.     return 0;
  760.  
  761. }
  762.  
  763. int main(int argc, char **argv) {
  764.  
  765.     int c;
  766.     int force_msr=0,force_perf_event=0,force_sysfs=0;
  767.     int core=0;
  768.     int result=-1;
  769.     int cpu_model;
  770.  
  771.     printf("\n");
  772.     printf("RAPL read -- use -s for sysfs, -p for perf_event, -m for msr\n\n");
  773.  
  774.     opterr=0;
  775.  
  776.     while ((c = getopt (argc, argv, "c:hmps")) != -1) {
  777.         switch (c) {
  778.         case 'c':
  779.             core = atoi(optarg);
  780.             break;
  781.         case 'h':
  782.             printf("Usage: %s [-c core] [-h] [-m]\n\n",argv[0]);
  783.             printf("\t-c core : specifies which core to measure\n");
  784.             printf("\t-h      : displays this help\n");
  785.             printf("\t-m      : forces use of MSR mode\n");
  786.             printf("\t-p      : forces use of perf_event mode\n");
  787.             printf("\t-s      : forces use of sysfs mode\n");
  788.             exit(0);
  789.         case 'm':
  790.             force_msr = 1;
  791.             break;
  792.         case 'p':
  793.             force_perf_event = 1;
  794.             break;
  795.         case 's':
  796.             force_sysfs = 1;
  797.             break;
  798.         default:
  799.             fprintf(stderr,"Unknown option %c\n",c);
  800.             exit(-1);
  801.         }
  802.     }
  803.  
  804.     (void)force_sysfs;
  805.  
  806.     cpu_model=detect_cpu();
  807.     detect_packages();
  808.  
  809.     if ((!force_msr) && (!force_perf_event)) {
  810.         result=rapl_sysfs(core);
  811.     }
  812.  
  813.     if (result<0) {
  814.         if ((force_perf_event) && (!force_msr)) {
  815.             result=rapl_perf(core);
  816.         }
  817.     }
  818.  
  819.     if (result<0) {
  820.         result=rapl_msr(core,cpu_model);
  821.     }
  822.  
  823.     if (result<0) {
  824.  
  825.         printf("Unable to read RAPL counters.\n");
  826.         printf("* Verify you have an Intel Sandybridge or newer processor\n");
  827.         printf("* You may need to run as root or have /proc/sys/kernel/perf_event_paranoid set properly\n");
  828.         printf("* If using raw msr access, make sure msr module is installed\n");
  829.         printf("\n");
  830.  
  831.         return -1;
  832.  
  833.     }
  834.  
  835.     return 0;
  836. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement