MQL4 ve MQL5'te Rakamları () atlayarak herhangi bir sayıdan (sadece tırnak işaretleri değil) sonra ondalık basamak sayısını alma - sayfa 14

 

Bir dizi yapıyı (uzunluk, sizeof(int)'nin katıdır) bir int[] ve geri dizisine çevirmenin hızlı bir uygulaması hakkında beyin fırtınası yapabilir miyim?

Pratik uygulama - kaynaklar aracılığıyla hızlı veri alışverişi. Sürümüm çok yönlü, bu yüzden yavaşlıyor.


MT5'in bu tür işlevleri vardır

StructToCharArray
CharArrayToStruct

MT4'te bunlara sahip değil ve muhtemelen olmayacak. Bu nedenle, sorunu bu işlevlerle (yararlıysa) ve onlarsız çözmeniz gerekir.

Sonuç, burada çok sayıda forum kullanıcısı için faydalı olacaktır.


Soruna benim çözümümün zaten mevcut olduğu en basit beyin fırtınası şablonunu yazdım

 // Решения задачи: https://www.mql5.com/ru/forum/287618/page14#comment_9806429

#define BENCH(A)                                                              \
{                                                                             \
   const ulong StartTime = GetMicrosecondCount ();                              \
  A;                                                                          \
   Print ( "Time[" + #A + "] = " + ( string )( GetMicrosecondCount () - StartTime)); \
}  

// Инициализация исходных данных
int InitData( MqlTick &Ticks[], const int Amount = 1 e6, const double Price = 1.2345 )
{
   const int Size = ArrayResize (Ticks, Amount);
  
   for ( int i = 0 ; i < Size; i++)
    Ticks[i].bid = Price;
    
   return (Size);
}

MqlTick TicksIn[];                   // Массив с исходными данными.
const int Init = InitData(TicksIn); // Инициализировали его.

// Проверка, что два массива совпадают.
bool IsCompare( const MqlTick &Ticks1[], const MqlTick &Ticks2[] )
{
   const int Size = ArraySize (Ticks1);  
   bool Res = (Size == ArraySize (Ticks2));
  
   for ( int i = 0 ; (i < Size) && Res; i++)
    Res = (Ticks1[i].bid == Ticks2[i].bid);
    
   return (Res);
}

void OnStart ()
{
   MqlTick TicksOut[];
   int Array[];
  
  BENCH(TicksToIntArray_fxsaber1(TicksIn, Array));   // Замерили конвертацию MqlTick[] -> int[].
  BENCH(IntArrayToTicks_fxsaber1(Array, TicksOut)); // Замерили конвертацию int[] -> MqlTick[].
  
   Print (IsCompare(TicksIn, TicksOut)); // Убедились, что тики на входе и выходе совпадают.
}

// Варианты реализаций
/***********************************************/
#include <TypeToBytes.mqh> // https://www.mql5.com/ru/code/16280

template < typename T1, typename T2>
int ArrayToArray( const T1 &Source[], T2 &Target[] )
{
   return (_ArrayCopy(Target, Source) / sizeof (T2));
}

// Перевод массива тиков в массив int[].
int TicksToIntArray_fxsaber1( const MqlTick &Ticks[], int &Array[] )
{
   return (ArrayToArray(Ticks, Array));
}

// Перевод массива int[] в массив тиков.
int IntArrayToTicks_fxsaber1( const int &Array[], MqlTick &Ticks[] )
{
   return (ArrayToArray(Array, Ticks));
}
/***********************************************/


Sonuç

 Time [TicksToIntArray_fxsaber1(TicksIn,Array)] = 2036468
Time [IntArrayToTicks_fxsaber1(Array,TicksOut)] = 2253915
true
 
Başka seçenek
 template < typename T>
union INTEGER
{
  T Data;
   int Integer[ sizeof (T) / sizeof ( int )];
};

// Перевод массива тиков в массив int[].
int TicksToIntArray_fxsaber2( const MqlTick &Ticks[], int &Array[] )
{
  INTEGER< MqlTick > TickInteger;
  
   const int Size1 = ArraySize (Ticks);
   const int Size2 = ArrayResize (Array, Size1 * sizeof ( MqlTick ) / sizeof ( int ));
   int j = 0 ;
  
   for ( int i = 0 ; (i < Size1) && (j < Size2); i++)
  {
    TickInteger.Data = Ticks[i];
    
    j += ArrayCopy (Array, TickInteger.Integer, j);
  }    
  
   return (j);
}

// Перевод массива int[] в массив тиков.
int IntArrayToTicks_fxsaber2( const int &Array[], MqlTick &Ticks[] )
{
  INTEGER< MqlTick > TickInteger;
  
   const int Size1 = ArraySize (Array);
   const int Size2 = ArrayResize (Ticks, Size1 * sizeof ( int ) / sizeof ( MqlTick ));
   int j = 0 ;
  
   for ( int i = 0 ; (i < Size1) && (j < Size2); j++)
  {
    i += ArrayCopy (TickInteger.Integer, Array, 0 , i, sizeof ( MqlTick ) / sizeof ( int ));

    Ticks[j] = TickInteger.Data;        
  }    
  
   return (j);
}


Sonuç

 Time [TicksToIntArray_fxsaber2(TicksIn,Array)] = 91967
Time [IntArrayToTicks_fxsaber2(Array,TicksOut)] = 79630
true


İkinci seçenekten çok daha hızlı bir şey. Muhtemelen hızlanmaz.

 

bir dizi yapıyı (uzunluk, sizeof(int)'nin bir katıdır) bir int[] dizisine ve geri aktarmanın hızlı uygulanması ?

Bunun gibi bir şey

 #property strict

template < typename S, typename T >
union UDT{
  UDT(){ for ( int i= 0 ;i< sizeof (S)/ sizeof (T);i++)t[i]= 0 ;}
  UDT(S&src){s=src;}
  UDT(T&src[], int k= 0 ){ for ( int i= 0 ;i< sizeof (S)/ sizeof (T);i++)t[i]=src[i+k];}
   void to(S&dst){dst=s;}
   void to(T&dst[], int k= 0 ){ for ( int i= 0 ;i< sizeof (S)/ sizeof (T);i++)dst[i+k]=t[i];}
  S s; T t[ sizeof (S)/ sizeof (T)];};

template < typename S, typename T >
void StructToArray(S&src[],T&dst[]){
   ArrayResize (dst, ArraySize (src)*( sizeof (S)/ sizeof (T)));
   for ( int i= 0 ;i< ArraySize (dst)/( sizeof (S)/ sizeof (T));i++){UDT<S,T>u(src[i]);u.to(dst,i*( sizeof (S)/ sizeof (T)));}}

template < typename S, typename T >
void ArrayToStruct(T&src[],S&dst[]){
   ArrayResize (dst, ArraySize (src)/( sizeof (S)/ sizeof (T)));
   for ( int i= 0 ;i< ArraySize (dst);i++){UDT<S,T>u(src,i*( sizeof (S)/ sizeof (T)));u.to(dst[i]);}}

void OnStart ()
 {
   MqlRates rates[],r2[];
   int l[];
   CopyRates ( _Symbol , _Period , 0 , 10 ,rates);
   for ( int i= 0 ;i< 10 ;i++) printf ( "open=%f, high=%f, low=%f, close=%f, time=%s" ,rates[i].open,rates[i].high,rates[i].low,rates[i].close, TimeToStr (rates[i].time));
   Print ( "" );
  StructToArray(rates,l);
  ArrayToStruct(l,r2);
   for ( int i= 0 ;i< ArraySize (r2);i++) printf ( "open=%f, high=%f, low=%f, close=%f, time=%s" ,r2[i].open,r2[i].high,r2[i].low,r2[i].close, TimeToStr (r2[i].time));
 }  


 
Ilya Malev :

Bunun gibi bir şey

https: //www.mql5.com/ru/forum/287618/page14#comment_9807465
TicksToIntArray_fxsaber2
Time [TicksToIntArray(TicksIn,Array)] = 735252
IntArrayToTicks_fxsaber2
Time [IntArrayToTicks(Array,TicksOut)] = 591458
true

https: //www.mql5.com/ru/forum/287618/page14#comment_9808274
TicksToIntArray_antfx1
Time [TicksToIntArray(TicksIn,Array)] = 398796
IntArrayToTicks_antfx1
Time [IntArrayToTicks(Array,TicksOut)] = 296646
true

Harika bir iş çıkardın! Kodu inceleyeceğim, teşekkürler.


ZY Benzer, ArrayCopy - bu hala bir fren.


ZYY Baştan sona çok farklı sonuçlar çıkıyor. Örneğin, Testlerin sırasını değiştirirseniz, her şey neredeyse tersine döner. Görünüşe göre, daha objektif bir hız ölçümüne ihtiyacımız var.

Dosyalar:
 
Fazla düşünmeden ve hata ayıklamadan aklıma gelen ilk şeyi yazdım, bu yüzden muhtemelen hatalarla dolu. Daha önce böyle bir görevle karşılaşmadım (sendikalarla yakın çalışmama rağmen).
 
fxsaber :

ZY Benzer, ArrayCopy - bu hala bir fren.

Az sayıda öğeyi kopyalamanın gerekli olduğu bazı yerel görevleri ölçtüğümü hatırlıyorum. 16 öğeye kadar, for döngüsü ArrayCopy'den belirgin şekilde daha hızlı çalıştı, daha fazla öğe olduğunda ArrayCopy daha hızlı çalıştı. Ve elbette, döngüsüz seçenek en hızlı şekilde çalışır (son sayfadaki işlevlerimin türü hakkında)

 
Ilya Malev :

en hızlı seçenek döngüler olmadan çalışır (son sayfadaki işlevlerimin türü hakkında)

anlamadım

 
fxsaber :

anlamadım

Demek istediğim bu, for(int i=0; i<5; i++) dst[i]=src[i]; dst[0]=src[0];dst[1]=src[1];dst[2]=src[2];dst[3]=src[3];dst[4]=src [4'ten daha yavaş ];

döngü kontrolü ile ilgili ek işlemler açısından oldukça açık olan)

Ve CopyArray, az önce kontrol ettiğim gibi, her iki seçenekten de çok daha hızlı çalışıyor, öyle görünüyor. Belki duruma göre değişir tabii.

 

Evet, bu çok daha hızlı çalışacaktır (mümkün olduğunda ArrayCopy ile değiştirilir, gerisi aynıdır):

 template < typename S, typename T >
union UTS2{
  UTS2(){ for ( int i= 0 ;i< sizeof (S)/ sizeof (T);i++)t[i]= 0 ;}
  UTS2(S&src){s=src;}
  UTS2(T&src[], int k= 0 ){ ArrayCopy (t,src, 0 ,k, sizeof (S)/ sizeof (T));} //for(int i=0;i<sizeof(S)/sizeof(T);i++)t[i]=src[i+k];}
   void to(S&dst){dst=s;}
   void to(T&dst[], int k= 0 ){ ArrayCopy (dst,t,k, 0 , sizeof (S)/ sizeof (T));} //for(int i=0;i<sizeof(S)/sizeof(T);i++)dst[i+k]=t[i];}
  S s; T t[ sizeof (S)/ sizeof (T)];};

template < typename S, typename T >
void StructToArray2(S&src[],T&dst[]){
   ArrayResize (dst, ArraySize (src)*( sizeof (S)/ sizeof (T)));
   for ( int i= 0 ;i< ArraySize (dst)/( sizeof (S)/ sizeof (T));i++){UTS2<S,T>u(src[i]);u.to(dst,i*( sizeof (S)/ sizeof (T)));}}

template < typename S, typename T >
void ArrayToStruct2(T&src[],S&dst[]){
   ArrayResize (dst, ArraySize (src)/( sizeof (S)/ sizeof (T)));
   for ( int i= 0 ;i< ArraySize (dst);i++){UTS2<S,T>u(src,i*( sizeof (S)/ sizeof (T)));u.to(dst[i]);}}

Aklıma gelen ilk şeyi denemeden yazdığımı söylüyorum))

 
Ilya Malev :

Ve CopyArray, az önce kontrol ettiğim gibi, her iki seçenekten de çok daha hızlı çalışıyor gibi görünüyor. Belki duruma göre değişir tabii.

ArrayCopy(), Sish'in memmove() ilkesine göre yapılırsa,

o zaman, ArrayCopy () hızının bellek ayırma hızına bağlı olduğunu düşünüyorum, eğer kopyalama için ara ara belleğin belleği hazırsa, bellek tahsis edilmemişse ArrayCopy () çok hızlı bir şekilde yürütülür, ardından istekler işletim sistemine bellek ayırmaya başlayacak

test etmeyi deneyebilirsiniz - büyük miktarda veri içeren ArrayCopy() öğesine bir çağrı yapın, böylece arabelleği değiş tokuş için hazırlayın ve ardından kopyalamak ve hızı ölçmek için daha küçük miktarlarda veri içeren ArrayCopy() ile bir döngü oluşturun

Neden: