저는 매우 긴 정수 (10 진수 약 10,000 자리)를 곱하기 위해 산술 연산을하고 있습니다. 내 도서관의 일환으로 2 개의 긴 번호를 추가하겠습니다.x64 어셈블러의 속도를 높입니다.
프로파일 링은 내 코드가 add() 및 sub() 루틴에서 시간의 최대 25 %까지 실행된다는 것을 보여주기 때문에 최대한 빨리 수행해야합니다. 그러나 나는 아직 많은 가능성을 보지 못했다. 어쩌면 당신은 나에게 도움, 조언, 통찰력 또는 아이디어를 줄 수 있습니다. 나는 그들을 시험 할 것이고 당신에게 돌아갈 것이다.
지금까지 내 추가 루틴은 몇 가지 설정을 수행 한 후 8 배 풀려 루프를 사용하여 다른 오프셋 (offset)를
mov rax, QWORD PTR [rdx+r11*8-64]
mov r10, QWORD PTR [r8+r11*8-64]
adc rax, r10
mov QWORD PTR [rcx+r11*8-64], rax
7 개 블록을 따라 다음 루프.
이전에 메모리에서 값을로드하려고 시도했지만 도움이되지 않았습니다. 나는 그것이 좋은 prefetching 때문이라고 생각합니다. 나는 Intel i7-3770 Ivy Bridge 4 코어 CPU를 사용합니다. 하지만 현대의 CPU에서 잘 작동하는 코드를 작성하고 싶습니다.
편집 : 몇 가지 타이밍을 수행했습니다. 약 2.25 cycles/word로 1k 단어를 추가합니다. ADC를 제거하면 MOV 만 남아 있으므로 약 1.95 cycles/word가 걸립니다. 따라서 주요 병목 현상은 메모리 액세스 인 것 같습니다. 라이브러리 memcpy()
은 약 0.65 cycles/word에서 작동하지만 입력이 하나 뿐이며 두 개가 아닙니다. SSE 레지스터를 사용하기 때문에 훨씬 빠릅니다.
몇 가지 질문 :
- 그것은 구조를 "부하, 부하, 저장소를 추가"또는 "부하가, 추가로 메모리"도움이 될 것이다 사용하는 것이 유용하다? 지금까지 내 테스트는 어떤 이점도 보이지 않았습니다.
- 평상시처럼 SSE (2,3,4)의 도움을받을 수 있습니까?
- 어드레싱 (스케일 된 인덱스 + 기본 플러스 오프셋)이 심하게 영향을 줍니까? 대신
ADD r11, 8
을 사용할 수 있습니다. - 루프 언 롤링은 어떻게됩니까? 나는 언 롤링이 샌디 브릿지 아키텍처 (Agner Fog http://www.agner.org/optimize/)에 좋지 않다고 읽었습니다. 그것이 선호되거나 피할 수 있습니까?
- (편집) SSE 레지스터를 사용하여 큰 덩어리의 단어를 메모리에서로드하고 저장하고 범용 레지스터 및 SSE 레지스터와 효율적으로 단어를 교환 할 수 있습니까?
매우 고맙게 생각합니다.
매우 큰 숫자를 곱하는 가장 빠른 방법은 빠른 푸리에 변환입니다. http://en.wikipedia.org/wiki/Multiplication_algorithm 어셈블러에서 로직을 구현하려 한 적이 없었습니다. Apperantly Prime95는 x86 어셈블리 로직에서 고속 푸리에 변환을 포함하고 있으며, 거기에서 (자유롭게) 취할 수 있습니다. –
감사합니다. 지금은 빨리 추가하고 싶습니다. – cxxl
GMP 소스를 살펴볼 수 있습니다. – zch