GPU'm ne bekliyor?


11

AMD Radeon HD 7800 serisi GPU'm ile kullanmak için bir OpenCL programı yazıyorum. AMD'nin OpenCL programlama kılavuzuna göre , bu GPU nesli zaman uyumsuz olarak çalışabilen iki donanım kuyruğuna sahiptir.

5.5.6 Komut Sırası

Güney Adaları ve sonrası için, cihazlar en az iki donanım bilgi işlem kuyruğunu destekler. Bu, bir uygulamanın, eşzamansız gönderim ve muhtemelen yürütme için iki komut kuyruğuyla küçük gönderilerin verimini artırmasına olanak tanır. Donanım hesaplama kuyrukları aşağıdaki sırayla seçilir: ilk kuyruk = çift OCL komut kuyrukları, ikinci kuyruk = tek OCL kuyrukları.

Bunu yapmak için, verileri GPU'ya beslemek için iki ayrı OpenCL komut kuyruğu oluşturdum. Kabaca, ana bilgisayar iş parçacığı üzerinde çalışan program şöyle görünür:

static const int kNumQueues = 2;
cl_command_queue default_queue;
cl_command_queue work_queue[kNumQueues];

static const int N = 256;
cl_mem gl_buffers[N];
cl_event finish_events[N];

clEnqueueAcquireGLObjects(default_queue, gl_buffers, N);

int queue_idx = 0;
for (int i = 0; i < N; ++i) {
  cl_command_queue queue = work_queue[queue_idx];

  cl_mem src = clCreateBuffer(CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, ...);

  // Enqueue a few kernels
  cl_mem tmp1 = clCreateBuffer(CL_READ_WRITE);
  clEnqueueNDRangeKernel(kernel1, queue, src, tmp1);

  clEnqueueNDRangeKernel(kernel2, queue, tmp1, tmp1);

  cl_mem tmp2 = clCreateBuffer(CL_READ_WRITE);
  clEnqueueNDRangeKernel(kernel2, queue, tmp1, tmp2);

  clEnqueueNDRangeKernel(kernel3, queue, tmp2, gl_buffer[i], finish_events + i);

  queue_idx = (queue_idx + 1) % kNumQueues;
}

clEnqueueReleaseGLObjects(default_queue, gl_buffers, N);
clWaitForEvents(N, finish_events);

Ile kNumQueues = 1, bu uygulama hemen hemen amaçlandığı gibi çalışır: daha sonra GPU tüm zaman oldukça meşgul olmak ile tamamlanması için çalışan tek bir komut kuyruğu tüm çalışmaları toplar. CodeXL profil oluşturucusunun çıktısına bakarak bunu görebiliyorum:

resim açıklamasını buraya girin

Ancak, ayarladığımda kNumQueues = 2, aynı şeyin olmasını bekliyorum, ancak çalışma iki kuyruğa eşit olarak bölündü. Bir şey varsa, her kuyruğun tek kuyrukla aynı özelliklere sahip olmasını beklerim: her şey bitene kadar sıralı olarak çalışmaya başlar. Ancak, iki kuyruk kullanırken, tüm çalışmaların iki donanım kuyruğuna bölünmediğini görebiliyorum:

resim açıklamasını buraya girin

GPU'nun çalışmasının başlangıcında, kuyruklar bazı çekirdekleri eşzamansız olarak çalıştırmayı başarır, ancak her ne kadar donanım kuyruklarını tam olarak kaplamıyor gibi görünüyor (benim anlayışım yanlış değilse). GPU çalışmasının sonuna doğru, sıralar donanım sıralarından yalnızca birine sıralı olarak iş ekliyor gibi görünüyor, ancak çekirdeklerin çalışmadığı zamanlar bile var. Ne oluyor? Çalışma zamanının nasıl davranması gerektiği konusunda bazı temel yanlış anlamaları var mı?

Bunun neden olduğuna dair birkaç teorim var:

  1. Serpiştirilmiş clCreateBufferçağrılar GPU'yu, ayrı ayrı çekirdeklerin yürütülmesini durduran, paylaşılan bir bellek havuzundan aygıt kaynaklarını eşzamanlı olarak ayırmaya zorluyor.

  2. Temel OpenCL uygulaması, mantıksal kuyrukları fiziksel kuyruklarla eşlemez ve yalnızca nesnelerin çalışma zamanında nereye yerleştirileceğine karar verir.

  3. GL nesneleri kullandığım için, GPU'nun yazma sırasında özel olarak ayrılmış belleğe erişimi senkronize etmesi gerekir.

Bu varsayımlardan herhangi biri doğru mu? GPU'nun iki kuyruk senaryosunda beklemesine neyin neden olabileceğini bilen var mı? Herhangi bir anlayış takdir edilecektir!


Programlama kılavuzunda iki donanım kuyruğu olduğunu nereden söylediğini bulamıyorum. Belgeden bir teklif gönderebilir misiniz? İki kuyruk olduğunu söyleyen bölümden bahsedin mi? OpenCL kullanılarak çalışma zamanında donanım kuyruklarının sayısı sorgulanabilir mi?
Andreas

Yazımı güncelledim. Olası bir icra diyor , ama eğer birkaçını yapabilirse neden hepsini yapamıyor? Ayrıca OpenCL çalışma zamanının donanım kuyruğu fikri yoktur, bu yüzden sorgulayabileceğiniz bir şey değildir.
Mokosha

Yanıtlar:


2

Genel olarak hesaplama kuyrukları, paralel olarak 2x dağıtım yapabileceğiniz anlamına gelmez. Hesaplama birimlerini tamamen doyurucu hale getiren tek bir kuyrukta daha iyi verim elde edilir. Bir kuyruk daha az kaynak tüketiyorsa (paylaşılan bellek veya kayıtlar) birden çok kuyruk yararlıdır, daha sonra ikincil kuyruklar aynı hesaplama biriminde çakışabilir.

Gerçek zamanlı renderleme için bu özellikle hesaplama / gölgelendiricilerde çok hafif olan, ancak sabit işlevli donanımda ağır olan, böylece GPU zamanlayıcıyı ikincil kuyruğu zaman uyumsuzluğunu çalıştırmak için serbest bırakan durumlarda geçerlidir.

Bunu sürüm notlarında da buldum. Aynı sorun olup olmadığını bilmiyorum, ama sadece CodeXL büyük değil olabilir. Gönderilerin uçuşta olduğu en iyi enstrümantasyona sahip olmayacağını umuyorum.

https://developer.amd.com/wordpress/media/2013/02/AMD_CodeXL_Release_Notes.pdf

Aynı anda eşzamansız veri aktarımı ve çekirdek yürütme gerçekleştiren bir uygulama için, Uygulama İzleme oturumu görünümünde gösterilen zaman çizelgesi bu işlemlerin çakıştığını göstermez. Bunun nedeni, sürücü ve donanımın profil oluşturma sırasında bu işlemleri eşzamanlı olmaya zorlamasıdır. (333.981)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.