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

 
따라서 설명된 버그는 개발자에게 흥미롭지 않습니다. 알겠습니다...
 
MT5 버그(빌드 2345)는 오랫동안 프로파일러 가 시작되고 작동하는 이유를 이해할 수 없었지만 결과가 어디에도 표시되지 않았습니다.
스크립트 프로젝트의 프로파일러는 최적화가 꺼져 있는 경우에만 결과를 표시하고, 최적화가 켜져 있으면 모든 것이 시작되고 작동하지만 결과가 없는 것으로 나타났습니다.
 
Sergey Dzyublik :
MT5 버그(빌드 2345)는 오랫동안 프로파일러 가 시작되고 작동하는 이유를 이해할 수 없었지만 결과가 어디에도 표시되지 않았습니다.
스크립트 프로젝트의 프로파일러는 최적화가 꺼져 있는 경우에만 결과를 표시하고, 최적화가 켜져 있으면 모든 것이 시작되고 작동하지만 결과가 없는 것으로 나타났습니다.

프로파일러는 최적화 없이 모든 지표에 대해 작동하지 않습니다. 두 번 나는 포럼에 그것에 대해 썼고 LAN의 개발자에게 코드를 던졌습니다. 답변이 없습니다.

 
MT5(빌드 2345)의 프로파일러 작업,
대략적으로 말하자면, 궁극적으로 동일한 결과를 제공하는 두 가지 알고리즘이 최적화 모드 에서 1.7배의 감소인 다른 속도로 실행되는 이유에 관심이 있었습니다.

 #include <stl_vector.mqh>

// TickCounts: 850
vector< int >::move test_vector_move_return_assign_by_index( int n){
   vector< int > v(n);
   for ( int i = 0 ; i < n; i++){
      v[i].UNREF  = i;
   }
   return v;
};

// TickCounts: 1450
vector< int >::move test_vector_move_return_push_back( int n){
   vector< int > v;
   // lazy implementation  
   v.reserve(n);                      
   for ( int i = 0 ; i < n; i++){
      v.push_back(i);
   }
   return v;
};


void OnStart ()
{
   for ( int i = 0 ; i < 20000 ; i++){
       vector< int > v_int_move = test_vector_move_return_assign_by_index( 1000 );
   }
   
   for ( int i = 0 ; i < 20000 ; i++){
      vector< int > v_int_move = test_vector_move_return_push_back( 1000 );
   }
}


결과적으로 MT5 프로파일러에 대한 실제 경험을 얻었고 작동에서 많은 결함이 발견되었습니다.
개발자가 이 정보에 관심이 있는지 여부가 명확하지 않고 버그를 현지화하는 데 몇 시간을 할애하고 싶지 않기 때문에 발견된 문제에 대한 간략한 정보만 제공됩니다.

1) 다른 알고리즘의 속도를 비교할 방법이 없습니다.
따라서 최적화가 활성화된 경우와 없는 경우 모두 나머지 알고리즘보다 3배 빠른 알고리즘이 프로파일러에서 가장 느린 것으로 판명될 수 있습니다.
분명히 알고리즘의 실행 시간에 영향을 미치는 프로파일러 부분에 일종의 오버헤드가 있습니다. 이 경우 프로파일러에서 알고리즘의 속도를 비교하는 것은 의미가 없습니다.

2) 화면의 히스토그램 툴팁에 잘못된 Count 값이 표시됩니다.
프로파일러는 함수가 예상대로 20K가 아니라 80K 번 실행되었다고 기록합니다. 유사하게 다른 라인에 대한 함수 내부에는 때때로 Count 초과가 있고, 일부 라인은 3번, 다른 라인은 2번이 있습니다.

3) 화면의 히스토그램 툴팁에 잘못된 시간 값이 표시됩니다.
프로파일러에서 알고리즘이 99.90%의 시간 동안 조건에 진입했다고 표시하는 경우가 있지만 실제로는 20K 중 한 번만 통과하는 것으로 나타났습니다.

 

이것은 버그가 아니라 참고 사항입니다!


마운트 5 빌드 2340.

어제 Data Catalog를 열었을 때 Indicators 폴더가 Experts 폴더로 어떻게 이동했는지 눈치채지 못했습니다. 그런 다음 MT5를 끄고 오늘 켰습니다. 아무 일도 없었던 것처럼 내비게이터에서도 표시기를 사용할 수 있습니다. 그러나 Data Catalog를 다시 열면 빈 폴더 Indicators가 나타나고 이미 일부 지표를 여기에 던졌습니다. 그러면 더 이상 네비게이터에 나타나지 않습니다. Indicators 폴더를 MQL5\Indicators로 되돌리면 문제가 해결됩니다.

 

MT5(빌드 2347) ArrayResize를 사용하여 배열에 하나의 요소를 추가할 때 메모리가 이전에 예약된 경우 왜 이렇게 큰 오버헤드가 발생합니까?

 #define K 1000
#define M ( 1000 * K)

#define   SpeedTest(test_count,msg,EX)        { uint mss= GetTickCount (); ulong count=test_count; for ( ulong ii= 0 ;ii<count&&! _StopFlag ;ii++){EX;} \
                                               printf ( "%-60s: loops=%i ms=%u" ,msg,count, GetTickCount ()-mss);}
                                              
class A{
public :
   int data;
};

struct B{
   int data;
};

template < typename T>
void test1( const int test_count, const int array_size){
   SpeedTest(
   test_count, "Test Class ArrayResize all" ,
   {
      T class_array[];
       for ( int i = 1 ; i <= array_size; i++){
         ArrayResize (class_array, array_size);
      }
   }
   )
};

template < typename T>
void test2( const int test_count, const int array_size){
   SpeedTest(
   test_count, "Test Class ArrayResize one by one with reserved memory" ,
   {
      T class_array[];
       ArrayResize (class_array, 1 , array_size - 1 );
       for ( int i = 2 ; i <= array_size; i++){
         ArrayResize (class_array, i);
      }
   }
   )
};

void OnStart ()
{
   const int test_count = 5 *K;
   const int array_size = 5 *K;  
  
  test1< int >(test_count, array_size);             // Avg time: 100
  test2< int >(test_count, array_size);             // Avg time: 190
  test1< int >(test_count, array_size);
  test2< int >(test_count, array_size);
  test1< int >(test_count, array_size);
  test2< int >(test_count, array_size);
  test1< int >(test_count, array_size);
  test2< int >(test_count, array_size);
  
printf ( "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" );
  test1<A>(test_count, array_size);               // Avg time: 810
  test2<A>(test_count, array_size);               // Avg time: 1460
  test1<A>(test_count, array_size);
  test2<A>(test_count, array_size);
  test1<A>(test_count, array_size);
  test2<A>(test_count, array_size);
  test1<A>(test_count, array_size);
  test2<A>(test_count, array_size);
  
printf ( "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" );
  test1<B>(test_count, array_size);               // Avg time: 110
  test2<B>(test_count, array_size);               // Avg time: 770
  test1<B>(test_count, array_size);
  test2<B>(test_count, array_size);
  test1<B>(test_count, array_size);
  test2<B>(test_count, array_size);
  test1<B>(test_count, array_size);
  test2<B>(test_count, array_size);
}

ArrayResize를 사용하여 내부 예약 알고리즘을 개선하는 것을 고려하십시오.

예를 들어 클래스의 경우 생성자를 호출하는 것 외에도 일종의 "목록에 내부 등록"을 수행한다고 가정할 수 있습니다.
그리고 ArrayResize를 사용하는 예약의 일부로 직접 메모리 할당 외에도 프로세스를 최적화할 수 있습니다.
- 생성된 인접 요소에서 데이터를 가져옵니다(예: 가상 기능 테이블에 대한 포인터).
- 아직 생성되지 않은 클래스의 "내부 등록"을 위한 사전 또는 예약 공간

 
Sergey Dzyublik :

MT5(빌드 2347) ArrayResize를 사용하여 배열에 하나의 요소를 추가할 때 메모리가 이전에 예약된 경우 왜 이렇게 큰 오버헤드가 발생합니까?

그마저도 도움이 되지 않는다.

       ArrayResize (class_array, 1 , array_size - 1 );
       for ( int i = 0 ; i < array_size; i++){
//         ArrayResize(class_array, i);
         ArrayResize (class_array, i , array_size - 1 );

말도 안되는 소리. 브레이크 가속 대신.


ZY 이상합니다. Documentation 0에서 예제를 실행한 결과입니다.

--- Test Fast: ArrayResize (arr, 100000 , 100000 )
1 . ArraySize (arr)= 100000 Time= 0 ms
2 . ArraySize (arr)= 200000 Time= 0 ms
3 . ArraySize (arr)= 300000 Time= 0 ms
---- Test Slow: ArrayResize (slow, 100000 )
1 . ArraySize (slow)= 100000 Time= 0 ms
2 . ArraySize (slow)= 200000 Time= 0 ms
Документация по MQL5: Операции с массивами / ArrayResize
Документация по MQL5: Операции с массивами / ArrayResize
  • www.mql5.com
При успешном выполнении функция возвращает количество всех элементов, содержащихся в массиве после изменения размера; в противном случае возвращает -1 и массив не меняет размеры. Если ArrayResize() применена к статическому массиву, таймсерии или индикаторному буферу, то размер массива остается прежним – такие массивы не могут быть...
 
Sergey Dzyublik :
MT5(빌드 2345)의 프로파일러 작업,
대략적으로 말하자면, 궁극적으로 동일한 결과를 제공하는 두 개의 알고리즘이 최적화 모드 에서 1.7배의 감소인 다른 속도로 실행되는 이유에 관심이 있었습니다.


...

불행히도 이 오랜 시간 프로파일러는 중요한 프로젝트에는 쓸모가 없습니다. 이미 신고를 시도했지만 개발자들의 관심이 없었다.
 
Sergey Dzyublik :

MT5(빌드 2347) ArrayResize를 사용하여 배열에 하나의 요소를 추가할 때 메모리가 이전에 예약된 경우 왜 이렇게 큰 오버헤드가 발생합니까?

비교하려면 다음과 같아야 합니다.

 void test1 ( const int test_count, const int array_size){
   SpeedTest(
   test_count,"Test Class ArrayResize all",
   {
      T class_array[];
       for ( int i = 0 ; i < array_size; i++){
         ArrayResize (class_array,  i );
      }
   }
   )
 
Alain Verleyen :

비교하려면 다음과 같아야 합니다.

내 입장에서는 무엇을 비교했어야 했는가.
배열에 얼마나 많은 요소가 배치될지 알고 있으며 한 번에 모두 생성하는 대신 생성되지 않은 요소를 위한 메모리를 예약합니다.
문제는 메모리를 예약하고 배열 요소 를 한 번에 하나씩 만들면 모든 것을 한 번에 만드는 것보다 몇 배나 더 많은 시간이 걸린다는 것입니다.
따라서 구조의 경우 - 7배 느립니다.
그리고 데이터 유형의 경우 class와 int는 두 배 느립니다.

이것은 매우 큰 차이이며, 원하는 경우 개발자가 제거할 수 있는 것 같습니다.