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

 
Vict :

잘못된 장소에서 어딘가를 파고 있습니다. 정렬이 전혀 필요하지 않습니다. 프로세서는 일부 int가 두 개의 캐시 라인에 들어가지 않도록 정렬이 필요합니다.

아니오, 프로세서 캐시는 일반적으로 데이터 프리페칭으로 로드되고 다양한 캐시 레벨은 일반적으로 분기 예측으로 로드됩니다. pack()은 1에서 실행되는 대신 모든 산술 연산 (2 int 추가)에 도달할 수 없습니다. 또는 3(가상) 주기는 데이터 정렬 분석 등을 초래합니다.

물리적 수준에서는 다음과 같이 작동해야 합니다. 컴파일러는 그 안에 실행 코드를 생성했습니다. 예,   pack(), 그러나 RAM에서 데이터를 로드할 때 int 데이터만 읽고 데이터 세그먼트 포인터가 즉시 다음 위치로 이동합니다.   pack() 바이트(int 바이트당 아님)


내가 많이 틀릴 수도 있지만 지금은 모든 프로세스(프로세서 자체의 작동 포함)가 가상화되고 최적화되어 있으므로 공부할 때 펜티엄 -1에 대한 책을 읽었기 때문에 추론합니다....얼마나 비쌌는지 한 번))))

 
Igor Makanu :

아니요, 프로세서 캐시는 일반적으로 데이터 프리페칭으로 로드되고 다양한 캐시 레벨은 일반적으로 분기 예측으로 로드되며, pack()은 1에서 실행되는 대신 모든 산술 연산 (2 int 추가)에 도달할 수 없습니다. 또는 3(가상) 주기는 데이터 정렬 분석 등을 초래합니다.

물리적 수준에서는 다음과 같이 작동해야 합니다. 컴파일러는 그 안에 실행 코드를 생성했습니다. 예,   pack(), 그러나 RAM에서 데이터를 로드할 때 int 데이터만 읽고 데이터 세그먼트 포인터가 즉시 다음 위치로 이동합니다.   pack() 바이트(int 바이트당 아님)

글쎄요, 저는 pack() 지정자가 CPU에 대한 서비스 정보라고 말하지 않았습니다. 제 말은 - 정렬된 이러한 모든 춤은 프로그래머가 아니라 CPU를 위한 것입니다. 당연히 이것은 구조체에 void를 삽입하여 컴파일러에 의해 구현됩니다.

 
Alexey Viktorov :

즉, MQL5에는 정렬이 전혀 없습니다.

오랫동안, 현재처럼.

 
Vict :

엉뚱한 곳에서 파고들고 있어, 당신에게 정렬은 전혀 필요하지 않습니다

글쎄, 한 가지 실제 사용이 마음에 들지만 - 다중 스레드 환경에서 다른 코어가 동일한 캐시 라인에 쓰지 않도록 데이터를 정렬하면 캐시의 지속적인 동기화로 인해 성능이 크게 저하될 수 있습니다. 글쎄, CPU 유형에도 많은 뉘앙스가 있습니다.

 
fxsaber :

오랫동안, 현재처럼.

그들이 그것에 대해 쓴 곳을 기억합니까?

 
fxsaber :

그러면 얼라인먼트의 의미가 사라질까봐

정렬이 수행하는 작업을 확인하기 위해 바이트 단위로 시도했습니다.

 #property strict

const uint FFFF= 0xFFFFFFFF ;
//+------------------------------------------------------------------+
struct A pack( 4 )
  {
   ushort             j;
  };
//+------------------------------------------------------------------+
struct B pack( 8 )
  {
   ushort             j;
  };
//+------------------------------------------------------------------+
union UnionCheckByte
  {
   uint               byte_2x4[ 2 ];
   A                 a;
   B                 b;
  };
//+------------------------------------------------------------------+
void OnStart ()
  {
   UnionCheckByte tst;
   tst.byte_2x4[ 0 ]=FFFF;   tst.byte_2x4[ 1 ]=FFFF;   // заполним память 0xFFFFFFFF FFFFFFFF
   Print ( "0xFFFFFFFF FFFFFFFF = " ,tst.byte_2x4[ 0 ], "," ,tst.byte_2x4[ 1 ]);   // проверим
   
   
   
   tst.byte_2x4[ 0 ]=FFFF;   tst.byte_2x4[ 1 ]=FFFF;   // заполним память 0xFFFFFFFF FFFFFFFF
   tst.a.j= 0 ;
   Print ( "A.  = " ,tst.byte_2x4[ 0 ], "," ,tst.byte_2x4[ 1 ]);   // проверим



   tst.byte_2x4[ 0 ]=FFFF;   tst.byte_2x4[ 1 ]=FFFF;   // заполним память 0xFFFFFFFF FFFFFFFF
   tst.b.j= 0 ;
   Print ( "B.  = " ,tst.byte_2x4[ 0 ], "," ,tst.byte_2x4[ 1 ]);   // проверим
  }
//+------------------------------------------------------------------+

2019.07.07 17:51:30.601 tst (EURUSD,H1) 0xFFFFFFFFFFFFFFFF = 4294967295.4294967295

2019.07.07 17:51:30.601 tst (EURUSD,H1) A.=4294901760.4294967295

2019.07.07 17:51:30.601 tst (EURUSD,H1) B.=4294901760.4294967295




아직 깨어나지 않았거나 pack(4) / pack(8) 정렬이 작동하지 않습니다. 컴파일러 에 구조 A와 B의 크기를 명확하게 지정했습니다.


비록 그렇다 하더라도:

 ZeroMemory (tst.a);   //tst.a.j=0;
아무것도 바뀌지 않았다
 
Alexey Viktorov :

그들이 그것에 대해 쓴 곳을 기억합니까?

문서에 있는지 기억이 안나네요.

 
Igor Makanu :

정렬이 수행하는 작업을 확인하기 위해 바이트 단위로 시도했습니다.

아직 깨어나지 않았거나 pack(4) / pack(8) 정렬이 작동하지 않습니다 . 컴파일러 에 구조 A와 B의 크기를 명확하게 지정했습니다.

그래서 이 토론이 시작되었습니다 . 모든 것이 전혀 그렇지 않은 것으로 나타났습니다.

글쎄요, 예는 틀렸습니다. ushort 필드를 0으로 만들면 추가 바이트가 전혀 변경될 필요가 없습니다.


ZeroMemory는 아마도 sizeof에 중점을 두며 어떤 이유에서든 두 경우 모두 듀스입니다.

 
fxsaber :

그래서 이 토론이 시작되었습니다 . 모든 것이 전혀 그렇지 않은 것으로 나타났습니다.

1. 글쎄요, 예는 여전히 틀립니다. ushort 필드를 0으로 만들면 추가 바이트가 전혀 변경될 필요가 없습니다.


2 ZeroMemory는 아마도 sizeof에 초점을 맞추고 있으며, 그 자체로 어떤 이유에서든 두 경우 모두 듀스입니다.


1. 네 동의합니다

2. ZeroMemory는 내 메모리를 재설정해야 합니다.


일반적으로 순수 MQL에서 pack()의 요점은 볼 수 없습니다. 최대값은 .dll에서 데이터를 구동할 수 있지만 확실히 작동해야 합니다. 그래서 개발자는

 
Igor Makanu :

2. ZeroMemory는 내 메모리를 재설정해야 합니다.

그렇게 간다

 struct A pack( 4 )
{
   short j;
   char i;
};

union U
{
  A a;
   uchar Bytes[ sizeof (A)];
  
  U() { ArrayInitialize ( this .Bytes, ( char ) 0xFF ); }
};

void OnStart ()
{
  U u;
  
   ArrayPrint (u.Bytes); // 255 255 255 255
  
   ZeroMemory (u.a);
   ArrayPrint (u.Bytes); // 0 0 0 0
}