Ошибки, баги, вопросы - страница 3259

 

Вчера столкнулся с проблемой в последних билдах платформы (3470) - мой код перестал компилироваться.

Сегодня еще поисследовал и нашел странное поведение компилятора (на мой взгляд это баг).

Подробно описал в англоязычной ветке форума https://www.mql5.com/en/forum/ 434751 #comment_42728507


Кто может подсказать куда слать багрепорты?

MQL5 compiler issue
MQL5 compiler issue
  • 2022.10.17
  • www.mql5.com
Today I ran into a problem with MQL5 compiler. Errors appear when compiling my old code. I have written simple example to demonstrate it...
 

слови баг в мт5.

когда выбираешь один скрипт, а на график падают совершенно другой. прикрепляю видео

Файлы:
 

Решил поэкспериментировать с OpenCL, сделал скрипт - код ниже, но вот беда - если запускаешь первый раз - считает и завершает работу корректно, но если запустить второй раз, то терминал зависает, перезагружается драйвер видеокарты, а иногда и компьютер уходит в перезагрузку. Компьютер FX-8350 32ГБ ОЗУ, видеокарта HD7950.

Скрипт запускается с настройками по умолчанию.

Может я забываю как то освободить от работы видеокарту, но вроде использую специфичные команды в конце кода.

Прошу помощи!

//+------------------------------------------------------------------+
//|                                                       Primer.mq5 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "-Aleks-"
#property link      "https://www.mql5.com/ru/users/-aleks-"
#property version   "1.00"
#property script_show_inputs
#property strict
//--- COpenCL class
#include <OpenCL/OpenCL.mqh>
COpenCL           m_OpenCL;
//--- исходные коды кернелов
#resource "tester.cl" as string cl_tester


sinput bool Random_Data=false;//Генерировать таблицу с данными?
input group "Параметры генерируемой таблицы"
sinput      int Strok_Total_Data_Random=1000;//Всего строк
sinput      int Stolb_Total_Data_Random=1000;//Всего столбцов
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
float arr_Data[];//Массив для первичных данных - выборка
float arr_Quant[];//Массив с таблицами неравенств (сплитов)
char arr_Target[];//Массив с целевыми
float arr_MiniData[]=//Массив для проверки логики с малым числом примеров - первичные данные
{
   7,0,1,
   8,1,2,
   9,0,3,
   10,1,1,
   11,0,2,
   12,1,3,
   13,0,1,
   14,1,2,
   15,0,3,
   16,1,1
};
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
float arr_MiniQuant[]=//Массив для проверки логики с малым числом примеров - таблицы неравенств (сплитов)
{
   0,10.5,
   0,14.5,
   0,15.5,
   1,0.5,
   2,0.5,
   2,1.5
};
char arr_MiniTarget[]=//Массив с целевыми
{
   0,
   1,
   0,
   1,
   0,
   1,
   0,
   1,
   0,
   1
};

int Strok_Total_Data=10;//Количество строк в таблице Data
int Stolb_Total_Data=3;//Количество столбцов в таблице Data

int Strok_Total_Quant=6;//Количество строк в таблице Quant
int Stolb_Total_Quant=2;//Количество столбцов в таблице Quant


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
{
   if(Random_Data==true)//Сгенерируем данные для оценки времени работы алгоритма
   {
      MathSrand(GetTickCount());
      float N_Random=0.0;//Переменная для сохранения случайного числа
      int Strok_Total_Quant_Random=0;

      int Size_Arr_RandomData=Strok_Total_Data_Random*Stolb_Total_Data_Random;
      float arr_RandomData[];
      float arr_RandomQuant[];
      int arr_RandomTarget[];

      ArrayResize(arr_RandomData,Size_Arr_RandomData);
      ArrayResize(arr_RandomTarget,Strok_Total_Data_Random);


      for(int i=0; i<Size_Arr_RandomData; i++) //Выберем комбинации
      {
         N_Random=RandomFloat(20);//Определяем число случайным образом
         arr_RandomData[i]=N_Random;
      }

      for(int i=0; i<Strok_Total_Data_Random; i++) //Выберем комбинации
      {
         N_Random=RandomFloat(2);//Определяем число случайным образом
         arr_RandomTarget[i]=(int)N_Random;
      }

      for(int i=0; i<Stolb_Total_Data_Random; i++) //Выберем комбинации для квантовой таблицы
      {
         N_Random=RandomFloat(20);//Определяем число сплитов
         if(N_Random<1)
            N_Random=1;
         int Size_arr_RandomQuant=ArraySize(arr_RandomQuant);
         ArrayResize(arr_RandomQuant,Size_arr_RandomQuant+(int)N_Random*2);
         Size_arr_RandomQuant=ArraySize(arr_RandomQuant);
         float arr_N_Random[];
         ArrayResize(arr_N_Random,(int)N_Random);
         for(int n=0; n<(int)N_Random; n++) //Выберем комбинации
         {
            arr_N_Random[n]=RandomFloat(20);//Определяем значение сплитов
         }
         ArraySort(arr_N_Random);
         for(int n=0; n<(int)N_Random; n++) //Выберем комбинации
         {
            arr_RandomQuant[Size_arr_RandomQuant-(int)N_Random*2+2*n]=(float)i;//Номер столбца
            arr_RandomQuant[Size_arr_RandomQuant-(int)N_Random*2+2*n+1]=arr_N_Random[n];//Значение сплита
         }
      }

      ArrayCopy(arr_Data,arr_RandomData,0,0,WHOLE_ARRAY);
      ArrayCopy(arr_Quant,arr_RandomQuant,0,0,WHOLE_ARRAY);
      ArrayCopy(arr_Target,arr_RandomTarget,0,0,WHOLE_ARRAY);

      Strok_Total_Data=Strok_Total_Data_Random;
      Stolb_Total_Data=Stolb_Total_Data_Random;
      Strok_Total_Quant_Random=ArraySize(arr_RandomQuant)/2;
      Strok_Total_Quant=Strok_Total_Quant_Random;
   }
   else
   {
      ArrayCopy(arr_Data,arr_MiniData,0,0,WHOLE_ARRAY);
      ArrayCopy(arr_Quant,arr_MiniQuant,0,0,WHOLE_ARRAY);
      ArrayCopy(arr_Target,arr_MiniTarget,0,0,WHOLE_ARRAY);
   }

   int arr_N_Quant[];//Массив в котором будем хранить число сплитов квантовой таблицы для каждого предиктора
   ArrayResize(arr_N_Quant,Stolb_Total_Data);
   ArrayInitialize(arr_N_Quant,-1);

   int New_Size=0;//Для установки размера массива
   int N_Calc=1;//Счетчик
   int N_Pred=0;//Счетчик столбцов (//Номер предиктора)

   for(int i=1; i<Strok_Total_Quant; i++)//Найдем число сплитов для каждого предиктора
   {
      //Print("2*i=",2*i," 2*(i-1)=",2*(i-1));
      if(arr_Quant[2*i]>arr_Quant[2*(i-1)])
      {
         arr_N_Quant[N_Pred++]=N_Calc;
         if(New_Size<N_Calc)
         {
            New_Size=N_Calc;
         }
         N_Calc=1;
      }
      else
         N_Calc++;
      if(i+1==Strok_Total_Quant)
         arr_N_Quant[N_Pred++]=N_Calc;//Если последний индекс столбца, то сохраним его
   }

   int arr_Max_Calc[];//Массив в котором будем искать максимум после сортировки
   ArrayCopy(arr_Max_Calc,arr_N_Quant);//Скопируем массив
   ArraySort(arr_Max_Calc);//Отсортируем массив
   int Max_Ind=ArrayMaximum(arr_Max_Calc,0,WHOLE_ARRAY);//Присвоем индекс максимального значения массива
   int Max_N=arr_Max_Calc[Max_Ind];//Присвоем максимальное значение массива
   int Size_arr_Quant_Trans=(Max_N+1)*Stolb_Total_Data;//Размер массива транспонированной квантовой таблицы

   float arr_Quant_Trans[];//Массив, куда запишем преобразованную таблицу с неравенствами
   ArrayResize(arr_Quant_Trans,Size_arr_Quant_Trans);
   ArrayInitialize(arr_Quant_Trans,0);
   Print("New_Size=",New_Size," Max_N=",Max_N);
   int Index=0;
   New_Size=0;
   N_Calc=1;//Счетчик числа сплитов предиктора
   N_Pred=0;
   double Split=0.0;//Значение сплита
   for(int i=1; i<Strok_Total_Quant; i++)//Транспонируем квантовую таблицу и записывем число сплитов
   {
      Index=(int)arr_Quant[2*(i-1)];
      arr_Quant_Trans[Stolb_Total_Data*(N_Calc)+Index]=arr_Quant[2*i-1];//Значение сплита

      if(arr_Quant[2*i]>arr_Quant[2*(i-1)])//Новый сплит
      {
         arr_Quant_Trans[Index]=(float)N_Calc;//Число сплитов в предикторе / столбца
         if(New_Size<N_Calc)
         {
            New_Size=N_Calc;
         }
         N_Calc=1;
      }
      else
         N_Calc++;
      if(i+1==Strok_Total_Quant)//Если последний индекс столбца, то сохраним число сплитов в предикторе / столбца
      {
         Index=(int)arr_Quant[2*i];
         arr_Quant_Trans[Index]=(float)N_Calc;//Число сплитов в предикторе / столбце
         arr_Quant_Trans[Stolb_Total_Data*(N_Calc)+Index]=arr_Quant[2*i+1];//Значение сплита -1 так как это последнее значение, а счетчик N_Calc ранее по коду учел новое
      }
   }


   ushort arr_Data_Q[];//Таблица №3 с результатами классификации(квантования) выборки.
   ArrayResize(arr_Data_Q,Strok_Total_Data*Stolb_Total_Data);
   ArrayInitialize(arr_Data_Q,0);

   float arr_Proc_Target[];//Процент принадлежности классов к целевой
   float arr_Proc_Otklik[];//Процент откликов классов ко всей таблице (выборке).
   ArrayResize(arr_Proc_Target,((Max_N+1)*Stolb_Total_Data)*2);//Делаем по размеру квантовой таблицы, умноженной на число разных значений (типов) целевых
   ArrayResize(arr_Proc_Otklik,((Max_N+1)*Stolb_Total_Data));//Делаем по размеру квантовой таблицы
   ArrayInitialize(arr_Proc_Target,0);
   ArrayInitialize(arr_Proc_Otklik,0);

   ushort arr_N_Class_Target[];//Считаем число целевых по их типам для каждого условного класса после квантования
   ushort arr_N_Class_Otklik[];//Считаем число откликов для каждого условного класса после квантования в выборке
   //ArrayResize(arr_N_Class_Target,((int)arr_Quant_Trans[p]+1)*2);//Умножаем на количество разных целевых ("0" и "1")
   //ArrayResize(arr_N_Class_Otklik,((int)arr_Quant_Trans[p]+1));//
   ArrayResize(arr_N_Class_Target,(Max_N+1)*2);//Умножаем на количество разных целевых ("0" и "1")
   ArrayResize(arr_N_Class_Otklik,Max_N+1);//

   ArrayInitialize(arr_N_Class_Target,0);
   ArrayInitialize(arr_N_Class_Otklik,0);

   /*
   __kernel void CalcPred(
   __global int *arr_Data,
   __global int *arr_Quant_Trans,
   __global int *arr_Target,
   __global int *arr_Data_Q,
   __global int *arr_N_Class_Target,
   __global int *arr_N_Class_Otklik,
     int p,
     int Stolb_Total_Data
    )
   */

   int index_kernel=0;
   int Handle_Context=0;
//---Инициализация файла с кернелами
   Print("Initialize=",m_OpenCL.Initialize(cl_tester,true));
   //CLProgramCreate(Handle_Context,cl_tester);
//--- установка количества кернелов
   Print("SetKernelsCount=",m_OpenCL.SetKernelsCount(1));
//--- создание кернелов
   Print("KernelCreate=",m_OpenCL.KernelCreate(index_kernel,"CalcPred"));
//--- создание буферов - указать количество буферов
   Print("SetBuffersCount=",m_OpenCL.SetBuffersCount(6));
//--- копирование буфера на видеокарту
   Print("BufferFromArray=",m_OpenCL.BufferFromArray(0,arr_Data,0,Stolb_Total_Data*Strok_Total_Data,CL_MEM_READ_ONLY));
   Print("BufferFromArray=",m_OpenCL.BufferFromArray(1,arr_Quant_Trans,0,Size_arr_Quant_Trans,CL_MEM_READ_ONLY));
   Print("BufferFromArray=",m_OpenCL.BufferFromArray(2,arr_Target,0,Strok_Total_Data,CL_MEM_READ_ONLY));
   Print("BufferFromArray=",m_OpenCL.BufferFromArray(3,arr_Data_Q,0,Stolb_Total_Data*Strok_Total_Data,CL_MEM_READ_WRITE));
   Print("BufferFromArray=",m_OpenCL.BufferFromArray(4,arr_N_Class_Target,0,(Max_N+1)*2,CL_MEM_READ_WRITE));
   Print("BufferFromArray=",m_OpenCL.BufferFromArray(5,arr_N_Class_Otklik,0,Max_N+1,CL_MEM_READ_WRITE));
//---привязка буфера к аргументу кернела
   Print("SetArgumentBuffer=",m_OpenCL.SetArgumentBuffer(index_kernel,0,0));
   Print("SetArgumentBuffer=",m_OpenCL.SetArgumentBuffer(index_kernel,1,1));
   Print("SetArgumentBuffer=",m_OpenCL.SetArgumentBuffer(index_kernel,2,2));
   Print("SetArgumentBuffer=",m_OpenCL.SetArgumentBuffer(index_kernel,3,3));
   Print("SetArgumentBuffer=",m_OpenCL.SetArgumentBuffer(index_kernel,4,4));
   Print("SetArgumentBuffer=",m_OpenCL.SetArgumentBuffer(index_kernel,5,5));
//---привязка параметра фукнкции к кернелу
   int p=0;
   Print("SetArgument=",m_OpenCL.SetArgument(index_kernel,6,p));
   Print("SetArgument=",m_OpenCL.SetArgument(index_kernel,7,Stolb_Total_Data));

//--- пространство задач для кернела - одномерное
   uint global_work_size[1];
//--- 1-е измерение
   global_work_size[0]=Strok_Total_Data;
//--- начальное смещение в пространстве задач для обоих измерений равно нулю
   uint global_work_offset[1]= {0};

   for(/*int*/ p=0; p<Stolb_Total_Data; p++)
   {

      Print("Execute=",m_OpenCL.Execute(index_kernel,1,global_work_offset,global_work_size));

      Print("BufferRead=",m_OpenCL.BufferRead(4,arr_N_Class_Target,0,0,(Max_N+1)*2));
      Print("BufferRead=",m_OpenCL.BufferRead(5,arr_N_Class_Otklik,0,0,Max_N+1));
      
      for(ushort q=0; q<arr_Quant_Trans[p]+1; q++)//Посчитаем проценты
      {
         int Summ=arr_N_Class_Target[2*q]+arr_N_Class_Target[2*q+1];
         //Print("Summ=",Summ);
         if (Summ>0)
         {
            arr_Proc_Target[Stolb_Total_Data*2*q+p*2]=float((double)arr_N_Class_Target[2*q]/(double)Summ*100.0);//Целевая "0"
            arr_Proc_Target[Stolb_Total_Data*2*q+p*2+1]=float((double)arr_N_Class_Target[2*q+1]/(double)Summ*100.0);//Целевая "1"
         }
         arr_Proc_Otklik[Stolb_Total_Data*q+p]=float((double)arr_N_Class_Otklik[q]/(double)Strok_Total_Data*100.0);

      }
   }
   Print("BufferRead=",m_OpenCL.BufferRead(3,arr_Data_Q,0,0,Stolb_Total_Data*Strok_Total_Data));
   Print("Задача №1 Таблица №3 с результатами классификации выборки.");
   ArrayPrint(arr_Data_Q);
   Print("Таблица №5 с результатами вычислений процента принадлежности классов к целевой.");
   ArrayPrint(arr_Proc_Target);
   Print("Таблица №6 с  результатами вычислений процента откликов классов ко всей таблице (выборке).");
   ArrayPrint(arr_Proc_Otklik);

   m_OpenCL.KernelFree(index_kernel);
   m_OpenCL.Shutdown();
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|Определяем комбинацию случайным образом
//+------------------------------------------------------------------+
float RandomFloat(float max_vl)
{
   return (float)MathFloor((MathRand()+MathRand()*32767.0)/1073741824.0*max_vl);  //случайное Int от 0 до  1073741824
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+

Ну и сам кернел

//+------------------------------------------------------------------+
//|                                                        tester.cl |
//+------------------------------------------------------------------+
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable
#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable

//+------------------------------------------------------------------+
//| Расчет
//+------------------------------------------------------------------+
__kernel void CalcPred(
__global int *arr_Data,
__global int *arr_Quant_Trans,
__global int *arr_Target,
__global int *arr_Data_Q,
__global int *arr_N_Class_Target,
__global int *arr_N_Class_Otklik,
 int p,
 int Stolb_Total_Data
 
 )
  {
  
   int Index_Data=0;//Индекс массива arr_Data и arr_Data_Q
   int Index_Quant_A=0;//Индекс массива arr_Quant_Trans для границы А
   int Index_Quant_B=0;//Индекс массива arr_Quant_Trans для границы Б  
//--- работает в одном измерении    
   size_t i=get_global_id(0);

         Index_Data=Stolb_Total_Data*i+p;
         for(ushort q=0; q<arr_Quant_Trans[p]+1; q++)
         {
            if(arr_Quant_Trans[p]<1)
            {
               arr_Data_Q[Index_Data]=0;//Обнуляем значение предиктора, так как нет информации о сплитах
               break;
            }
            else
            {
               if(q==0)//Первый сплит
               {
                  Index_Quant_A=Stolb_Total_Data*(q+1)+p;//Рассчитаем индекс первой границы
                  if(arr_Data[Index_Data]<=arr_Quant_Trans[Index_Quant_A])
                  {
                     arr_Data_Q[Index_Data]=q+1;
                     break;
                  }
               }
               else
               {
                  Index_Quant_A=Stolb_Total_Data*(q+1-1)+p;//Рассчитаем индекс первой границы
                  Index_Quant_B=Stolb_Total_Data*(q+1)+p;//Рассчитаем индекс последней границы
                  if(q==arr_Quant_Trans[p])//Последний сплит "q" будет равно arr_Quant_Trans[p] при выходе за пределы массива)
                  {
                     if(arr_Data[Index_Data]>arr_Quant_Trans[Index_Quant_A])
                     {
                        arr_Data_Q[Index_Data]=q+1;
                        break;

                     }
                  }
                  else//Средние сплиты
                  {
                     if(arr_Data[Index_Data]>arr_Quant_Trans[Index_Quant_A] && arr_Data[Index_Data]<=arr_Quant_Trans[Index_Quant_B])
                     {
                        arr_Data_Q[Index_Data]=q+1;
                        break;
                     }
                  }
               }
            }
         }
         int Calc_Index=0;
         switch(arr_Target[i])
         {
         case 0:
            Calc_Index=((int)arr_Data_Q[Index_Data]-1)*2;
            break;
         case 1:
            Calc_Index=((int)arr_Data_Q[Index_Data]-1)*2+1;
            break;
         }
         arr_N_Class_Target[Calc_Index]++;//Прибавим 1 для подсчета целевой
         Calc_Index=((int)arr_Data_Q[Index_Data]-1);//Индекс для массива arr_N_Class_Otklik
         arr_N_Class_Otklik[Calc_Index]++;//Прибавим 1 для подсчета откликов
  }
 
Ошибка при компиляции:
void g( int& ) {}
int f( int i )
{
    while ( 1 )
    {
        if ( i == 1 )
            return 0;
        else
            g( i );
        continue; //(*)
    }
} //Error: '}' - not all control paths return a value
А без (*) нормально. А какая разница?
 
Aleksey Vyazmikin #:

Решил поэкспериментировать с OpenCL, сделал скрипт - код ниже, но вот беда - если запускаешь первый раз - считает и завершает работу корректно, но если запустить второй раз, то терминал зависает, перезагружается драйвер видеокарты, а иногда и компьютер уходит в перезагрузку. Компьютер FX-8350 32ГБ ОЗУ, видеокарта HD7950.

Скрипт запускается с настройками по умолчанию.

Может я забываю как то освободить от работы видеокарту, но вроде использую специфичные команды в конце кода.

Прошу помощи!

Ну и сам кернел

Добавил в конце скрипта принудительное удаление всего и вся - не помогло. Если не трудно, попробуйте у себя запусить скрипт - может это только у меня такой глюк.

//--- удаляем в обратной последовательности все созданные OpenCL контексты
  CLBufferFree(0);//Удаляет буфер OpenCL.
  CLBufferFree(1);//Удаляет буфер OpenCL.
  CLBufferFree(2);//Удаляет буфер OpenCL.
  CLBufferFree(3);//Удаляет буфер OpenCL.
  CLBufferFree(4);//Удаляет буфер OpenCL.
  CLBufferFree(5);//Удаляет буфер OpenCL.
  
  CLKernelFree(index_kernel);//Удаляет функцию запуска OpenCL.
  int program=m_OpenCL.GetProgram();//Возвращает хендл программы OpenCL.
  CLProgramFree(0);//Удаляет OpenCL программу.

  int context=m_OpenCL.GetContext();//Возвращает хендл контекста OpenCL
  CLContextFree(context);//Удаляет контекст OpenCL.


   //m_OpenCL.KernelFree(index_kernel);
   m_OpenCL.Shutdown();
   //delete m_OpenCL;
 
Ошибка при компиляции:
void g( const int&  i   ) { Print( i    ); }
void g( const int&  i[] ) { Print( i[0] ); }
template<typename T>
void f( T& t ) { g( t ); } //(*)
void OnStart()
{
    int i1 =      1;
    f(  i1 );
    int i2[1] = { 2 };
    f(  i2 ); //Error: 'i2' - parameter conversion not allowed
}

Зачем плодить ИДЕНТИЧНЫЕ (*) шаблоны отдельно для массива? Количество шаблонов увеличивается в геометрической прогрессии на каждый такой аргумент. Почему в MQL - t не может быть массивом? Тем более, что в С++ все нормально компилируется

 

Уважаемые разработчики!

Очень жду от Вас ответа по данному вопросу!

 
Aleksey Vyazmikin #:

Уважаемые разработчики!

Очень жду от Вас ответа по данному вопросу!

Разобрался сам - разные типы массивов были.

 

Что это значит?

2022.10.25 23:40:46.143 MQL5    VirtualAlloc failed in large allocator, size=40000000016
 
Aleksey Vyazmikin #:

Что это значит?

Спасибо за сообщение.

Это ошибка пула памяти, - не хвалило памяти в системе, при попытке выделить блок на ~40ГБ

Это создавался массив ?
Если нет, предоставте пожалуйста исходный код MQL программы (через ЛС), для которой данная ошибка воспроизводится.