OpenCL:真正的挑战 - 页 4

 
TheXpert:

最难的方法是FeedPatterns。

一目了然,没有办法加速:相对于数据量,内核 的工作非常少(数据多,工作少),所有的收益都会被来回复制吃掉。

你可以尝试在VS中明确要求编译器将其并行化,或者为处理器创建并行线程。

OpenCL: от наивного кодирования - к более осмысленному
OpenCL: от наивного кодирования - к более осмысленному
  • 2012.06.05
  • Sceptic Philozoff
  • www.mql5.com
В данной статье продемонстрированы некоторые возможности оптимизации, открывающиеся при хотя бы поверхностном учете особенностей "железа", на котором исполняется кернел. Полученные цифры весьма далеки от предельных, но даже они показывают, что при том наборе возможностей, который имеется здесь и сейчас (OpenCL API в реализации разработчиков терминала не позволяет контролировать некоторые важные для оптимизации параметры - - в частности, размер локальной группы), выигрыш в производительности в сравнении с исполнением хостовой программы очень существенен.
 
TheXpert:
最终,我打算将其转移到MQL。
是否有严格的必要? 我想研究AMP已经很久了,现在有机会了...
 
kazakov.v:

一目了然,没有办法加速:相对于数据量,内核 的工作非常少(数据多,工作少),所有的收益都会被来回复制吃掉。

你可以尝试在VS中明确告诉编译器将其并行化,或者为处理器创建并行线程。

为什么,这些任务完全适用于OpenCL?

void Solver::FeedPattern(const Pattern &pattern)
  {
   size_t size=pattern.Size();

   assert(size==m_PatternSize);
   if(size!=m_PatternSize)
     {
      return;
     }

   const std::vector<double>&values=pattern.Values();
   double etalon=pattern.Etalon();

   size_t i;

   for(i=0; i<size;++i)
     {
      for(size_t j=0; j<size;++j)
        {
         m_Matrix[i][j]+=values[i]*values[j];
        }
      m_Matrix[i][size]+=values[i];
      m_Matrix[i][size+1]+=values[i]*etalon;
     }

   for(i=0; i<size;++i)
     {
      m_Matrix[size][i]+=values[i];
     }
   m_Matrix[size][size]+=1;
   m_Matrix[size][size+1]+=etalon;
  }

而绿色的东西也能做到这一点。

 
Urain:

为什么,这些任务在OpenCL上都很好

而且你也可以做绿色的东西。

我们需要在OpenCL和C++中做一个实现和比较测试,如果有增加,那么就翻译一切。
 

CL_DEVICE_PREFERRED_VECTOR_WIDTH_*表示最大矢量尺寸还是最佳尺寸?

当CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE=2时,double3和double4已经很慢了?

 
Roffild:

CL_DEVICE_PREFERRED_VECTOR_WIDTH_*表示最大矢量尺寸还是最佳尺寸?

当CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE=2时,double3和double4已经很慢了?

1.到最大。

2- 减速不太可能很严重,但不会提高执行速度。

 
MQL OpenCL只是对原始API的一个封装。
我需要知道关于这个包装器的实现的答案和说明。

CLContextCreate() = clCreateCommandQueue(clCreateContextFromType(CL_DEVICE_TYPE_X))?
这实际上是一个设备的队列,而不是一个环境?

缓冲区的读/写是同步的还是异步的?
clEnqueue[读/写]Buffer(enqueue, buffer, CL_TRUE) - 这里是CL_TRUE或CL_FALSE ?

bool CLExecute(intkernel) = clEnqueueTask()。
bool CLExecute(int kernel, uint work_dim, works...) = clEnqueueNDRangeKernel()。
clEnqueueNativeKernel() - 没有实现。

CLExecute()是否立即返回控制权?它不会在执行的时候阻止它?
似乎需要2-40毫秒才能将其设置到队列中......。

现在,主要问题来了。
什么时候和什么情况下调用clFinish()?而 且由于没有clFinish(),很难排队。

而MQL的帮助中根本没有描述CL_MEM_*_HOST_PTR,但它们在那里是存在的。

我终于将我的指标完全转换为OpenCL风格。
从2013.01.09到2013.10.10在M5上运行测试,使用 "OHLC on M1"。
320秒--翻译前
55秒 - 在MQL5上进行OpenCL风格的仿真。
// подготовка данных общая и копия kernel на MQL5, а эмуляция через:
for (int get_global_id = maxcount-1; get_global_id>-1; get_global_id--) NoCL(params,m_result,get_global_id);
但GPU的运行对我来说是令人沮丧的:(
我曾希望在30秒内运行测试,但收到的CLBufferWrite的测试结果是完全滞后的!

以32%的速度加载显卡,在没有CL_MEM_*_HOST_PTR的情况下,1710秒内通过测试
用CL_MEM_ALLOC_HOST_PTR在22%时加载显卡并在740秒内完成测试
CL_MEM_COPY_HOST_PTR和CL_MEM_USE_HOST_PTR导致CLExecute:5109(ERR_OPENCL_EXECUTE)。

那么,如何正确地交换数据?

而在测试器中仍然没有选择CPU进行计算。

视频适配器 = ATI Radeon HD 5850
处理器 = AMD Phenom(tm) II X4 925处理器
 
Roffild:
CLContextCreate() = clCreateCommandQueue(clCreateContextFromType(CL_DEVICE_TYPE_X))?
这实际上是一个设备的队列,而不是一个背景?
是的,上下文和队列是按设备创建的(研究表明,opencl在几个不同的设备上不能正确工作)。
缓冲区的读/写是同步的还是异步的?
clEnqueue[读/写]Buffer(enqueue, buffer, CL_TRUE) - 这里是CL_TRUE或CL_FALSE ?
读和写是同步的。
bool CLExecute(intkernel) = clEnqueueTask()。
bool CLExecute(int kernel, uint work_dim, works...) = clEnqueueNDRangeKernel()。
clEnqueueNativeKernel() - 没有实现。
CLExecute()是否立即返回控制权?它不会在执行的时候阻止它?

现在是主要问题。
什么时候和什么情况下调用clFinish()?而 且由于没有clFinish(),很难形成一个队列。
不调用,必须使用从内存中读取。
而在MQL帮助中根本就没有关于CL_MEM_*_HOST_PTR的描述。

我终于将我的指标完全转换为OpenCL风格。
从2013.01.09到2013.10.10在M5上运行测试,使用 "OHLC on M1"。
320秒--翻译前
55秒 - 在MQL5上进行OpenCL风格的仿真。
但GPU的运行对我来说是令人沮丧的:(
我希望测试能在30毫秒内运行,结果CLBufferWrite完全滞后了!

以32%的速度加载显卡,在没有CL_MEM_*_HOST_PTR的情况下,1710秒内通过测试
以22%的速度加载显卡,用CL_MEM_ALLOC_HOST_PTR在740秒内完成测试
CL_MEM_COPY_HOST_PTR和CL_MEM_USE_HOST_PTR导致CLExecute:5109(ERR_OPENCL_EXECUTE)。

那么,如何正确地交换数据?
目前终端不支持CL_MEM_COPY_HOST_PTR和CL_MEM_USE_HOST_PTR标志(我们正在调查这个问题)。
而在测试器中仍然没有选择CPU进行计算。
你是否尝试过明确指定CPU设备?
 

试着给我们提供异步缓冲区和clFinish()如何

有一种假设是,是同步写入的速度变慢了,甚至AMD CodeXL也暗示了这一点。

"clEnqueueWriteBuffer:不必要的同步。阻止写"

而在CPU测试器中,它甚至不能按数字选择。错误#865549

 
呃...关于在GPU上使用OpenCL提高速度的文章,结果是一个童话故事,因为他们没有处理真正的任务。

这个月,我写了几千行代码来征服OpenCL。

因此,为了调试OpenCL,我不得不从MQL模拟函数,通过AMD CodeXL在C/C++中运行它们。

我将在M5上重复2013.01.09至2013.10.10的测试结果,使用 "OHLC on M1"。
320秒--翻译前
55秒 - MQL5上的OpenCL风格仿真

"OpenCL风格 "是将CopyHigh/CopyTime/CopyOpen/...的调用 数量降到最低。并在这些函数被调用后增加处理数组的代码量。

而这些计算正是关于OpenCL的漂亮文章所缺乏的。

不使用OpenCL的测试结果。
核心1 EURUSD,M5:在55427毫秒内产生了1108637点(55953条)(历史总条数131439,总时间55520毫秒)。
55427 ms / 1108637 tick = 0.04999 ms/tick - 每个CPU 1 tick(在OpenCL上执行不应超过这个时间)。

这是我在C/C++中运行自己的代码并通过AMD CodeXL运行得到的结果。
0.02000 ms - 0.05000 ms - 在GPU上执行我的内核
0.35300毫秒 - 以500KB/s的速度调用clEnqueueWriteBuffer的168个字节。
0.35300 ms - 一次clEnqueueWriteBuffer调用3.445 KBytes,9.500 MBytes/s(平均传输时间相同)。

168字节是。
double open[21]={1.3668,1.3661,1.36628,1.3664,1.36638,1.36629,1.3664,1.36881,1.36814,1.3692,1.36918,1.36976,1.36816,1.36776,1.36779,1.3695,1.36927,1.36915,1.3679,1.36786,1.36838};

而我得到了3,445 KByte,因为21*168的阵列大小计算错误,但即使这样也不影响传输时间。

总结一下: 即使我设法将我的内核优化到0.02000毫秒,这确实比通常的MQL通道(0.04999毫秒)快~2倍,但这一切都归结于GPU的读写速度(0.35300毫秒--比MQL计算慢了~7倍!)。

在我的测试器中,CPU没有被选中用于OpenCL,所以我不能使用另外3个空核......

P.S.
55秒还不是MQL的优化极限,它只是在没有支持的情况下的OpenCL模拟:)
Документация по MQL5: Доступ к таймсериям и индикаторам / CopyHigh
Документация по MQL5: Доступ к таймсериям и индикаторам / CopyHigh
  • www.mql5.com
Доступ к таймсериям и индикаторам / CopyHigh - Документация по MQL5
原因: