약 10 억 번 테스트 한 후 imm64
이 0.1 나노 초인 경우 m64
보다 빠릅니다. m64
은 더 빠를 것 같지만 실제로 이해할 수는 없습니다. 다음 코드의 val_ptr
의 주소가 바로 값이 아닌가?x86-64의 경우보다 빠른, imm64 또는 m64 중 어느 것입니까?
# Text section
.section __TEXT,__text,regular,pure_instructions
# 64-bit code
.code64
# Intel syntax
.intel_syntax noprefix
# Target macOS High Sierra
.macosx_version_min 10,13,0
# Make those two test functions global for the C measurer
.globl _test1
.globl _test2
# Test 1, imm64
_test1:
# Move the immediate value 0xDEADBEEFFEEDFACE to RAX (return value)
movabs rax, 0xDEADBEEFFEEDFACE
ret
# Test 2, m64
_test2:
# Move from the RAM (val_ptr) to RAX (return value)
mov rax, qword ptr [rip + val_ptr]
ret
# Data section
.section __DATA,__data
val_ptr:
.quad 0xDEADBEEFFEEDFACE
측정 코드는 다음과 같습니다 그래서
#include <stdio.h> // For printf
#include <stdlib.h> // For EXIT_SUCCESS
#include <math.h> // For fabs
#include <stdint.h> // For uint64_t
#include <stddef.h> // For size_t
#include <string.h> // For memset
#include <mach/mach_time.h> // For time stuff
#define FUNCTION_COUNT 2 // Number of functions to test
#define TEST_COUNT 0x10000000 // Number of times to test each function
// Type aliases
typedef uint64_t rettype_t;
typedef rettype_t(*function_t)();
// External test functions (defined in Assembly)
rettype_t test1();
rettype_t test2();
// Program entry point
int main() {
// Time measurement stuff
mach_timebase_info_data_t info;
mach_timebase_info(&info);
// Sums to divide by the test count to get average
double sums[FUNCTION_COUNT];
// Initialize sums to 0
memset(&sums, 0, FUNCTION_COUNT * sizeof (double));
// Functions to test
function_t functions[FUNCTION_COUNT] = {test1, test2};
// Useless results (should be 0xDEADBEEFFEEDFACE), but good to have
rettype_t results[FUNCTION_COUNT];
// Function loop, may get unrolled based on optimization level
for (size_t test_fn = 0; test_fn < FUNCTION_COUNT; test_fn++) {
// Test this MANY times
for (size_t test_num = 0; test_num < TEST_COUNT; test_num++) {
// Get the nanoseconds before the action
double nanoseconds = mach_absolute_time();
// Do the action
results[test_fn] = functions[test_fn]();
// Measure the time it took
nanoseconds = mach_absolute_time() - nanoseconds;
// Convert it to nanoseconds
nanoseconds *= info.numer;
nanoseconds /= info.denom;
// Add the nanosecond count to the sum
sums[test_fn] += nanoseconds;
}
}
// Compute the average
for (size_t i = 0; i < FUNCTION_COUNT; i++) {
sums[i] /= TEST_COUNT;
}
if (FUNCTION_COUNT == 2) {
// Print some fancy information
printf("Test 1 took %f nanoseconds average.\n", sums[0]);
printf("Test 2 took %f nanoseconds average.\n", sums[1]);
printf("Test %d was faster, with %f nanoseconds difference\n", sums[0] < sums[1] ? 1 : 2, fabs(sums[0] - sums[1]));
} else {
// Else, just print something
for (size_t fn_i = 0; fn_i < FUNCTION_COUNT; fn_i++) {
printf("Test %zu took %f clock ticks average.\n", fn_i + 1, sums[fn_i]);
}
}
// Everything went fine!
return EXIT_SUCCESS;
}
, 정말 빠른 인 m64
또는 imm64
?
그런데 인텔 코어 i7 아이비 브리지와 DDR3 RAM을 사용하고 있습니다. 나는 macOS High Sierra를 실행 중입니다.
편집 : 나는 ret
지침을 삽입하고, 지금 imm64
빨리 밝혀졌다.
정확히 어떻게 테스트 했습니까? 당신의'_test1'은 리턴하지 않습니다 : 그것은'_test2'로 넘어갑니다. (또한 넘어짐). 전혀 풀어 봤니? –
테스트 함수의 호출마다'mach_absolute_time()'을 두 번 호출합니다!?!?! ???? ???? 적어도 RDTSC 명령 (21 uops 및 IvB에서 27c 당 하나의 처리량)을 실행해야하기 때문에 오랜 시간이 걸립니다. 아마도 프론트 엔드에서 병목 현상을 일으키지 않을 것입니다. –
하지만 어떻게 해결할 수 있습니까? – SpilledMango