Compare commits
33 Commits
1bfc162845
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 94167e05fd | |||
| 7177add4ce | |||
| 37d3340df9 | |||
| fcdaf41495 | |||
| cec0662e68 | |||
| ba31dd9f8c | |||
| f355ab2d25 | |||
| 46ee06406f | |||
| 5c97a99839 | |||
| 2cb6f1beb6 | |||
| 4945a298ac | |||
| 063183e46c | |||
| 12f25cfe51 | |||
| 57acc5e16f | |||
| 43718ff047 | |||
| 297d9c53f3 | |||
| b2cb252822 | |||
| a7d977210e | |||
| 96ae35912f | |||
| dd512f8304 | |||
| 389a494bfc | |||
| f18ecde7bc | |||
| 9104a41e2d | |||
| 7ce7101240 | |||
| dca94a0edf | |||
| b7d33de2d7 | |||
| b1b90bc6f5 | |||
| 3a0917ed58 | |||
| 4b905a56a5 | |||
| 967b1524d7 | |||
| ab99d4b003 | |||
| 22466ea56f | |||
| 9ddb991b94 |
@@ -1,2 +1,2 @@
|
||||
all:
|
||||
clang++ -g dasm.cpp -o dasm
|
||||
clang++ -g dasm.cc -o dasm
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
all:
|
||||
clang++ -g dasm.cpp -o dasm
|
||||
clang++ -g dasm.cc -o dasm
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
all:
|
||||
clang++ -g dasm.cpp -o dasm
|
||||
clang++ -g dasm.cc -o dasm
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
CC=clang++
|
||||
CFLAGS=-g -O0 -Wall -Wextra
|
||||
LIBS=-Wl,-rpath,./lib -L./lib -lsim86
|
||||
SRC=*.cpp
|
||||
SRC=*.cc
|
||||
OUT=sim86
|
||||
|
||||
all:
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
mk_haversine_fscanf:
|
||||
clang++ -g cpp/fscanf.cpp cpp/haversine.cpp -o cpp/haverscan
|
||||
clang++ -g cpp/fscanf.cc cpp/haversine.cc -o cpp/haverscan
|
||||
|
||||
run_haversine_fscanf:
|
||||
cd ./cpp && ./haverscan
|
||||
|
||||
mk_haversine_strtok:
|
||||
clang++ -g cpp/strtok.cpp cpp/haversine.cpp -o cpp/haverstrtok
|
||||
clang++ -g cpp/strtok.cc cpp/haversine.cc -o cpp/haverstrtok
|
||||
|
||||
run_haversine_strtok:
|
||||
cd ./cpp && ./haverstrtok
|
||||
|
||||
mk_test:
|
||||
clang++ -g -lpthread cpp/test.cpp cpp/haversine.cpp -o cpp/test
|
||||
clang++ -g -lpthread cpp/test.cc cpp/haversine.cc -o cpp/test
|
||||
|
||||
run_test:
|
||||
cd ./cpp && ./test
|
||||
|
||||
5
haversine_02/.gitignore
vendored
5
haversine_02/.gitignore
vendored
@@ -1,8 +1,13 @@
|
||||
.cache
|
||||
.vscode
|
||||
.idea
|
||||
compile_commands.json
|
||||
count_and_distances
|
||||
pairs.json
|
||||
cache_test
|
||||
main
|
||||
genhavr
|
||||
prochavr
|
||||
reptest
|
||||
memtest
|
||||
timer_test*
|
||||
|
||||
42
haversine_02/.vscode/launch.json
vendored
42
haversine_02/.vscode/launch.json
vendored
@@ -1,42 +0,0 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Debug clustered generator",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"program": "${workspaceFolder}/genhavr",
|
||||
"args": [
|
||||
"--cluster",
|
||||
"10"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Debug uniform generator",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"program": "${workspaceFolder}/genhavr",
|
||||
"args": [
|
||||
"10"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Debug processor",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"program": "${workspaceFolder}/prochavr",
|
||||
"args": [
|
||||
"${workspaceFolder}/pairs.json"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Debug timer test",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"program": "${workspaceFolder}/timer_test"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -4,6 +4,12 @@ CC=clang
|
||||
CXX=clang++
|
||||
CFLAGS="-Wall -Wextra -I$(realpath ./include) "
|
||||
|
||||
ASM=nasm
|
||||
ASM_FLAGS="-f elf64 "
|
||||
|
||||
AR=ar
|
||||
AR_FLAGS="rcs"
|
||||
|
||||
# PARSE ARGUMENTS
|
||||
# From this StackOverflow answer https://stackoverflow.com/a/14203146
|
||||
while [[ $# > 0 ]];do
|
||||
@@ -30,24 +36,23 @@ done
|
||||
|
||||
# BUILD TYPE
|
||||
if [[ $RELEASE == true ]]; then
|
||||
CFLAGS+="-O3"
|
||||
CFLAGS+="-g -O1"
|
||||
else
|
||||
CFLAGS+="-g"
|
||||
fi
|
||||
|
||||
|
||||
# GENERATOR
|
||||
GENSRC="./src/generator/gen_argparser.cpp \
|
||||
./src/generator/generator.cpp \
|
||||
./src/haversine.cpp \
|
||||
./src/point_types.cpp \
|
||||
./src/generator/main.cpp"
|
||||
GENSRC="./src/generator/gen_argparser.cc \
|
||||
./src/generator/generator.cc \
|
||||
./src/haversine.cc \
|
||||
./src/point_types.cc \
|
||||
./src/generator/main.cc"
|
||||
GENOUT=genhavr
|
||||
|
||||
(set -x ; $CXX $CFLAGS $GENSRC -o $GENOUT)
|
||||
echo
|
||||
|
||||
|
||||
# PROFILER
|
||||
PROFSRC="../src/profiler/timer.c"
|
||||
PROFFLAGS="-c "
|
||||
@@ -59,20 +64,41 @@ JSONFLAGS="-c "
|
||||
JSON_BUILD_DIR=json_build
|
||||
|
||||
PROCSRC="./$JSON_BUILD_DIR/*.o \
|
||||
./src/haversine.cpp \
|
||||
./src/point_types.cpp \
|
||||
./src/processor/proc_argparser.cpp \
|
||||
./src/processor/main.cpp "
|
||||
./src/haversine.cc \
|
||||
./src/point_types.cc \
|
||||
./src/processor/proc_argparser.cc \
|
||||
./src/processor/main.cc "
|
||||
PROCOUT=prochavr
|
||||
|
||||
# MEMTESTER
|
||||
MEMTESTSRC="./src/memtester/*.c"
|
||||
MEMTESTOUT=memtest
|
||||
|
||||
(set -x ; $CC $CFLAGS $MEMTESTSRC -o $MEMTESTOUT)
|
||||
echo
|
||||
|
||||
# REPTEST ASSEMBLY
|
||||
ASM_BUILD_DIR=reptest_build
|
||||
ASM_SRC="./src/repetition_testing/reptest_functions.asm"
|
||||
ASM_OBJ="./$ASM_BUILD_DIR/funcs.o"
|
||||
ASM_LIB="./$ASM_BUILD_DIR/libfuncs.a"
|
||||
|
||||
mkdir $ASM_BUILD_DIR
|
||||
|
||||
(set -x ; $ASM $ASM_FLAGS $ASM_SRC -o $ASM_OBJ)
|
||||
(set -x ; $AR $AR_FLAGS $ASM_LIB $ASM_OBJ)
|
||||
echo
|
||||
|
||||
if [[ $BASIC_PROFILING == true ]] || [[ $FULL_PROFILING == true ]]; then
|
||||
if [[ $FULL_PROFILING == true ]]; then
|
||||
JSONFLAGS+="-DFULL_PROFILING"
|
||||
PROCFLAGS="-DFULL_PROFILING"
|
||||
REPTESTFLAGS="-DFULL_PROFILING"
|
||||
PROFFLAGS+="-DFULL_PROFILING"
|
||||
elif [[ $BASIC_PROFILING == true ]]; then
|
||||
JSONFLAGS+="-DBASIC_PROFILING"
|
||||
PROCFLAGS="-DBASIC_PROFILING"
|
||||
REPTESTFLAGS="-DBASIC_PROFILING"
|
||||
PROFFLAGS+="-DBASIC_PROFILING"
|
||||
fi
|
||||
|
||||
@@ -85,6 +111,13 @@ if [[ $BASIC_PROFILING == true ]] || [[ $FULL_PROFILING == true ]]; then
|
||||
echo
|
||||
|
||||
cd ../
|
||||
|
||||
# REPETITION TESTING
|
||||
REPTESTSRC="./src/repetition_testing/*.cc ./$PROF_BUILD_DIR/*.o $ASM_LIB"
|
||||
REPTESTOUT=reptest
|
||||
|
||||
(set -x ; $CXX $CFLAGS $REPTESTFLAGS $REPTESTSRC -o $REPTESTOUT)
|
||||
echo
|
||||
fi
|
||||
|
||||
mkdir $JSON_BUILD_DIR
|
||||
@@ -98,6 +131,5 @@ cd ../
|
||||
(set -x ; $CXX $CFLAGS $PROCFLAGS $PROCSRC -o $PROCOUT)
|
||||
echo
|
||||
|
||||
|
||||
# CLEAR BUILD FILES
|
||||
rm -rvf $JSON_BUILD_DIR $PROF_BUILD_DIR
|
||||
rm -rvf $JSON_BUILD_DIR $PROF_BUILD_DIR $ASM_BUILD_DIR
|
||||
|
||||
@@ -61,6 +61,8 @@ u64 read_cpu_timer(void);
|
||||
// CPU frequency in hz/sec
|
||||
u64 get_cpu_freq(u64 milliseconds);
|
||||
|
||||
f64 time_in_seconds(u64 cpu_time, u64 cpu_freq);
|
||||
|
||||
void profile_start(u64 count);
|
||||
void profile_end();
|
||||
|
||||
|
||||
71
haversine_02/include/repetition_testing/reptester.h
Normal file
71
haversine_02/include/repetition_testing/reptester.h
Normal file
@@ -0,0 +1,71 @@
|
||||
#ifndef REPTESTER_H
|
||||
#define REPTESTER_H
|
||||
|
||||
#include "aliases.h"
|
||||
|
||||
struct reptest_params {
|
||||
const char *filename;
|
||||
char *buffer;
|
||||
u64 read_size;
|
||||
u64 read_count;
|
||||
};
|
||||
|
||||
struct reptest_results {
|
||||
u64 bytes_read;
|
||||
u64 read_time;
|
||||
u64 page_faults;
|
||||
};
|
||||
|
||||
struct time_stats {
|
||||
u64 min_time;
|
||||
u64 max_time;
|
||||
u64 avg_time;
|
||||
u64 total_time;
|
||||
};
|
||||
|
||||
struct mem_stats {
|
||||
u64 min_faults;
|
||||
u64 max_faults;
|
||||
u64 avg_faults;
|
||||
u64 total_bytes;
|
||||
u64 total_faults;
|
||||
};
|
||||
|
||||
struct reptester {
|
||||
reptest_params params;
|
||||
|
||||
const u64 cpu_freq;
|
||||
|
||||
f64 wait_time_secs;
|
||||
f64 test_time_secs;
|
||||
u64 test_start_time;
|
||||
|
||||
u64 current_run;
|
||||
time_stats tstats;
|
||||
mem_stats mstats;
|
||||
|
||||
reptest_results results;
|
||||
};
|
||||
|
||||
enum alloc_type {
|
||||
ALLOC_TYPE_WITHOUT_MALLOC,
|
||||
ALLOC_TYPE_WITH_MALLOC,
|
||||
|
||||
COUNT_ALLOC_TYPE,
|
||||
};
|
||||
|
||||
typedef void (*reptest_func)(reptester *tester, alloc_type type);
|
||||
|
||||
struct func_data {
|
||||
const char *names[COUNT_ALLOC_TYPE];
|
||||
reptest_func func;
|
||||
};
|
||||
|
||||
void handle_alloc(reptester *tester, alloc_type type);
|
||||
void handle_free(reptester *tester, alloc_type type);
|
||||
void run_func_test(reptester *tester, reptest_func func, const char *func_name,
|
||||
alloc_type type);
|
||||
u64 page_fault_count();
|
||||
void print_results(reptester *tester, const char *name);
|
||||
|
||||
#endif // !REPTESTER_H
|
||||
@@ -23,8 +23,6 @@ INTERNAL jentity_t *add_value(parser_t *parser);
|
||||
INTERNAL void add_collection(parser_t *parser);
|
||||
|
||||
jentity_t *load_json(const char *filepath) {
|
||||
SAMPLE_START(PROFILER_ID_READ_JSON_FILE, "READ JSON FILE");
|
||||
|
||||
FILE *fp = fopen(filepath, "r");
|
||||
|
||||
if (!fp) {
|
||||
@@ -40,12 +38,14 @@ jentity_t *load_json(const char *filepath) {
|
||||
char *json = (char *)malloc(sizeof(char) * (length + 1));
|
||||
memset(json, 0, length + 1);
|
||||
|
||||
SAMPLE_START(PROFILER_ID_READ_JSON_FILE, "READ JSON FILE");
|
||||
|
||||
fread(json, sizeof(char), length, fp);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
SAMPLE_END(PROFILER_ID_READ_JSON_FILE, length);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
SAMPLE_START(PROFILER_ID_PARSER_SETUP, "JSON PARSER SETUP");
|
||||
|
||||
lexer_t *lexer = NULL;
|
||||
|
||||
125
haversine_02/src/memtester/main.c
Normal file
125
haversine_02/src/memtester/main.c
Normal file
@@ -0,0 +1,125 @@
|
||||
#include "aliases.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define PAGESIZE 4096
|
||||
|
||||
#if _WIN32
|
||||
|
||||
// clang-format off
|
||||
#include <intrin.h>
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
// clang-format on
|
||||
|
||||
typedef struct {
|
||||
bool Initialized;
|
||||
HANDLE ProcessHandle;
|
||||
} os_metrics;
|
||||
|
||||
static os_metrics GlobalMetrics;
|
||||
|
||||
static u64 ReadWindowsPageFaultCount(void) {
|
||||
PROCESS_MEMORY_COUNTERS_EX MemoryCounters = {0};
|
||||
MemoryCounters.cb = sizeof(MemoryCounters);
|
||||
GetProcessMemoryInfo(GlobalMetrics.ProcessHandle,
|
||||
(PROCESS_MEMORY_COUNTERS *)&MemoryCounters,
|
||||
sizeof(MemoryCounters));
|
||||
|
||||
u64 Result = MemoryCounters.PageFaultCount;
|
||||
return Result;
|
||||
}
|
||||
|
||||
static void InitializeOSMetrics(void) {
|
||||
if (!GlobalMetrics.Initialized) {
|
||||
GlobalMetrics.Initialized = true;
|
||||
GlobalMetrics.ProcessHandle =
|
||||
OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE,
|
||||
GetCurrentProcessId());
|
||||
}
|
||||
}
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
typedef struct rusage rusage_t;
|
||||
|
||||
u64 nix_page_fault_count() {
|
||||
rusage_t usage;
|
||||
|
||||
getrusage(RUSAGE_SELF, &usage);
|
||||
|
||||
return usage.ru_minflt + usage.ru_majflt;
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
u64 page_fault_count() {
|
||||
#if _WIN32
|
||||
return ReadWindowsPageFaultCount();
|
||||
#else
|
||||
return nix_page_fault_count();
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 2 || argc > 2) {
|
||||
printf("Usage: %s [NUMBER OF PAGES TO ALLOCATE]\n", argv[0]);
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
#if _WIN32
|
||||
InitializeOSMetrics();
|
||||
#endif
|
||||
|
||||
u64 page_count = atol(argv[1]);
|
||||
u64 alloc_size = page_count * PAGESIZE;
|
||||
u64 touch_size = 0;
|
||||
|
||||
printf("Page Count,Touch Count,Fault Count,Extra Faults\n");
|
||||
|
||||
for (u64 touch_count = 0; touch_count <= page_count; ++touch_count) {
|
||||
touch_size = touch_count * PAGESIZE;
|
||||
|
||||
#if _WIN32
|
||||
u8 *data = (u8 *)VirtualAlloc(0, alloc_size, MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
#else
|
||||
u8 *data = (u8 *)mmap(NULL, alloc_size, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
#endif
|
||||
|
||||
if (!data) {
|
||||
printf("Failed to allocate memory\n");
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
u64 fault_start = page_fault_count();
|
||||
|
||||
for (u64 i = 0; i < touch_size; ++i) {
|
||||
data[i] = (u8)i;
|
||||
}
|
||||
|
||||
u64 fault_end = page_fault_count();
|
||||
|
||||
u64 faults = fault_end - fault_start;
|
||||
|
||||
printf("%llu,%llu,%llu,%lld\n", (unsigned long long)page_count,
|
||||
(unsigned long long)touch_count, (unsigned long long)faults,
|
||||
((long long)faults - touch_count));
|
||||
|
||||
#if _WIN32
|
||||
VirtualFree(data, 0, MEM_RELEASE);
|
||||
#else
|
||||
munmap((void *)data, alloc_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -38,12 +38,13 @@ u64 read_cpu_timer(void) { return __rdtsc(); }
|
||||
|
||||
u64 get_cpu_freq(u64 milliseconds) {
|
||||
u64 os_freq = get_os_frequency();
|
||||
u64 os_start = get_os_time();
|
||||
u64 cpu_start = read_cpu_timer();
|
||||
u64 os_end = 0;
|
||||
u64 os_elapsed = 0;
|
||||
u64 os_wait_time = os_freq * milliseconds / 1000;
|
||||
|
||||
u64 os_start = get_os_time();
|
||||
u64 cpu_start = read_cpu_timer();
|
||||
|
||||
while (os_elapsed < os_wait_time) {
|
||||
os_end = get_os_time();
|
||||
os_elapsed = os_end - os_start;
|
||||
@@ -61,6 +62,10 @@ u64 get_cpu_freq(u64 milliseconds) {
|
||||
return cpu_freq;
|
||||
}
|
||||
|
||||
f64 time_in_seconds(u64 cpu_time, u64 cpu_freq) {
|
||||
return (f64)cpu_time / cpu_freq;
|
||||
}
|
||||
|
||||
void profile_start(u64 count) {
|
||||
profiler.cpu_freq = get_cpu_freq(1000);
|
||||
profiler.start = read_cpu_timer();
|
||||
|
||||
1756
haversine_02/src/repetition_testing/main.cc
Normal file
1756
haversine_02/src/repetition_testing/main.cc
Normal file
File diff suppressed because it is too large
Load Diff
529
haversine_02/src/repetition_testing/reptest_functions.asm
Normal file
529
haversine_02/src/repetition_testing/reptest_functions.asm
Normal file
@@ -0,0 +1,529 @@
|
||||
global mov_all_bytes_asm
|
||||
global nop_all_bytes_asm
|
||||
global nop_1x3_all_bytes_asm
|
||||
global nop_1x9_all_bytes_asm
|
||||
global inc_all_bytes_asm
|
||||
global dec_all_bytes_asm
|
||||
global align64_loop
|
||||
global align1_loop
|
||||
global align15_loop
|
||||
global align31_loop
|
||||
global align63_loop
|
||||
global align75_loop
|
||||
global align90_loop
|
||||
global align112_loop
|
||||
global rat_add
|
||||
global rat_mov_add
|
||||
global read_1
|
||||
global read_2
|
||||
global read_3
|
||||
global read_4
|
||||
global read_8
|
||||
global write_1
|
||||
global write_2
|
||||
global write_3
|
||||
global write_4
|
||||
global write_8
|
||||
global read_1x2_low
|
||||
global read_1x2_high
|
||||
global read_2x2
|
||||
global read_4x2
|
||||
global read_8x2
|
||||
global read_4x2_simd
|
||||
global read_8x2_simd
|
||||
global read_16x2_simd
|
||||
global read_32x2_simd_offset
|
||||
global read_32x2_simd_no_offset
|
||||
global read_16x4_simd
|
||||
global read_32x4_simd
|
||||
global cache_test ; Expects 3 inputs (pointer, read_count, mask)
|
||||
global cache_test_unaligned ; Expects 3 inputs (pointer, read_count, mask)
|
||||
|
||||
mov_all_bytes_asm:
|
||||
xor rax, rax
|
||||
|
||||
.loop:
|
||||
mov BYTE [rdi + rax * 1], al
|
||||
inc rax
|
||||
cmp rsi, rax
|
||||
jne .loop
|
||||
|
||||
ret
|
||||
|
||||
nop_all_bytes_asm:
|
||||
xor rax, rax
|
||||
|
||||
.loop:
|
||||
db 0x0f, 0x1f, 0x00
|
||||
inc rax
|
||||
cmp rdi, rax
|
||||
jne .loop
|
||||
|
||||
ret
|
||||
|
||||
nop_1x3_all_bytes_asm:
|
||||
xor rax, rax
|
||||
|
||||
.loop:
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
inc rax
|
||||
cmp rdi, rax
|
||||
jne .loop
|
||||
|
||||
ret
|
||||
|
||||
nop_1x9_all_bytes_asm:
|
||||
xor rax, rax
|
||||
|
||||
.loop:
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
inc rax
|
||||
cmp rdi, rax
|
||||
jne .loop
|
||||
|
||||
ret
|
||||
|
||||
inc_all_bytes_asm:
|
||||
xor rax, rax
|
||||
|
||||
.loop:
|
||||
inc rax
|
||||
cmp rdi, rax
|
||||
jne .loop
|
||||
|
||||
ret
|
||||
|
||||
dec_all_bytes_asm:
|
||||
.loop:
|
||||
dec rdi
|
||||
jnz .loop
|
||||
|
||||
ret
|
||||
|
||||
align64_loop:
|
||||
xor rax, rax
|
||||
|
||||
align 64
|
||||
.loop:
|
||||
inc rax
|
||||
cmp rdi, rax
|
||||
jne .loop
|
||||
|
||||
ret
|
||||
|
||||
align1_loop:
|
||||
xor rax, rax
|
||||
|
||||
align 64
|
||||
nop
|
||||
.loop:
|
||||
inc rax
|
||||
cmp rdi, rax
|
||||
jne .loop
|
||||
|
||||
ret
|
||||
|
||||
align15_loop:
|
||||
xor rax, rax
|
||||
|
||||
align 64
|
||||
%rep 15
|
||||
nop
|
||||
%endrep
|
||||
.loop:
|
||||
inc rax
|
||||
cmp rdi, rax
|
||||
jne .loop
|
||||
|
||||
ret
|
||||
|
||||
align31_loop:
|
||||
xor rax, rax
|
||||
|
||||
align 64
|
||||
%rep 31
|
||||
nop
|
||||
%endrep
|
||||
.loop:
|
||||
inc rax
|
||||
cmp rdi, rax
|
||||
jne .loop
|
||||
|
||||
ret
|
||||
|
||||
align63_loop:
|
||||
xor rax, rax
|
||||
|
||||
align 64
|
||||
%rep 63
|
||||
nop
|
||||
%endrep
|
||||
.loop:
|
||||
inc rax
|
||||
cmp rdi, rax
|
||||
jne .loop
|
||||
|
||||
ret
|
||||
|
||||
align75_loop:
|
||||
xor rax, rax
|
||||
|
||||
align 64
|
||||
%rep 75
|
||||
nop
|
||||
%endrep
|
||||
.loop:
|
||||
inc rax
|
||||
cmp rdi, rax
|
||||
jne .loop
|
||||
|
||||
ret
|
||||
|
||||
align90_loop:
|
||||
xor rax, rax
|
||||
|
||||
align 64
|
||||
%rep 90
|
||||
nop
|
||||
%endrep
|
||||
.loop:
|
||||
inc rax
|
||||
cmp rdi, rax
|
||||
jne .loop
|
||||
|
||||
ret
|
||||
|
||||
align112_loop:
|
||||
xor rax, rax
|
||||
|
||||
align 64
|
||||
%rep 112
|
||||
nop
|
||||
%endrep
|
||||
.loop:
|
||||
inc rax
|
||||
cmp rdi, rax
|
||||
jne .loop
|
||||
|
||||
ret
|
||||
|
||||
rat_add:
|
||||
mov rax, rdi
|
||||
|
||||
.loop:
|
||||
add rcx, 1
|
||||
add rcx, 1
|
||||
dec rax
|
||||
jnz .loop
|
||||
ret
|
||||
|
||||
rat_mov_add:
|
||||
mov rax, rdi
|
||||
|
||||
.loop:
|
||||
mov rcx, rax
|
||||
add rcx, 1
|
||||
mov rcx, rax
|
||||
add rcx, 1
|
||||
dec rax
|
||||
jnz .loop
|
||||
ret
|
||||
|
||||
read_1:
|
||||
align 64
|
||||
.loop:
|
||||
mov rax, [rdi]
|
||||
sub rsi, 1
|
||||
jnle .loop
|
||||
|
||||
ret
|
||||
|
||||
read_2:
|
||||
align 64
|
||||
.loop:
|
||||
%rep 2
|
||||
mov rax, [rdi]
|
||||
%endrep
|
||||
sub rsi, 2
|
||||
jnle .loop
|
||||
|
||||
ret
|
||||
|
||||
read_3:
|
||||
align 64
|
||||
.loop:
|
||||
%rep 3
|
||||
mov rax, [rdi]
|
||||
%endrep
|
||||
sub rsi, 3
|
||||
jnle .loop
|
||||
|
||||
ret
|
||||
|
||||
read_4:
|
||||
align 64
|
||||
.loop:
|
||||
%rep 4
|
||||
mov rax, [rdi]
|
||||
%endrep
|
||||
sub rsi, 4
|
||||
jnle .loop
|
||||
|
||||
ret
|
||||
|
||||
read_8:
|
||||
align 64
|
||||
.loop:
|
||||
%rep 8
|
||||
mov rax, [rdi]
|
||||
%endrep
|
||||
sub rsi, 8
|
||||
jnle .loop
|
||||
|
||||
ret
|
||||
|
||||
write_1:
|
||||
align 64
|
||||
.loop:
|
||||
mov QWORD [rdi], 0
|
||||
sub rsi, 1
|
||||
jnle .loop
|
||||
|
||||
ret
|
||||
|
||||
write_2:
|
||||
align 64
|
||||
.loop:
|
||||
%rep 2
|
||||
mov QWORD [rdi], 0
|
||||
%endrep
|
||||
sub rsi, 2
|
||||
jnle .loop
|
||||
|
||||
ret
|
||||
|
||||
write_3:
|
||||
align 64
|
||||
.loop:
|
||||
%rep 3
|
||||
mov QWORD [rdi], 0
|
||||
%endrep
|
||||
sub rsi, 3
|
||||
jnle .loop
|
||||
|
||||
ret
|
||||
|
||||
write_4:
|
||||
align 64
|
||||
.loop:
|
||||
%rep 4
|
||||
mov QWORD [rdi], 0
|
||||
%endrep
|
||||
sub rsi, 4
|
||||
jnle .loop
|
||||
|
||||
ret
|
||||
|
||||
write_8:
|
||||
align 64
|
||||
.loop:
|
||||
%rep 8
|
||||
mov QWORD [rdi], 0
|
||||
%endrep
|
||||
sub rsi, 8
|
||||
jnle .loop
|
||||
|
||||
ret
|
||||
|
||||
read_1x2_low:
|
||||
align 64
|
||||
.loop:
|
||||
%rep 2
|
||||
mov al, [rdi]
|
||||
%endrep
|
||||
sub rsi, 2
|
||||
jnle .loop
|
||||
|
||||
ret
|
||||
|
||||
read_1x2_high:
|
||||
align 64
|
||||
.loop:
|
||||
%rep 2
|
||||
mov ah, [rdi]
|
||||
%endrep
|
||||
sub rsi, 2
|
||||
jnle .loop
|
||||
|
||||
ret
|
||||
|
||||
read_2x2:
|
||||
align 64
|
||||
.loop:
|
||||
%rep 2
|
||||
mov ax, [rdi]
|
||||
%endrep
|
||||
sub rsi, 2
|
||||
jnle .loop
|
||||
|
||||
ret
|
||||
|
||||
read_4x2:
|
||||
align 64
|
||||
.loop:
|
||||
%rep 2
|
||||
mov eax, [rdi]
|
||||
%endrep
|
||||
sub rsi, 2
|
||||
jnle .loop
|
||||
|
||||
ret
|
||||
|
||||
read_8x2:
|
||||
align 64
|
||||
.loop:
|
||||
%rep 2
|
||||
mov rax, [rdi]
|
||||
%endrep
|
||||
sub rsi, 2
|
||||
jnle .loop
|
||||
|
||||
ret
|
||||
|
||||
read_4x2_simd:
|
||||
xor rax, rax
|
||||
|
||||
align 64
|
||||
.loop:
|
||||
mov r8d, [rdi]
|
||||
mov r8d, [rdi + 4]
|
||||
add rax, 8
|
||||
cmp rax, rsi
|
||||
jb .loop
|
||||
|
||||
ret
|
||||
|
||||
read_8x2_simd:
|
||||
xor rax, rax
|
||||
|
||||
align 64
|
||||
.loop:
|
||||
mov r8, [rdi]
|
||||
mov r8, [rdi + 8]
|
||||
add rax, 16
|
||||
cmp rax, rsi
|
||||
jb .loop
|
||||
|
||||
ret
|
||||
|
||||
read_16x2_simd:
|
||||
xor rax, rax
|
||||
|
||||
align 64
|
||||
.loop:
|
||||
vmovdqu xmm0, [rdi]
|
||||
vmovdqu xmm0, [rdi + 16]
|
||||
add rax, 32
|
||||
cmp rax, rsi
|
||||
jb .loop
|
||||
|
||||
ret
|
||||
|
||||
read_32x2_simd_offset:
|
||||
xor rax, rax
|
||||
|
||||
align 64
|
||||
.loop:
|
||||
vmovdqu ymm0, [rdi]
|
||||
vmovdqu ymm0, [rdi + 32]
|
||||
add rax, 64
|
||||
cmp rax, rsi
|
||||
jb .loop
|
||||
|
||||
ret
|
||||
|
||||
read_32x2_simd_no_offset:
|
||||
xor rax, rax
|
||||
|
||||
align 64
|
||||
.loop:
|
||||
vmovdqu ymm0, [rdi]
|
||||
vmovdqu ymm0, [rdi]
|
||||
add rax, 64
|
||||
cmp rax, rsi
|
||||
jb .loop
|
||||
|
||||
ret
|
||||
|
||||
read_16x4_simd:
|
||||
xor rax, rax
|
||||
|
||||
align 64
|
||||
.loop:
|
||||
%rep 2
|
||||
vmovdqu xmm0, [rdi]
|
||||
vmovdqu xmm0, [rdi + 16]
|
||||
%endrep
|
||||
add rax, 64
|
||||
cmp rax, rsi
|
||||
jb .loop
|
||||
|
||||
ret
|
||||
|
||||
read_32x4_simd:
|
||||
xor rax, rax
|
||||
|
||||
align 64
|
||||
.loop:
|
||||
%rep 2
|
||||
vmovdqu ymm0, [rdi]
|
||||
vmovdqu ymm0, [rdi]
|
||||
%endrep
|
||||
add rax, 128
|
||||
cmp rax, rsi
|
||||
jb .loop
|
||||
|
||||
ret
|
||||
|
||||
cache_test:
|
||||
xor r10, r10 ; Zero loop counter
|
||||
mov rbx, rdi ; Save original pointer
|
||||
.loop:
|
||||
add rdi, r10 ; Advance the pointer
|
||||
add r10, 128 ; Increment loop counter
|
||||
and r10, rdx ; Mask offset
|
||||
vmovdqu ymm0, [rdi + 0]
|
||||
vmovdqu ymm1, [rdi + 32]
|
||||
vmovdqu ymm2, [rdi + 64]
|
||||
vmovdqu ymm3, [rdi + 96]
|
||||
mov rdi, rbx ; Restore original pointer
|
||||
sub rsi, 128 ; Decrement count
|
||||
ja .loop
|
||||
ret
|
||||
|
||||
cache_test_unaligned:
|
||||
xor r10, r10 ; Zero loop counter
|
||||
add rdi, 5 ; Unalign pointer
|
||||
mov rbx, rdi ; Save original pointer
|
||||
.loop:
|
||||
add rdi, r10 ; Advance the pointer
|
||||
add r10, 128 ; Increment loop counter
|
||||
and r10, rdx ; Mask offset
|
||||
vmovdqu ymm0, [rdi + 0]
|
||||
vmovdqu ymm1, [rdi + 32]
|
||||
vmovdqu ymm2, [rdi + 64]
|
||||
vmovdqu ymm3, [rdi + 96]
|
||||
mov rdi, rbx ; Restore original pointer
|
||||
sub rsi, 128 ; Decrement count
|
||||
ja .loop
|
||||
ret
|
||||
168
haversine_02/src/repetition_testing/reptester.cc
Normal file
168
haversine_02/src/repetition_testing/reptester.cc
Normal file
@@ -0,0 +1,168 @@
|
||||
#include "repetition_testing/reptester.h"
|
||||
#include "profiler/timer.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
void handle_alloc(reptester *tester, alloc_type type) {
|
||||
switch (type) {
|
||||
case ALLOC_TYPE_WITH_MALLOC:
|
||||
if (!(tester->params.buffer)) {
|
||||
tester->params.buffer = (char *)mmap(
|
||||
NULL, tester->params.read_size + 1, PROT_READ | PROT_WRITE,
|
||||
MAP_ANON | MAP_SHARED | MAP_NORESERVE, -1, 0);
|
||||
memset(tester->params.buffer, 0, tester->params.read_size + 1);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void handle_free(reptester *tester, alloc_type type) {
|
||||
switch (type) {
|
||||
case ALLOC_TYPE_WITH_MALLOC:
|
||||
if (tester->params.buffer) {
|
||||
munmap(tester->params.buffer, tester->params.read_size + 1);
|
||||
tester->params.buffer = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void run_func_test(reptester *tester, reptest_func func, const char *func_name,
|
||||
alloc_type type) {
|
||||
tester->test_start_time = read_cpu_timer();
|
||||
tester->test_time_secs = 0.0;
|
||||
tester->current_run = 1;
|
||||
tester->tstats = {
|
||||
UINT64_MAX, // min_time
|
||||
0, // max_time
|
||||
0, // avg_time
|
||||
0, // total_time
|
||||
};
|
||||
tester->mstats = {
|
||||
UINT64_MAX, // min_faults
|
||||
0, // max_faults
|
||||
0, // avg_faults
|
||||
0, // total_bytes
|
||||
0, // total_faults
|
||||
};
|
||||
tester->results = {};
|
||||
|
||||
char *buffer = NULL;
|
||||
|
||||
if (type == ALLOC_TYPE_WITH_MALLOC) {
|
||||
buffer = tester->params.buffer;
|
||||
tester->params.buffer =
|
||||
(char *)mmap(NULL, tester->params.read_size + 1, PROT_READ | PROT_WRITE,
|
||||
MAP_ANON | MAP_SHARED | MAP_NORESERVE, -1, 0);
|
||||
memset(tester->params.buffer, 0, tester->params.read_size + 1);
|
||||
}
|
||||
|
||||
while (tester->test_time_secs <= tester->wait_time_secs) {
|
||||
func(tester, type);
|
||||
|
||||
if (tester->results.bytes_read <
|
||||
tester->params.read_size * tester->params.read_count) {
|
||||
printf("Failed to read the entire file (Total size: %lu, Bytes read: "
|
||||
"%lu)\n",
|
||||
tester->params.read_size, tester->results.bytes_read);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
tester->tstats.total_time += tester->results.read_time;
|
||||
tester->mstats.total_bytes += tester->results.bytes_read;
|
||||
tester->mstats.total_faults += tester->results.page_faults;
|
||||
|
||||
if (tester->results.read_time > tester->tstats.max_time) {
|
||||
tester->tstats.max_time = tester->results.read_time;
|
||||
tester->mstats.max_faults = tester->results.page_faults;
|
||||
} else if (tester->results.read_time < tester->tstats.min_time) {
|
||||
tester->test_start_time = read_cpu_timer();
|
||||
tester->tstats.min_time = tester->results.read_time;
|
||||
tester->mstats.min_faults = tester->results.page_faults;
|
||||
}
|
||||
|
||||
if (tester->results.page_faults > tester->mstats.max_faults) {
|
||||
tester->mstats.max_faults = tester->results.page_faults;
|
||||
} else if (tester->results.page_faults < tester->mstats.min_faults) {
|
||||
tester->mstats.min_faults = tester->results.page_faults;
|
||||
}
|
||||
|
||||
tester->test_time_secs = time_in_seconds(
|
||||
read_cpu_timer() - tester->test_start_time, tester->cpu_freq);
|
||||
|
||||
++(tester->current_run);
|
||||
}
|
||||
|
||||
if (type == ALLOC_TYPE_WITH_MALLOC) {
|
||||
munmap(tester->params.buffer, tester->params.read_size + 1);
|
||||
tester->params.buffer = buffer;
|
||||
}
|
||||
|
||||
print_results(tester, func_name);
|
||||
}
|
||||
|
||||
u64 page_fault_count() {
|
||||
rusage usage;
|
||||
|
||||
getrusage(RUSAGE_SELF, &usage);
|
||||
|
||||
return usage.ru_minflt + usage.ru_majflt;
|
||||
}
|
||||
|
||||
void print_results(reptester *tester, const char *name) {
|
||||
f64 kb = 1024.0;
|
||||
f64 gb = kb * kb * kb;
|
||||
|
||||
f64 size_in_kb =
|
||||
(f64)(tester->params.read_size * tester->params.read_count) / kb;
|
||||
f64 size_in_gb =
|
||||
(f64)(tester->params.read_size * tester->params.read_count) / gb;
|
||||
|
||||
u64 run_count = tester->current_run - 1;
|
||||
|
||||
tester->tstats.avg_time = tester->tstats.total_time / run_count;
|
||||
tester->mstats.avg_faults = tester->mstats.total_faults / run_count;
|
||||
|
||||
printf("\n%s: %lu runs\n", name, run_count);
|
||||
|
||||
printf("MIN: %lu (%fGB/s)", tester->tstats.min_time,
|
||||
size_in_gb /
|
||||
time_in_seconds(tester->tstats.min_time, tester->cpu_freq));
|
||||
if (tester->mstats.min_faults > 0) {
|
||||
printf(", FAULTS: %lu (%fK/fault)\n", tester->mstats.min_faults,
|
||||
size_in_kb / tester->mstats.min_faults);
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("MAX: %lu (%fGB/s)", tester->tstats.max_time,
|
||||
size_in_gb /
|
||||
time_in_seconds(tester->tstats.max_time, tester->cpu_freq));
|
||||
if (tester->mstats.max_faults > 0) {
|
||||
printf(", FAULTS: %lu (%fK/fault)\n", tester->mstats.max_faults,
|
||||
size_in_kb / tester->mstats.max_faults);
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("AVG: %lu (%fGB/s)", tester->tstats.avg_time,
|
||||
size_in_gb /
|
||||
time_in_seconds(tester->tstats.avg_time, tester->cpu_freq));
|
||||
if (tester->mstats.avg_faults > 0) {
|
||||
printf(", FAULTS: %lu (%fK/fault)\n", tester->mstats.avg_faults,
|
||||
tester->mstats.total_bytes / kb / tester->mstats.avg_faults);
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user