#c #c 11 #opencl
Вопрос:
Предположим, у меня была программа на OpenCL:
...
const unsigned char* binaries;
size_t binaries_size;
assign_binaries(amp;binaries, amp;binaries_size); // my assign function, assigns bin and bin_size
std::vector<std::vector<unsigned char>> Binaries;
cl::Program prog = cl::Program(context, device_list, Binaries, amp;binary_status, amp;err);
...
Как бы я стал подталкивать
binaries
и
binaries_size
в
Binaries
?
В документах OpenCL говорится::
Binaries: A vector of pairs of a pointer to a binary object and its length.
Однако для меня это не имеет смысла, так как существует очевидное несоответствие типов.
Комментарии:
1. Вот что меня смутило (в приведенной ссылке):
typedef vector< vector< unsigned char > > Binaries
Что такоеvector
? Так ли этоstd::vector
? Так ли этоcl::vector
? Оглядываясь вокруг, я только что обнаружил открытые привязки C — Совместимость : Для заголовка 2.0 мы теперь предполагаем наличие стандартной библиотеки, если не требуется иное. Мы используем std::массив, std::вектор, std::shared_ptr и std::строку повсюду, чтобы безопасно управлять памятью и снизить вероятность повторения предыдущих ошибок управления памятью.2. В этом случае мой (теперь удаленный) ответ даже мог бы сработать. Вы можете попробовать
cl::Program prog = cl::Program(context, device_list, { std::vector<unsigned char>(binaries, binaries binaries_size) }, amp;binary_status, amp;err);
. Кстати. используете ли вы OpenCL 1.1 или OpenCL 2.0? (Потому что, по-видимому, существуют различия в отношенииvector
)3. ладно, стыдно: мне действительно очень понравился другой ответ … в любом случае, спасибо. Я полагаю, что это OpenCL 1.2.
4. Я все еще могу его восстановить. Я немного забеспокоился, когда понял, что
vector
в документе OpenCL. это не обязательноstd::vector
так . (Я должен признать, что я немного разбираюсь в C , но совсем не в OpenCL.) После того, как я узнал, что сейчас в моем 1-м комментарии, это может быть даже полезно.5. Пожалуйста, взгляните на ссылку совместимости . Они также упомянули, как обращаться с контейнерами до OpenCL 2.0…
Ответ №1:
Как бы я стал подталкивать
binaries
и
binaries_size
в
Binaries
?
Есть много способов добиться этого.
TL;DR: Наиболее компактный код для достижения цели OPs, вероятно,:
cl::Program prog
= cl::Program(context, device_list,
{ std::vector<unsigned char>(binaries, binaries binaries_size) },
amp;binary_status, amp;err);
Более длинная история:
MCVE для демонстрации двух:
#include <iomanip>
#include <iostream>
#include <vector>
// the OpenCL typedef
using Binaries = std::vector<std::vector<unsigned char>>;
void print(const Binariesamp; binaries)
{
std::cout << "Binaries: [" << binaries.size() << "]: {n";
for (const std::vector<unsigned char>amp; binary : binaries) {
std::cout << " [" << binary.size() << "]: {" ;
const char* sep = " ";
for (const unsigned char value : binary) {
std::cout << sep << "0x"
<< std::hex << std::setw(2) << std::setfill('0') << (unsigned)value;
sep = ", ";
}
std::cout << " }n";
}
std::cout << "}n";
}
int main()
{
// sample data
const unsigned char data[] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
};
// OPs initial exposure of data
const unsigned char *binaries = data;
const size_t binaries_size = std::size(data);
// filling a Binaries var.:
Binaries vecBinaries1;
vecBinaries1.push_back(
std::vector<unsigned char>(binaries, binaries binaries_size));
print(vecBinaries1);
// or
const Binaries vecBinaries2(1, std::vector<unsigned char>(binaries, binaries binaries_size));
print(vecBinaries2);
}
Выход:
Binaries: [1]: {
[8]: { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }
}
Binaries: [1]: {
[8]: { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }
}
Пожалуйста, обратите внимание , что данные подготавливаются binaries
, а затем копируются в конструктор std::vector<unsigned char>(binaries, binaries binaries_size)
std::vector
.
std::vector
предоставляет множество конструкторов. В этом случае используется конструктор с first
last
итератором и:
template< class InputIt >
vector( InputIt first, InputIt last,
const Allocatoramp; alloc = Allocator() );
(Это аромат (5)
в связанном документе.)
Однако это может быть ненужным шагом копирования. Предоставление данных в a std::vector<unsigned char>
с самого начала может быть использовано для избавления от этого.
Функция push_back() может использоваться с семантикой перемещения (что предотвращает 2-е ненужное глубокое копирование). (Это описано в связанном документе.) (2)
Если конструктор внутреннего вектора передается непосредственно в качестве аргумента, это приводит к значению R, которое автоматически запускает семантику перемещения.
Если существует промежуточное хранилище внутреннего вектора (например, в локальной переменной), семантика перемещения все еще может быть принудительной с std::move()
:
std::vector<unsigned char> vecBinary3(binaries, binaries binaries_size);
Binaries vecBinaries3;
vecBinaries3.push_back(std::move(vecBinary3));
print(vecBinaries3);
Выход:
Binaries: [1]: {
[8]: { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }
}
Я также добавил инициализацию фигурных скобок (которая в данном случае является инициализацией прямого списка).
const Binaries vecBinaries4 {
std::vector<unsigned char>(binaries, binaries binaries_size)
};
print(vecBinaries4);
Выход:
Binaries: [1]: {
[8]: { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }
}
(Должен признаться, я все еще считаю, что брейс-инит. немного пугающе. Следовательно, я изо всех сил старался упомянуть об этом вообще, но должен был бы для полноты картины.)
В некоторых случаях, например, если у вас есть вектор интегралов, вы должны быть осторожны, чтобы отличать конструктор с размером n
и начальным значением заполнения от конструктора со списком инициализации из двух значений. Для обоих вариантов необходимо указать два целых значения, но вид и количество скобок определяют, какой конструктор используется. Это может легко привести к путанице.
Пример:
#include <iostream>
#include <vector>
void print(const std::vector<int>amp; values)
{
std::cout << '{';
const char* sep = " ";
for (const int value : values) {
std::cout << sep << value;
sep = ", ";
}
std::cout << " }n";
}
int main()
{
// sample 1:
print({ 1, 2 });
// sample 2:
print(std::vector<int>(1, 2));
// sample 3:
print(std::vector<int>{ 1, 2 });
// sample 4:
print(std::vector<int>({ 1, 2 }));
}
Выход:
{ 1, 2 }
{ 2 }
{ 1, 2 }
{ 1, 2 }