diff --git a/.gitignore b/.gitignore index 3208ea7..1c8a0cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ cpufetch +*.o diff --git a/Makefile b/Makefile index 0c806af..6fd77c7 100644 --- a/Makefile +++ b/Makefile @@ -15,11 +15,12 @@ ifneq ($(OS),Windows_NT) ifeq ($(arch), $(filter $(arch), x86_64 amd64 i686)) SRC_DIR=src/x86/ SOURCE += $(COMMON_SRC) $(SRC_DIR)cpuid.c $(SRC_DIR)apic.c $(SRC_DIR)cpuid_asm.c $(SRC_DIR)uarch.c - HEADERS += $(COMMON_HDR) $(SRC_DIR)cpuid.h $(SRC_DIR)apic.h $(SRC_DIR)cpuid_asm.h $(SRC_DIR)uarch.h + HEADERS += $(COMMON_HDR) $(SRC_DIR)cpuid.h $(SRC_DIR)apic.h $(SRC_DIR)cpuid_asm.h $(SRC_DIR)uarch.h $(SRC_DIR)freq/freq.h os := $(shell uname -s) ifeq ($(os), Linux) - SOURCE += freq.o + SOURCE += $(SRC_DIR)freq/freq.c freq_nov.o freq_sse.o freq_avx.o freq_avx512.o + HEADERS += $(SRC_DIR)freq/freq.h CFLAGS += -pthread endif CFLAGS += -DARCH_X86 -std=c99 -fstack-protector-all @@ -69,8 +70,17 @@ static: $(OUTPUT) strict: CFLAGS += -O2 -Werror -fsanitize=undefined -D_FORTIFY_SOURCE=2 strict: $(OUTPUT) -freq.o: Makefile $(SRC_DIR)freq.c $(SRC_DIR)freq.h - $(CC) $(CFLAGS) $(SANITY_FLAGS) -c -mavx -mfma -pthread $(SRC_DIR)freq.c -o freq.o +freq_nov.o: Makefile $(SRC_DIR)freq/freq_nov.c $(SRC_DIR)freq/freq_nov.h + $(CC) $(CFLAGS) $(SANITY_FLAGS) -c -pthread $(SRC_DIR)freq/freq_nov.c -o $@ + +freq_sse.o: Makefile $(SRC_DIR)freq/freq_sse.c $(SRC_DIR)freq/freq_sse.h + $(CC) $(CFLAGS) $(SANITY_FLAGS) -c -msse -pthread $(SRC_DIR)freq/freq_sse.c -o $@ + +freq_avx.o: Makefile $(SRC_DIR)freq/freq_avx.c $(SRC_DIR)freq/freq_avx.h + $(CC) $(CFLAGS) $(SANITY_FLAGS) -c -mavx -mfma -pthread $(SRC_DIR)freq/freq_avx.c -o $@ + +freq_avx512.o: Makefile $(SRC_DIR)freq/freq_avx512.c $(SRC_DIR)freq/freq_avx512.h + $(CC) $(CFLAGS) $(SANITY_FLAGS) -c -mavx512f -mfma -pthread $(SRC_DIR)freq/freq_avx512.c -o $@ $(OUTPUT): Makefile $(SOURCE) $(HEADERS) $(CC) $(CFLAGS) $(SANITY_FLAGS) $(SOURCE) -o $(OUTPUT) @@ -79,7 +89,7 @@ run: $(OUTPUT) ./$(OUTPUT) clean: - @rm -f $(OUTPUT) freq.o + @rm -f $(OUTPUT) *.o install: $(OUTPUT) install -Dm755 "cpufetch" "$(DESTDIR)$(PREFIX)/bin/cpufetch" diff --git a/src/x86/cpuid.c b/src/x86/cpuid.c index 322bf59..5547c28 100644 --- a/src/x86/cpuid.c +++ b/src/x86/cpuid.c @@ -18,7 +18,7 @@ #include "../common/args.h" #include "apic.h" #include "uarch.h" -#include "freq.h" +#include "freq/freq.h" #define CPU_VENDOR_INTEL_STRING "GenuineIntel" #define CPU_VENDOR_AMD_STRING "AuthenticAMD" @@ -194,8 +194,10 @@ int64_t get_peak_performance(struct cpuInfo* cpu, struct topology* topo, int64_t int64_t freq; #ifdef __linux__ - if(accurate_pp) freq = measure_avx_frequency(cpu); - else freq = max_freq; + if(accurate_pp) + freq = measure_frequency(cpu); + else + freq = max_freq; #else // Silence compiler warning (void)(accurate_pp); diff --git a/src/x86/freq.h b/src/x86/freq.h deleted file mode 100644 index a9b38b6..0000000 --- a/src/x86/freq.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __FREQ__ -#define __FREQ__ - -#include -#include "../common/cpu.h" - -int64_t measure_avx_frequency(struct cpuInfo* cpu); - -#endif diff --git a/src/x86/freq.c b/src/x86/freq/freq.c similarity index 72% rename from src/x86/freq.c rename to src/x86/freq/freq.c index d103426..b23233f 100644 --- a/src/x86/freq.c +++ b/src/x86/freq/freq.c @@ -1,8 +1,13 @@ #define _GNU_SOURCE #include +#include "../../common/global.h" +#include "../uarch.h" #include "freq.h" -#include "../common/global.h" +#include "freq_nov.h" +#include "freq_sse.h" +#include "freq_avx.h" +#include "freq_avx512.h" #include #include @@ -13,10 +18,8 @@ #include #include -#define MEASURE_TIME_SECONDS 5 #define MAX_NUMBER_THREADS 512 #define FREQ_VECTOR_SIZE 1<<16 -#define LOOP_ITERS 100000000 struct freq_thread { bool end; @@ -80,44 +83,38 @@ void* measure_freq(void *freq_ptr) { return NULL; } -void* compute_avx() { - bool end = false; - - struct timeval begin, now; - - __m256 a = _mm256_set1_ps(1.5); - __m256 b = _mm256_set1_ps(1.2); - __m256 c = _mm256_set1_ps(0.0); - - gettimeofday(&begin, NULL); - while(!end) { - for(uint64_t i=0; i < LOOP_ITERS; i++) { - c = _mm256_fmadd_ps(a, b, c); - } - - gettimeofday(&now, NULL); - double elapsed = (now.tv_sec - begin.tv_sec) + ((now.tv_usec - begin.tv_usec)/1000000.0); - end = elapsed >= (double) MEASURE_TIME_SECONDS; - } - - FILE* fp = fopen("/dev/null", "w"); - if(fp == NULL) { - printf("fopen: %s", strerror(errno)); - } - else { - fprintf(fp, "%f", c[0]); - fclose(fp); - } - - return NULL; -} - -int64_t measure_avx_frequency(struct cpuInfo* cpu) { +int64_t measure_frequency(struct cpuInfo* cpu) { int ret; + int num_spaces; struct freq_thread* freq_struct = malloc(sizeof(struct freq_thread)); freq_struct->end = false; freq_struct->measure = false; + void* (*compute_function)(void*); + + if(cpu->feat->AVX512 && vpus_are_AVX512(cpu)) { + printf("cpufetch is measuring the AVX512 frequency..."); + compute_function = compute_avx512; + num_spaces = 45; + } + else if(cpu->feat->AVX || cpu->feat->AVX2) { + printf("cpufetch is measuring the AVX frequency..."); + compute_function = compute_avx; + num_spaces = 42; + } + else if(cpu->feat->SSE) { + printf("cpufetch is measuring the SSE frequency..."); + compute_function = compute_sse; + num_spaces = 42; + } + else { + printf("cpufetch is measuring the frequency (no vector instructions)..."); + compute_function = compute_nov; + num_spaces = 63; + } + + fflush(stdout); + pthread_t freq_t; if(pthread_create(&freq_t, NULL, measure_freq, freq_struct)) { fprintf(stderr, "Error creating thread\n"); @@ -126,7 +123,7 @@ int64_t measure_avx_frequency(struct cpuInfo* cpu) { pthread_t* compute_th = malloc(sizeof(pthread_t) * cpu->topo->total_cores); for(int i=0; i < cpu->topo->total_cores; i++) { - ret = pthread_create(&compute_th[i], NULL, compute_avx, NULL); + ret = pthread_create(&compute_th[i], NULL, compute_function, NULL); if(ret != 0) { fprintf(stderr, "Error creating thread\n"); @@ -134,9 +131,6 @@ int64_t measure_avx_frequency(struct cpuInfo* cpu) { } } - printf("cpufetch is measuring AVX2 frequency..."); - fflush(stdout); - sleep_ms(500); freq_struct->measure = true; @@ -153,6 +147,6 @@ int64_t measure_avx_frequency(struct cpuInfo* cpu) { return -1; } - printf("\r "); + printf("\r%*c", num_spaces, ' '); return freq_struct->freq; } diff --git a/src/x86/freq/freq.h b/src/x86/freq/freq.h new file mode 100644 index 0000000..8d86a14 --- /dev/null +++ b/src/x86/freq/freq.h @@ -0,0 +1,9 @@ +#ifndef __FREQ__ +#define __FREQ__ + +#include +#include "../../common/cpu.h" + +int64_t measure_frequency(struct cpuInfo* cpu); + +#endif diff --git a/src/x86/freq/freq_avx.c b/src/x86/freq/freq_avx.c new file mode 100644 index 0000000..051d947 --- /dev/null +++ b/src/x86/freq/freq_avx.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MEASURE_TIME_SECONDS 5 +#define LOOP_ITERS 100000000 + +void* compute_avx() { + bool end = false; + + struct timeval begin, now; + + __m256 a = _mm256_set1_ps(1.5); + __m256 b = _mm256_set1_ps(1.2); + __m256 c = _mm256_set1_ps(0.0); + + gettimeofday(&begin, NULL); + while(!end) { + for(uint64_t i=0; i < LOOP_ITERS; i++) { + c = _mm256_fmadd_ps(a, b, c); + } + + gettimeofday(&now, NULL); + double elapsed = (now.tv_sec - begin.tv_sec) + ((now.tv_usec - begin.tv_usec)/1000000.0); + end = elapsed >= (double) MEASURE_TIME_SECONDS; + } + + FILE* fp = fopen("/dev/null", "w"); + if(fp == NULL) { + printf("fopen: %s", strerror(errno)); + } + else { + fprintf(fp, "%f", c[0]); + fclose(fp); + } + + return NULL; +} + diff --git a/src/x86/freq/freq_avx.h b/src/x86/freq/freq_avx.h new file mode 100644 index 0000000..5a3de14 --- /dev/null +++ b/src/x86/freq/freq_avx.h @@ -0,0 +1,6 @@ +#ifndef __FREQ_AVX__ +#define __FREQ_AVX__ + +void* compute_avx(); + +#endif diff --git a/src/x86/freq/freq_avx512.c b/src/x86/freq/freq_avx512.c new file mode 100644 index 0000000..6835a15 --- /dev/null +++ b/src/x86/freq/freq_avx512.c @@ -0,0 +1,5 @@ +#include + +void* compute_avx512() { + return NULL; +} diff --git a/src/x86/freq/freq_avx512.h b/src/x86/freq/freq_avx512.h new file mode 100644 index 0000000..53aefb3 --- /dev/null +++ b/src/x86/freq/freq_avx512.h @@ -0,0 +1,6 @@ +#ifndef __FREQ_AVX512__ +#define __FREQ_AVX512__ + +void* compute_avx512(); + +#endif diff --git a/src/x86/freq/freq_nov.c b/src/x86/freq/freq_nov.c new file mode 100644 index 0000000..95b95dd --- /dev/null +++ b/src/x86/freq/freq_nov.c @@ -0,0 +1,5 @@ +#include + +void* compute_nov() { + return NULL; +} diff --git a/src/x86/freq/freq_nov.h b/src/x86/freq/freq_nov.h new file mode 100644 index 0000000..1073e6c --- /dev/null +++ b/src/x86/freq/freq_nov.h @@ -0,0 +1,6 @@ +#ifndef __FREQ_NO_VECTOR__ +#define __FREQ_NO_VECTOR__ + +void* compute_nov(); + +#endif diff --git a/src/x86/freq/freq_sse.c b/src/x86/freq/freq_sse.c new file mode 100644 index 0000000..4e33c92 --- /dev/null +++ b/src/x86/freq/freq_sse.c @@ -0,0 +1,5 @@ +#include + +void* compute_sse() { + return NULL; +} diff --git a/src/x86/freq/freq_sse.h b/src/x86/freq/freq_sse.h new file mode 100644 index 0000000..73869ca --- /dev/null +++ b/src/x86/freq/freq_sse.h @@ -0,0 +1,6 @@ +#ifndef __FREQ_SSE__ +#define __FREQ_SSE__ + +void* compute_sse(); + +#endif