Решил поэкспериментировать с 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"asstring cl_tester
sinputbool Random_Data=false;//Генерировать таблицу с данными?input group "Параметры генерируемой таблицы"sinputint Strok_Total_Data_Random=1000;//Всего строкsinputint 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;//Количество строк в таблице Dataint Stolb_Total_Data=3;//Количество столбцов в таблице Dataint Strok_Total_Quant=6;//Количество строк в таблице Quantint Stolb_Total_Quant=2;//Количество столбцов в таблице Quant//+------------------------------------------------------------------+//| |//+------------------------------------------------------------------+voidOnStart()
{
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_Qint 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])
{
case0:
Calc_Index=((int)arr_Data_Q[Index_Data]-1)*2;
break;
case1:
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 )
return0;
else
g( i );
continue; //(*)
}
} //Error: '}' - not all control paths return a value
Решил поэкспериментировать с OpenCL, сделал скрипт - код ниже, но вот беда - если запускаешь первый раз - считает и завершает работу корректно, но если запустить второй раз, то терминал зависает, перезагружается драйвер видеокарты, а иногда и компьютер уходит в перезагрузку. Компьютер FX-8350 32ГБ ОЗУ, видеокарта HD7950.
Скрипт запускается с настройками по умолчанию.
Может я забываю как то освободить от работы видеокарту, но вроде использую специфичные команды в конце кода.
Прошу помощи!
Ну и сам кернел
Добавил в конце скрипта принудительное удаление всего и вся - не помогло. Если не трудно, попробуйте у себя запусить скрипт - может это только у меня такой глюк.
void g( const int& i ) { Print( i ); }
void g( constint& i[] ) { Print( i[0] ); }
template<typename T>
void f( T& t ) { g( t ); } //(*)
voidOnStart()
{
int i1 = 1;
f( i1 );
int i2[1] = { 2 };
f( i2 ); //Error: 'i2' - parameter conversion not allowed
}
Зачем плодить ИДЕНТИЧНЫЕ (*) шаблоны отдельно для массива? Количество шаблонов увеличивается в геометрической прогрессии на каждый такой аргумент. Почему в MQL - t не может быть массивом? Тем более, что в С++ все нормально компилируется
Вчера столкнулся с проблемой в последних билдах платформы (3470) - мой код перестал компилироваться.
Сегодня еще поисследовал и нашел странное поведение компилятора (на мой взгляд это баг).
Подробно описал в англоязычной ветке форума https://www.mql5.com/en/forum/ 434751 #comment_42728507
Кто может подсказать куда слать багрепорты?
слови баг в мт5.
когда выбираешь один скрипт, а на график падают совершенно другой. прикрепляю видео
Решил поэкспериментировать с OpenCL, сделал скрипт - код ниже, но вот беда - если запускаешь первый раз - считает и завершает работу корректно, но если запустить второй раз, то терминал зависает, перезагружается драйвер видеокарты, а иногда и компьютер уходит в перезагрузку. Компьютер FX-8350 32ГБ ОЗУ, видеокарта HD7950.
Скрипт запускается с настройками по умолчанию.
Может я забываю как то освободить от работы видеокарту, но вроде использую специфичные команды в конце кода.
Прошу помощи!
Ну и сам кернел
Решил поэкспериментировать с OpenCL, сделал скрипт - код ниже, но вот беда - если запускаешь первый раз - считает и завершает работу корректно, но если запустить второй раз, то терминал зависает, перезагружается драйвер видеокарты, а иногда и компьютер уходит в перезагрузку. Компьютер FX-8350 32ГБ ОЗУ, видеокарта HD7950.
Скрипт запускается с настройками по умолчанию.
Может я забываю как то освободить от работы видеокарту, но вроде использую специфичные команды в конце кода.
Прошу помощи!
Ну и сам кернел
Добавил в конце скрипта принудительное удаление всего и вся - не помогло. Если не трудно, попробуйте у себя запусить скрипт - может это только у меня такой глюк.
Зачем плодить ИДЕНТИЧНЫЕ (*) шаблоны отдельно для массива? Количество шаблонов увеличивается в геометрической прогрессии на каждый такой аргумент. Почему в MQL - t не может быть массивом? Тем более, что в С++ все нормально компилируется
Уважаемые разработчики!
Очень жду от Вас ответа по данному вопросу!
Уважаемые разработчики!
Очень жду от Вас ответа по данному вопросу!
Разобрался сам - разные типы массивов были.
Что это значит?
Что это значит?
Спасибо за сообщение.
Это ошибка пула памяти, - не хвалило памяти в системе, при попытке выделить блок на ~40ГБ
Это создавался массив ?
Если нет, предоставте пожалуйста исходный код MQL программы (через ЛС), для которой данная ошибка воспроизводится.