Szukaj…


Wprowadzenie

W tym temacie omówiono różne sposoby umieszczania danych w miejscu, w którym urządzenie może uzyskać do nich dostęp.

Czytanie tablicy

Aby odczytać tablicę z urządzenia z powrotem do hosta, jeden wywołuje

clEnqueueReadBuffer($queue, $memobj, $blocking, $offset, $size, $target, 0, null, null);

Kolejka $ to CommandQueue, która została użyta do przydzielenia pamięci w urządzeniu. $ Memobj zawiera adres do pamięci urządzenia, $ offset i rozmiar $ dodatkowo określają, skąd i ile danych jest kopiowanych. $ Target jest wskaźnikiem do pamięci hosta, w którym będą przechowywane dane. $ Target musi zostać przydzielony i mieć odpowiedni rozmiar.

Czytanie tekstury

Czytanie obrazu jest prawie jak czytanie tablicy. Jedyna różnica polega na tym, że rozmiar i przesunięcie muszą być trójwymiarowe.

clEnqueueReadImage($queue, $memobj, $blocking, $offset, $size, $stride, $slice_pitch, $target, 0, null, null);

$ Stride określa, ile bajtów ma rząd. Zwykle jest to tylko szerokość * (bajtów na piksel), ale ktoś może chcieć to zmienić, aby wyrównać dane z bankami pamięci. To samo dotyczy $ slice_pitch, tyle że ta wartość dotyczy trzeciego wymiaru.

Pisanie tekstury 2D

Aby skopiować teksturę na urządzenie, konieczne są dwa kroki

  1. Przydziel pamięć na urządzeniu
  2. Skopiuj obraz do urządzenia
  _mem = clCreateImage2D($context, $mem_flags, $image_format, $width, $height, $stride, $source, &err);

$ Mem_flags określają sposób alokacji pamięci. Może być tylko do odczytu, tylko do zapisu lub jedno i drugie. Dodatkowo możesz określić, gdzie i jak alokowana jest pamięć. $ szerokość, $ wysokość i $ krok są dość oczywiste.

Jeśli twoje mem_flags skopiują dane, gotowe. Jeśli chcesz to zrobić ręcznie w późniejszym czasie, będziesz musiał wywołać inną funkcję, gdy będziesz gotowy.

err = clEnqueueWriteImage($queue, _mem, $blocking, $offset, $size, $stride, $slice_pitch, $source, 0, null, null);

Przesunięcie $ i rozmiar $ określają region obrazu, który chcesz skopiować do pamięci docelowej. $ Stride określa, ile bajtów ma rząd. Zwykle jest to tylko szerokość * (bajtów na piksel), ale ktoś może chcieć to zmienić, aby wyrównać dane z bankami pamięci. To samo dotyczy $ slice_pitch, tyle że ta wartość dotyczy trzeciego wymiaru. Zarówno $ stride, jak i $ slice_pitch muszą pasować do twoich danych wejściowych.

Flagi pamięci

Przy przydzielaniu pamięci masz możliwość wyboru pomiędzy różnymi trybami:

  • Pamięć tylko do odczytu
  • Napisz tylko pamięć
  • Odczyt / zapis pamięci

Pamięć tylko do odczytu jest przydzielana w obszarze pamięci stałej __, a pozostałe dwa są przydzielane w normalnym regionie __globalnym.

Oprócz dostępności możesz określić, gdzie ma być przydzielona pamięć.

  • Nieokreślony: pamięć jest przydzielana do pamięci urządzenia, tak jak można się spodziewać. Wskaźnik $ source można ustawić na null.
  • CL_MEM_USE_HOST_PTR: Informuje urządzenie, że dane znajdują się w systemowej pamięci RAM i nie należy ich przenosić. Zamiast tego dane są przetwarzane bezpośrednio w pamięci RAM.
  • CL_MEM_COPY_HOST_PTR: Informuje urządzenie, aby skopiowało wszystkie wartości pod danym adresem do pamięci urządzenia lub, używając CL_MEM_ALLOC_HOST_PTR, do oddzielnego obszaru pamięci w pamięci RAM systemu.
  • CL_MEM_ALLOC_HOST_PTR: Informuje urządzenie o przydzieleniu miejsca w pamięci RAM systemu. Jeśli zostanie użyty jako jedyny parametr, wskaźnik $ source można ustawić na null.

Szybki dostęp do globalnej pamięci urządzenia jest najszybszy. Ale musisz także wywołać go dwukrotnie, aby skopiować dane. Używanie wskaźnika Host jest najwolniejsze, podczas gdy Alloc_host_ptr oferuje wyższą prędkość.

Korzystając z use_host_ptr, urządzenie robi dokładnie to: wykorzystuje twoje dane w ramce systemowej, która oczywiście jest stronicowana przez system operacyjny. Każde wywołanie pamięci musi przejść przez procesor, aby obsłużyć potencjalne błędy strony. Gdy dane są dostępne, procesor kopiuje je do przypiętej pamięci i przekazuje do kontrolera DMA przy użyciu cennych cykli zegara procesora. Przeciwnie, replace_host_ptr przydziela pamięć przypiętą do pamięci RAM systemu. Ta pamięć jest umieszczona poza mechanizmem zamiany stron i dlatego ma gwarantowaną dostępność. Dlatego urządzenie może całkowicie pominąć jednostkę centralną podczas uzyskiwania dostępu do pamięci RAM systemu i wykorzystywać DMA do szybkiego kopiowania danych do urządzenia.

Pisanie tablicy

Napisanie tablicy składa się z dwóch kroków:

  1. Przydzielanie pamięci
  2. Kopiowanie danych

Aby przydzielić pamięć, wystarczy zadzwonić do

_mem = clCreateBuffer($queue, $mem_flags, $size, $host_ptr, &err);

wystarczy. Jeśli zdecydowałeś się skopiować wskaźnik hosta przez mem_flags, to koniec. W przeciwnym razie możesz skopiować dane w dowolnym momencie

err = clEnqueueWriteBuffer($queue, _mem, $blocking, $offset, $size, $source, 0, null, null);


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow