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

 

Recall that the protracted discussion was born out of a proposed method for creating optimal mini-algorithms.

For example, in this code the lines that were obtained through this mechanism are highlighted.

Forum on trading, automated trading systems and testing trading strategies

Peculiarities of mql5 language, subtleties and techniques of work

fxsaber, 2024.05.06 23:50

void TimeToStruct2100_fxsaber( const datetime dt, MqlDateTime &dt_struct )
{
  const uint time = (uint)dt;
  
  dt_struct.sec = (int)(time % 60);
  dt_struct.min = (int)(time / 60) % 60;
  dt_struct.hour = (int)(time / 3600) % 24;
  
  dt_struct.day_of_year = (int)(time / (24 * 3600));
  dt_struct.day_of_week = (dt_struct.day_of_year + THURSDAY) % 7;
  
  const int Year = ((dt_struct.day_of_year << 2) + 2) / (365 * 4 + 1); // to 2100
  const bool Flag = ((Year & 3) == 2);
  
  dt_struct.day_of_year -= Year * 365 + ((Year + 2) >> 2);
//  dt_struct.day_of_year -= ((Year * 1461 + 1) >> 2) + Flag;
  
  dt_struct.year = Year + 1970;
  
  dt_struct.mon = (dt_struct.day_of_year + Flag) < 31 ? 1 : (dt_struct.day_of_year * 5 + 166) / 153;
  
  static const int Months[] = {0, 0-1, 31-1, 59-1, 90-1, 120-1, 151-1, 181-1, 212-1,243-1, 273-1, 304-1, 334-1};
  
  dt_struct.day = dt_struct.day_of_year - Months[dt_struct.mon] + (Flag && (dt_struct.mon < 3));
  
  dt_struct.day_of_year += Flag;
  
  return;
}
There were other variants. As a result, it seems that we got the world's fastest Time formulas via MQL+MathTester.
Алгоритмическая или реальная оптимизация?
Алгоритмическая или реальная оптимизация?
  • 2024.04.16
  • www.mql5.com
Для ускорения оптимизации ТС делают следующее Увеличивают количество параллельных вычислительных потоков. Пробуют разные компиляторы. Переписывают код под особенности железа (OpenCL, GPU и т.д.)
 
Nikolai Semko #:
I agree in general, but just the other day there was a task when TimeToStruct was used about 1000 times per second. A small thing, of course, but a nice little thing.
I can assume that there will be other similar tasks. I made my own variant with caching.

I use caching, for example, when calculating the HMAC SHA-256 key for REST-API, which takes a long time to calculate and is used several times a minute at random moments.

But a function that has 1 sec precision and is called many times per second, I would calculate once per second (i.e. external control). Your solution is also an option, but doing internal caching in every such case seems like crutches.

 
Alain Verleyen #:
1,000 times a second? I can't imagine how that's possible?

Well maybe I exaggerated a bit about 1000, but a few hundred times per second is for sure. For 4K screens, maybe 1000.
Time Scale for Dynamic Peak Charting


I think there are still tasks outside of the GUI. But for now, I agree, it's hard to imagine it.

 
Edgar Akhmadeev #:

I use caching for example when calculating the HMAC SHA-256 key for the REST-API, which takes a long time to calculate and is applied several times a minute at random times.

But a function that has 1 sec precision and is called many times per second, I would calculate once per second (i.e. external control). Your solution is also an option, but doing internal caching in every such case seems like crutches.

where are the crutches?

bool TimeToStruct2100(datetime time, MqlDateTime& dt_struct) {
   static const int dm[13] = {0, -1, 30, 58, 89, 119, 150, 180, 211,242, 272, 303, 333};
   static int last_days = 0;
   static int last_result_m = 0;
   static int last_result_y = 0;
   static int last_result_yd = 0;
   static int last_result_d = 0;
   int days    = (int)(time / (60 * 60 * 24));
   if (last_days!=days) {
      last_days = days;
      last_result_y    = ((days << 2) + 2) / 1461;
      last_result_yd = days - ((last_result_y * 1461 + 1) >> 2);
      int isleap  = ((last_result_y & 3) == 2);
      int leapadj = ((last_result_yd < (59 + isleap)) ? 0 : (2 - isleap));
      last_result_m   = ((((last_result_yd + leapadj) * 12) + 373) / 367);
      last_result_d   = last_result_yd-dm[last_result_m] -((last_result_yd>59)?isleap:0);
   }
   dt_struct.year           = last_result_y+1970;
   dt_struct.mon            = last_result_m;
   dt_struct.day            = last_result_d;
   dt_struct.hour           = (int)((time / 3600) % 24);
   dt_struct.min            = (int)((time / 60) % 60);
   dt_struct.sec            = (int)(time % 60);
   dt_struct.day_of_week    = (days + 4) % 7;
   dt_struct.day_of_year    = last_result_yd;
   return (true);
}

I don't see crutches in not counting again what has already been counted before. Even if it costs 20 bytes of extra memory allocated for static variables

 
Nikolai Semko #:
where is the crutch?

I mean that the cache will have to be implemented for each case separately, where it is applicable. Instead of not running calculations when it is not necessary.

I don't think a cache is not a useful thing. Files in the OS are cached, and can be accessed very quickly with frequent operations. But in a programme you can and should keep frequently needed data in memory, not in files. I gave it as an example or analogy.

I have already said that your method is also applicable. But you can come at it from another angle.

 
Edgar Akhmadeev #:

I mean that the cache will have to be implemented for each case separately, where applicable. Instead of not running calculations when it is not necessary.

I don't think cache is not useful. Files in the OS are cached, and can be accessed very quickly with frequent operations. But in a programme you can and should keep frequently needed data in memory, not in files. I gave it as an example or analogy.

I have already said that your method is also applicable. But you can come at it from another angle.

I don't understand what side you are talking about. It seems that you haven't penetrated into the essence of the code. In this case, there are always calculations, only part of them, the most expensive one, uses stored values in static variables if the input time is the same as the previous input time.
 
Nikolai Semko #:
I don't understand which side you're talking about. It seems that you have not got into the essence of the code. In this case, there are always calculations, only part of them, the most costly, uses stored values in static variables, if the input time is the same day as the previous input time.

It is precisely because you are the author of the idea that you will stand on the defence to the last. There's no reason to get worked up, you're the one who misunderstood me.

I'm not talking about the fact that the calculation is the same day, but about the fact that you calculate hundreds of times per second, although the result is accurate to 1 second, and it is enough to call the function once per second (that's the other way round).

I'm not saying that a once-a-day cache isn't useful, I'm talking about an unfortunate example of calling a function many times a second.

I'll leave you to it. I don't like protracted debates and even less so holivars.
 
Edgar Akhmadeev #:

I use caching for example when calculating the HMAC SHA-256 key for the REST-API, which takes a long time to calculate and is applied several times a minute at random times.

But a function that has 1 sec precision and is called many times per second, I would calculate once per second (i.e. external control). Your solution is also an option, but doing internal caching in every such case seems like crutches.

Edgar Akhmadeev #:

Exactly because you are the author of the idea, you will stand on the defence to the last. There is no reason to get wound up, it's you who misunderstand me.

I'm not talking about the fact that the calculation goes on the same day, but about the fact that you calculate hundreds of times per second, although the result is accurate to 1 second, and it's enough to call the function once per second (that's the other way round).

I'm not saying that a once-a-day cache isn't useful, I'm talking about an unfortunate example of calling a function many times a second.

I'll leave you to it. I don't like protracted debates and even more so holivars.

It is hard to understand what you are talking about
I am not the author of the idea, I only tried to speed up and extend existing functions. Ah, if we are talking about hashing, then yes. It's my idea.
I didn't start it at all.
It seems that you somehow think that the current time is input to this function, if you talk about accuracy of 1 second. The input of this function is not the current time. To demonstrate this, I recorded the animated gif above, in which you can clearly see that this function is used to form the lower date-time scale. And you can see that the frequency of accessing the TimeToStruct2100() function is hundreds of times per second to form time scales of different scales. In the case of hashing, this function is on average about twice as fast.

 
Nikolai Semko #:

This function inputs different non current time. To demonstrate this, I have recorded the animated gif above, in which you can clearly see that the lower date-time scale is formed with the help of this function.

Well, that's it. Thank you all, everyone is free ))

 
Nikolai Semko #:

where's the crutch?

I don't see crutches in not counting again what has already been counted before. Even if it costs 20 bytes of extra memory allocated for static variables

Please post a file with the final versions of these functions.

Reason: