오류, 버그, 질문 - 페이지 2505

 

편집기의 오래된 버그:

- 파일을 새 이름으로 저장합니다(예: name_v1.2).
- 커서를 어떤 변수(또는 함수 호출 )에 둡니다.
- Alt+g 누르기

- 이전 파일이 열리고 편집이 해당 파일로 이동합니다(

 
Vict :

일반적으로 나는 이것을 기대하지도 않았습니다.

코드가 약간 복잡합니다. 캐시 라인에 맞지 않는 요소를 쳐서 직접 두드려 보았지만 잘 되지 않았습니다. 그 중), 그러나 나는 코드를 많이 편집하지 않았습니다. 그러나 이 방법은 훨씬 더 인상적입니다. 캐시 라인에 속하지 않는 요소에 대해 16개의 추가 중 하나만 수행되지만 가시적인 결과를 제공합니다.

추신: 이 경우 하나의 단락을 삭제하지 않고 두 개의 단락을 삽입하여 RIGHT_ALIGNED를 수행하는 것이 더 객관적입니다(이렇게 하면 두 경우 모두에 대해 두 개의 캐시 라인 업데이트를 달성할 수 있음). 따라서 가속은 더 완만하지만 여전히 약 1.5배 중요합니다.

죄송하지만 얼라인먼트는 어디에 사용하나요? 예는 다른 것에 관한 것입니다.

추신: 주석 없이 원시 형식으로 코드를 퍼뜨리는 것은 대화 상대에게 무례합니다.

 

타사 라이브러리, 특히 dotnet에서 MQL 구조의 개체를 사용하기 위해 정렬이 추가되었음을 올바르게 지적했습니다.

팩 구조/클래스의 필드 정렬이 추가된 것은 dotnet 라이브러리에 대한 지원을 추가할 때였습니다.

간단히 말해서 다음과 같이 작동합니다.

각 유형(char, short, int, ...)에는 기본적으로 고유한 정렬(각각 1, 2, 4바이트)이 있습니다.
구조 필드의 경우 기본 및 사용자 정의(팩을 통해)의 최소 두 가지 정렬이 선택됩니다.

동시에 패킹된 객체의 크기는 배열의 객체 필드에 대한 주소 지정이 항상 "올바른" 방식으로 설정됩니다(pack을 통해 지정, 기본적으로 1바이트).
이 구조의 크기를 정렬하는 잘못된 인상이 생성되는 것은 후자 때문입니다. 그렇지 않은 경우 필드 주소가 정렬되어 구조 크기의 정렬이 수반됩니다.



예를 들어

 struct A pack( 8 )
  {
   double d;
   char    c;
  };

void OnStart ()
  {
   Print ( sizeof (A));
   
  }

결과 16, d의 첫 번째 필드에 대한 주소는 항상 8바이트로 정렬됩니다.

 
fxsaber :

집에서의 발사는 눈에 띄는 차이를 보이지 않았습니다.

나는 원래의 아이디어를 염두에 두었습니다(첫 번째 코드에서 주소를 잘못 계산했습니다). 그것이 어렵지 않다면 결과를 보는 것이 흥미로울 것입니다.

 #define WRONG_ALIGNED
#define CACHE_LINE_SIZE 64

struct 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 )

void OnStart ()
{
   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 배의 안정적인 차이가 있습니다.
 
Vict :

나는 원래의 아이디어를 염두에 두었습니다(첫 번째 코드에서 주소를 잘못 계산했습니다). 그것이 어렵지 않다면 결과를 보는 것이 흥미로울 것입니다.

본질적으로 WRONG_ALIGNED를 사용하거나 사용하지 않고 동일한 일이 발생합니다. 두 개의 인접한 캐시 라인에 쓰는 동안 각각에서(패드에 쓰기는 항상 올바른 주소에 있음) 유일한 차이점은 WRONG_ALIGNED를 사용하면 다음과 같은 경우가 있다는 것입니다(항상 그런 것은 아님). ar의 항목 중 하나는 uint로 이동하며 캐시 라인에 완전히 들어 가지 않습니다. 약 1.5 배의 안정적인 차이가 있습니다.

이 줄로 무엇을 얻으려고 하는지 설명해 주시겠습니까? 이전 예에서 이것은 가비지 코드였습니다.

 int index = int (CACHE_LINE_SIZE - getaddr(data[rndnum].ar[ 0 ]) % CACHE_LINE_SIZE) / sizeof ( int );
 
Francuz :

이 줄로 무엇을 얻으려고 하는지 설명해 주시겠습니까? 이전 예에서 이것은 가비지 코드였습니다.

현재 캐시 라인(패드가 있는 위치)에서 위치를 찾고 해당 요소가 다음 캐시 라인에 있도록 ar[]에 대한 인덱스를 가져옵니다(요소가 WRONG_ALIGNED인 두 개의 캐시 라인에 있을 수 있음).

 
Vict :

현재 캐시 라인(패드가 있는 위치)에서 위치를 찾고 해당 요소가 다음 캐시 라인에 있도록 ar[]에 대한 인덱스를 가져옵니다(요소가 WRONG_ALIGNED인 두 개의 캐시 라인에 있을 수 있음).

이제 우리는 변위에 대해 이야기하고 있습니다. 그러나 당신이 보여주는 것은 당신이 인생에서 결코 만날 수 없는 순전히 합성적인 예입니다. 실제 예에서 속도의 증가는 기껏해야 약 1%입니다. 그러한 미약한 가속을 위해 정원을 울타리로 묶지 않아야합니다.

PS 또한 레지스터의 크기를 잘못 계산했습니다.
 
Francuz :

이제 우리는 변위에 대해 이야기하고 있습니다. 그러나 당신이 보여주는 것은 당신이 인생에서 결코 만날 수 없는 순전히 합성적인 예입니다. 실제 예에서 속도의 증가는 기껏해야 약 1%입니다. 그러한 미약한 가속을 위해 정원을 울타리로 묶지 않아야합니다.

아니요, 이것은 매우 실제적인 예입니다. 그것에서 항목의 25%만이 캐시 라인의 교차점에서 "문제" 위치에서 발생합니다. 많은가요? 예를 들어, 긴 이중 배열이 있고 4개의 값만 하나의 캐시 라인에 들어갈 수 있으며 정렬에 신경 쓰지 않고(컴파일러가 자동으로 수행하지 않음) 25%를 얻습니다. 문제가 있는 복식의 경우 - 내 예와 같습니다. 정렬에 대해 말하는 뉘앙스가 더 많지만 그것에 대해 이야기하지 않겠습니다. 문제에 대한 포괄적인 지식이 없습니다.

글쎄, 소유자는 바린입니다.

PS 또한 레지스터의 크기를 잘못 계산했습니다.
예, 전혀 생각하지 않았습니다.
 
Vict :

아니요, 이것은 매우 실제적인 예입니다. 그것에서 항목의 25%만이 캐시 라인의 교차점에서 "문제" 위치에서 발생합니다. 많은가요? 예를 들어, 긴 이중 배열이 있고 4개의 값만 하나의 캐시 라인에 들어갈 수 있으며 정렬에 신경 쓰지 않고(컴파일러가 자동으로 수행하지 않음) 25%를 얻습니다. 문제가 있는 복식의 경우 - 내 예와 같습니다. 정렬에 대해 말하는 뉘앙스가 더 많지만 그것에 대해 이야기하지 않겠습니다. 문제에 대한 포괄적인 지식이 없습니다.

글쎄, 소유자는 바린입니다.

다시 한번 말하지만 레지스터의 크기를 혼동하고 있습니다.

 
Francuz :

다시 한번 말하지만 레지스터의 크기를 혼동하고 있습니다.

신이 옳다고 하다