를 사용하고 싶은 향상된 담당자 MOVSB(ERMSB)고 대역폭 사용자 정의memcpy 를
.
ERMSB 으로 소개되었 Ivy Bridge 마이크로 아키텍처. 섹션을 참조하십시오"향상된 담당자 MOVSB 및 STOSB 작업(ERMSB)"에서인텔 최적화 manual너't know what ERMSB 입니다.
내가 아는 유일한 방법을 이렇게 직접적으로 인라인이 어셈블리입니다. 나는 다음과 같은 함수에서 https://groups.google.com/forum/#!항목/수 있습니다.습니다.도움말/-Bmlm_EG_fE
static inline void *__movsb(void *d, const void *s, size_t n) {
asm volatile ("rep movsb"
: "=D" (d),
"=S" (s),
"=c" (n)
: "0" (d),
"1" (s),
"2" (n)
: "memory");
return d;
}
을 사용할 때 그러나 이것은 대역폭 보다 훨씬 적으로memcpy 를
.
__movsb
가 15GB/smemcpy 를
get26GB/s 내 i7-6700HQ(스카이 레이크)시스템,우분투 16.10,DDR4@2400MHz 듀얼 채널 32GB,GCC6.2.
이유는 대역폭이 많이 낮을 가진REP MOVSB
? 내가 무엇을 할 수가합니다.
는 코드는 다음과 같습니다 내가 사용하는 이 테스트합니다.
//gcc -O3 -march=native -fopenmp foo.c
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stddef.h>
#include <omp.h>
#include <x86intrin.h>
static inline void *__movsb(void *d, const void *s, size_t n) {
asm volatile ("rep movsb"
: "=D" (d),
"=S" (s),
"=c" (n)
: "0" (d),
"1" (s),
"2" (n)
: "memory");
return d;
}
int main(void) {
int n = 1<<30;
//char *a = malloc(n), *b = malloc(n);
char *a = _mm_malloc(n,4096), *b = _mm_malloc(n,4096);
memset(a,2,n), memset(b,1,n);
__movsb(b,a,n);
printf("%d\n", memcmp(b,a,n));
double dtime;
dtime = -omp_get_wtime();
for(int i=0; i<10; i++) __movsb(b,a,n);
dtime += omp_get_wtime();
printf("dtime %f, %.2f GB/s\n", dtime, 2.0*10*1E-9*n/dtime);
dtime = -omp_get_wtime();
for(int i=0; i<10; i++) memcpy(b,a,n);
dtime += omp_get_wtime();
printf("dtime %f, %.2f GB/s\n", dtime, 2.0*10*1E-9*n/dtime);
}
이유는 나에 관심있는rep movsb
을 기반으로 이 댓글
오브 및 Haswell 으로,버퍼 크기에 맞는 MLC 을 이길 수 있습니 movntdqa 를 사용하여 담당자 movsb;movntdqa 발생 RFO 로 LLC,rep movsb 지 않... 담당자 movsb 보다 훨씬 빠르게 작업을 처리 movntdqa 경우 스트리밍을 메모리에브 및 스웰(지만 알고 있어야 pre-브 그것은 느립니다!)
여기에는 나의 결과는 동일한 시스템에서tinymembnech.
C copy backwards : 7910.6 MB/s (1.4%)
C copy backwards (32 byte blocks) : 7696.6 MB/s (0.9%)
C copy backwards (64 byte blocks) : 7679.5 MB/s (0.7%)
C copy : 8811.0 MB/s (1.2%)
C copy prefetched (32 bytes step) : 9328.4 MB/s (0.5%)
C copy prefetched (64 bytes step) : 9355.1 MB/s (0.6%)
C 2-pass copy : 6474.3 MB/s (1.3%)
C 2-pass copy prefetched (32 bytes step) : 7072.9 MB/s (1.2%)
C 2-pass copy prefetched (64 bytes step) : 7065.2 MB/s (0.8%)
C fill : 14426.0 MB/s (1.5%)
C fill (shuffle within 16 byte blocks) : 14198.0 MB/s (1.1%)
C fill (shuffle within 32 byte blocks) : 14422.0 MB/s (1.7%)
C fill (shuffle within 64 byte blocks) : 14178.3 MB/s (1.0%)
---
standard memcpy : 12784.4 MB/s (1.9%)
standard memset : 30630.3 MB/s (1.1%)
---
MOVSB copy : 8712.0 MB/s (2.0%)
MOVSD copy : 8712.7 MB/s (1.9%)
SSE2 copy : 8952.2 MB/s (0.7%)
SSE2 nontemporal copy : 12538.2 MB/s (0.8%)
SSE2 copy prefetched (32 bytes step) : 9553.6 MB/s (0.8%)
SSE2 copy prefetched (64 bytes step) : 9458.5 MB/s (0.5%)
SSE2 nontemporal copy prefetched (32 bytes step) : 13103.2 MB/s (0.7%)
SSE2 nontemporal copy prefetched (64 bytes step) : 13179.1 MB/s (0.9%)
SSE2 2-pass copy : 7250.6 MB/s (0.7%)
SSE2 2-pass copy prefetched (32 bytes step) : 7437.8 MB/s (0.6%)
SSE2 2-pass copy prefetched (64 bytes step) : 7498.2 MB/s (0.9%)
SSE2 2-pass nontemporal copy : 3776.6 MB/s (1.4%)
SSE2 fill : 14701.3 MB/s (1.6%)
SSE2 nontemporal fill : 34188.3 MB/s (0.8%)
참고하는 시스템에SSE2 사본을 프리패치된
도보다 더 빨리MOVSB 복사
.
에서 내 원한 테스트를 해제하지 않습니다. 나는 장애인 터보고 다시 테스트하고 나타나지 않을 만들의 많은 차이가 있습니다. 그러나 변경하는 전원 관리를 만들지 않는 큰 차이가 있습니다.
가
sudo cpufreq-set -r -g performance
나는 때로는 볼 20GB/srep movsb
.
가
sudo cpufreq-set -r -g powersave
최고 약 17GB/s. 하지만memcpy 를
보이지 않는 것에 민감한 전력 관리합니다.
확인하여 주파수를 사용하여(turbostat
)[없는 스피드스텝을 사용](https://askubuntu.com/a/620114/259597 함),performance
및절
유휴,1 핵심 부하와 4 핵심 부하. 나는 Intel's MKL 조밀한 행렬의 곱셈를 만드는 로드리고 스레드의 수를 설정을 사용하여OMP_SET_NUM_THREADS
. 여기에는 테이블의 결과(수 GHz).
SpeedStep idle 1 core 4 core
powersave OFF 0.8 2.6 2.6
performance OFF 2.6 2.6 2.6
powersave ON 0.8 3.5 3.1
performance ON 3.5 3.5 3.1
이와 함께절
도와 스피드스텝 비활성화 CPU
여전히 시계 아래로 유휴 상태의 주파수0.8GHz
. It's 만으로 성능이 없는 스피드스텝 CPU 에서 실행되는 일정한 주파수이다.
나는 사용자.gsudo 조정기를 설정-r 성능(기 때문에
조정기를 설정 되었을 주는 이상한 결과)설정. 이집 터보도했던 사용하지 않는 터보다.
이 주제에 아주 가까이 내 마음에 그리고 최근 조사에는,그래서 나는'll 에서 보면 몇 가지 각도:역사,일부 기술 사항(대부분 학술)테스트 결과에 내 상자,그리고 마지막으로 하려고 대답은 실제 문제는 언제 어디서rep movsb
의미가 있습니다.
부분적으로,이것은전화하는 결과를 공유-만약 당신을 실행할 수 있[Tinymembench](https://github.com/ssvb/tinymembench 다)및 공유하는 결과가 세부정보와 함께 귀하의 CPU RAM 구성 그것은 좋은 것입니다. 특히 있을 경우 4-채널의 설치,아이비리자,서버 상자,등등.
성능의 역사는 빠른 문자열로 복사 지침이 되었습의 비트가 계단식으로 일-예:기간의 정체성능 교류와 함께 큰 업그레이드는 라인으로 그들을 나보다 더 빨리 경쟁에 접근한다. 예를 들어,거기에서 점프 성능 Nehalem(대부분 타겟팅을 시작 오버헤드)에서 다시 아이비브릿지(가장 타겟팅을 총 처리량을 위한 대형 복사본). 을 찾을 수 있습 decade-old 에 대한 통찰력 어려움의 구현rep movs
지침에서는 인텔의 엔지니어에서 이 thread.
예를 들어,가이드는 이전의 소개 Ivy Bridge,전형적인[조언](https://stackoverflow.com/a/8429084/149138 는)그들을 피하기 위해 사용하거나 매우 조심스럽게1.
현재(만,June2016)가이드에는 다양한 복잡하고 다 일치하지 않는 조언과 같2:
특정 변종의 구현은 선택된 실행 시간 데이터를 기반으로 레이아웃,정렬 및 카운터(우 exc)값입니다. 대 예를 들어,MOVSB/STOSB 가진 담당자는 접두어로 사용되어야 카운터 값보다 작거나 같은 세 가지 최고의 성능을 얻을 수 있습니다. 그래서 사본 3 바이트는? 지't 필요로
대표
에 대한 접두사에서는 첫 번째 장소,이후로 주장이 시작 대기 시간을~9 주기 당신은 거의 확실히 더 나은 간단한 DWORD 또는 QWORDmov
의 비트와 함께 비트-을 만지작거리고 마스크에 사용하지 않는 바이트를(혹은 2 개의 명시적인 바이트 단어는mov 의 크기를 알고 있는 경우 정확히 세). 그들은 말하기: String 이동/저장소 지침을 여러 개 있는 데이터의 세부. 대 효율적인 데이터 이동,대규모 데이터 세부적으로는 바람직합니다. 이것은 더 나은 효율성에 의해 달성될 수 있습 분 임의의 카운터 값의 번호로 두 단어 플러스의 단바이트 이동과 함께 카운트 값보다 작거나 같 3. 이것은 확실히 잘못된 것 같다 현재 하드웨어와 함께 ERMSB 는
rep movsb은 적어도,빠른 속도로는 빠르게,보다
movd또는
movq변형을 위한 대형 복사본입니다. 일반적으로,그 부분(3.7.5)현재 가이드 혼합되어 합리적이고 나쁘게 되는 조언. 이것은 일반적 처리량 Intel 매뉴얼,그들은 이후에 업데이트 증분 패션에 대한 각각의 건축(그 취지를 커버하는 거의 두 가지 수십 년 동안의 가치를 아키텍처에서도 현재 설명서),및 오래된 섹션은 자주 업데이트되지 않을 교체 또는 조건부 조언이지 않는't 에 적용되는 현재 건물입니다. 그들은 다음에 덮 ERMSB 에서 명시적으로 섹션 3.7.6. 나't 통해 이동의 나머지 조언을 철저하게,하지만 나는'll 요약의 좋은 부분에서"을 사용하는 이유 그"다. 다른 중요한 주장 가이드에서는 스웰,
rep movsb`을 사용하도록 개선되었습 256-bit 작업이 내부적으로 합니다.기술적 고려 사항
이것은 단지 요약의 기본 이점과 불리는
대표
지침에서 implementation standpoint.이점에 대한
rep movs
- 때
rep
movs 명령이 발행된 CPUknows 는 전체 블록을 차지 알려진 크기를 전송할 수 있습니다. 이 도울 수 있는 그것의 운영을 최적화하는 방법에 있는 그것은 없으로 개별 지침,예를 들어: -피 RFO 요구 때 그것을 알고 전체 캐시 라인이 덮어쓸 수 있습니다. 발행 prefetch 행하여 즉시 요청을 처리하고 정확하게. 하드웨어리에서 좋은 일을 검출하는memcpy 를
같은 패턴이지만,그것은 여전히 몇 가지 읽기 킥이"over-prefetch"많은 캐쉬 라인의 끝을 넘어 복사한다.rep movsb
을 정확히 알고 있는 지역의 크기와 프리패치할 수 있습니다.- 분명히는 보장은 없 주문의 저장 중에서3단일
rep movs
도울 수 있는 간소화 뿐 아니라 교통이 단순히 다른 측면의 이동,대한 간단한mov
지침을 준수해야는 오히려는 엄격한 메모리 주문4.- 원칙적으로,
rep movs
명령을 활용할 수 있는 다양한 건축 트릭지 않는't 에 노출 ISA. 예를 들어,아키텍처에 있는 넓은 내부 데이터 경로가 ISA 노출5그리고담당자 movs
사용할 수 있는 내부적으로 합니다.단점
1.
rep movsb
을 구현해야 합니다 특정한 의미할 수 있는 것보다 더 강한 근본적인 소프트웨어 요구 사항입니다. 특히,memcpy 를
금지 겹치는 지,그리고 무시할 수 있는 가능성하지만,rep movsb
할 수 있습을 생산하는 예상된 결과입니다. 에는 현재 구현 대부분 영향을 미치를 시작한 오버헤드지만,아마의 큰 블록의 처리량을 자랑합니다. 마찬가지로,rep movsb
지원해야 합니다 바이트 단위 세분화된 복사본을 경우에 당신은 실제로 그것을 사용하여 복사이 큰 블록는 여러 개의 대형 전력의 2.- 소프트웨어 있을 수 있습에 대한 정보를 정렬,복사기 및싱 가능한 전달할 수 없는 하드웨어를 사용하는 경우
rep movsb
. 컴파일러는 종종 확인할 수 있습니다형의 메모리 블록6그리고 그렇게 피할 수 있는 많은 작업을 시작하는 대 movs`해야 할 every 호출을 기반으로 합니다.테스트 결과
여기에는 테스트 결과에 대한 많은 다른 복사하는 방법에서[
tinymembench
](https://github.com/ssvb/tinymembench 에)내 i7-6700HQ 에 2.6GHz(너무 나쁜 나는 동일한 CPU 그래서 우리는't 새로운 데이터 지점을...):
C copy backwards : 8284.8 MB/s (0.3%)
C copy backwards (32 byte blocks) : 8273.9 MB/s (0.4%)
C copy backwards (64 byte blocks) : 8321.9 MB/s (0.8%)
C copy : 8863.1 MB/s (0.3%)
C copy prefetched (32 bytes step) : 8900.8 MB/s (0.3%)
C copy prefetched (64 bytes step) : 8817.5 MB/s (0.5%)
C 2-pass copy : 6492.3 MB/s (0.3%)
C 2-pass copy prefetched (32 bytes step) : 6516.0 MB/s (2.4%)
C 2-pass copy prefetched (64 bytes step) : 6520.5 MB/s (1.2%)
---
standard memcpy : 12169.8 MB/s (3.4%)
standard memset : 23479.9 MB/s (4.2%)
---
MOVSB copy : 10197.7 MB/s (1.6%)
MOVSD copy : 10177.6 MB/s (1.6%)
SSE2 copy : 8973.3 MB/s (2.5%)
SSE2 nontemporal copy : 12924.0 MB/s (1.7%)
SSE2 copy prefetched (32 bytes step) : 9014.2 MB/s (2.7%)
SSE2 copy prefetched (64 bytes step) : 8964.5 MB/s (2.3%)
SSE2 nontemporal copy prefetched (32 bytes step) : 11777.2 MB/s (5.6%)
SSE2 nontemporal copy prefetched (64 bytes step) : 11826.8 MB/s (3.2%)
SSE2 2-pass copy : 7529.5 MB/s (1.8%)
SSE2 2-pass copy prefetched (32 bytes step) : 7122.5 MB/s (1.0%)
SSE2 2-pass copy prefetched (64 bytes step) : 7214.9 MB/s (1.4%)
SSE2 2-pass nontemporal copy : 4987.0 MB/s
몇 가지 주요 테이크 아웃:
-는rep movs
방법보다 더 빨리 다른 모든 방법을 하지't"non-temporal"7며,보다 상당히 빠르게"C"접근법이 어떤 복사본 8 바이트다.
-면"non-temporal"방법은 빠르게,에 의해 최대 약 26%보다rep movs
그들-그러나는's 훨씬 작은 델타 보다 당신이보고(26GB/s 의 대 15GB/s=~73%).
-사용하지 않는 경우에는 비즈-임시 저장,사용 8 바이트의 사본에서 C 꽤 많은만큼 좋은 128-bit wide SSE 로드/상점이다. 는's 기 때문에 좋은 사본을 반복을 생성할 수 있는 충분한 메모리압의 포화의 대역폭(예를 들어,2.6GHz1store/사이클8bytes=26GB/s stores).
-이 없는 명시적 256-bit 알고리즘에서 tinymembench 제외하고(아"standard"memcpy 를
)하지만 그것은 아마는't 문제로 인해 위의 참고.
-의 처리량을 늘리의 일시적 저장소 접근 방법을 통해 시간들에 대해 1.45x 는 매우 가까이 1.5x 경우 기대 NT 없 1 3 전송을(즉,1,읽기 1 위해 쓰 NT vs2 읽기,1 쓰). 는rep movs
접근이 거짓말에서 중간에 있습니다.
-의 조합이 매우 낮은 메모리 대기와 겸손 2-채널 대역폭을 의미이 특정 칩게 발생할 수 있 포화의 메모리 대역폭에서 하나의 스레드는 동작을 변경합니다.
-rep movsd
를 사용하는 것으rep movsb
에서 이러 칩입니다. 는's 기 때문에 재미있 ERMSB 만 명시적으로 대상movsb
이 시험에서 이 archs 와 ERMSB 쇼movsb
공연보다 훨씬 빠르게movsd
. 이것은 주로 학부터movsb
더보다 일반적으로movsd
anyway.
보고스웰 결과친절하게 제공하여 iwillnotexist 의견에,우리는 같은 일반적인 동향(가장 관련성이 높은 결과를 추출):
C copy : 6777.8 MB/s (0.4%)
standard memcpy : 10487.3 MB/s (0.5%)
MOVSB copy : 9393.9 MB/s (0.2%)
MOVSD copy : 9155.0 MB/s (1.6%)
SSE2 copy : 6780.5 MB/s (0.4%)
SSE2 nontemporal copy : 10688.2 MB/s (0.3%)
는rep movsb
접근 방식은 여전히 느린 것보다 비 측memcpy 를
지만,약 14%여기는(비~26%에서 스카이 레이크 테스트). 장점 NT 의 기술은 위의 그들의 시간적인 사촌은 지금~57%,심지어 조금 이상 이론적 이익의 대역폭 감소입니다.
rep movs
?마지막으로 자신의 실제적인 질문에:때 또는 왜 당신은 그것을 사용해야합니까? 그것은 그 이상에서 소개하고 몇 가지 새로운 아이디어가 있습니다. 불행하게도 없습니다 간단한 대답:'ll 가 무역하는 다양한 요인을 포함하여,일부는 당신은 아마 수 있't 알지도 정확히 같은 미래의 발전이 있습니다.
참고는 대안rep movsb
할 수 있는 최적화된 libcmemcpy 를
(사본을 포함하는 인라인하여 컴파일러),또는이 될 수 있습 손으로 압연memcpy 를
버전입니다. 아래의 몇 가지 이점을 적용에서만 비교하는 하나 또 다른 이러한 대안(예를들면,"단순"도움에 대 한 손으로 압연전지에 대한 건축-memcpy 를
)하지만,일부 모두 적용됩니다.
일부 환경에서는 거기에 제한 지침 또는 특정을 사용하여 특정 레지스터가 있습니다. 예를 들어,리눅스 커널을 사용하여 SSE/AVX 또는 FP 레지스터는 일반적으로 허용되지 않습니다. 따라서 대부분의 최적화memcpy 를
개으로 사용할 수 없습니다 그들은 그에 의존하 SSE 또는 AVX 등록,그리고 보통 64-bitmov
-기반 복사본을 사용에 x86. 이러한 플랫폼을 사용하여,rep movsb
할 수 있습의 대부분은 성능의 최적화된memcpy 를
을 파괴하지 않고에 대한 제한 SIMD 코드입니다.
좀 더 일반적인 예로 들 수 있습 있는 코드를 대상 많은 세대의 하드웨어,그리고는't 을 사용 하드웨어-특정 파견(예를 들어,사용하는cpuid
). 여기서 당신은 수도에 사용하도록 강제 만 나이 명령어 세트는 규칙이 어떤 AVX,등등.rep movsb
는 것도 좋은 방법이 여기 수 있기 때문"숨겨진"액세스를 넓은 하중과 상점을 사용하지 않고 새로운다. 를 대상으로 하는 경우에는 사전 ERMSB 하드웨어를'd 을 볼 수 있는 경우rep movsb
성능이 허용,하지만...
좋은 측면의rep movsb
할 수 있습,in theory 활용 건축에 대한 개선이 미래에 아키텍처,없이 소스의 변화,그 명시적 이동을 할 수 없습니다. 예를 들어,256-bit 데이터 경로가 도입,rep movsb
할 수 있었다 그것들을 활용하는(주장에 의해 인텔)없이 모든 변경 사항에 필요한 소프트웨어입니다. 소프트웨어를 사용하여 128-bit 동(는 최적의 전 Haswell)을 수정해야하고 다시 컴파일.
그래서 그것은 모두 소프트웨어에 유지 관리 혜택(을 변경할 필요가 없는 원본)및 혜택에 대한 기존 바이너리(필요 없이 배포하는 새로운 바이너리를 활용하는 개선).
이것이 얼마나 중요한 일인지에 따라 유지 보수 모형(예를들면,얼마나 자주 새로운 바이너리 배포에서 연습)과 매우 어려운 판단하는 방법 이러한 지시가 될 가능성이 있다. 에서 이상 인텔은 종류의 인도에서 사용하는 이 방향으로만 투입해서 적어도 reasonable 미래의 성능(15.3.3.6):
담당자 MOVSB 및 담당자 STOSB 계속 수행하는 합리적으로 잘에 미래 프로세서를 지원합니다.
겹치는 다음 작업
이 혜택지't 에서 평범
memcpy 를
벤치마크의 코스에 의해 정의하지 않't 후속 작업을 겹쳐,그 크기의 이득이 될 수 있는 것을 신중하게 측정하에서 실시 시나리오. 로 최대한 활용할 수 있습을 다시 수행해야 하는 조직의 코드를 둘러싼memcpy 를
. 이 혜택은 지적된 인텔의 최적화 설명서(섹션 11.16.3.4)및 그들의 말: 을 때 수은 것으로 알려진 적어도 천개의 바이트는 더 많은 사용하여, 개선된 담당자 MOVSB/STOSB 을 제공할 수 있는 또 다른 장점은 분할 비용의 비 소비 코드입니다. 휴리스틱 이해할 수 있다 의 값을 사용하여 Cnt=4096 고 작성 memset()예를 들어:•256-bit SIMD 의 구현을 작성 memset()를 발급해야/실행 은퇴 128 개의 인스턴스의 32 비트 저장 가동과 함께 VMOVDQA,기 non-소비 지침 시퀀스를 만들 수 있습니다 그들의 방법 은퇴.
•인스턴스의 강화된 담당자 STOSB 로우 exc=4096 은 디코딩로 오래 micro-op 흐름에 의해 제공 하드웨어 있지만,은퇴로 명령입니다. 많은 store_data 작업이 완료해야합니다 기 전에 결과를 작성 memset()사용할 수 있습니다. 기 때문에 완료 의 데이터를 저장 작업이 연결된 프로그램-기 위해 은퇴 상당한 부분의 비용 코드에 스트림할 수 있을 통해 프로세스 문제가/실행하고 은퇴,기본적으로 비용유하는 경우 non-소비 순서 경쟁하지 않는 상점을 위한 버퍼 리소스입니다. 그래서 인텔은 말하고 있는 모든 어떤 한 후 마이크로 연산 후에 코드
rep movsb
발표했지만,그 동안의 많은 상점에서 여전히 항공편 그리고담당자 movsb
전체적으로지 않았't 은퇴직,마이크로 연산에서 다음 지침을 더 만들 수 있습을 통해 진행 순서는 기계보다 그들이 할 수 있는 경우에는 코드가 후 복사본을 반복입니다. 의 마이크로 연산에서 명시적 부하 및 저장 반복 모두가 실제로 은퇴 별도로에서 프로그램 순서입니다. 있는 일어나면서 약탈해 다음과 같은 마이크로 연산. 있는't 할 수 없는 방법에 대한 자세한 정보를 매우 긴 microcoded 명령처럼 담당자 movsb
일했습니다. 우리는't 는 방법을 정확하게 알고있는 마이크로 코드를 가지 요청의 다른 스트림 마이크로 연산에서 마이크로 시퀀서,또는 마이크로 연산하는 방법이 중요하다고 생각합니다. 는 경우에는 개인 마이크로 연산 don't 은퇴해야한다는 별도로,아마도 전체 명령만 하나의 슬롯에 ROB? 프런트-엔드 피드 OoO 기계장치는rep movsb
명령에 uop 캐시 활성화하는 마이크로 시퀀 ROM(MS-ROM)를 보내기 마이크로 마이크로 연산으로 큐를 공급하는 문제,이름 변경,단계입니다. It's 아마도 가능하지 않은 어떤 다른 마이크로 연산하는 혼합에 있는 그리고 문제점/execute8는 동안rep movsb
여전히 발행하는,그러나 이후 지침을 가져올 수 있/디코딩 및 문제 오른쪽 마지막 후rep movsb
uop 않는 동안,몇 가지의 복사지't 실행되는 아직이다. 이것은 단지 유용한 경우 적어도 일부 이후 코드는't 결과에 따라 달라집의memcpy 를
(는't 한). 이제 크기의 이득은 제한:대부분에서 실행할 수 있습니다 N 지침(마이크로 연산이 실제로)이상 느린rep movsb
instruction,에서 어떤 시점'll stall NROB 사이즈. 현재 롭의 크기~200(192 스웰,224 에서 스카이 레이크),는's 최대의 이익을~200 사이클의 무료 작업에 대한 후속 코드는 IPC 를 1. 200 사이클을 복사할 수 있습니다 주위에 어딘가에 800 바이트에서 10gb/s,그래서 사본의 크기를 얻을 수 있습 무료에 가까운 작업의 비용 복사본(방식으로 복사본을 만드는 무료입니다). 사본으로 크기를 얻을 훨씬 더 큰 그러나의 상대적 중요성이 급격하게 줄어듭(예를 들어,복사하는 경우 80KB 대신,무료 작업의 1%를 복사용). 여전히,그것은 매우 흥미있는 적당한 크기의 복사본입니다. 루프 복사지't 완전히 차단 이후 지침에서 실행,중 하나입니다. 인텔은 세부 사항으로 이동하지 않는 크기의 이익을,또는 어떤 종류의 복사 또는 주변의 코드가 있는 대부분의 혜택을 누릴 수 있습니다. (뜨겁거나 찬 목적지 또는 소스,높은 ILP 또는 저렴한 ILP 높은 대기 시간 후 코드).드 크기
실행된 코드 크기(몇 바이트)는 현미경에 비해 일반적인 최적화
memcpy 를
루틴입니다. 는 경우에도 모든 제한에 의해 나가-캐(을 포함한 uop 캐시)미스,감소된 코드 사이즈 될 수 있습니다. 다시,우리가 할 수 바인딩 크기의 이 혜택 크기를 기반으로의 복사본입니다. 나't 이 실제로 그것을 수치적으로,그러나 직관은 줄이는 동적 코드 크기에 의해 B 바이트를 저장할 수 있습니다 가장C*B
캐리,약속 C. 모든 call 을memcpy 를
발생 캐시 놓치 비용(또는 이익)한 번만의 이점이 높은 처리량이의 바이트 수를 복사됩니다. 그래서 대규모 전송이 높은 처리량을 지배하게 될 것이 캐시 효과. 다시,이것은 무언가를하는 것입니다 쇼에서는 일반 벤치마크 전체 반복이 의심에 맞 uop 캐시입니다. You'll 필요한 실제 장소에서 테스트를 평가하는 이 효과가 있다.키는 특정 최적화
당신이보고서에 하드웨어,
rep movsb
었고 상당히 느린 것보다는 플랫폼memcpy 를
. 그러나,여기에 보고서가 있다 반대의 결과에 이전 하드웨어(Ivy Bridge). 는's 완전히 그럴듯한 것으로 보이는 문자열에는 이동 작업을 주기적으로-그러나 모든 세대,그래서 그것을 잘 수 있습니다 더 빠르게 또는 적어도 묶어(어떤 시점에서 그것을 이길 수 있습에 기반한 다른 이점)에서는 아키텍처는 최신 가지만 뒤에 그 이후에 하드웨어입니다. Quoting디 Glew,사람을 알아야 한 두 가지에 대한 이를 구현한 후에 이들에 P6: 큰 약점을하고 빠른 문자열에서 마이크로었[...]의 마이크로 떨어의 조정과 함께 모든 세대를 받고,느린 느려질 때까지 누군가가 있어 주위를 담합니다. 그냥 남자 라이브러리 복사 폭포의 곡이다. 나는 것이 가능하다는 것 중 하나 는 기회를 놓쳤었을 사용하 128-bit 로드하고 저장할 때 게 되었습니다. 이 경우에는,그것으로 볼 수 있는 또 다른"특정 플랫폼"최적화를 적용하는 일반적인 매트릭-in-the-bookmemcpy 를
루틴에서 찾을 표준 라이브러리와 JIT 컴파일러:만에서 사용하는 아키텍처는 것이 좋다. JIT 또는 훼 컴파일이 쉽지만,정적으로 컴파일된 바이너리 이 필요 없는 플랫폼 특정 파견하지만,자주 이미 존재한다(때로는 구현에 링크를 시간),또는mtune
인수될 수 있는지 확인해 정적 결정합니다.단순
도에서 스카이 레이크,그것은 어디인가 떨어진 뒤에는 절대 가장 빠른 비의 시간적 기술,그것은 여전히 대부분보다 더 빨리 방식과는 very simple. 이 의미는 더 적은 시간에서 유효성,적은 수의 미스터리 버그,더 적은 시간을 조정하고 업데이트 몬스터`memcpy 를 구현한(또는,반대로,더 적은에 의존성의 변덕 표준 라이브러리 구현 자에 의존하는 경우는).
대기 시간이딩 플랫폼
메모리량에 바인딩 알고리즘9실제로 수 운영에서 두 개의 주요한 전반적인 정권:DRAM bandwidth 또는 동시/지연이다. 첫 번째드 중 하나는 당신은 아마 잘 알고:DRAM 하위 시스템에는 특정 이론 대역폭을 계산할 수 있다는 매우 쉽게 수에 따라 채널의 데이터 평가/폭이 및 주파수이다. 예를 들어,내 DDR4-2133 시스템으로 2 개 채널 시청이 있는 최대의 대역폭 2.133 8 2 =34.1GB/s,동누에보고 방주. 당신이't 이상 유지하는 비율에서 DRAM(일반적으로 다소 적으로 인해 다양한 비효율성)추가되는 모든 코어에는 소켓(즉,그것은 글로벌 제한에 대한 단일 소켓스 시스템). 다른 제한을 부과하여 어떻게 동시에 많은 요청의 핵심할 수 있는 실제로 문제를 하위 시스템 메모리. 상상하면 핵심만 있는 1 개의 요청에서 진행되면,64-byte 캐시인 경우에 요청을 완료되면,당신은 수행할 수 있습니다. 가정은 또한 매우 빠른 50ns 메모리 대기 시간이 길어집니다. 그럼에도 불구하고 큰 34.1GB/s DRAM bandwidth,you'd 만 64bytes/50ns=1.28GB/s,또는 4%미만 최대의 대역폭이 있습니다. 실제,코어할 수 있는 문제는 하나 이상의 요청 시,하지만 무제한 숫자입니다. 그것은 일반적으로 있다는 점을 이해하고 10line 채 buffers 당 핵심 사 L1 과 메모리 계층 구조,그리고 아마 16 그래서 채우기 버퍼를 사 L2 및 DRAM. 리 경쟁에 대한 동일한 자원이지만,이상을 줄일 수 있는 효과적인 대기 시간이 길어집니다. 에 대한 더 많은 정보에서 보고의 게시물박사의 대역폭이에 기록 topic대부분에서 인텔 포럼입니다. 여전히,most 최신 Cpu 에 의해 제한됩니다 this 요인,아 RAM 대역폭이 있습니다. 그들은 일반적으로 달성하는 12-20GB/s 의 코어당하는 동안,RAM 대역폭을 수 있습 50+GB/s(4 채널 시스템)가 있습니다. 만 최근 일부 gen2-채널"클라이언트"코어가는 것 같은 더 나은 언코어,아마도 더 많은 선 버퍼를 칠 수 있습니다 DRAM 제한에 하나의 핵심,그리고 우리의 스카이 레이크는 칩이 될 것들 중 하나입니다. 지금은 물론,이유가 있는 인텔 디자인 시스템 50GB/s DRAM bandwidth 는 동안을 유지<20GB/s 당 중핵으로 인해 동시성 제한:전 제한이 소켓 및 후자는 당 핵심입니다. 그래서 각각의 중핵 8 코어 시스템에 밀 수 있 20GB/s 의 가치가 요구되는 시점에서 그들이 될 것입니다 DRAM 제한이 있습니다. 왜 나는가에 대해 이? 기 때문에 최적의
memcpy 를
종종 구현에 따라 달라집하는 정권을 운영합니다. 당신은 DRAM BW limited(으로 우리 칩을 분명히 있지만,대부분의 아't on a single core)에 사용하여,비간 기록이 매우 중요하기 때문에 저장 읽기 위해 소유하는 정상적으로 폐기물 1/3 의 대역폭이 있습니다. 당신이 볼 수 있는 정확하게 테스트 결과에 위 memcpy 를 구현하는 don't 사용 NT 저장을 잃게의 1/3 자 대역폭이 있습니다. 만약 당신 동시성 제한되는,그러나,상황에서 균일하고 때로는 반대로,그러나입니다. 당신은 DRAM 대역폭을 절약하는,그래서 NT 저장하지 않't 도움말 및 그들도 해칠 수 있기 때문을 증가시킬 수 있습니 대기 때문에 전달 시간을 줄 버퍼할 수 있는 더 이상 보다는 시나리오를 prefetch 제공합 RFO 라인 LLC(또는 L2)및 그 후 저장을 완료에 LLC 에 대한 효과적인 낮은 대기 시간이 길어집니다. 마지막으로,_server_uncores 하는 경향이 훨씬 느리게 NT 점 이상 클라이언트 사람(그리고 높은 대역폭)을 강조하는 이 효과가 있다. 그래서 다른 플랫폼에서는 찾을 수 있습 NT 점은 보다 적게 유용(적어도 당신에 대해 하나의 스레드 성능)와 아마도rep movsb
승리는(있다면 그것은 두 세계의 최고). 정말,이 마지막 항목은 대부분 테스트합니다. 나는 알 NT 저장을 잃게 자신의 명백한 이점을 위한 하나의 스레드에서 테스트를 가장 archs(를 포함하여 현재 서버 archs),but I don't know howrep movsb
수행됩니다 상대적으로...참조
다른 좋은 소스 정의에 통합합니다. comp.아치 조의
rep movsb
대 대안입니다. 의 많은 좋은 주점에 대해 예측,구현 방법 I've 종종 제안은 작은 블록을 사용하여 겹치는 첫 번째 및/또는 읽기/쓰기하는 것보다 쓰기만 정확하게 필요한 바이트 수를(예를 들어,구현하는 모든 사본 9 일부터 16 바이트로 8 바이트로 복사할 수 있는 중첩에 최대 7 개의 바이트).1아마도 기도하는 것입 제한하는 경우,예를 들어,코드 크기는 매우 중요합니다. 2볼섹션 3.7.5:담당자 접두사과 데이터 이동. 3그 열쇠를 주의 이용만을 위해 다양한 상점에서 하나의 명령 자체:완료되면 블록의 상점이 여전히 나타나는 주문과 관련하여 이전과 이후의 저장합니다. 그래서 코드를 볼 수 있습니다 상점에서는
rep movs
기 with 관련하여 각 other 지와 관련하여 이전 또는 이후의 저장(그's 후자를 보장 당신은 일반적으로 필요). 그것만이 문제가 사용하는 경우에는 최종 사본의 대상적으로 동기화를 플래그를 대신 별도의 저장합니다. 4Note non-시간별 상점에는 또한 대부분의 피 주문 요구 사항에 있지만,연습rep movs
에 더욱 자유가 있기 때문에 여전히 몇 가지 주문 제약에서 화장실/NT 저장합니다. 5이것은 일반적이었다 후반 부분에서의 32-비트 시대에,많은 칩했 64-비트 데이터 경로(e.g 을 지원하기 위해,FPUs 는 지원을 위한 64 비트이블 타입)으로 구성되어 있습니다. 오늘날,"neutered"와 같은 칩을 Pentium 또는 Celeron 브랜드 AVX 장애인이지만,아마도rep movs
마이크로 사용할 수 있습 256b 드/상점이다. 6E.g., 로 인한 언어 맞춤 규정,선형성 또는 사업자,싱 규칙 또는 기타 정보를 결정은 컴파일때 정해진다. 의 경우에는 맞춤는 경우에도,정확한 정렬할 수 있't 결정,그들은 적어도 할 수있는 호이스트를 맞춤 검사 루프 또는 그렇지 않으면을 제거 중복을 검사합니다. 7I'm 가정을 만드는"standard"memcpy 를
는 선택 아닌 일시적 접근,이는 매우 가능성이 크기의 버퍼입니다. 8지 않는't 반드시는 명백한 이후,그것은 될 수 있는 경우 uop 스트림에 의해 생성되는rep movsb
단순도 독차지하지 말라 파견하고 그 다음은 보이는 것이 매우 다음과 같은 명시적으mov
경우입니다. 그것은 보인다는't 로 작동하는 것이나 마이크로 연산에서 후속한 지침 수 있습과 어울려 마이크로 연산에서 microcodedrep movsb
. 9I.e., 그할 수 있는 문제의 큰 숫자의 독립 메모리 요청에 따라서 포화할 수 있 DRAM-to-core 대역폭,는`memcpy 를 될 수 있을 것이스(및신을 순전히 대기 시간에 바인딩 부과 같은 포인터를 쫓고).
Ivy Bridge 마이크로 아키텍처(프로세서 발표에서 2012 년,2013 년)도입 Enhanced 담당자 MOVSB(우리는 여전히을 확인할 필요가 해당 비트)그리고 우리에 복사하는 메모리 빠르다. 저렴한 버전이 나중에 프로세서를 가지고 있으므로-Kaby 호 Celeron 및 Pentium,released in2017,don't AVX 는 사용되었을 수 있는 빠른 메모리로 복사하지만,여전히 향상된 담당자 MOVSB. 담당자 MOVSB(ERMSB)만보다 더 빨리 AVX 복사 또는 일반적인 사용이 등록할 경우 복사본 블록 크기는 최소 256 바이트입니다. 블록에 대한 아래 64 바이트를,그것은 훨씬 느리기 때문에 거기에 높은 내부에서 시작 ERMSB-35cycles. 보 Intel 수동에 최적화 섹션 3.7.6 향상된 담당자 MOVSB 및 STOSB 작업(ERMSB)http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf
시작비용은 35 주기 -원본과 목적지 주소를 맞춰야 하는 16 바이트의 경계; -소스 영역이 겹치지 않는 대상 영역 -길이가야 할 여러 개의 64 을 생산하는 더 높은 성능 -의 방향을 전달(CLD). 앞서 말했듯이,REP MOVSB 시작을 능가하는 다른 방법을 때의 길이는 최소 256 바이트를,하지만 명확한 혜택을 통해 AVX 복사,길이가 더 이상 2048 바이트입니다. 의 효과에 대한 맞춤 경우 담당자 MOVSB 대 AVX 복사,Intel 매뉴얼은 다음과 같은 정보: -는 경우 원본 버퍼에 정렬되지 않은 경우에 미치는 영향 ERMSB 구현에 대 128-bit AVX 비슷; -는 경우 목적지 버퍼에 정렬되지 않은 경우에 미치는 영향 ERMSB 구현할 수 있습 25%강직하는 동안,128 비트 AVX 의 구현 memcpy 를 저하시킬 수 있습니다만 5%,상대하는 16 바이트의 정렬 시나리오이다. 가에서 테스트를 만들 Intel Core i5-6600,에서 64 비트,그리고 나이에 비해 담당자 MOVSB memcpy 를()간단한 MOV RAX,[SRC];MOV[DST],RAX 구현데이터에 맞는 L1 캐시: 담당자 MOVSB memcpy 를():
- 1622400000 data blocks of 32 bytes took 17.9337 seconds to copy; 2760.8205 MB/s
- 1622400000 data blocks of 64 bytes took 17.8364 seconds to copy; 5551.7463 MB/s
- 811200000 data blocks of 128 bytes took 10.8098 seconds to copy; 9160.5659 MB/s
- 405600000 data blocks of 256 bytes took 5.8616 seconds to copy; 16893.5527 MB/s
- 202800000 data blocks of 512 bytes took 3.9315 seconds to copy; 25187.2976 MB/s
- 101400000 data blocks of 1024 bytes took 2.1648 seconds to copy; 45743.4214 MB/s
- 50700000 data blocks of 2048 bytes took 1.5301 seconds to copy; 64717.0642 MB/s
- 25350000 data blocks of 4096 bytes took 1.3346 seconds to copy; 74198.4030 MB/s
- 12675000 data blocks of 8192 bytes took 1.1069 seconds to copy; 89456.2119 MB/s
- 6337500 data blocks of 16384 bytes took 1.1120 seconds to copy; 89053.2094 MB/s
MOV RAX...memcpy 를():
- 1622400000 data blocks of 32 bytes took 7.3536 seconds to copy; 6733.0256 MB/s
- 1622400000 data blocks of 64 bytes took 10.7727 seconds to copy; 9192.1090 MB/s
- 811200000 data blocks of 128 bytes took 8.9408 seconds to copy; 11075.4480 MB/s
- 405600000 data blocks of 256 bytes took 8.4956 seconds to copy; 11655.8805 MB/s
- 202800000 data blocks of 512 bytes took 9.1032 seconds to copy; 10877.8248 MB/s
- 101400000 data blocks of 1024 bytes took 8.2539 seconds to copy; 11997.1185 MB/s
- 50700000 data blocks of 2048 bytes took 7.7909 seconds to copy; 12710.1252 MB/s
- 25350000 data blocks of 4096 bytes took 7.5992 seconds to copy; 13030.7062 MB/s
- 12675000 data blocks of 8192 bytes took 7.4679 seconds to copy; 13259.9384 MB/s
그래서,128 비트 블록,REP MOVSB 보다 느린 단순한 MOV RAX 에 복사본을 반복지 않음(풀). 이 ERMSB 구현 시작을 능가할 것으로 MOV 렉스 루프만 양식을 시작 256 바이트다.
놀랍게도,이전 아키텍처(Nehalem 이상),는't 직이 향상된 담당자 MOVB 했다,아주 빠른 담당자 MOVSD/MOVSQ(하지만 담당자 MOVSB/MOVSW)구현이 큰 블록은,하지만 충분히 큰 소형 L1 캐시입니다. 인텔 최적화 설명서(2.5.6 담당자 문자열을 증진)는 다음과 같은 정보와 관련 Nehalem 마이크로 아키텍처-Intel Core i5,i7 및 Xeon 프로세서에서 발표는 2009 년과 2010.
대기 시간에 대한 MOVSB,9 사이클을 경우 exc<4,그렇지 않으면 담당자 MOVSB 로우 exc>9 50 주기 시작한 비용. -작은 문자열(우 exc<4):대기 시간이의 담당자 MOVSB9 주기 -작은 문자열(우 exc 은 4~9):없음 공식에서 정보를 인텔은 설명서,아마도 더 이상 9 주기만 50 주기 -긴 문자열(우 exc>9):50 주기 시작한 비용. 내 결론:REP MOVSB 은 거의 쓸모에 Nehalem.
견적에 인텔 최적화 설명서(2.5.6 담당자 문자열을 증진):
-짧은 문자열(우 exc<=12):대기 시간이의 담당자 MOVSW/MOVSD/MOVSQ 은 약 20 주기입니다. -속 문자열(우 exc>=76:제외 담당자 MOVSB):프로세서 제공하는 하드웨어 구현의 최적화 이동하여 많은 조각으로의 데이터에서는 16 바이트로 가능합니다. 대기 시간의 대표 문자열에는 대기 시간이 다를 경우 중 하나는 16 바이트의 데이터 전송에 걸쳐 있 캐시 선을 경계: =Split-free:대기 시간의 시작 비용의 약 40 주기 각 64 바이트의 데이터가 4 주기입니다. =캐시 분할:지연성의 시작용에 대 35 사이클과 각 64 바이트의 데이터를 추가한 6 주기입니다. 중급 문자열 길이:지연의 담당자 MOVSW/MOVSD/MOVSQ 가 시작비용은 약 15 플러스 사이클 하나의 사이클에 대한 각 반복의 데이터 이동에 말씀/dword/qword. Intel 하지 않는 것이 정확하 여기에. 위의 견적을 우리는 이해를 위한 매우 큰 메모리 블록,REP MOVSW 은 한 빨리 담당자 MOVSD/MOVSQ 지만,테스트 결과는 대표 MOVSD/MOVSQ 은 빠르면서,담당자 MOVSW 도보다 느리게 담당자 MOVSB 에 Nehalem 및 웨스트미어. 에 따라 제공된 정보 인텔에 매뉴얼에서,이전에 인텔 microarchitectures(전 2008)을 시작하는 비용은 훨씬 더 높습니다. 결론:만 필요한 경우에는 데이터를 복사에 맞는 L1 캐시,단지 4 주기 복사하 64 바이트의 데이터는 우수하고,당신이't 을 사용할 필요가 XMM 등록!
담당자 MOVSD/MOVSQ 가 보편적인 솔루션을 작동하는 우수한 모든 인텔 프로세서(아 ERMSB 필수)는 경우에 데이터를 맞추는 L1 캐시
여기에의 테스트는 담당자 MOVS 때*소스 및 대상에 L1 캐시,블록의 충분히 큰되지 않을 심각하게 영향을 받는 시작용,그러나지 않는 대형을 초과하 L1 캐시 크기입니다. 출처:http://users.atw.hu/instlatx64/ Yonah(2006-2008)
REP MOVSB 10.91 B/c
REP MOVSW 10.85 B/c
REP MOVSD 11.05 B/c
Nehalem(2009-2010)
REP MOVSB 25.32 B/c
REP MOVSW 19.72 B/c
REP MOVSD 27.56 B/c
REP MOVSQ 27.54 B/c
웨스트미어(2010-2011)
REP MOVSB 21.14 B/c
REP MOVSW 19.11 B/c
REP MOVSD 24.27 B/c
Ivy Bridge(2012-2013)-향상된 담당자 MOVSB
REP MOVSB 28.72 B/c
REP MOVSW 19.40 B/c
REP MOVSD 27.96 B/c
REP MOVSQ 27.89 B/c
스카이 레이크(2015-2016)-향상된 담당자 MOVSB
REP MOVSB 57.59 B/c
REP MOVSW 58.20 B/c
REP MOVSD 58.10 B/c
REP MOVSQ 57.59 B/c
Kaby 호수(2016 에서 2017 사)-향상된 담당자 MOVSB
REP MOVSB 58.00 B/c
REP MOVSW 57.69 B/c
REP MOVSD 58.00 B/c
REP MOVSQ 57.89 B/c
당신이 볼로 구현의 담당자 MOVS 크게 다릅니다 하나의 마이크로 아키텍처니다. 일부 프로세서,다음과 같 Ivy Bridge-REP MOVSB 가장 빠르다,이기는 하지만 약간 더 빠르게 보다 REP MOVSD/MOVSQ 지만,의심의 여지는 모든 프로세서에서부터 Nehalem,REP MOVSD/MOVSQ 작품을 아주 잘 당신은 심지 않는't 해야"향상된 담당자 MOVSB"기 때문에,아이비브릿지(2013)을 Enhacnced 담당자 MOVSB,REP MOVSD 여 동일한 바이트계 데이터로에 Nehalem(2010)없이 Enhacnced 담당자 MOVSB, 사실 담당자 MOVSB 되었고 매우 빠른만 이후 스카이 레이크(2015 년)-으로 빠르게 두 번에 Ivy Bridge. 그래서 이 Enhacnced 담당자 MOVSB 비트에 CPUID 혼동 될 수 있습니다-그것은 단지는 것을 보여줍REP MOVSB
그 자체가 좋은,그러나지 않는 모든REP MOVS*
더 빠릅니다.
가장 복잡 ERMBSB 구현에 Ivy Bridge 마이크로 아키텍처. 그렇다,아주 오래된 프로세서,전 ERMSB,REP MOVS대형 블록했 사용하여 캐시 프로토콜지 않는 기능을 사용할 수 있을 정기적인 코드(없음-RFO). 하지만 이 프로토콜은 더 이상에서 사용 Ivy Bridge 는 ERMSB. 에 따라디 Glew's 의견에 대답"이유는 복잡한 memcpy 를/작성 memset 니까?"에서 베드로는 코르 답변에 캐시 프로토콜지 않는 기능을 사용할 수 있을 정기적인 코드는 한번 사용하면서 이전 프로세서지만,더 이상에 Ivy Bridge. 과가 온다는 이유에 대한 설명을 시작하는 비용을 위해 이렇게 높은 담당자 MOVS:"큰 위한 오버헤드를 선택하고 올바른 방법은 주로의 부족으로 인해 마이크로점 예측". 또한 발생했습니다 흥미로운 참고 Pentium Pro(P6)1996 년에 구현된 담당자 MOVS*64 비트 마이크로 로드점 및 no-RFO 캐시 프로토콜들을 위반하지 않은 메모리를 주문과는 달리,ERMSB 에 Ivy Bridge.
당신은 당신이 원하는:
응답을 표시하는 경우 유용 ERMSB
그러나 나는'm 지 그것이 무엇을 의미를 생각은 그것이 의미하는 것입니다. 보고 3.7.6.1 문서 당신은 링크를,그것은 명시적으로 말한다:
구현 memcpy 를 사용하여 ERMSB 지 않을 수도 있습에 도달하는 동일한 수준의 처리량으로 사용하는 256 비트 또는 128 비트 AVX 대안에 따라 길이와 맞춤 요소입니다.
그래서 그냥 있기 때문에CPUID
에 대한 지원을 나타냅 ERMSB,지 않는't 을 보장하는 담당자 MOVSB 될 것입니다 가장 빠른 방법으로 복사하는 메모리. 그것은 단지 그't 빨아로 가서 이전의 Cpu 가 있습니다.
그러나 그냥 있을 수 있기 때문에 대안을 수 있는,특정 조건에서 빠르게 실행하지 않는't 는 것을 의미 담당자 MOVSB 는 것은 쓸모가 없다. 이제는 성능 저는 이 명령을 사용하여 발생하는 사라지고,그것은 잠재적으로 유용한 명령을 다시합니다.
기억,그것은 작은 코드(2 바이트!) 의 일부에 비해 더 많은 참여 memcpy 를 루틴을 나는 볼 수 있습니다. 이후로드 및 실행의 큰 덩어리 코드가 패널티(던지기의 일부는 다른 코드의 cpu's cache),때로는'이점'의 AVX et al 이 될 것으로 오프셋의 영향을의 나머지 부분에서 당신의 코드입니다. 에 따라 달라집하고 있습니다.
당신은 또한 요청:
이유는 대역폭이 많이 낮을 가진 담당자 MOVSB? 무엇을 할 수 있습니 그것을 개선?
아't 될 수"뭔가를"을 담당자 MOVSB 실행하는 더 빠르다. 그것은 그것이 무엇입니다.
고 싶은 경우 더 높은 속도를 당신이 보고서에서 memcpy 를,당신을 발굴 할 수 있는 소스입니다. It's 밖으로 어딘가에 있을 것 이다. 또는 당신을 추적 할 수 있습니다로서 그것을 디버거와 실제 코드의 경로를니다. 나의 기대는's 의 일부를 사용하여 그 AVX 지침으로 작업 128 256bits 니다.
할 수 있습니다 또는 그냥...음,우리에게 물었다 말하지 않습니다.
작성 memset()
/memmove()
/memcpy 를()
(참조하십시오어[gcc/config/i386/i386.c:expand_set_or_movmem_via_rep()](https://raw.githubusercontent.com/gcc-mirror/gcc/master/gcc/config/i386/i386.c 에서)GCC 소스도 보기 위해stringop_algs
에서 같은 파일을 참조 아키텍쳐에 의존적인 개). 그래서,아무 이유 없이 기대하는 대규모 이익을 사용하여 자신만의 변형으로 GCC(지 않는 한 당신이've forgotten 중요한 물건을 정렬과 같은 속성에 대한 정렬 데이터,또는 사용하지 않는 충분히 특정 최적화를 다음과 같-O2-march=-mtune=
). 에 동의하는 경우,그에 대한 답변을 명시된 질문은 더 많거나 적은에서는 관계가 없습니다.
(나가기memrepeat()
,그 반대의memcpy 를()
에 비해memmove()
,그 반복하여 초기의 일부 버퍼를 채우기 위해 전체 buffer.) 나는 현재 아이비리 기계에서 사용(Core i5-6200U 노트북,리눅스 4.4.0x86-64 커널을 가진erm
에서/proc/cpuinfo
flags). 고 싶었기 때문에 찾으면 나를 찾을 수 있습는 경우 사용자 지정 memcpy 를()변형에 따라rep movsb
능가할 것 이라고 간단한memcpy 를()
,썼다 지나치게 복잡한 벤치마크입니다.
핵심 아이디어는 메인 프로그램으로 할당하는 세 가지 큰 메모리 영역:원래
,현재
,그리고올바른
,각각은 정확히 동일한 크기,그리고 적어도 페이지 정렬되어 있습니다. 사본 작업으로 그룹화 세트로 각각 설정하는 고유한 속성이처럼,모두 소스 및 대상이 되는 정렬(일부를 수의 바이트),또는 모든 길이에 같은 범위에 있습니다. 각 설정을 사용하여 설명한 배열의src
,dst
,n
쌍둥이 어디든src``src+n-1
과dst
에서dst+n-1
에 완전히현재
지역입니다.
AXorshift*PRNG 초기화하는 데 사용됩니다본래
로 임의의 데이터입니다. (같은 경고 했 위에,이것은 지나치게 복잡하지만,제가 확인하고 싶어 나는'm 지 않을 떠나기 쉬운 바로 가기를 위한 컴파일러입니다.) 올바른
지역에 의해 얻어진을 시작으로본래
데이터에서현재
,적용하는 모든 쌍둥이에서는 현재 설정을 사용하여,memcpy 를()
에서 제공하는 C 라이브러리,그리고 복사하현재
지역올바른
. 이것은 각각의 벤치마킹 기능을 확인할을 제대로 동작합니다.
각 설정의 복사 작업 시간이 초과의 큰 숫자를 사용하여 시간과 동일한 기능,그리고 중간의 이러한 사용에 대한 비교입니다. (제 생각에는,중앙값에게 가장 의미에서 벤치마킹,제공하고 현명한 의미--기능은 적어도는 적어도 빠른 시간이 절반으로 줄어듭니다.)
을 피하는 컴파일러 최적화,가 프로그램으로 부하의 함수를 벤치마크하고,동적으로 실행된 시간입니다. 기능 모두가 같은 형태로,`void function(void,const void*,size_t)--주는 것과는 달리
memcpy 를()와
memmove(),그들은 아무것도 반환하지 않습니다. 벤치마크(라는 설정의 사본을 운영)을 동적으로 생성하여 함수를 호출(는 포인터
현재`지역의 크기는 매개변수로,다른 사람의 사이에서).
불행하게도,내가 없는 경우 설정
static void rep_movsb(void *dst, const void *src, size_t n)
{
__asm__ __volatile__ ( "rep movsb\n\t"
: "+D" (dst), "+S" (src), "+c" (n)
:
: "memory" );
}
치
static void normal_memcpy(void *dst, const void *src, size_t n)
{
memcpy(dst, src, n);
}
gcc-벽-O2-march=비브-mtune=브
를 사용하여 GCC5.4.0 에서 앞서 언급한 코어 i5-6200U 노트북 linux-4.4.0 64-bit kernel. 복사 4096 바이트의 정렬하고 크기의 덩어리가 가까이 온다,그러나입니다.
즉,적어도에 따라서 지금까지 발견하지 않는 경우 사용하는rep movsb
memcpy 를 변해도 됩니다. 하지 않는 것을 의미 없이 그러한 경우;난't 하나를 발견했다.
(이 시점에서의 코드입니다 스파게티 mess I'm 더 부끄러워보다 자랑하는,그래서 내가 생략 게시 소스지 않으면 누군가 묻습니다. 위의 설명이 충분해야를 쓰는 더 나은 하나,하지만.) 이 놀라게하지 않는 나에게 많은,하지만. C 컴파일러를 추정할 수 있고 많은 정보를 대형의 포인터 연산자,그리고 여부를 바이트 수를 복사본은 컴파일 시간 상수로,여러 개의 적당한 힘의 두 가지. 이 정보는 것입/해야 될 사용하는 컴파일러를 대체하는 C 라이브러리memcpy 를()
/memmove()
기능으로 그 자체.
GCC 는 정확하게 이(예보[gcc/config/i386/i386.c:expand_set_or_movmem_via_rep()](https://raw.githubusercontent.com/gcc-mirror/gcc/master/gcc/config/i386/i386.c 에서)GCC 소스도 보기 위해stringop_algs
에서 같은 파일을 참조 아키텍쳐에 의존적인 개). 실제로,memcpy 를()
/작성 memset()
/memmove()
이 별도로 최적화에 대한 꽤 몇 가지 x86processor 개;그것은 매우 놀라는 경우에 저 GCC 개발자 아직 포함되지 않 erm 지원합니다.
GCC 제공하는 여러 가지기능 attributes는 개발자가 사용할 수 있습을 통해 생성되는 코드입니다. 예를 들어,alloc_align(n)
알 GCC 함수가 반환하는 메모리에 정렬되어n
바이트입니다. 응용 프로그램이나 라이브러리를 선택할 수 있는 구현이의 함수에서 사용하는 실행 시간을 생성하여,"해결 프로그램을 함"(반환하는 함수 포인터),그리고 정의하는 기능을 사용하여ifunc(resolver)
특성이 있습니다.
하나의 가장 일반적인 패턴에서 사용 코드를 이
some_type *pointer = __builtin_assume_aligned(ptr, alignment);
는ptr
는 어떤 포인터맞춤
는 바이트 수를 정렬되;GCC 다음을 알고 있/서는포인터
의 정렬된맞춤
바이트입니다.
다른 유용한 내장,이기는 하지만 훨씬 더 많이 사용제대로,은__builtin_prefetch()
. 을 극대화하는 전체 대역폭/효율성,내가 찾는 대기 시간을 최소화에서 각 하위 작동,최상의 결과를 얻을 수 있습니다. (복사에 대한 흩어져있는 요소를 연속 임시 저장소,이 같은 어려울리는 일반적으로 포함한 전체 캐시인 경우에는 너무 많은 요소 프리패치된 대부분의 캐시 낭비를 저장하여 사용되지 않는 항목입니다.)
훨씬 더 많은 효율적인 방법으로 데이터를 이동합니다. 이 요즘의 구현memcpy 를
을 생성하는 아키텍처 코드에서는 컴파일러 최적화에 따라 메모리의 맞춤 데이터 및 기타 요인입니다. 이로써 더 나은 비 캐시간 지침 XMM 및 기타 등록에서는 86 세계입니다.
할 때 열심히-코드rep movsb
방지 이의 사용에 내장.
따라서,같은 것memcpy 를
지 않는 한 당신이 뭔가를 쓰는 것이 있음을 아주 특정 하드웨어 및려고 하는 경우가 아니면 시간이 걸릴를 쓰는 고도로 최적화된memcpy 를
기능 어셈블리에서(또는 사용하는 C 수준에 내장),당신은 당신멀더 나을 수 있도록 컴파일러를 위해 그것을 알아내기 위해 당신입니다.
일반적으로memcpy 를()
가이드:
는)경우에는 데이터 복사되는 작은(이하 어쩌면 20 바이트)및 크기가 고정되어 있으면,컴파일러 않습니다. 이유:컴파일러를 사용할 수 있는 정상으로 mov
지침을 피하기 시작 오버 헤드.
b)만약 데이터 복사되는 작은(이하 4KiB)을 맞춰 사용,rep movsb
(는 경우 ERMSB 지원)또는rep movsd
(는 경우 ERMSB 은 지원되지 않습니다). 이유:사용하여 SSE 또는 AVX 대안의 엄청난 금액을 가지고 있"시작한 오버헤드"기 전에 그것을 복사본다.
c)데이터 복사되는 작은(이하 4KiB)과 반드시 보장하는 것은 아닙 맞춰 사용,rep movsb
. 이유:사용하여 SSE 또는 AVX,거나 사용하는rep movsd
대량의 플러스 일부는rep movsb
시작 또는 끝에,너무 많은 오버헤드가 발생합니다.
d)다른 모든 경우 다음과 같은 코드를 사용하면 됩니다:
mov edx,0
.again:
pushad
.nextByte:
pushad
popad
mov al,[esi]
pushad
popad
mov [edi],al
pushad
popad
inc esi
pushad
popad
inc edi
pushad
popad
loop .nextByte
popad
inc edx
cmp edx,1000
jb .again
이유:이 될 것입니다 너무 느려서 그것은 강제 프로그래머 대안을 찾지 않는't 포함 복사한 거대한 방울의 데이터 및 결과 소프트웨어는 것입니다 훨씬 더 빠르기 때문에 큰 복사 방울의 데이터를 피할 수 있습니다.