OpenCL: 실제 문제 - 페이지 5

 
SD에서 응용 프로그램을 만들고 코드를 첨부하십시오(PM을 통해 가능). 귀하의 코드를 분석하겠습니다.
Общайтесь с разработчиками через Сервисдеск!
Общайтесь с разработчиками через Сервисдеск!
  • www.mql5.com
Ваше сообщение сразу станет доступно нашим отделам тестирования, технической поддержки и разработчикам торговой платформы.
 

내 코드의 어떤 부분이 특히 관심이 있습니까? 나는 다른 파일에 많은 의존성을 가지고 있습니다.

지금 내가 가지고 있는 문제는 테스터의 1틱 동안 버퍼를 쓰고 읽는 것뿐이며 확인하는 것으로 충분합니다.

 #property copyright ""
#property link        ""

int hcontext, hprogram, hkernel, hbuffer[ 5 ];

void InitGlobal()
{
   for ( int cdev = ( int ) CLGetInfoInteger ( 0 , CL_DEVICE_COUNT )- 1 ; cdev>- 1 ; cdev--)
   {
       string name;
       CLGetInfoString (cdev, CL_DEVICE_NAME , name);
       Print ( "Device #" ,cdev, " = " ,name);
   }
   
   string source =
"kernel void tester(global double *price, global double *result)                                   \r\n"
"{                                                                                                 \r\n"
"   int global_index = get_global_id(0);                                                           \r\n"
"   result[global_index] = price[global_index] / global_index;                                     \r\n"
"}                                                                                                 \r\n"
;
   
   hcontext = CLContextCreate ( CL_USE_GPU_ONLY );
   string build_log;
   hprogram = CLProgramCreate (hcontext, source, build_log);
   Print ( "build log = " , build_log);
   hkernel = CLKernelCreate (hprogram, "tester" );
}

void DeinitGlobal()
{
   CLBufferFree (hbuffer[ 0 ]);
   CLBufferFree (hbuffer[ 1 ]);
   
   CLKernelFree (hkernel);
   CLProgramFree (hprogram);
   CLContextFree (hcontext);
}

int OnInit ()
{
   InitGlobal();
   return ( 0 );
}

void OnDeinit ( const int reason)
{
   DeinitGlobal();
}

// Скрипт, в отличии от эксперта, можно дебажить на выходных :)
//void OnStart() {  InitGlobal();
void OnTick () {
   double price[ 30 ];
   CopyClose ( _Symbol , _Period , 0 , ArraySize (price),price);
   
   static bool firststart = true ;
   if (firststart)
   {
      firststart = false ;
       uint bufsize = sizeof (price);
       Print ( "Размер буфера в байтах =" ,bufsize);
      hbuffer[ 0 ] = CLBufferCreate (hcontext, bufsize, CL_MEM_READ_ONLY );
      hbuffer[ 1 ] = CLBufferCreate (hcontext, bufsize, CL_MEM_WRITE_ONLY );
      
       CLSetKernelArgMem (hkernel, 0 , hbuffer[ 0 ]);
       CLSetKernelArgMem (hkernel, 1 , hbuffer[ 1 ]);
   }
   
   // А вот здесь не хватает clGetMemObjectInfo(buffer, CL_MEM_SIZE) для проверки размера.
   
   CLBufferWrite (hbuffer[ 0 ], price);
   
   uint units = ( uint ) CLGetInfoInteger (hcontext, CL_DEVICE_MAX_COMPUTE_UNITS );
   uint global_work_offset[] = { 0 };
   uint global_work_size[ 1 ];
   uint local_work_size[ 1 ];
   global_work_size[ 0 ] = ArraySize (price);
   local_work_size[ 0 ] = global_work_size[ 0 ] / units;
   bool exec = CLExecute (hkernel, 1 , global_work_offset, global_work_size, local_work_size); // async
   if (exec == false ) Print ( "Error in " , __FUNCSIG__ , " CLExecute: " , GetLastError ());
   
   CLBufferRead (hbuffer[ 1 ], price);
   
   if ( MQL5InfoInteger ( MQL5_PROGRAM_TYPE ) == PROGRAM_SCRIPT ) DeinitGlobal();
}

스크립트 시작:

2013.10.30 18:55:40 OpenCL_buffer_test (EURUSD,H1) 장치 #1 = AMD Phenom(tm) II X4 925 프로세서
2013.10.30 18:55:40 OpenCL_buffer_test (EURUSD,H1) 장치 #0 = Cypress
2013.10.30 18:55:40 OpenCL_buffer_test (EURUSD,H1) OpenCL: GPU 장치 'Cypress' 선택
2013.10.30 18:55:40 OpenCL_buffer_test (EURUSD,H1) 빌드 로그 =
2013.10.30 18:55:40 OpenCL_buffer_test (EURUSD,H1) 버퍼 크기(바이트) =240

2013.01.09부터 2013.10.10까지 테스터 전문가가 M5에서 "OHLC on M1"으로 출시:

2013.10.30 19:01:44 Core 1 EURUSD,M5: Experts\OpenCL_buffer_test.ex5 테스트 2013.01.09 00:00 ~ 2013.10.10 00:00 시작
2013.10.30 19:01:44 코어 1 2013.01.09 00:00:00 디바이스 #0 = 사이프러스
2013.10.30 19:01:44 Core 1 2013.01.09 00:00:00 OpenCL: GPU 장치 'Cypress' 선택
2013.10.30 19:01:44 코어 1 2013.01.09 00:00:00 빌드 로그 =
2013.10.30 19:01:44 코어 1 2013.01.09 00:00:00 버퍼 크기(바이트) = 240
2013.10.30 19:04:55 코어 1 EURUSD,M5: 192443ms 이내에 생성된 1108637틱(55953바)(역사의 총 바 131439, 총 시간 192521ms)
2013.10.30 19:04:55 코어 1 294MB 메모리 사용

테스터에는 1개의 장치만 있음을 유의하십시오.

만약

   //CLBufferRead(hbuffer[1], price);

그 다음에

2013.10.30 19:16:00 Core 1 EURUSD,M5: 88218ms 이내에 생성된 1108637틱(55953바)(역사의 총 바 131439, 총 시간 88297ms)
 
읽기는 반드시 필요합니다. 사실 이것은 커널의 완료를 기다리는 기능입니다. 왜냐하면 CLExecute 는 실행을 위해 작업만 큐에 넣고 완료를 기다리지 않고 MQL 프로그램에 제어를 반환합니다.
 
이 특정 예에서 OpenCL 사용의 이점은 버퍼 복사 오버헤드에 의해 소모됩니다.

OHLC 데이터에 대한 계산이 필요한 경우 경제적인 기록, 즉 더 큰 크기의 버퍼를 미리 만들고 새 데이터가 도착하면 이 새 데이터만 추가하여 커널에 버퍼의 새 시작과 크기를 알립니다.
OpenCL: Мост в параллельные миры
OpenCL: Мост в параллельные миры
  • 2012.05.16
  • Sceptic Philozoff
  • www.mql5.com
В конце января 2012 года компания-разработчик терминала MetaTrader 5 анонсировала нативную поддержку OpenCL в MQL5. В статье на конкретном примере изложены основы программирования на OpenCL в среде MQL5 и приведены несколько примеров "наивной" оптимизации программы по быстродействию.
 

OHLC 전송을 최적화하더라도( CLSetKernelArg 를 통해 마지막 막대를 전송함) 결과 버퍼를 읽을 때 여전히 충돌합니다.

2013.10.31 19:24:13 코어 1 EURUSD,M5: 114489ms 이내에 1108637틱(55953바) 생성(역사의 총 바 131439, 총 시간 114598ms)
(CLBufferWrite(hbuffer[0], price) 행; IF 아래로 이동)
 
Roffild : 어... GPU에서 OpenCL을 사용한 속도 향상에 대한 기사는 실제 작업이 아니기 때문에 동화로 판명되었습니다.

글쎄, 누가 당신을 막고 있습니다. 동화가 아니도록 실제를 가져 와서 쓰십시오. 그러나 여전히 가속이 있도록 예를 찾으십시오. 이것이 가장 어려운 부분입니다.

내 기사에 대해 이야기하면 ... 글쎄, 나는 교육 프로그램을 썼습니다. 그리고 행렬 곱셈은 매우 유용한 연산입니다.

PS 그건 그렇고, CPU가 Intel인 경우 x86 코어의 에뮬레이션은 경쟁사의 CPU보다 훨씬 빠릅니다. 코어의 경우입니다.

HD5850: 원칙적으로 꽤 괜찮은 카드지만 최신 카드가 더 좋습니다. 더 많은 파리뿐만 아니라 OpenCL에 대한 최적화 덕분입니다. 예를 들어 전역 메모리 액세스 시간이 크게 단축되었습니다.

PPS OpenCL은 만병 통치약은 아니지만 드문 경우지만 상당히 가속화할 수 있는 실제 도구입니다. 그리고 다른 경우에는 그다지 편리하지 않지만 가속이 그렇게 인상적이지 않습니다.

 
Roffild :
어... GPU에서 OpenCL로 속도 향상에 대한 기사는 실제 작업이 아니기 때문에 동화로 판명되었습니다.

이 방법이 아닙니다. 동화 - "모든 알고리즘은 OpenCL에서 가속화될 수 있습니다". 아무 것도 아닙니다.

OpenCL의 첫 번째 분기는 ocl 가속 가능성을 갖기 위해 알고리즘이 가져야 하는 기준을 완전히 설명합니다.

행운을 빕니다.

 

주장은 계산 속도에 관한 것이 아닙니다. 여기서 가속은 2배입니다(0.02ms 대 0.05ms).

기사에 정보가 없다는 주장:

  • 작은 버퍼라도 읽기/쓰기 시 지연 = 0.35300ms - 이것이 대부분의 알고리즘을 OpenCL로 변환하는 것을 무의미하게 만드는 이유입니다!
  • 테스터는 OpenCL용 CPU를 선택하지 않습니다. 이것은 어디에도 보고되지 않습니다!

나는 아마도 약속을 읽고 GPU로 테스트 속도를 높이고 싶었던 첫 번째 사람 일 것입니다 ...

MetaDriver : OpenCL의 첫 번째 분기는 알고리즘이 ocl-speedup 잠재력을 갖기 위해 가져야 하는 기준을 완전히 설명합니다.

내 게시물을 다시 읽으십시오.

주요 기준: 1틱 동안 "OpenCL 스타일"의 MQL 코드 실행은 시간 = Number_of_Buffers * 0.35300ms 를 초과해야 합니다.

마이크로초(1000마이크로초 = 1밀리초)의 정확도로 MQL에서 알고리즘의 속도를 알아내려면 테스터와 Total_Time/Number_Ticks(내 최고 게시물)에서 여러 번 실행해야 합니다.

버퍼 지연이 아닌 경우 내 코드는 ~30초 만에 테스트를 통과했습니다. 이는 "OpenCL 스타일" MQL(55초)보다 ~2배, 일반 코드(320초)보다 ~11배 빠릅니다.

다른 기준은 무엇입니까?

 
Roffild : 기사에 정보가 없다는 주장:
  • 작은 버퍼라도 읽기/쓰기 시 지연 = 0.35300ms - 이것이 대부분의 알고리즘을 OpenCL로 변환하는 것을 무의미하게 만드는 이유입니다!

OpenCL과의 커뮤니케이션 경험으로 판단할 때 모든 알고리즘이 어리석게도 직접적으로 가속되는 것은 아니라는 점을 이미 이해했을 것입니다. 여기서 주요 문제 중 하나는 전역 메모리에 대한 액세스를 최소화하는 것입니다.

그건 그렇고, 이제 장치의 전역 메모리에 대한 임의 액세스와 유사한 문제를 해결해야 합니다(이 임의 액세스는 너무 빈번하고 이것은 빌어먹을 오버헤드입니다). 나는 모스크바를 켜 자마자 확실히 결정할 것입니다.

테스터는 OpenCL용 CPU를 선택하지 않습니다. 이것은 어디에도 보고되지 않습니다!

서비스 데스크에 편지를 쓰고 그러한 기능의 필요성을 정당화하십시오.

테스터가 사용되지 않으면 이미 완료된 것입니다(이것은 내 응용 프로그램입니다). 아직 테스터로 테스트는 안해봤습니다.



 
Mathemat :

모든 알고리즘이 어리석게도 직접 가속되는 것은 아니라고 이미 썼습니다. 여기에 mosk를 포함해야 하며 주요 문제 중 하나는 전역 메모리에 대한 액세스를 최소화하는 것입니다.

음, 초, 이제 장치의 전역 메모리에 대한 임의 액세스와 유사한 문제를 해결해야 합니다(이 임의 액세스는 너무 자주 발생합니다). 나는 모스크바를 켜 자마자 확실히 결정할 것입니다.

0.35300ms 커널 내부의 전역 메모리 액세스가 아니라 clEnqueue[Read/Write]Buffer ()를 특별히 참조하기 때문에 두뇌를 켜야 합니다.

두 번째는 커널 자체를 최적화하여 해결되지만 첫 번째는 철의 한계이며 여기서 두뇌가 도움이 되지 않습니다.

OpenCL: From Naive Towards More Insightful Programming
OpenCL: From Naive Towards More Insightful Programming
  • 2012.06.29
  • Sceptic Philozoff
  • www.mql5.com
This article focuses on some optimization capabilities that open up when at least some consideration is given to the underlying hardware on which the OpenCL kernel is executed. The figures obtained are far from being ceiling values but even they suggest that having the existing resources available here and now (OpenCL API as implemented by the developers of the terminal does not allow to control some parameters important for optimization - particularly, the work group size), the performance gain over the host program execution is very substantial.
사유: