From 131d860de6fec7f6e3148fc82d074fe7ba89cf45 Mon Sep 17 00:00:00 2001 From: Dr-Noob Date: Sun, 28 Jun 2020 12:47:03 +0200 Subject: [PATCH] Print total cache sizes (for L1 and L2, but also for L3 in case we run in dual socket!) --- src/main.c | 48 ++++++++++------- src/printer.c | 9 ++-- src/printer.h | 11 ++-- src/standart.c | 138 ++++++++++++++++++++++++++++++++----------------- src/standart.h | 7 +-- 5 files changed, 133 insertions(+), 80 deletions(-) diff --git a/src/main.c b/src/main.c index 0f7b457..212364c 100644 --- a/src/main.c +++ b/src/main.c @@ -8,24 +8,29 @@ #include "global.h" /*** -SAMPLE OUTPUT - -Name: Intel Core i7-4790K -Frequency: 4.0 GHz -NÂșCores: 4 cores(8 threads) -AXV: AVX,AVX2 -SSE: SSE,SSE2,SSE4.1,SSE4.2 -FMA: FMA3 -AES: Yes -SHA: No -L1 Size: 32KB(Data)32KB(Instructions) -L2 Size: 512KB -L3 Size: 8MB -Peak FLOPS: 512 GFLOP/s(in simple precision) + ################ + ####### ####### + #### #### + ### #### + ### ### Name: Intel(R) Xeon(R) CPU E5-2698 v4 @ 2.20GHz + ### ### Sockets: 2 + Cores: 20 (40 threads) + Frequency: 3.60 GHz + ## ### ######### ###### ###### ### ### AVX: AVX,AVX2 + ## ### ### ### ### #### #### ### ### SSE: SSE,SSE2,SSE3,SSSE3,SSE4_1,SSE4_2 + ## ### ### ### ### ### ### ### ### FMA: FMA3 +## ## ### ### ##### ######### ## ### L1d Size: 32KB (1MB Total) +## ## L1i Size: 32KB (1MB Total) +### 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[]) { 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* aes = get_str_aes(cpu); char* sha = get_str_sha(cpu); - char* l1 = get_str_l1(cach); - char* l2 = get_str_l2(cach); - char* l3 = get_str_l3(cach); + char* l1i = get_str_l1i(cach, topo); + char* l1d = get_str_l1d(cach, topo); + 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)); setAttribute(art,ATTRIBUTE_NAME,cpuName); @@ -107,7 +113,8 @@ int main(int argc, char* argv[]) { setAttribute(art,ATTRIBUTE_FMA,fma); setAttribute(art,ATTRIBUTE_AES,aes); 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_L3,l3); setAttribute(art,ATTRIBUTE_PEAK,pp); @@ -122,7 +129,8 @@ int main(int argc, char* argv[]) { free(fma); free(aes); free(sha); - free(l1); + free(l1i); + free(l1d); free(l2); free(l3); free(pp); diff --git a/src/printer.c b/src/printer.c index 0e1d6d7..66346d7 100644 --- a/src/printer.c +++ b/src/printer.c @@ -26,25 +26,26 @@ #define TITLE_FMA "FMA: " #define TITLE_AES "AES: " #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_L3 "L3 Size: " #define TITLE_PEAK "Peak FLOPS: " /*** CENTER TEXT ***/ -#define LINES_SPACE_UP 4 +#define LINES_SPACE_UP 3 #define LINES_SPACE_DOWN 4 static const char* ATTRIBUTE_FIELDS [ATTRIBUTE_COUNT] = { TITLE_NAME, TITLE_FREQUENCY, TITLE_NCORES, TITLE_AVX, TITLE_SSE, TITLE_FMA, TITLE_AES, TITLE_SHA, - TITLE_L1, TITLE_L2, TITLE_L3, + TITLE_L1i, TITLE_L1d, TITLE_L2, TITLE_L3, TITLE_PEAK }; static const int ATTRIBUTE_LIST[ATTRIBUTE_COUNT] = { ATTRIBUTE_NAME, ATTRIBUTE_FREQUENCY, ATTRIBUTE_NCORES, ATTRIBUTE_AVX, ATTRIBUTE_SSE, ATTRIBUTE_FMA, ATTRIBUTE_AES, ATTRIBUTE_SHA, - ATTRIBUTE_L1, ATTRIBUTE_L2, ATTRIBUTE_L3, + ATTRIBUTE_L1i, ATTRIBUTE_L1d, ATTRIBUTE_L2, ATTRIBUTE_L3, ATTRIBUTE_PEAK }; struct ascii { diff --git a/src/printer.h b/src/printer.h index 220899c..e34eaad 100644 --- a/src/printer.h +++ b/src/printer.h @@ -4,7 +4,7 @@ #include "standart.h" #include "ascii.h" -#define ATTRIBUTE_COUNT 12 +#define ATTRIBUTE_COUNT 13 #define ATTRIBUTE_NAME 0 #define ATTRIBUTE_FREQUENCY 1 #define ATTRIBUTE_NCORES 2 @@ -13,10 +13,11 @@ #define ATTRIBUTE_FMA 5 #define ATTRIBUTE_AES 6 #define ATTRIBUTE_SHA 7 -#define ATTRIBUTE_L1 8 -#define ATTRIBUTE_L2 9 -#define ATTRIBUTE_L3 10 -#define ATTRIBUTE_PEAK 11 +#define ATTRIBUTE_L1i 8 +#define ATTRIBUTE_L1d 9 +#define ATTRIBUTE_L2 10 +#define ATTRIBUTE_L3 11 +#define ATTRIBUTE_PEAK 12 typedef int STYLE; #define STYLES_COUNT 3 diff --git a/src/standart.c b/src/standart.c index 1482153..ad46c04 100644 --- a/src/standart.c +++ b/src/standart.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -202,6 +201,7 @@ struct cpuInfo* get_cpu_info() { return cpu; } +// 80/2/20 struct topology* get_topology_info(struct cpuInfo* cpu) { struct topology* topo = malloc(sizeof(struct topology)); uint32_t eax = 0; @@ -222,8 +222,7 @@ struct topology* get_topology_info(struct cpuInfo* cpu) { switch(cpu->cpu_vendor) { case VENDOR_INTEL: - if (cpu->maxLevels >= 0x0000000B) { - //TODO: This idea only works with no NUMA systems + if (cpu->maxLevels >= 0x0000000B) { eax = 0x0000000B; ecx = 0x00000000; cpuid(&eax, &ebx, &ecx, &edx); @@ -640,67 +639,110 @@ char* get_str_sha(struct cpuInfo* cpu) { return string; } -// String functions -char* get_str_l1(struct cache* cach) { - // 2*2 for digits, 4 for two 'KB' and 6 for '(D)' and '(I)' - uint32_t size = (2*2+4+6+1); +int32_t get_value_as_smallest_unit(char ** str, uint32_t value) { + int32_t sanity_ret; + *str = malloc(sizeof(char)* 7); //4 for digits, 2 for units + + 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; - char* string = malloc(sizeof(char)*size); - sanity_ret = snprintf(string,size,"%d"STRING_KILOBYTES"(D)%d"STRING_KILOBYTES"(I)",cach->L1d/1024,cach->L1i/1024); - assert(sanity_ret > 0); + char* string = malloc(sizeof(char) * max_size); + char* tmp1; + 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; } -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) { char* string = malloc(sizeof(char) * 5); snprintf(string, 5, STRING_NONE); return string; } - else { - 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; - } + return get_str_cache(cach->L2, topo, false); } -char* get_str_l3(struct cache* cach) { +char* get_str_l3(struct cache* cach, struct topology* topo) { if(cach->L3 == UNKNOWN) { char* string = malloc(sizeof(char) * 5); snprintf(string, 5, STRING_NONE); return string; } - else { - 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; - } + return get_str_cache(cach->L3, topo, true); } char* get_str_freq(struct frequency* freq) { diff --git a/src/standart.h b/src/standart.h index caa0b9f..6bca7cb 100644 --- a/src/standart.h +++ b/src/standart.h @@ -31,9 +31,10 @@ char* get_str_fma(struct cpuInfo* cpu); char* get_str_aes(struct cpuInfo* cpu); char* get_str_sha(struct cpuInfo* cpu); -char* get_str_l1(struct cache* cach); -char* get_str_l2(struct cache* cach); -char* get_str_l3(struct cache* cach); +char* get_str_l1i(struct cache* cach, struct topology* topo); +char* get_str_l1d(struct cache* cach, struct topology* topo); +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);