如何从Arrayfire明确获取线性索引
How to explicitly get linear indices from arrayfire?
假设我有一个 stl::array<float, 24> foo
,它是列的线性化sTL吊坠,用于列格式格式阵列阵列,例如af::array bar = af::array(4,3,2, 1, f32);
。因此,我有一个 af::dim4
对象dims
具有bar
的尺寸,最多4 af::seq
-objects,并且有线性化阵列foo
。
如何显式获得代表例如foo
的索引(即bar
的线性化版本)2.nd和3.rd行,即bar(af::seq(1,2), af::span, af::span, af::span)
?我有一个小的代码示例,其中显示了我想要的。最后,我还解释了为什么我想要这个。
af::dim4 bigDims = af::dim4(4,3,2);
stl::array<float, 24> foo; // Resides in RAM and is big
float* selBuffer_ptr; // Necessary for AF correct type autodetection
stl::vector<float> selBuffer;
// Load some data into foo
af::array selection; // Resides in VRAM and is small
af::seq selRows = af::seq(1,2);
af::seq selCols = af::seq(bigDims[1]); // Emulates af::span
af::seq selSlices = af::seq(bigDims[2]); // Emulates af::span
af::dim4 selDims = af::dim4(selRows.size, selCols.size, selSlices.size);
dim_t* linIndices;
// Magic functionality getting linear indices of the selection
// selRows x selCols x selSlices
// Assign all indexed elements to a consecutive memory region in selBuffer
// I know their positions within the full dataset, b/c I know the selection ranges.
selBuffer_ptr = static_cast<float> &(selBuffer[0]);
selection = af::array(selDims, selBuffer_ptr); // Copies just the selection to the device (e.g. GPU)
// Do sth. with selection and be happy
// I don't need to write back into the foo array.
arrayfire必须实现这样的逻辑才能访问元素,我找到了几个相关的类/功能,例如 af::index, af::seqToDims, af::gen_indexing, af::array::operator()
-但是我还不知道一个简单的方法。
我考虑了基本上重新实现operator()
,因此它的工作方式类似,但不需要引用数组对象。但是,如果Arrayfire-Framework中有一种简单的方法,这可能会浪费努力。
背景:我要这样做的原因是因为ArrayFire不允许仅在与GPU后端链接时将数据存储在主内存(CPU-Context)中。由于我有很大一部分数据,只需要按部分处理,并且VRAM非常有限,所以我想从始终驻留在主内存中的stl-container实例化 af::array
-objects临时。p>当然,我知道我可以编程一些索引魔术以解决我的问题,但是我想使用相当复杂的 af::seq
对象,这可能会有效地实现索引逻辑复杂。
在与帕文·雅拉曼奇利(Pavan Yalamanchili)进行讨论之后,我设法获得了我想共享的工作代码,以防其他人只需要在RAM中握住他的变量并在compoy-on-on-on-将其部分使用到VRAM,即Arrayfire Universe(如果在GPU或NVIDIA上链接到OpenCL)。
该解决方案还将帮助任何在项目中其他地方使用AF的人,并且想要具有方便的方式,可以使用(N&lt; = 4)访问大型线性的N-DIM数组。
// Compile as: g++ -lafopencl malloc2.cpp && ./a.out
#include <stdio.h>
#include <arrayfire.h>
#include <af/util.h>
#include <cstdlib>
#include <iostream>
#define M 3
#define N 12
#define O 2
#define SIZE M*N*O
int main() {
int _foo; // Dummy variable for pausing program
double* a = new double[SIZE]; // Allocate double array on CPU (Big Dataset!)
for(long i = 0; i < SIZE; i++) // Fill with entry numbers for easy debugging
a[i] = 1. * i + 1;
std::cin >> _foo; // Pause
std::cout << "Full array: ";
// Display full array, out of convenience from GPU
// Don't use this if "a" is really big, otherwise you'll still copy all the data to the VRAM.
af::array ar = af::array(M, N, O, a); // Copy a RAM -> VRAM
af_print(ar);
std::cin >> _foo; // Pause
// Select a subset of the full array in terms of af::seq
af::seq seq0 = af::seq(1,2,1); // Row 2-3
af::seq seq1 = af::seq(2,6,2); // Col 3:5:7
af::seq seq2 = af::seq(1,1,1); // Slice 2
// BEGIN -- Getting linear indices
af::array aidx0 = af::array(seq0);
af::array aidx1 = af::array(seq1).T() * M;
af::array aidx2 = af::reorder(af::array(seq2), 1, 2, 0) * M * N;
af::gforSet(true);
af::array aglobal_idx = aidx0 + aidx1 + aidx2;
af::gforSet(false);
aglobal_idx = af::flat(aglobal_idx).as(u64);
// END -- Getting linear indices
// Copy index list VRAM -> RAM (for easier/faster access)
uintl* global_idx = new uintl[aglobal_idx.dims(0)];
aglobal_idx.host(global_idx);
// Copy all indices into a new RAM array
double* a_sub = new double[aglobal_idx.dims(0)];
for(long i = 0; i < aglobal_idx.dims(0); i++)
a_sub[i] = a[global_idx[i]];
// Generate the "subset" array on GPU & diplay nicely formatted
af::array ar_sub = af::array(seq0.size, seq1.size, seq2.size, a_sub);
std::cout << "Subset array: "; // living on seq0 x seq1 x seq2
af_print(ar_sub);
return 0;
}
/*
g++ -lafopencl malloc2.cpp && ./a.out
Full array: ar
[3 12 2 1]
1.0000 4.0000 7.0000 10.0000 13.0000 16.0000 19.0000 22.0000 25.0000 28.0000 31.0000 34.0000
2.0000 5.0000 8.0000 11.0000 14.0000 17.0000 20.0000 23.0000 26.0000 29.0000 32.0000 35.0000
3.0000 6.0000 9.0000 12.0000 15.0000 18.0000 21.0000 24.0000 27.0000 30.0000 33.0000 36.0000
37.0000 40.0000 43.0000 46.0000 49.0000 52.0000 55.0000 58.0000 61.0000 64.0000 67.0000 70.0000
38.0000 41.0000 44.0000 47.0000 50.0000 53.0000 56.0000 59.0000 62.0000 65.0000 68.0000 71.0000
39.0000 42.0000 45.0000 48.0000 51.0000 54.0000 57.0000 60.0000 63.0000 66.0000 69.0000 72.0000
ar_sub
[2 3 1 1]
44.0000 50.0000 56.0000
45.0000 51.0000 57.0000
*/
该解决方案使用了一些无证件的AF函数,据说由于在global_idx上运行的for循环而慢,但是到目前为止,如果要专门在CPU上持有数据并仅与该零件共享,那么它的确可以做到最好的。用于处理的AF的GPU上下文。
如果有人知道一种加快此代码的方法,我仍然开放建议。
- C++为构建时间获取QDateTime的可靠方法
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 使用指针从C++中的数组中获取最大值
- 如何获取std::result_of函数的返回类型
- 如何在openssl-ecc中获取十六进制格式的私钥
- 使用Unreal C++获取VR耳机的世界位置/方向
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 从C字符串中获取奇怪的字符串长度
- 为什么我的for循环不能正确获取argv
- 从python中调用C++函数并获取返回值
- 如何获取一个数字的前3位
- 获取字符串的长度并将其分配给数组
- 无法获取菜单选择以运行函数.C++
- 数组长度,为什么从命令行获取时不能使用它?
- 获取用于多维访问的线性索引
- OPENCV 3.4.1获取经过定制训练的线性SVM HOG DETECTMULTISCALE的原始形式
- 如何从Arrayfire明确获取线性索引
- 从文件中获取亚线性时间的输入
- 如何使用 C++ 获取线性回归线的斜率