高效Tensor張量生成
Efficient Tensor Creation
從C++中的Excel數據中創建Tensor張量的方法有很多種,在簡單性和性能之間都有不同的折衷。本文討論了一些方法及其權衡。
提示
繼續閱讀之前請務必閱讀C++指南
將數據直接寫入Tensor張量
如果能做到這一點就更好了。
不要複製數據或包裝現有數據,而是直接將數據寫入Tensor張量。
正向
對於進程內和進程外的執行,這將在沒有副本的情況下工作
沒有內存對齊要求
不需要使用刪除程序
反向
可能需要對現有的應用程序進行大量的重構,才能使其正常工作
實例
可以將數據直接接收到Tensor張量的底層緩衝區中:
// Allocate a
tensor
auto tensor = allocator->allocate_tensor({6, 6});
// Get a pointer
to the underlying buffer
auto data = tensor->get_raw_data_ptr();
// Some function
that writes data directly into this buffer
recv_message_into_buffer(data);
或者可以手動填寫Tensor張量:
// Allocate a
tensor
auto tensor = allocator->allocate_tensor({256, 256});
const auto &dims = tensor->get_dims();
// Get an
accessor
auto accessor = tensor->accessor<2>();
// Write data
directly into it
for (int i = 0; i < dims[0]; i++)
{
for (int j = 0; j < dims[1]; j++)
{
accessor[i][j] = i * j;
}
}
甚至可以將其與TBB並行:
// Allocate a
tensor
auto tensor = allocator->allocate_tensor({256, 256});
const auto &dims = tensor->get_dims();
// Get an
accessor
auto accessor = tensor->accessor<2>();
// Write data
into the tensor in parallel
tbb::parallel_for(
// Parallelize in blocks of 16 by 16
tbb:blocked_range2d<size_t>(0, dims[0], 16, 0, dims[1], 16),
// Run this lambda in parallel for each block in the range above
[&](const blocked_range2d<size_t>& r) {
for(size_t i = r.rows().begin(); i != r.rows().end(); i++)
{
for(size_t j = r.cols().begin(); j != r.cols().end(); j++)
{
accessor[i][j] = i * j;
}
}
}
);
包裝現有內存
如果已經在某個緩衝區中保存了數據,那麼這個方法很好。
正向
在進程內執行期間,這將在沒有副本的情況下工作
如果已經有數據很容易做到
反向
需要了解什麼是刪除者以及如何正確使用
爲了有效地使用TF,數據需要64字節對齊
注意:這不是一個硬性要求,但是TF可以在引擎蓋下複製未對齊的數據
與#1相比,這會在進程外執行期間生成一個額外的副本
實例
從cv::Mat包裝數據:
cv::Mat image = … // An image from somewhere
auto tensor = allocator->tensor_from_memory<uint8_t>(
// Dimensions
{1, image.rows, image.cols, image.channels()},
// Data
image.data,
// Deleter
[image](void * unused) {
// By capturing `image` in this deleter, we ensure
// that the underlying data does not get deallocated
// before we're done with the tensor.
}
);
將數據複製到Tensor張量中
正向
很容易做到
無內存對齊要求
不需要使用刪除程序
反向
在進程內執行期間總是生成一個額外的副本
與#1相比,這會在進程外執行期間生成一個額外的副本(儘管此副本是由用戶顯式編寫的)
實例
從cv::Mat複製:
cv::Mat image = … // An image from somewhere
auto tensor = allocator->allocate_tensor<uint8_t>(
// Dimensions
{1, image.rows, image.cols, image.channels()}
);
// Copy data
into the tensor
tensor->copy_from(image.data, tensor->get_num_elements());
該用哪一個?
一般來說,按業績衡量的方法順序如下:
直接將數據寫入Tensor張量
包裝現有內存
將數據複製到Tensor張量中
也就是說,分析是朋友。
簡單性和性能之間的折衷對於大Tensor張量和小Tensor張量也是不同的,因爲副本對於小Tensor張量更便宜。