Features of the mql5 language, subtleties and tricks - page 250

 
fxsaber #:

Parity.

template <typename T>
void Swap1( T &Value1, T &Value2 )
{
  const T Tmp = Value1;
  
  Value1 = Value2;
  Value2 = Tmp;
}

template <typename T>
void Swap2( T &Value1, T &Value2 )
{
  static T Tmp;
  
  Tmp = Value1;
  Value1 = Value2;
  Value2 = Tmp;
}

static wins for simple types and loses for structures.

Files:
 
fxsaber #:

static wins for simple types and loses for structures.

This is a very strange result. IMHO, they have something wrong. Below is the code that g++ generates. Either your test is incorrect or the developers have messed up in the compiler. Well, Test1 cannot consume more CPU time than Test2)

And yes, you can easily kill all this if you optimise the code incorrectly beforehand. Pay attention to Swap3. It seems to be an obvious optimisation, but at the output, due to the fact that we work not with a value, but with a reference, we have the most unbelievable overhead


 
Vladimir Simakov #:

Either your test is incorrect, or the developers have messed up the compiler. Well, Test1 cannot consume more CPU time than Test2)

I am incompetent in these matters. I don't think these messages will work.
 
Vladimir Simakov #:

That's a very strange result. IMHO, but something is wrong with them. Below is the code that g++ generates.


MQL is not C++ ; except for its appearance... It is not correct to compare it with gcc.

It is leaning towards C# in general .

PS/ well, in the example: static loses for structures, because there (figuratively) is also a destructor. On all calls except the first one, what was in static must be destroyed and/or the copy method must be called.

PPS/ (for those who wish) you can experiment with static T& or static T* to avoid unnecessary copies and destructors.

 
Maxim Kuznetsov #:

MQL is not C++ ; it is only externally similar...it is not correct to compare it with gcc

it is leaning towards C# in general .

PS/ well, in the example: static loses for structures, because there (figuratively) is also a destructor. On all calls except the first one, what was in static must be destroyed and/or the copy method must be called.

PPS/ (for those who wish) you can experiment with static T& or static T* to avoid unnecessary copies and destructors.

I don't agree with this one bit.

  1. Everything ultimately comes down to machine code that is executed on the processor.
  2. C# has nothing to do with it. It has nothing in common.
  3. A trivial destructor is not called.
And now the main point. I have shown how swap breaks. I don't see any other way to make the variant with static storage duration execute faster than with local storage duration. So, if this really happens during optimisation, it is a reason to correct it.
 
Vladimir Simakov #:

I don't agree once.

  1. Everything ultimately comes down to machine code that is executed on a processor.
  2. C# has nothing to do with it. It has nothing in common.
  3. A trivial destructor is not called.
And now the main point. I have shown how swap breaks. I don't see any other way to make the variant with static storage duration execute faster than with local storage duration. So, if this really happens during optimisation, it is a reason to correct it.

About the principle: the authors of the language pedal "managed code". And this is Sharp, from which, however, they had earlier renounced :-)

Again, it is not C++ and not even close to it. Neither you nor I can compare the final codes there and there and justify why it is so and why it is true/not true somewhere. That is why comparisons are incorrect. You don't have an asm output from MQL, do you? There is nothing to compare it with.

 
Vladimir Simakov #:

If this does happen during optimisation, it is a reason to correct it.

There are a lot of such corrections. Ilyas does not eat his bread for nothing. I am sure that work is going on.


From recent questions to optimisation, what I found.

 

time of bar opening for a given time and TF, when it is known for sure that the bar exists at this time. For example, by the time of opening and closing positions.

Most programmers will use a combination of iTime and iBarShift. This will be the slowest implementation, especially such an implementation requires an up-to-date history of uploaded data or combed arrays. Moreover, this approach may generate errors if the required history is missing.

More advanced programmers will solve this problem through MqlDateTime structure and TimeToStruct() function. This is not a bad solution and fast enough.

But there is a third solution, which is more productive than the previous solution several times:

//+------------------------------------------------------------------+
// получает время открытия виртуального бара по входному времени и Таймфрейму, вне зависимости от того, существует реальный бар или нет.
// корректно считает только до 28.02.2100 !!!!
// не является заменой iBarShift!!! Не зависит от истории баров.  
datetime getStartTimeOfBarFast(ENUM_TIMEFRAMES tf, datetime t) {
   if (tf==0) tf=_Period;

   int ts=0;
   if (tf<PERIOD_MN1) {
      ushort i_tf= ushort(tf);
      uchar _i =uchar(i_tf>>14);
      int n = i_tf & 0x0FFF;
      ts = (_i==0)?n*60:(_i==1)?n*60*60:60*60*24*7;
   }
   if (tf<PERIOD_W1) return t-t%ts;
   if (tf==PERIOD_W1) return t-(t+4*24*60*60)%ts;
   else { // Period MN1
      static int dm[12] = {0,31,61,92,122,153,184, 214, 245, 275, 306, 337};
      static int last_days = 0;
      static datetime last_result = 0;
      int days = int(t/(24*60*60));
      if (last_days!=days) {
         last_days = days;
         int d1 = (days+306+365)%1461;
         int y = d1/365;
         datetime t1 = t - t%(24*60*60) - d1*24*60*60;
         int m = 0;
         if (d1==1460) {
            m=11;
            y--;
         };
         int d = d1-y*365+1;
         if (d!=31) if (d==276) m = 9;
            else m = int (d/30.68);
         if (m<0 || m>11) return -1;
         last_result = t1+y*365*24*60*60+dm[m]*24*60*60;
      }
      return last_result;
   }
}
//+------------------------------------------------------------------+

The main difficulty in this algorithm is calculating the time of the beginning of the month (highlighted in green) Please don't try to understand the workings of the algorithm. There's some magic going on there that resulted from going from simple to complex.

Alternative.

#define  DAY (24 * 3600)

// Работает до конца XXI-века.
datetime GetMonthTime3( const int Year, const int Month )
{
  static const double Months[] = {0, 0.45, 31 * 1.01, 59 * 1.01, 90 * 1.007, 120 * 1.005, 151 * 1.004, 181 * 1.004,
                                  212 * 1.003, 243 * 1.003, 273 * 1.002, 304 * 1.002, 334 * 1.002};

  return((datetime)(((Year - 1970) * 365.25 + Months[Month]) * DAY) / DAY * DAY);
}
Алгоритмическая или реальная оптимизация?
Алгоритмическая или реальная оптимизация?
  • www.mql5.com
Для ускорения оптимизации ТС делают следующее Увеличивают количество параллельных вычислительных потоков. Пробуют разные компиляторы. Переписывают код под особенности железа (OpenCL, GPU и т.д.)
 
fxsaber #:

Alternative.

Well, not quite an alternative, of course, because this is a completely different problem. I calculated the year and month from the date, but here they are already input.
My implementation of such a task without numerical methods, but only logically, would be, for example, the following:

datetime GetMonthTime4(const int Year, const int Month ) {
   static const int dm[13] = {0, 0, 31, 59, 90, 120, 151, 181, 212 ,243, 273, 304, 334};
   return datetime(uint((Year-1970)*365+ (Year-1968)/4 - ((Year%4==0 && Month<3)?1:0) + dm[Month])*24*60*60);
}

I don't think the difference in performance would be significant, especially since I don't have double types

I am not against numerical methods of solving problems (what you call algorithmic optimisation), I often use them myself, but in this case you are applying algorithmic optimisation to a static system, and it is normal.
I am always against optimisation for TS, which are always dynamic rather than static systems, because the market itself is dynamic and variable. That is why such optimisation is more correctly called fitting of parameters to the historical period of time. This is self-deception and a waste of time.
The set of parameters found with the help of such "optimisation" will behave quite differently in the future.
Try to solve the problem of getting the day of the month from the input datetime using such a numerical method .
I doubt you will be able to.

char GetDayOfMonth(datetime time) {?}
 
Nikolai Semko #:

I am always against optimisation for TS, which are always dynamic rather than static systems, because the market itself is dynamic and variable. That is why such optimisation is more correctly called fitting of parameters to the historical period of time. This is self-deception and a waste of time. The set of parameters found with the help of such "optimisation" will behave quite differently in the future.

I don't understand why this is here.