코드가 약간 복잡합니다. 캐시 라인에 맞지 않는 요소를 쳐서 직접 두드려 보았지만 잘 되지 않았습니다. 그 중), 그러나 나는 코드를 많이 편집하지 않았습니다. 그러나 이 방법은 훨씬 더 인상적입니다. 캐시 라인에 속하지 않는 요소에 대해 16개의 추가 중 하나만 수행되지만 가시적인 결과를 제공합니다.
추신: 이 경우 하나의 단락을 삭제하지 않고 두 개의 단락을 삽입하여 RIGHT_ALIGNED를 수행하는 것이 더 객관적입니다(이렇게 하면 두 경우 모두에 대해 두 개의 캐시 라인 업데이트를 달성할 수 있음). 따라서 가속은 더 완만하지만 여전히 약 1.5배 중요합니다.
타사 라이브러리, 특히 dotnet에서 MQL 구조의 개체를 사용하기 위해 정렬이 추가되었음을 올바르게 지적했습니다.
팩 구조/클래스의 필드 정렬이 추가된 것은 dotnet 라이브러리에 대한 지원을 추가할 때였습니다.
간단히 말해서 다음과 같이 작동합니다.
각 유형(char, short, int, ...)에는 기본적으로 고유한 정렬(각각 1, 2, 4바이트)이 있습니다. 구조 필드의 경우 기본 및 사용자 정의(팩을 통해)의 최소 두 가지 정렬이 선택됩니다.
동시에 패킹된 객체의 크기는 배열의 객체 필드에 대한 주소 지정이 항상 "올바른" 방식으로 설정됩니다(pack을 통해 지정, 기본적으로 1바이트). 팩 이 구조의 크기를 정렬하는 잘못된 인상이 생성되는 것은 후자 때문입니다. 그렇지 않은 경우 필드 주소가 정렬되어 구조 크기의 정렬이 수반됩니다.
나는 원래의 아이디어를 염두에 두었습니다(첫 번째 코드에서 주소를 잘못 계산했습니다). 그것이 어렵지 않다면 결과를 보는 것이 흥미로울 것입니다.
#define WRONG_ALIGNED
#define CACHE_LINE_SIZE 64struct Data {
#ifdef WRONG_ALIGNED
ushort pad;
#else
uint pad;
#endif
uint ar[CACHE_LINE_SIZE/ sizeof ( int )+ 1 ];
};
#import "msvcrt.dll"long memcpy( uint &, uint &, long );
#import
#define getaddr(x) memcpy(x, x, 0 )
voidOnStart ()
{
Data data[ 32768 ];
ZeroMemory (data);
srand ( GetTickCount ());
ulong start_time = GetMicrosecondCount ();
for ( unsigned i = 0 ; i < 10000 ; ++ i) {
int rndnum = rand ();
while (++rndnum < 32768 ) {
int index = int (CACHE_LINE_SIZE - getaddr(data[rndnum].ar[ 0 ]) % CACHE_LINE_SIZE) / sizeof ( int );
++ data[rndnum].ar[index];
++ data[rndnum].pad;
}
}
Alert ( GetMicrosecondCount () - start_time);
Print (data[ 100 ].ar[ 0 ]);
Print (data[ 100 ].pad);
}
/*
WRONG_ALIGNED:
6206397
6185472
RIGHT_ALIGNED
4089827
4003213
*/
본질적으로 WRONG_ALIGNED를 사용하거나 사용하지 않고 동일한 일이 발생합니다. 두 개의 인접한 캐시 라인에 쓰는 동안 각각에서(패드에 쓰기는 항상 올바른 주소에 있음) 유일한 차이점은 WRONG_ALIGNED를 사용하면 다음과 같은 경우가 있다는 것입니다(항상 그런 것은 아님). ar의 항목 중 하나는 uint로 이동하며 캐시 라인에 완전히 들어 가지 않습니다. 약 1.5 배의 안정적인 차이가 있습니다.
나는 원래의 아이디어를 염두에 두었습니다(첫 번째 코드에서 주소를 잘못 계산했습니다). 그것이 어렵지 않다면 결과를 보는 것이 흥미로울 것입니다.
본질적으로 WRONG_ALIGNED를 사용하거나 사용하지 않고 동일한 일이 발생합니다. 두 개의 인접한 캐시 라인에 쓰는 동안 각각에서(패드에 쓰기는 항상 올바른 주소에 있음) 유일한 차이점은 WRONG_ALIGNED를 사용하면 다음과 같은 경우가 있다는 것입니다(항상 그런 것은 아님). ar의 항목 중 하나는 uint로 이동하며 캐시 라인에 완전히 들어 가지 않습니다. 약 1.5 배의 안정적인 차이가 있습니다.
이 줄로 무엇을 얻으려고 하는지 설명해 주시겠습니까? 이전 예에서 이것은 가비지 코드였습니다.
int index = int (CACHE_LINE_SIZE - getaddr(data[rndnum].ar[ 0 ]) % CACHE_LINE_SIZE) / sizeof ( int );
이제 우리는 변위에 대해 이야기하고 있습니다. 그러나 당신이 보여주는 것은 당신이 인생에서 결코 만날 수 없는 순전히 합성적인 예입니다. 실제 예에서 속도의 증가는 기껏해야 약 1%입니다. 그러한 미약한 가속을 위해 정원을 울타리로 묶지 않아야합니다.
아니요, 이것은 매우 실제적인 예입니다. 그것에서 항목의 25%만이 캐시 라인의 교차점에서 "문제" 위치에서 발생합니다. 많은가요? 예를 들어, 긴 이중 배열이 있고 4개의 값만 하나의 캐시 라인에 들어갈 수 있으며 정렬에 신경 쓰지 않고(컴파일러가 자동으로 수행하지 않음) 25%를 얻습니다. 문제가 있는 복식의 경우 - 내 예와 같습니다. 정렬에 대해 말하는 뉘앙스가 더 많지만 그것에 대해 이야기하지 않겠습니다. 문제에 대한 포괄적인 지식이 없습니다.
아니요, 이것은 매우 실제적인 예입니다. 그것에서 항목의 25%만이 캐시 라인의 교차점에서 "문제" 위치에서 발생합니다. 많은가요? 예를 들어, 긴 이중 배열이 있고 4개의 값만 하나의 캐시 라인에 들어갈 수 있으며 정렬에 신경 쓰지 않고(컴파일러가 자동으로 수행하지 않음) 25%를 얻습니다. 문제가 있는 복식의 경우 - 내 예와 같습니다. 정렬에 대해 말하는 뉘앙스가 더 많지만 그것에 대해 이야기하지 않겠습니다. 문제에 대한 포괄적인 지식이 없습니다.
편집기의 오래된 버그:
- 파일을 새 이름으로 저장합니다(예: name_v1.2).
- 커서를 어떤 변수(또는 함수 호출 )에 둡니다.
- Alt+g 누르기
- 이전 파일이 열리고 편집이 해당 파일로 이동합니다(
일반적으로 나는 이것을 기대하지도 않았습니다.
코드가 약간 복잡합니다. 캐시 라인에 맞지 않는 요소를 쳐서 직접 두드려 보았지만 잘 되지 않았습니다. 그 중), 그러나 나는 코드를 많이 편집하지 않았습니다. 그러나 이 방법은 훨씬 더 인상적입니다. 캐시 라인에 속하지 않는 요소에 대해 16개의 추가 중 하나만 수행되지만 가시적인 결과를 제공합니다.
추신: 이 경우 하나의 단락을 삭제하지 않고 두 개의 단락을 삽입하여 RIGHT_ALIGNED를 수행하는 것이 더 객관적입니다(이렇게 하면 두 경우 모두에 대해 두 개의 캐시 라인 업데이트를 달성할 수 있음). 따라서 가속은 더 완만하지만 여전히 약 1.5배 중요합니다.
죄송하지만 얼라인먼트는 어디에 사용하나요? 예는 다른 것에 관한 것입니다.
추신: 주석 없이 원시 형식으로 코드를 퍼뜨리는 것은 대화 상대에게 무례합니다.
타사 라이브러리, 특히 dotnet에서 MQL 구조의 개체를 사용하기 위해 정렬이 추가되었음을 올바르게 지적했습니다.
팩 구조/클래스의 필드 정렬이 추가된 것은 dotnet 라이브러리에 대한 지원을 추가할 때였습니다.
간단히 말해서 다음과 같이 작동합니다.
각 유형(char, short, int, ...)에는 기본적으로 고유한 정렬(각각 1, 2, 4바이트)이 있습니다.
구조 필드의 경우 기본 및 사용자 정의(팩을 통해)의 최소 두 가지 정렬이 선택됩니다.
동시에 패킹된 객체의 크기는 배열의 객체 필드에 대한 주소 지정이 항상 "올바른" 방식으로 설정됩니다(pack을 통해 지정, 기본적으로 1바이트).
팩 이 구조의 크기를 정렬하는 잘못된 인상이 생성되는 것은 후자 때문입니다. 그렇지 않은 경우 필드 주소가 정렬되어 구조 크기의 정렬이 수반됩니다.
예를 들어
결과 16, d의 첫 번째 필드에 대한 주소는 항상 8바이트로 정렬됩니다.
집에서의 발사는 눈에 띄는 차이를 보이지 않았습니다.
나는 원래의 아이디어를 염두에 두었습니다(첫 번째 코드에서 주소를 잘못 계산했습니다). 그것이 어렵지 않다면 결과를 보는 것이 흥미로울 것입니다.
본질적으로 WRONG_ALIGNED를 사용하거나 사용하지 않고 동일한 일이 발생합니다. 두 개의 인접한 캐시 라인에 쓰는 동안 각각에서(패드에 쓰기는 항상 올바른 주소에 있음) 유일한 차이점은 WRONG_ALIGNED를 사용하면 다음과 같은 경우가 있다는 것입니다(항상 그런 것은 아님). ar의 항목 중 하나는 uint로 이동하며 캐시 라인에 완전히 들어 가지 않습니다. 약 1.5 배의 안정적인 차이가 있습니다.나는 원래의 아이디어를 염두에 두었습니다(첫 번째 코드에서 주소를 잘못 계산했습니다). 그것이 어렵지 않다면 결과를 보는 것이 흥미로울 것입니다.
본질적으로 WRONG_ALIGNED를 사용하거나 사용하지 않고 동일한 일이 발생합니다. 두 개의 인접한 캐시 라인에 쓰는 동안 각각에서(패드에 쓰기는 항상 올바른 주소에 있음) 유일한 차이점은 WRONG_ALIGNED를 사용하면 다음과 같은 경우가 있다는 것입니다(항상 그런 것은 아님). ar의 항목 중 하나는 uint로 이동하며 캐시 라인에 완전히 들어 가지 않습니다. 약 1.5 배의 안정적인 차이가 있습니다.이 줄로 무엇을 얻으려고 하는지 설명해 주시겠습니까? 이전 예에서 이것은 가비지 코드였습니다.
이 줄로 무엇을 얻으려고 하는지 설명해 주시겠습니까? 이전 예에서 이것은 가비지 코드였습니다.
현재 캐시 라인(패드가 있는 위치)에서 위치를 찾고 해당 요소가 다음 캐시 라인에 있도록 ar[]에 대한 인덱스를 가져옵니다(요소가 WRONG_ALIGNED인 두 개의 캐시 라인에 있을 수 있음).
현재 캐시 라인(패드가 있는 위치)에서 위치를 찾고 해당 요소가 다음 캐시 라인에 있도록 ar[]에 대한 인덱스를 가져옵니다(요소가 WRONG_ALIGNED인 두 개의 캐시 라인에 있을 수 있음).
이제 우리는 변위에 대해 이야기하고 있습니다. 그러나 당신이 보여주는 것은 당신이 인생에서 결코 만날 수 없는 순전히 합성적인 예입니다. 실제 예에서 속도의 증가는 기껏해야 약 1%입니다. 그러한 미약한 가속을 위해 정원을 울타리로 묶지 않아야합니다.
PS 또한 레지스터의 크기를 잘못 계산했습니다.이제 우리는 변위에 대해 이야기하고 있습니다. 그러나 당신이 보여주는 것은 당신이 인생에서 결코 만날 수 없는 순전히 합성적인 예입니다. 실제 예에서 속도의 증가는 기껏해야 약 1%입니다. 그러한 미약한 가속을 위해 정원을 울타리로 묶지 않아야합니다.
아니요, 이것은 매우 실제적인 예입니다. 그것에서 항목의 25%만이 캐시 라인의 교차점에서 "문제" 위치에서 발생합니다. 많은가요? 예를 들어, 긴 이중 배열이 있고 4개의 값만 하나의 캐시 라인에 들어갈 수 있으며 정렬에 신경 쓰지 않고(컴파일러가 자동으로 수행하지 않음) 25%를 얻습니다. 문제가 있는 복식의 경우 - 내 예와 같습니다. 정렬에 대해 말하는 뉘앙스가 더 많지만 그것에 대해 이야기하지 않겠습니다. 문제에 대한 포괄적인 지식이 없습니다.
글쎄, 소유자는 바린입니다.
아니요, 이것은 매우 실제적인 예입니다. 그것에서 항목의 25%만이 캐시 라인의 교차점에서 "문제" 위치에서 발생합니다. 많은가요? 예를 들어, 긴 이중 배열이 있고 4개의 값만 하나의 캐시 라인에 들어갈 수 있으며 정렬에 신경 쓰지 않고(컴파일러가 자동으로 수행하지 않음) 25%를 얻습니다. 문제가 있는 복식의 경우 - 내 예와 같습니다. 정렬에 대해 말하는 뉘앙스가 더 많지만 그것에 대해 이야기하지 않겠습니다. 문제에 대한 포괄적인 지식이 없습니다.
글쎄, 소유자는 바린입니다.
다시 한번 말하지만 레지스터의 크기를 혼동하고 있습니다.
다시 한번 말하지만 레지스터의 크기를 혼동하고 있습니다.