ComputeLibrary CLTensor 数据传输
ComputeLibrary CLTensor data transfer
我正在将 ARM ComputeLibrary 集成到一个项目中。
这不是我熟悉的 API 语义,但我正在研究文档和示例。
目前,我正在尝试将 std::vector
的内容复制到 CLTensor
。然后使用ARMCL GEMM操作。
我一直在构建一个 MWE,如下所示,目的是让矩阵乘法正常工作。
为了从标准 C++ std::vector
或 std::ifstream
获取输入数据,我正在尝试基于 this example shown in the docs.
的基于迭代器的方法
但是,我一直遇到段错误。
源码中有an example of sgemm using CLTensor
,这也是我的灵感来源。但是,它从 Numpy 数组获取输入数据,因此到目前为止不相关。
我不确定在 ARMCL 中 CLTensor
和 Tensor
是否有不相交的方法。但我觉得他们是一个共同的接口ITensor
。不过,我还没有找到一个等效的例子,它使用 CLTensor
而不是 Tensor
作为这个基于迭代器的方法。
您可以在下面看到我正在使用的代码,它在第 64 行失败 (*reinterpret_cast..
)。我不完全确定它执行的操作是什么,但我的猜测是我们有我们的 ARMCL 迭代器 input_it
,它递增 n * m
次,每次迭代设置 [=12= 的值] 在该地址到相应的输入值。 reinterpret_cast
只是为了让类型一起玩得很好?
我认为我的 Iterator 和 Window 对象没问题,但不能确定。
#include "arm_compute/core/Types.h"
#include "arm_compute/runtime/CL/CLFunctions.h"
#include "arm_compute/runtime/CL/CLScheduler.h"
#include "arm_compute/runtime/CL/CLTuner.h"
#include "utils/Utils.h"
namespace armcl = arm_compute;
namespace armcl_utils = arm_compute::utils;
int main(int argc, char *argv[])
{
int n = 3;
int m = 2;
int p = 4;
std::vector<float> src_a = {2, 1,
6, 4,
2, 3};
std::vector<float> src_b = {5, 2, 1, 6,
3, 7, 4, 1};
std::vector<float> c_targets = {13, 11, 6, 13,
42, 40, 22, 40,
19, 25, 14, 15};
// Provides global access to a CL context and command queue.
armcl::CLTuner tuner{};
armcl::CLScheduler::get().default_init(&tuner);
armcl::CLTensor a{}, b{}, c{};
float alpha = 1;
float beta = 0;
// Initialize the tensors dimensions and type:
const armcl::TensorShape shape_a(m, n);
const armcl::TensorShape shape_b(p, m);
const armcl::TensorShape shape_c(p, n);
a.allocator()->init(armcl::TensorInfo(shape_a, 1, armcl::DataType::F32));
b.allocator()->init(armcl::TensorInfo(shape_b, 1, armcl::DataType::F32));
c.allocator()->init(armcl::TensorInfo(shape_c, 1, armcl::DataType::F32));
// configure sgemm
armcl::CLGEMM sgemm{};
sgemm.configure(&a, &b, nullptr, &c, alpha, beta);
// // Allocate the input / output tensors:
a.allocator()->allocate();
b.allocator()->allocate();
c.allocator()->allocate();
// // Fill the input tensor:
// // Simplest way: create an iterator to iterate through each element of the input tensor:
armcl::Window input_window;
armcl::Iterator input_it(&a, input_window);
input_window.use_tensor_dimensions(shape_a);
std::cout << " Dimensions of the input's iterator:\n";
std::cout << " X = [start=" << input_window.x().start() << ", end=" << input_window.x().end() << ", step=" << input_window.x().step() << "]\n";
std::cout << " Y = [start=" << input_window.y().start() << ", end=" << input_window.y().end() << ", step=" << input_window.y().step() << "]\n";
// // Iterate through the elements of src_data and copy them one by one to the input tensor:
execute_window_loop(input_window, [&](const armcl::Coordinates & id)
{
std::cout << "Setting item [" << id.x() << "," << id.y() << "]\n";
*reinterpret_cast<float *>(input_it.ptr()) = src_a[id.y() * m + id.x()]; //
},
input_it);
// armcl_utils::init_sgemm_output(dst, src0, src1, armcl::DataType::F32);
// Configure function
// Allocate all the images
// src0.allocator()->import_memory(armcl::Memory(&a));
//src0.allocator()->allocate();
//src1.allocator()->allocate();
// dst.allocator()->allocate();
// armcl_utils::fill_random_tensor(src0, -1.f, 1.f);
// armcl_utils::fill_random_tensor(src1, -1.f, 1.f);
// Dummy run for CLTuner
//sgemm.run();
std::vector<float> lin_c(n * p);
return 0;
}
您遗漏的部分(无可否认,在文档中可以更好地解释!)是您需要映射/取消映射 OpenCL 缓冲区,以便 CPU.
如果您查看 fill_random_tensor (which is what's used in the cl_sgemm example 内部,您会接到 tensor.map();
的电话
因此,如果您在创建迭代器之前 map()
您的缓冲区,那么我相信它应该可以工作:
a.map();
input_it(&a, input_window);
execute_window_loop(...)
{
}
a.unmap(); //Don't forget to unmap the buffer before using it on the GPU
希望对您有所帮助
我正在将 ARM ComputeLibrary 集成到一个项目中。
这不是我熟悉的 API 语义,但我正在研究文档和示例。
目前,我正在尝试将 std::vector
的内容复制到 CLTensor
。然后使用ARMCL GEMM操作。
我一直在构建一个 MWE,如下所示,目的是让矩阵乘法正常工作。
为了从标准 C++ std::vector
或 std::ifstream
获取输入数据,我正在尝试基于 this example shown in the docs.
但是,我一直遇到段错误。
源码中有an example of sgemm using CLTensor
,这也是我的灵感来源。但是,它从 Numpy 数组获取输入数据,因此到目前为止不相关。
我不确定在 ARMCL 中 CLTensor
和 Tensor
是否有不相交的方法。但我觉得他们是一个共同的接口ITensor
。不过,我还没有找到一个等效的例子,它使用 CLTensor
而不是 Tensor
作为这个基于迭代器的方法。
您可以在下面看到我正在使用的代码,它在第 64 行失败 (*reinterpret_cast..
)。我不完全确定它执行的操作是什么,但我的猜测是我们有我们的 ARMCL 迭代器 input_it
,它递增 n * m
次,每次迭代设置 [=12= 的值] 在该地址到相应的输入值。 reinterpret_cast
只是为了让类型一起玩得很好?
我认为我的 Iterator 和 Window 对象没问题,但不能确定。
#include "arm_compute/core/Types.h"
#include "arm_compute/runtime/CL/CLFunctions.h"
#include "arm_compute/runtime/CL/CLScheduler.h"
#include "arm_compute/runtime/CL/CLTuner.h"
#include "utils/Utils.h"
namespace armcl = arm_compute;
namespace armcl_utils = arm_compute::utils;
int main(int argc, char *argv[])
{
int n = 3;
int m = 2;
int p = 4;
std::vector<float> src_a = {2, 1,
6, 4,
2, 3};
std::vector<float> src_b = {5, 2, 1, 6,
3, 7, 4, 1};
std::vector<float> c_targets = {13, 11, 6, 13,
42, 40, 22, 40,
19, 25, 14, 15};
// Provides global access to a CL context and command queue.
armcl::CLTuner tuner{};
armcl::CLScheduler::get().default_init(&tuner);
armcl::CLTensor a{}, b{}, c{};
float alpha = 1;
float beta = 0;
// Initialize the tensors dimensions and type:
const armcl::TensorShape shape_a(m, n);
const armcl::TensorShape shape_b(p, m);
const armcl::TensorShape shape_c(p, n);
a.allocator()->init(armcl::TensorInfo(shape_a, 1, armcl::DataType::F32));
b.allocator()->init(armcl::TensorInfo(shape_b, 1, armcl::DataType::F32));
c.allocator()->init(armcl::TensorInfo(shape_c, 1, armcl::DataType::F32));
// configure sgemm
armcl::CLGEMM sgemm{};
sgemm.configure(&a, &b, nullptr, &c, alpha, beta);
// // Allocate the input / output tensors:
a.allocator()->allocate();
b.allocator()->allocate();
c.allocator()->allocate();
// // Fill the input tensor:
// // Simplest way: create an iterator to iterate through each element of the input tensor:
armcl::Window input_window;
armcl::Iterator input_it(&a, input_window);
input_window.use_tensor_dimensions(shape_a);
std::cout << " Dimensions of the input's iterator:\n";
std::cout << " X = [start=" << input_window.x().start() << ", end=" << input_window.x().end() << ", step=" << input_window.x().step() << "]\n";
std::cout << " Y = [start=" << input_window.y().start() << ", end=" << input_window.y().end() << ", step=" << input_window.y().step() << "]\n";
// // Iterate through the elements of src_data and copy them one by one to the input tensor:
execute_window_loop(input_window, [&](const armcl::Coordinates & id)
{
std::cout << "Setting item [" << id.x() << "," << id.y() << "]\n";
*reinterpret_cast<float *>(input_it.ptr()) = src_a[id.y() * m + id.x()]; //
},
input_it);
// armcl_utils::init_sgemm_output(dst, src0, src1, armcl::DataType::F32);
// Configure function
// Allocate all the images
// src0.allocator()->import_memory(armcl::Memory(&a));
//src0.allocator()->allocate();
//src1.allocator()->allocate();
// dst.allocator()->allocate();
// armcl_utils::fill_random_tensor(src0, -1.f, 1.f);
// armcl_utils::fill_random_tensor(src1, -1.f, 1.f);
// Dummy run for CLTuner
//sgemm.run();
std::vector<float> lin_c(n * p);
return 0;
}
您遗漏的部分(无可否认,在文档中可以更好地解释!)是您需要映射/取消映射 OpenCL 缓冲区,以便 CPU.
如果您查看 fill_random_tensor (which is what's used in the cl_sgemm example 内部,您会接到 tensor.map();
因此,如果您在创建迭代器之前 map()
您的缓冲区,那么我相信它应该可以工作:
a.map();
input_it(&a, input_window);
execute_window_loop(...)
{
}
a.unmap(); //Don't forget to unmap the buffer before using it on the GPU
希望对您有所帮助