Created
November 8, 2016 00:20
-
-
Save CryptoManiac/1fc20439c00cf2b5848e736d824fb5e5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <sys/timeb.h> | |
#include <sys/types.h> | |
#include <vector> | |
#ifdef _WIN32 | |
# include <windows.h> | |
#else | |
# include <sys/time.h> | |
# include <unistd.h> | |
#endif | |
#include <iostream> | |
#include <iomanip> | |
#include <cstdint> | |
#if !defined(__clang__) && !defined(__INTEL_COMPILER) | |
#define __volatile__ volatile | |
#else | |
#define __volatile__ | |
#endif | |
using namespace std; | |
double time_s() | |
{ | |
#if defined(_WIN32) | |
struct __timeb64 time_struct; | |
int64_t time_ms; | |
_ftime64_s(&time_struct); | |
time_ms = (int64_t)time_struct.time; | |
time_ms *= 1000; | |
time_ms += time_struct.millitm; | |
return (time_ms / 1000.0); | |
#else | |
struct timeval time_struct; | |
int64_t time_ms; | |
gettimeofday(&time_struct, 0); | |
time_ms = (int64_t)time_struct.tv_sec; | |
time_ms *= 1000; | |
time_ms += (time_struct.tv_usec / 1000); | |
return (time_ms / 1000.0); | |
#endif | |
} | |
#define HALT 0 | |
#define PUSH 1 | |
#define DEC 2 | |
#define JUMP_NZ 3 | |
#ifdef _MSC_VER | |
# ifndef __INTEL_COMPILER_BUILD_DATE | |
# ifdef _WIN64 | |
# error "MSVC64 isn't supported, please use clang or intel c++ compiler" | |
# else | |
# define STORE(index,label) __asm lea eax, label __asm mov edx, data\ | |
__asm mov [edx][index * TYPE program],eax | |
# define JUMP() { void* addr = *(ip++); __asm jmp addr } | |
# define JUMP_INDIRECT() { void* addr = program[*(code++)]; __asm jmp addr } | |
# endif | |
# else | |
# define STORE(index,label) program[index] = &&label | |
# define JUMP() goto **(ip++) | |
# define JUMP_INDIRECT() goto *program[*(code++)] | |
# endif | |
#else | |
# define STORE(index,label) program[index] = &&label | |
# define JUMP() goto **(ip++) | |
# define JUMP_INDIRECT() goto *program[*(code++)] | |
#endif | |
#define GET_OPCODES 0 | |
#define RUN 1 | |
void execute_direct(void** program, vector<size_t>& stack, int operation) { | |
void** ip = (void**)program; | |
if (operation == GET_OPCODES) goto get_opcodes; | |
JUMP(); | |
op_halt: | |
return; | |
op_push: | |
stack.push_back(*((size_t*)(ip++))); | |
JUMP(); | |
op_dec: | |
{ | |
stack[stack.size() - 1]--; | |
JUMP(); | |
} | |
op_jump_nz: | |
{ | |
auto v = stack[stack.size() - 1]; | |
auto target = *(ip++); | |
if (v) { | |
ip = (void**)target; | |
} | |
JUMP(); | |
} | |
get_opcodes: | |
STORE(HALT, op_halt); | |
STORE(PUSH, op_push); | |
STORE(DEC, op_dec); | |
STORE(JUMP_NZ, op_jump_nz); | |
} | |
void execute_indirect(size_t* code, vector<size_t>& stack, int operation) { | |
void* buf[4]; | |
void** program = &buf[0]; | |
STORE(HALT, op_halt); | |
STORE(PUSH, op_push); | |
STORE(DEC, op_dec); | |
STORE(JUMP_NZ, op_jump_nz); | |
JUMP_INDIRECT(); | |
op_halt: | |
return; | |
op_push: | |
stack.push_back(*((size_t*)(code++))); | |
JUMP_INDIRECT(); | |
op_dec: | |
{ | |
stack[stack.size() - 1]--; | |
JUMP_INDIRECT(); | |
} | |
op_jump_nz: | |
{ | |
auto target = *(code++); | |
auto v = stack[stack.size() - 1]; | |
if (v) { | |
code = (size_t*)target; | |
} | |
JUMP_INDIRECT(); | |
} | |
get_opcodes: | |
STORE(HALT, op_halt); | |
STORE(PUSH, op_push); | |
STORE(DEC, op_dec); | |
STORE(JUMP_NZ, op_jump_nz); | |
} | |
void test_direct() { | |
vector<size_t> stack; | |
void* opcodes[4]; | |
void* program[6]; | |
double start_time, end_time; | |
execute_direct(opcodes, stack, GET_OPCODES); | |
program[0] = opcodes[PUSH]; | |
program[1] = (void*)2000000000; | |
program[2] = opcodes[DEC]; | |
program[3] = opcodes[JUMP_NZ]; | |
program[4] = &program[2]; | |
program[5] = opcodes[HALT]; | |
start_time = time_s(); | |
execute_direct(program, stack, RUN); | |
end_time = time_s(); | |
cout << "Direct threaded done in " << (end_time - start_time) << " seconds." << endl; | |
} | |
void test_indirect() { | |
vector<size_t> stack; | |
size_t program[6]; | |
double start_time, end_time; | |
program[0] = PUSH; | |
program[1] = 2000000000; | |
program[2] = DEC; | |
program[3] = JUMP_NZ; | |
program[4] = (size_t)&program[2]; | |
program[5] = HALT; | |
start_time = time_s(); | |
execute_indirect(program, stack, RUN); | |
end_time = time_s(); | |
cout << "Indirect threaded done in " << (end_time - start_time) << " seconds." << endl; | |
} | |
int main() { | |
test_direct(); | |
test_indirect(); | |
return 0; | |
} |
model name : Intel(R) Xeon(R) CPU E5405 @ 2.00GHz
$ g++-5 -O2 -std=c++11 dispatchtest_stack.cxx
$ ./a.out && ./a.out && ./a.out
Direct threaded done in 9.873 seconds.
Indirect threaded done in 12.187 seconds.
Direct threaded done in 9.833 seconds.
Indirect threaded done in 12.201 seconds.
Direct threaded done in 9.836 seconds.
Indirect threaded done in 12.197 seconds.
$ /opt/llvm-3.9.0/bin/clang++ -O2 -std=c++11 dispatchtest_stack.cxx
$ ./a.out && ./a.out && ./a.out
Direct threaded done in 7.48 seconds.
Indirect threaded done in 10.048 seconds.
Direct threaded done in 7.473 seconds.
Indirect threaded done in 10.052 seconds.
Direct threaded done in 7.479 seconds.
Indirect threaded done in 10.048 seconds.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
model name : Intel(R) Xeon(R) CPU 5130 @ 2.00GHz
$ g++-5 -std=c++11 -O2 dispatchtest_stack.cxx
$ ./a.out && ./a.out && ./a.out
Direct threaded done in 10.892 seconds.
Indirect threaded done in 12.792 seconds.
Direct threaded done in 10.895 seconds.
Indirect threaded done in 12.795 seconds.
Direct threaded done in 10.892 seconds.
Indirect threaded done in 12.791 seconds.
$ g++-6 -std=c++11 -O2 dispatchtest_stack.cxx
$ ./a.out && ./a.out && ./a.out
Direct threaded done in 10.894 seconds.
Indirect threaded done in 12.794 seconds.
Direct threaded done in 10.896 seconds.
Indirect threaded done in 12.79 seconds.
Direct threaded done in 10.894 seconds.
Indirect threaded done in 12.793 seconds.
$ clang++ -std=c++11 -O2 dispatchtest_stack.cxx
$ ./a.out && ./a.out && ./a.out
Direct threaded done in 7.514 seconds.
Indirect threaded done in 11.912 seconds.
Direct threaded done in 7.511 seconds.
Indirect threaded done in 11.9 seconds.
Direct threaded done in 7.511 seconds.
Indirect threaded done in 11.859 seconds.
$ icpc -std=c++11 -O2 dispatchtest_stack.cxx
$ ./a.out && ./a.out && ./a.out
Direct threaded done in 10.392 seconds.
Indirect threaded done in 12.434 seconds.
Direct threaded done in 10.452 seconds.
Indirect threaded done in 12.454 seconds.
Direct threaded done in 10.476 seconds.
Indirect threaded done in 30.197 seconds.