Я написал эти два решения для Project Euler Q14 в сборке и на С++. Они представляют собой одинаковый подход грубой силы для тестирования гипотезы Collatz. Сборочный раствор был собран с помощью
nasm -felf64 p14.asm && gcc p14.o -o p14
C++ был скомпилирован с
g++ p14.cpp -o p14
Сборка, p14.asm
section .data
fmt db "%d", 10, 0
global main
extern printf
section .text
main:
mov rcx, 1000000
xor rdi, rdi ; max i
xor rsi, rsi ; i
l1:
dec rcx
xor r10, r10 ; count
mov rax, rcx
l2:
test rax, 1
jpe even
mov rbx, 3
mul rbx
inc rax
jmp c1
even:
mov rbx, 2
xor rdx, rdx
div rbx
c1:
inc r10
cmp rax, 1
jne l2
cmp rdi, r10
cmovl rdi, r10
cmovl rsi, rcx
cmp rcx, 2
jne l1
mov rdi, fmt
xor rax, rax
call printf
ret
С++, p14.cpp
#include <iostream>
using namespace std;
int sequence(long n) {
int count = 1;
while (n != 1) {
if (n % 2 == 0)
n /= 2;
else
n = n*3 + 1;
++count;
}
return count;
}
int main() {
int max = 0, maxi;
for (int i = 999999; i > 0; --i) {
int s = sequence(i);
if (s > max) {
max = s;
maxi = i;
}
}
cout << maxi << endl;
}
Я знаю о оптимизации компилятора, чтобы улучшить скорость и все, но я не вижу много способов оптимизации моего решения сборки (говоря программно не математически).
Код С++ имеет модуль каждого члена и деления каждый четный член, где сборка - только одно подразделение на четный член.
Но сборка занимает в среднем 1 секунду дольше, чем решение на С++. Почему это? Я прошу из любопытства.
Изменить: Время выполнения по запросу
Моя система: 64-разрядная Linux на 1,4 ГГц Intel Celeron 2955U (микроархитектура Haswell).
-
g++
(unoptimized): avg 1272 мс -
g++ -O3
avg 578 мс -
оригинал asm (div) avg 2650 мс
-
Asm (shr)
avg 679 мс -
@johnfound asm, собранный с помощью nasm avg 501 мс
-
@hidefromkgb asm avg 200 мс
-
@hidefromkgb asm оптимизирован @Peter Cordes avg 145 мс
-
@Veedrac С++ avg 81 ms с
-O3
, 305ms с-O0