OpenCL: gerçek problemler - sayfa 4

 
TheXpert :

En ağır yöntem FeedPatterns'dir.

Önceden, hızlandırmak mümkün olmayacak: Veri miktarıyla ilgili olarak çekirdekler için çok az iş var (çok fazla veri, az iş), tüm kazanç ileri geri kopyalanarak yok edilecek.

VS'de, derleyiciden açıkça paralelleştirmesini veya işlemci için paralel iş parçacıkları oluşturmasını deneyebilirsiniz.

OpenCL: от наивного кодирования - к более осмысленному
OpenCL: от наивного кодирования - к более осмысленному
  • 2012.06.05
  • Sceptic Philozoff
  • www.mql5.com
В данной статье продемонстрированы некоторые возможности оптимизации, открывающиеся при хотя бы поверхностном учете особенностей "железа", на котором исполняется кернел. Полученные цифры весьма далеки от предельных, но даже они показывают, что при том наборе возможностей, который имеется здесь и сейчас (OpenCL API в реализации разработчиков терминала не позволяет контролировать некоторые важные для оптимизации параметры - - в частности, размер локальной группы), выигрыш в производительности в сравнении с исполнением хостовой программы очень существенен.
 
TheXpert :
Sonunda, MQL'ye geçeceğim.
Ve ne, kesinlikle gerekli mi? AMP konusuna bile sarıldım. Uzun zamandır içine girmek istiyordum ama işte bir sebep var gibi..
 
kazakov.v :

Önceden, hızlandırmak mümkün olmayacak: Veri miktarıyla ilgili olarak çekirdekler için çok az iş var (çok fazla veri, az iş), tüm kazanç ileri geri kopyalanarak yok edilecek.

VS'de, derleyiciden açıkça paralelleştirmesini veya işlemci için paralel iş parçacıkları oluşturmasını deneyebilirsiniz.

Peki, neden, bu görevler OpenCL'ye tam olarak uyuyor

 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;
  }

ve yeşil de.

 
Urain :

Peki, neden, bu görevler OpenCL'ye tam olarak uyuyor

ve yeşil de.

OpenCL ve C++ üzerinde bir uygulama ve karşılaştırmalı bir test yapmak gerekir, eğer bir artış varsa, o zaman her şeyi çevirin.
 

CL_DEVICE_PREFERRED_VECTOR_WIDTH_*'dan gelen bilgi, vektörün maksimum boyutunu mu yoksa optimal olanı mı gösterir?

CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE=2 ile double3 ve double4 zaten yavaşlayacak mı?

 
Roffild :

CL_DEVICE_PREFERRED_VECTOR_WIDTH_*'dan gelen bilgi, vektörün maksimum boyutunu mu yoksa optimal olanı mı gösterir?

CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE=2 ile double3 ve double4, yavaşlayacak mı?

1. Maksimuma.

2. Çok yavaşlaması pek olası değil ama yürütme hızında bir artış olmayacak.

 
MQL OpenCL, orijinal API üzerinde yalnızca bir sarıcıdır.
Bu sarmalayıcının uygulanmasıyla ilgili cevapları ve açıklamaları bilmem gerekiyor.

CLContextCreate() = clCreateCommandQueue(clCreateContextFromType(CL_DEVICE_TYPE_X)) ?
Aslında bir bağlam değil, tek bir cihaz için bir kuyruk mu?

Tamponlar eşzamanlı mı yoksa eşzamansız olarak mı okunuyor/yazılıyor?
clEnqueue[Oku/Yaz]Tampon(kuyruğa al, arabelleğe al, CL_TRUE) - burada CL_TRUE mu yoksa CL_FALSE mi?

bool CLExecute(int çekirdek ) = clEnqueueTask();
bool CLExecute(int çekirdek, uint work_dim, çalışır...) = clEnqueueNDRangeKernel();
clEnqueueNativeKernel() - uygulanmadı.

CLExecute() hemen kontrolü döndürür mü? Çalışma zamanı için engellenmiyor mu?
Sırada kurulum için 2-40 ms süre var gibi görünüyor...

Ve şimdi asıl soru:
clFinish() ne zaman ve hangi koşullarda çağrılır? Ve clFinish()'in olmaması, sıraya girmeyi zorlaştırıyor.

Ve MQL yardımı, CL_MEM_*_HOST_PTR'yi hiç açıklamaz, ancak bunlar mevcuttur.

Sonunda göstergemi OpenCL stiline geçirdim.
"OHLC on M1" ile M5'te 2013.01.09'dan 2013.10.10'a kadar olan testi geçmek:
320 saniye - aktarımdan önce
55 saniye - MQL5'te OpenCL tarzı öykünme:
 // подготовка данных общая и копия kernel на MQL5, а эмуляция через:
for ( int get_global_id = maxcount- 1 ; get_global_id>- 1 ; get_global_id--) NoCL( params ,m_result,get_global_id);
Ama GPU'daki başlatma beni üzdü :(
Testi 30 saniyeden daha kısa sürede geçmeyi umuyordum ama CLBufferWrite'ta tam bir fren yaptım!

%32 oranında video yükleme ve testi CL_MEM_*_HOST_PTR olmadan 1710 saniyede geçme
CL_MEM_ALLOC_HOST_PTR ile %22 oranında video yükleme ve testi 740 saniyede geçme
CL_MEM_COPY_HOST_PTR ve CL_MEM_USE_HOST_PTR, CLExecute ile sonuçlanır: 5109 (ERR_OPENCL_EXECUTE)

Peki veri paylaşmanın doğru yolu nedir?

Ve şimdiye kadar, test cihazı hesaplamalar için CPU'yu seçmiyor.

Vidyaha = ATI Radeon HD 5850
İşlemci = AMD Phenom(tm) II X4 925 İşlemci
 
Roffild :
CLContextCreate() = clCreateCommandQueue(clCreateContextFromType(CL_DEVICE_TYPE_X)) ?
Aslında bir bağlam değil, tek bir cihaz için bir kuyruk mu?
Evet, aygıt başına bir bağlam ve bir sıra oluşturulur (araştırma, opencl'nin birkaç farklı aygıtla düzgün çalışmadığını göstermiştir).
Tamponlar eşzamanlı mı yoksa eşzamansız olarak mı okunuyor/yazılıyor?
clEnqueue[Oku/Yaz]Tampon(kuyruğa al, arabelleğe al, CL_TRUE) - burada CL_TRUE mu yoksa CL_FALSE mi?
Okuma ve yazma senkronizedir.
bool CLExecute(int çekirdek ) = clEnqueueTask();
bool CLExecute(int çekirdek, uint work_dim, çalışır...) = clEnqueueNDRangeKernel();
clEnqueueNativeKernel() - uygulanmadı.
CLExecute() hemen kontrolü döndürür mü? Çalışma zamanı için engellenmiyor mu?
Evet
Ve şimdi asıl soru:
clFinish() ne zaman ve hangi koşullarda çağrılır? Ve clFinish()'in olmaması, sıraya girmeyi zorlaştırıyor.
Çağrılmaz, hafızadan okunmalıdır.
Ve MQL yardımı, CL_MEM_*_HOST_PTR'yi hiç açıklamaz, ancak mevcuttur.

Sonunda göstergemi OpenCL stiline geçirdim.
"OHLC on M1" ile M5'te 2013.01.09'dan 2013.10.10'a kadar olan testi geçmek:
320 saniye - aktarımdan önce
55 saniye - MQL5'te OpenCL tarzı öykünme:
Ama GPU'daki başlatma beni üzdü :(
30 ms'den daha kısa bir test geçişi bekliyordum ama CLBufferWrite'ta tam bir fren aldım!

%32 oranında video yükleme ve testi CL_MEM_*_HOST_PTR olmadan 1710 saniyede geçme
CL_MEM_ALLOC_HOST_PTR ile %22 oranında video yükleme ve testi 740 saniyede geçme
CL_MEM_COPY_HOST_PTR ve CL_MEM_USE_HOST_PTR, CLExecute ile sonuçlanır: 5109 (ERR_OPENCL_EXECUTE)

Peki veri paylaşmanın doğru yolu nedir?
CL_MEM_COPY_HOST_PTR ve CL_MEM_USE_HOST_PTR bayrakları şu anda terminal tarafından desteklenmemektedir (bu sorunu araştırıyoruz).
Ve şimdiye kadar, test cihazı hesaplamalar için CPU'yu seçmiyor.
CPU aygıtını açıkça belirtmeyi denediniz mi?
 

Belki bize zaman uyumsuz arabellekler ve clFinish() vermeyi deneyin?

AMD CodeXL'in bile ima ettiği, yavaşlayan eşzamanlı kayıt olduğu varsayımı var:

"clEnqueueWriteBuffer: Gereksiz senkronizasyon. Yazmayı engelleme"

Ve test cihazında CPU, sayıya göre bile seçilmez. Hata #865549

 
Eh... GPU'da OpenCL ile hızı artırmayla ilgili makaleler bir peri masalı oldu, çünkü gerçek görevleri tanımlamıyorlar :(

OpenCL'i fethetmek için bu ay binlerce kod satırını kör ettim.

Bu nedenle, OpenCL'de hata ayıklamak için, AMD CodeXL üzerinden çalıştırmak için C / C ++ içindeki MQL'den işlevleri taklit etmek zorunda kaldım.

2013.01.09'dan 2013.10.10'a M5'te "OHLC on M1" ile testi geçmenin sonuçlarını tekrarlayacağım:
320 saniye - aktarımdan önce
55 saniye - MQL5'te OpenCL tarzı öykünme

"OpenCL stili", CopyHigh/CopyTime/CopyOpen/ ... çağrılarının sayısını minimumda tutmak ve bu işlevler çağrıldıktan sonra dizileri işlemek için kod miktarını artırmaktır.

Ancak OpenCL'deki güzel makaleler için bu hesaplamalar yeterli değildir:

OpenCL olmadan testi geçmenin sonucu:
Çekirdek 1 EURUSD,M5: 55427 ms içinde oluşturulan 1108637 tik (55953 bar) (geçmişteki toplam çubuklar 131439, toplam süre 55520 ms)
55427 ms / 1108637 onay = 0,04999 ms/tick - CPU'da 1 onay (OpenCL'de yürütme bu süreyi geçmemelidir)

Ancak bu verileri C/C++ kodumu çalıştırarak ve AMD CodeXL üzerinden çalıştırarak aldım:
0.02000 ms - 0.05000 ms - çekirdeğimi GPU'da çalıştırıyor
0.35300 ms - 500 KB/s ile 168 Bayt için clEnqueueWriteBuffer'a bir çağrı
0.35300 ms - 9.500 MB/s ile 3.445 KB için clEnqueueWriteBuffer'a bir çağrı (ortalama aktarım süreleri aynıdır)

168 bayt:
Çift Açık [21] = {1.3668,1.3661,1.36628,1.3664,1.36638,1.36629,1.3664,1.36881,1.36814,13692,136918,16976,136816,136776,196779,13695,136927,1369,136927,136915,13679,136786 ,19,136786,136838};

Ve 21 * 168 dizisinin boyutunu hesaplamadaki bir hata nedeniyle 3.445 KB aldım, ancak bu bile aktarım süresini etkilemedi.

Sonuç olarak: çekirdeğimi 0.02000 ms'ye optimize etmeyi başarsam bile, bu normal MQL geçişinden (0.04999 msn) gerçekten ~ 2 kat daha hızlıdır, o zaman her şey GPU'daki okuma / yazma hızına dayanır (0.35300 ms - ~ MQL hesaplamalarından 7 kat daha yavaş!) .

OpenCL için test cihazımda CPU seçilmedi, bu yüzden 3 boş çekirdek daha kullanamıyorum...

not
55 saniye MQL optimizasyonunun sınırı değildir, ancak destek olmadığında yalnızca OpenCL öykünmesi :)
Документация по MQL5: Доступ к таймсериям и индикаторам / CopyHigh
Документация по MQL5: Доступ к таймсериям и индикаторам / CopyHigh
  • www.mql5.com
Доступ к таймсериям и индикаторам / CopyHigh - Документация по MQL5