В моей текущей реализации OpenCL я хотел сэкономить время с аргументами, избегая их передачи каждый раз, когда я хотел использовать буфер внутри ядра, и иметь более короткий список аргументов для своего ядра.
Итак, я создал структуру (рабочую область), которая содержит указатель на буфер в памяти устройства, структура действует как объект с переменной-членом, к которой вы хотите обращаться через время, и вы хотите остаться в живых в течение всего выполнения,У меня никогда не было проблем с AMD GPU или даже с процессором.Но у Nvidia много проблем с этим.Это всегда кажется проблемой выравнивания, никогда не доходящей до правого буфера и т. Д.
Вот некоторый код, чтобы помочь, см. Вопрос ниже:
Структура, определенная на хосте:
#define SRC_IMG 0 // (float4 buffer) Source image
#define LAB_IMG 1 // (float4 buffer) LAB image
// NOTE: The size of this array should be as much as the last define + 1.
#define __WRKSPC_SIZE__ 2
// Structure defined on host.
struct Workspace
{
cl_ulong getPtr[__WRKSPC_SIZE__];
};
struct HostWorkspace
{
cl::Buffer srcImg;
cl::Buffer labImg;
};
Структура, определенная на устройстве:
typedef struct __attribute__(( packed )) gpuWorkspace
{
ulong getPtr[__WRKSPC_SIZE__];
} gpuWorkspace_t;
Обратите внимание, что на устройстве я использую ulong, а на хосте я использую cl_ulong, как показано здесь OpenCL: использование struct в качестве аргумента ядра .
Поэтому, когда cl :: Buffer для исходного изображения или изображения LAB созданы, я сохраняю их в объект HostWorkspace, поэтому до тех пор, пока этот объект не будет освобожден, ссылка на cl :: Buffer сохраняется, поэтому буфер существует длявесь проект на хосте и defacto на устройстве.
Теперь мне нужно передать эти данные устройству, поэтому у меня есть простое ядро, которое запускает рабочую область моего устройства следующим образом:
__kernel void Workspace_Init(__global gpuWorkspace_t* wrkspc,
__global float4* src,
__global float4* LAB)
{
// Get the ulong pointer on the first element of each buffer.
wrkspc->getPtr[SRC_IMG] = &src[0];
wrkspc->getPtr[LAB_IMG] = &LAB[0];
}
где wrkspc - это буфер, выделенный с помощью struct Workspace
, а src + LAB - это всего лишь буфер, выделяемый как изображения массивов 1D.
И потом, в любом из моих ядер, если я хочу использовать src или LAB,Я делаю следующее:
__kernel void ComputeLABFromSrc(__global gpuWorkspace_t* wrkSpc)
{
// =============================================================
// Get pointer from work space.
// =============================================================
// Cast back the pointer of first element as a normal buffer you
// want to use along the execution of the kernel.
__global float4* srcData = ( __global float4* )( wrkSpc->getPtr[SRC_IMG] );
__global float4* labData = ( __global float4* )( wrkSpc->getPtr[LAB_IMG] );
// Code kernel as usual.
}
Когда я начал использовать это, у меня было 4-5 изображений, которые шли хорошо, с другой структурой, подобной этой:
struct Workspace
{
cl_ulong imgPtr;
cl_ulong labPtr;
};
, где у каждого изображения был свой указатель.
В определенный момент я достигаю больше изображений, и у меня возникли некоторые проблемы.Так что я ищу в Интернете, и я нашел некоторые рекомендации, что sizeof () структуры может отличаться между устройством / хостом, поэтому я изменяю его на один массив одновременно, и это прекрасно работает до 16 элементов.
Так что я ищу больше, и я нашел рекомендацию об атрибуте ((упакованный)), который я надел на структуру устройства (см. Выше).Но теперь я достигаю 26 элементов, когда я проверяю размер структуры на устройстве или на хосте, размер равен 208 (elements * sizeof (cl_ulong) == 26 * 8).Но у меня все еще есть проблема, похожая на мою предыдущую модель, мой указатель читается где-то в середине предыдущего изображения и т. Д.
Так что мне интересно, если кто-нибудь когда-нибудь попробовал подобную модель (возможно, сдругой подход) или есть какие-либо советы, чтобы иметь «твердую» модель с этим.
Обратите внимание, что все ядра хорошо закодированы, у меня хороший результат при выполнении на AMD или на CPU с тем же кодом.Единственная проблема на Nvidia.