openCL (C++) 中的二进制文件
Binaries in openCL (C++)
假设我在 openCL 中有一个程序:
...
const unsigned char* binaries;
size_t binaries_size;
assign_binaries(&binaries, &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, &binary_status, &err);
...
我将如何推动
binaries
和
binaries_size
进入
Binaries
?
在 OpenCL docs 中,它说:
Binaries: A vector of pairs of a pointer to a binary object and its length.
但是,这对我来说毫无意义,因为存在明显的类型不匹配。
How would I go about pushing
binaries
and
binaries_size
into
Binaries
?
有很多方法可以做到这一点。
TL;DR: 最紧凑的实现OP意图的代码大概是:
cl::Program prog
= cl::Program(context, device_list,
{ std::vector<unsigned char>(binaries, binaries + binaries_size) },
&binary_status, &err);
长话短说:
一个 MCVE 来演示两个:
#include <iomanip>
#include <iostream>
#include <vector>
// the OpenCL typedef
using Binaries = std::vector<std::vector<unsigned char>>;
void print(const Binaries& binaries)
{
std::cout << "Binaries: [" << binaries.size() << "]: {\n";
for (const std::vector<unsigned char>& 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
的构造函数 std::vector<unsigned char>(binaries, binaries + binaries_size)
中。
std::vector
提供多种constructors。在这种情况下,使用带有 first
和 last
迭代器的构造函数:
template< class InputIt >
vector( InputIt first, InputIt last,
const Allocator& alloc = Allocator() );
(链接文档中的风味 (5)
。)
但是,这可能是一个不必要的复制步骤。从一开始就在 std::vector<unsigned char>
中提供数据可以用来摆脱这种情况。
push_back() 可以与移动语义一起使用(这可以防止 2nd 不必要的深度复制)。 (它是链接文档中的风味 (2)
。)
如果直接将内部向量的构造函数作为参数传递,则会产生一个 RValue,它将自动触发移动语义。
如果有内部向量的中间存储(例如在局部变量中),移动语义仍然可以用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 }
}
我还添加了大括号初始化(在本例中是 direct-list-initialization)。
const Binaries vecBinaries4 {
std::vector<unsigned char>(binaries, binaries + binaries_size)
};
print(vecBinaries4);
输出:
Binaries: [1]: {
[8]: { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }
}
(我必须承认,我仍然认为 brace init 有点吓人。因此,我很难提及它,但为了完整起见我还是应该提及。)
在某些情况下,例如如果你有一个积分向量,你必须小心区分具有大小 n
和初始填充值的构造函数与具有两个值的初始化列表的构造函数。
对于两者,您必须提供两个整数值,但括号的种类和数量决定使用哪个构造函数。这很容易造成混淆。
示例:
#include <iostream>
#include <vector>
void print(const std::vector<int>& 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 }
假设我在 openCL 中有一个程序:
...
const unsigned char* binaries;
size_t binaries_size;
assign_binaries(&binaries, &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, &binary_status, &err);
...
我将如何推动
binaries
和
binaries_size
进入
Binaries
?
在 OpenCL docs 中,它说:
Binaries: A vector of pairs of a pointer to a binary object and its length.
但是,这对我来说毫无意义,因为存在明显的类型不匹配。
How would I go about pushing
binaries
and
binaries_size
into
Binaries
?
有很多方法可以做到这一点。
TL;DR: 最紧凑的实现OP意图的代码大概是:
cl::Program prog
= cl::Program(context, device_list,
{ std::vector<unsigned char>(binaries, binaries + binaries_size) },
&binary_status, &err);
长话短说:
一个 MCVE 来演示两个:
#include <iomanip>
#include <iostream>
#include <vector>
// the OpenCL typedef
using Binaries = std::vector<std::vector<unsigned char>>;
void print(const Binaries& binaries)
{
std::cout << "Binaries: [" << binaries.size() << "]: {\n";
for (const std::vector<unsigned char>& 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
的构造函数 std::vector<unsigned char>(binaries, binaries + binaries_size)
中。
std::vector
提供多种constructors。在这种情况下,使用带有 first
和 last
迭代器的构造函数:
template< class InputIt >
vector( InputIt first, InputIt last,
const Allocator& alloc = Allocator() );
(链接文档中的风味 (5)
。)
但是,这可能是一个不必要的复制步骤。从一开始就在 std::vector<unsigned char>
中提供数据可以用来摆脱这种情况。
push_back() 可以与移动语义一起使用(这可以防止 2nd 不必要的深度复制)。 (它是链接文档中的风味 (2)
。)
如果直接将内部向量的构造函数作为参数传递,则会产生一个 RValue,它将自动触发移动语义。
如果有内部向量的中间存储(例如在局部变量中),移动语义仍然可以用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 }
}
我还添加了大括号初始化(在本例中是 direct-list-initialization)。
const Binaries vecBinaries4 {
std::vector<unsigned char>(binaries, binaries + binaries_size)
};
print(vecBinaries4);
输出:
Binaries: [1]: {
[8]: { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }
}
(我必须承认,我仍然认为 brace init 有点吓人。因此,我很难提及它,但为了完整起见我还是应该提及。)
在某些情况下,例如如果你有一个积分向量,你必须小心区分具有大小 n
和初始填充值的构造函数与具有两个值的初始化列表的构造函数。
对于两者,您必须提供两个整数值,但括号的种类和数量决定使用哪个构造函数。这很容易造成混淆。
示例:
#include <iostream>
#include <vector>
void print(const std::vector<int>& 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 }