简体   繁体   English

openCL (C++) 中的二进制文件

[英]Binaries in openCL (C++)

Suppose I had a program in openCL:假设我在 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);

...

How would I go about pushing我将如何去推动

binaries

and

binaries_size

into进入

Binaries

? ?

In the OpenCL docs , it says:OpenCL 文档中,它说:

Binaries: A vector of pairs of a pointer to a binary object and its length.

However, this makes no sense to me, as there is an obvious type mismatch.但是,这对我来说没有意义,因为存在明显的类型不匹配。

How would I go about pushing我将如何去推动

binaries

and

binaries_size

into进入

Binaries

? ?

There are many ways to accomplish this.有很多方法可以实现这一点。

TL;DR : The most compact code to achieve OPs intention is probably: TL;DR :实现 OP 意图的最紧凑的代码可能是:

cl::Program prog
  = cl::Program(context, device_list,
    { std::vector<unsigned char>(binaries, binaries + binaries_size) }, 
    &binary_status, &err);

A longer story:一个更长的故事:

An MCVE to demonstrate two:一个 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);
}

Output:输出:

Binaries: [1]: {
  [8]: { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }
}
Binaries: [1]: {
  [8]: { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }
}

Please, note that data is prepared in binaries , and then copied into the constructor std::vector<unsigned char>(binaries, binaries + binaries_size) of std::vector .请,音符数据被在制备binaries ,然后复制到构造std::vector<unsigned char>(binaries, binaries + binaries_size)std::vector

std::vector provides a variety of constructors . std::vector提供了多种构造函数 In this case, the constructor with first and last iterator is used:在这种情况下,使用带有firstlast迭代器的构造函数:

template< class InputIt >
vector( InputIt first, InputIt last,
        const Allocator& alloc = Allocator() );

(It's flavor (5) in the linked doc.) (它是链接文档中的风味(5) 。)

However, this might be an unnecessary copy-step.但是,这可能是不必要的复制步骤。 Providing the data in a std::vector<unsigned char> from the beginning could be used to get rid of this.从一开始就在std::vector<unsigned char>提供数据可用于摆脱这种情况。

The push_back() can be used with move semantic (which prevents a 2 nd unnecessary deep-copy).push_back()可以与移动语义一起使用(防止第二次不必要的深度复制)。 (It's flavor (2) in the linked doc.) If the constructor of the inner vector is passed as argument directly, it results in an RValue which will trigger the move semantic automagically. (它是链接文档中的风格(2) 。)如果直接将内部向量的构造函数作为参数传递,则会产生一个 RValue,它将自动触发移动语义。

If there is an intermediate storage of the inner vector (eg in a local variable), the move semantic still can be forced with std::move() :如果有内部向量的中间存储(例如在局部变量中),仍然可以使用std::move()强制移动语义:

  std::vector<unsigned char> vecBinary3(binaries, binaries + binaries_size);
  Binaries vecBinaries3;
  vecBinaries3.push_back(std::move(vecBinary3));
  print(vecBinaries3);

Output:输出:

Binaries: [1]: {
  [8]: { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }
}

Live Demo on coliru在coliru上进行现场演示


I also added brace initialization (which in this case is direct-list-initialization ).我还添加了大括号初始化(在这种情况下是direct-list-initialization )。

  const Binaries vecBinaries4 {
    std::vector<unsigned char>(binaries, binaries + binaries_size)
  };
  print(vecBinaries4);

Output:输出:

Binaries: [1]: {
  [8]: { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }
}

(I must admit, I still consider brace init. a little bit scaring. Hence, I struggled to mention it at all but I should for completeness.) (我必须承认,我仍然认为大括号初始化。有点吓人。因此,我根本没有提到它,但为了完整起见,我应该这样做。)

In certain cases, eg if you have a vector of integrals, you have to be careful to distinguish the constructor with size n and an initial fill value from the constructor with an initialization list of two values.在某些情况下,例如,如果您有一个积分向量,则必须小心区分大小为n和初始填充值的构造函数与具有两个值的初始化列表的构造函数。 For both, you have to provide two integral values, but the kind and number of brackets decide which constructor is used.对于两者,您必须提供两个整数值,但括号的种类和数量决定使用哪个构造函数。 This can result in confusion easily.这很容易导致混淆。

Example:例子:

#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 }));
}

Output:输出:

{ 1, 2 }
{ 2 }
{ 1, 2 }
{ 1, 2 }

Live Demo on coliru在coliru上进行现场演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM