Print total cache sizes (for L1 and L2, but also for L3 in case we run in dual socket!)

This commit is contained in:
Dr-Noob
2020-06-28 12:47:03 +02:00
parent 92992be225
commit 131d860de6
5 changed files with 133 additions and 80 deletions

View File

@@ -8,24 +8,29 @@
#include "global.h" #include "global.h"
/*** /***
SAMPLE OUTPUT ################
####### #######
Name: Intel Core i7-4790K #### ####
Frequency: 4.0 GHz ### ####
NºCores: 4 cores(8 threads) ### ### Name: Intel(R) Xeon(R) CPU E5-2698 v4 @ 2.20GHz
AXV: AVX,AVX2 ### ### Sockets: 2
SSE: SSE,SSE2,SSE4.1,SSE4.2 Cores: 20 (40 threads)
FMA: FMA3 Frequency: 3.60 GHz
AES: Yes ## ### ######### ###### ###### ### ### AVX: AVX,AVX2
SHA: No ## ### ### ### ### #### #### ### ### SSE: SSE,SSE2,SSE3,SSSE3,SSE4_1,SSE4_2
L1 Size: 32KB(Data)32KB(Instructions) ## ### ### ### ### ### ### ### ### FMA: FMA3
L2 Size: 512KB ## ## ### ### ##### ######### ## ### L1d Size: 32KB (1MB Total)
L3 Size: 8MB ## ## L1i Size: 32KB (1MB Total)
Peak FLOPS: 512 GFLOP/s(in simple precision) ### L2 Size: 256KB (4MB Total)
### L3 Size: 50M (100MB Total)
#### #### Peak Perf.: 2.30 TFLOP/s
##### ##########
########## ################
###############################
***/ ***/
static const char* VERSION = "0.410"; static const char* VERSION = "0.411";
void print_help(char *argv[]) { void print_help(char *argv[]) {
printf("Usage: %s [--version] [--help] [--style STYLE]\n\ printf("Usage: %s [--version] [--help] [--style STYLE]\n\
@@ -94,9 +99,10 @@ int main(int argc, char* argv[]) {
char* fma = get_str_fma(cpu); char* fma = get_str_fma(cpu);
char* aes = get_str_aes(cpu); char* aes = get_str_aes(cpu);
char* sha = get_str_sha(cpu); char* sha = get_str_sha(cpu);
char* l1 = get_str_l1(cach); char* l1i = get_str_l1i(cach, topo);
char* l2 = get_str_l2(cach); char* l1d = get_str_l1d(cach, topo);
char* l3 = get_str_l3(cach); char* l2 = get_str_l2(cach, topo);
char* l3 = get_str_l3(cach, topo);
char* pp = get_str_peak_performance(cpu,topo,get_freq(freq)); char* pp = get_str_peak_performance(cpu,topo,get_freq(freq));
setAttribute(art,ATTRIBUTE_NAME,cpuName); setAttribute(art,ATTRIBUTE_NAME,cpuName);
@@ -107,7 +113,8 @@ int main(int argc, char* argv[]) {
setAttribute(art,ATTRIBUTE_FMA,fma); setAttribute(art,ATTRIBUTE_FMA,fma);
setAttribute(art,ATTRIBUTE_AES,aes); setAttribute(art,ATTRIBUTE_AES,aes);
setAttribute(art,ATTRIBUTE_SHA,sha); setAttribute(art,ATTRIBUTE_SHA,sha);
setAttribute(art,ATTRIBUTE_L1,l1); setAttribute(art,ATTRIBUTE_L1i,l1i);
setAttribute(art,ATTRIBUTE_L1d,l1d);
setAttribute(art,ATTRIBUTE_L2,l2); setAttribute(art,ATTRIBUTE_L2,l2);
setAttribute(art,ATTRIBUTE_L3,l3); setAttribute(art,ATTRIBUTE_L3,l3);
setAttribute(art,ATTRIBUTE_PEAK,pp); setAttribute(art,ATTRIBUTE_PEAK,pp);
@@ -122,7 +129,8 @@ int main(int argc, char* argv[]) {
free(fma); free(fma);
free(aes); free(aes);
free(sha); free(sha);
free(l1); free(l1i);
free(l1d);
free(l2); free(l2);
free(l3); free(l3);
free(pp); free(pp);

View File

@@ -26,25 +26,26 @@
#define TITLE_FMA "FMA: " #define TITLE_FMA "FMA: "
#define TITLE_AES "AES: " #define TITLE_AES "AES: "
#define TITLE_SHA "SHA: " #define TITLE_SHA "SHA: "
#define TITLE_L1 "L1 Size: " #define TITLE_L1i "L1i Size: "
#define TITLE_L1d "L1d Size: "
#define TITLE_L2 "L2 Size: " #define TITLE_L2 "L2 Size: "
#define TITLE_L3 "L3 Size: " #define TITLE_L3 "L3 Size: "
#define TITLE_PEAK "Peak FLOPS: " #define TITLE_PEAK "Peak FLOPS: "
/*** CENTER TEXT ***/ /*** CENTER TEXT ***/
#define LINES_SPACE_UP 4 #define LINES_SPACE_UP 3
#define LINES_SPACE_DOWN 4 #define LINES_SPACE_DOWN 4
static const char* ATTRIBUTE_FIELDS [ATTRIBUTE_COUNT] = { TITLE_NAME, TITLE_FREQUENCY, static const char* ATTRIBUTE_FIELDS [ATTRIBUTE_COUNT] = { TITLE_NAME, TITLE_FREQUENCY,
TITLE_NCORES, TITLE_AVX, TITLE_SSE, TITLE_NCORES, TITLE_AVX, TITLE_SSE,
TITLE_FMA, TITLE_AES, TITLE_SHA, TITLE_FMA, TITLE_AES, TITLE_SHA,
TITLE_L1, TITLE_L2, TITLE_L3, TITLE_L1i, TITLE_L1d, TITLE_L2, TITLE_L3,
TITLE_PEAK }; TITLE_PEAK };
static const int ATTRIBUTE_LIST[ATTRIBUTE_COUNT] = { ATTRIBUTE_NAME, ATTRIBUTE_FREQUENCY, static const int ATTRIBUTE_LIST[ATTRIBUTE_COUNT] = { ATTRIBUTE_NAME, ATTRIBUTE_FREQUENCY,
ATTRIBUTE_NCORES, ATTRIBUTE_AVX, ATTRIBUTE_SSE, ATTRIBUTE_NCORES, ATTRIBUTE_AVX, ATTRIBUTE_SSE,
ATTRIBUTE_FMA, ATTRIBUTE_AES, ATTRIBUTE_SHA, ATTRIBUTE_FMA, ATTRIBUTE_AES, ATTRIBUTE_SHA,
ATTRIBUTE_L1, ATTRIBUTE_L2, ATTRIBUTE_L3, ATTRIBUTE_L1i, ATTRIBUTE_L1d, ATTRIBUTE_L2, ATTRIBUTE_L3,
ATTRIBUTE_PEAK }; ATTRIBUTE_PEAK };
struct ascii { struct ascii {

View File

@@ -4,7 +4,7 @@
#include "standart.h" #include "standart.h"
#include "ascii.h" #include "ascii.h"
#define ATTRIBUTE_COUNT 12 #define ATTRIBUTE_COUNT 13
#define ATTRIBUTE_NAME 0 #define ATTRIBUTE_NAME 0
#define ATTRIBUTE_FREQUENCY 1 #define ATTRIBUTE_FREQUENCY 1
#define ATTRIBUTE_NCORES 2 #define ATTRIBUTE_NCORES 2
@@ -13,10 +13,11 @@
#define ATTRIBUTE_FMA 5 #define ATTRIBUTE_FMA 5
#define ATTRIBUTE_AES 6 #define ATTRIBUTE_AES 6
#define ATTRIBUTE_SHA 7 #define ATTRIBUTE_SHA 7
#define ATTRIBUTE_L1 8 #define ATTRIBUTE_L1i 8
#define ATTRIBUTE_L2 9 #define ATTRIBUTE_L1d 9
#define ATTRIBUTE_L3 10 #define ATTRIBUTE_L2 10
#define ATTRIBUTE_PEAK 11 #define ATTRIBUTE_L3 11
#define ATTRIBUTE_PEAK 12
typedef int STYLE; typedef int STYLE;
#define STYLES_COUNT 3 #define STYLES_COUNT 3

View File

@@ -1,6 +1,5 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <stdbool.h> #include <stdbool.h>
@@ -202,6 +201,7 @@ struct cpuInfo* get_cpu_info() {
return cpu; return cpu;
} }
// 80/2/20
struct topology* get_topology_info(struct cpuInfo* cpu) { struct topology* get_topology_info(struct cpuInfo* cpu) {
struct topology* topo = malloc(sizeof(struct topology)); struct topology* topo = malloc(sizeof(struct topology));
uint32_t eax = 0; uint32_t eax = 0;
@@ -222,8 +222,7 @@ struct topology* get_topology_info(struct cpuInfo* cpu) {
switch(cpu->cpu_vendor) { switch(cpu->cpu_vendor) {
case VENDOR_INTEL: case VENDOR_INTEL:
if (cpu->maxLevels >= 0x0000000B) { if (cpu->maxLevels >= 0x0000000B) {
//TODO: This idea only works with no NUMA systems
eax = 0x0000000B; eax = 0x0000000B;
ecx = 0x00000000; ecx = 0x00000000;
cpuid(&eax, &ebx, &ecx, &edx); cpuid(&eax, &ebx, &ecx, &edx);
@@ -640,67 +639,110 @@ char* get_str_sha(struct cpuInfo* cpu) {
return string; return string;
} }
// String functions int32_t get_value_as_smallest_unit(char ** str, uint32_t value) {
char* get_str_l1(struct cache* cach) { int32_t sanity_ret;
// 2*2 for digits, 4 for two 'KB' and 6 for '(D)' and '(I)' *str = malloc(sizeof(char)* 7); //4 for digits, 2 for units
uint32_t size = (2*2+4+6+1);
if(value/1024 >= 1024)
sanity_ret = snprintf(*str, 6,"%d"STRING_MEGABYTES,value/(1<<20));
else
sanity_ret = snprintf(*str, 6,"%d"STRING_KILOBYTES,value/(1<<10));
return sanity_ret;
}
// String functions
char* get_str_cache_two(int32_t cache_size, uint32_t physical_cores) {
// 4 for digits, 2 for units, 2 for ' (', 3 digits, 2 for units and 7 for ' Total)'
uint32_t max_size = 4+2 + 2 + 4+2 + 7 + 1;
int32_t sanity_ret; int32_t sanity_ret;
char* string = malloc(sizeof(char)*size); char* string = malloc(sizeof(char) * max_size);
sanity_ret = snprintf(string,size,"%d"STRING_KILOBYTES"(D)%d"STRING_KILOBYTES"(I)",cach->L1d/1024,cach->L1i/1024); char* tmp1;
assert(sanity_ret > 0); char* tmp2;
int32_t tmp1_len = get_value_as_smallest_unit(&tmp1, cache_size);
int32_t tmp2_len = get_value_as_smallest_unit(&tmp2, cache_size * physical_cores);
if(tmp1_len < 0) {
printBug("get_value_as_smallest_unit: snprintf returned a negative value for input: %d\n", cache_size);
return NULL;
}
if(tmp2_len < 0) {
printBug("get_value_as_smallest_unit: snprintf returned a negative value for input: %d\n", cache_size * physical_cores);
return NULL;
}
uint32_t size = tmp1_len + 2 + tmp2_len + 7 + 1;
sanity_ret = snprintf(string, size, "%s (%s Total)", tmp1, tmp2);
if(sanity_ret < 0) {
printBug("get_str_cache_two: snprintf returned a negative value for input: '%s' and '%s'\n", tmp1, tmp2);
return NULL;
}
free(tmp1);
free(tmp2);
return string; return string;
} }
char* get_str_l2(struct cache* cach) { char* get_str_cache_one(int32_t cache_size) {
// 4 for digits, 2 for units, 2 for ' (', 3 digits, 2 for units and 7 for ' Total)'
uint32_t max_size = 4+2 + 1;
int32_t sanity_ret;
char* string = malloc(sizeof(char) * max_size);
char* tmp;
int32_t tmp_len = get_value_as_smallest_unit(&tmp, cache_size);
if(tmp_len < 0) {
printBug("get_value_as_smallest_unit: snprintf returned a negative value for input: %d\n", cache_size);
return NULL;
}
uint32_t size = tmp_len + 1;
sanity_ret = snprintf(string, size, "%s", tmp);
if(sanity_ret < 0) {
printBug("get_str_cache_one: snprintf returned a negative value for input: '%s'\n", tmp);
return NULL;
}
free(tmp);
return string;
}
char* get_str_cache(int32_t cache_size, struct topology* topo, bool llc) {
if(llc) {
if(topo->sockets == 1)
return get_str_cache_one(cache_size);
else
return get_str_cache_two(cache_size, topo->sockets);
}
else
return get_str_cache_two(cache_size, topo->physical_cores);
}
char* get_str_l1i(struct cache* cach, struct topology* topo) {
return get_str_cache(cach->L1i, topo, false);
}
char* get_str_l1d(struct cache* cach, struct topology* topo) {
return get_str_cache(cach->L1d, topo, false);
}
char* get_str_l2(struct cache* cach, struct topology* topo) {
if(cach->L2 == UNKNOWN) { if(cach->L2 == UNKNOWN) {
char* string = malloc(sizeof(char) * 5); char* string = malloc(sizeof(char) * 5);
snprintf(string, 5, STRING_NONE); snprintf(string, 5, STRING_NONE);
return string; return string;
} }
else { return get_str_cache(cach->L2, topo, false);
int32_t sanity_ret;
char* string;
if(cach->L2/1024 >= 1024) {
//1 for digit, 2 for 'MB'
uint32_t size = (1+2+1);
string = malloc(sizeof(char)*size);
sanity_ret = snprintf(string,size,"%d"STRING_MEGABYTES,cach->L2/(1048576));
}
else {
//4 for digits, 2 for 'KB'
uint32_t size = (4+2+1);
string = malloc(sizeof(char)*size);
sanity_ret = snprintf(string,size,"%d"STRING_KILOBYTES,cach->L2/1024);
}
assert(sanity_ret > 0);
return string;
}
} }
char* get_str_l3(struct cache* cach) { char* get_str_l3(struct cache* cach, struct topology* topo) {
if(cach->L3 == UNKNOWN) { if(cach->L3 == UNKNOWN) {
char* string = malloc(sizeof(char) * 5); char* string = malloc(sizeof(char) * 5);
snprintf(string, 5, STRING_NONE); snprintf(string, 5, STRING_NONE);
return string; return string;
} }
else { return get_str_cache(cach->L3, topo, true);
int32_t sanity_ret;
char* string;
if(cach->L3/1024 >= 1024) {
//1 for digit, 2 for 'MB'
uint32_t size = (1+2+1);
string = malloc(sizeof(char)*size);
sanity_ret = snprintf(string,size,"%d"STRING_MEGABYTES,cach->L3/(1048576));
}
else {
//4 for digits, 2 for 'KB'
uint32_t size = (4+2+1);
string = malloc(sizeof(char)*size);
sanity_ret = snprintf(string,size,"%d"STRING_KILOBYTES,cach->L3/1024);
}
assert(sanity_ret > 0);
return string;
}
} }
char* get_str_freq(struct frequency* freq) { char* get_str_freq(struct frequency* freq) {

View File

@@ -31,9 +31,10 @@ char* get_str_fma(struct cpuInfo* cpu);
char* get_str_aes(struct cpuInfo* cpu); char* get_str_aes(struct cpuInfo* cpu);
char* get_str_sha(struct cpuInfo* cpu); char* get_str_sha(struct cpuInfo* cpu);
char* get_str_l1(struct cache* cach); char* get_str_l1i(struct cache* cach, struct topology* topo);
char* get_str_l2(struct cache* cach); char* get_str_l1d(struct cache* cach, struct topology* topo);
char* get_str_l3(struct cache* cach); char* get_str_l2(struct cache* cach, struct topology* topo);
char* get_str_l3(struct cache* cach, struct topology* topo);
char* get_str_freq(struct frequency* freq); char* get_str_freq(struct frequency* freq);