如何从 arrayfire 显式获取线性索引?

2024-01-01

假设我有一个stl::array<float, 24> foo这是列主格式 arrayfire 数组的线性化 STL 挂件,例如af::array bar = af::array(4,3,2, 1, f32);。所以我有一个af::dim4 object dims尺寸为bar, 我最多有 4 个af::seq-objects 和我有线性化数组foo.

如何明确获得foo(即线性化版本bar) 代表例如第二行和第三行,即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 框架中有一个简单的方法,这可能会浪费精力。

背景:我想要这样做的原因是因为 arrayfire 不允许在与 GPU 后端链接时仅将数据存储在主内存(CPU 上下文)中。由于我有大量数据需要逐段处理,并且 VRAM 非常有限,所以我想实例化af::array-来自始终驻留在主内存中的 stl 容器的临时对象。

当然,我知道我可以编写一些索引魔法来解决我的问题,但我想使用相当复杂的af::seq对象,这可能会使索引逻辑的有效实现变得复杂。


在与 Pavan Yalamanchili 在 Gitter 上进行讨论后,我设法获得了一段工作代码,我想分享它,以防其他人只需要在 RAM 中保存他的变量并将其使用时复制部分到 VRAM,即 Arrayfire 宇宙(如果与 GPU 或 Nvidia 上的 OpenCL 链接)。

该解决方案还可以帮助任何在项目中其他地方使用 AF 的人,以及想要以一种方便的方式访问大型线性化 N 维数组 (N

//  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 函数,并且由于 for 循环在 global_idx 上运行,据说速度很慢,但到目前为止,如果 on 想要独占在 CPU 上下文中保存数据并仅与 GPU 上下文共享部分,那么它确实是最好的解决方案AF 进行处理。

如果有人知道加快此代码速度的方法,我仍然愿意寻求建议。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从 arrayfire 显式获取线性索引? 的相关文章

  • 使用 C# 登录《我的世界》

    我正在尝试为自己和一些朋友创建一个简单的自定义 Minecraft 启动器 我不需要启动 Minecraft 的代码 只需要登录的实际代码行 例如 据我所知 您过去可以使用 string netResponse httpGET https
  • GetType() 在 Type 实例上返回什么?

    我在一些调试过程中遇到了这段代码 private bool HasBaseType Type type out Type baseType Type originalType type GetType baseType GetBaseTyp
  • C++ 是否可以在 MacOS 上与 OpenMP 和 boost 兼容?

    我现在已经尝试了很多事情并得出了一些结论 也许 我监督了一些事情 但似乎我无法完成我想要的事情 问题是 是否有可能使用 OpenMP 和 boost 在 MacOS High Sierra 上编译 C 一些发现 如果我错了请纠正我 Open
  • 查找进程的完整路径

    我已经编写了 C 控制台应用程序 当我启动应用程序时 不使用cmd 我可以看到它列在任务管理器的进程列表中 现在我需要编写另一个应用程序 在其中我需要查找以前的应用程序是否正在运行 我知道应用程序名称和路径 所以我已将管理对象搜索器查询写入
  • 查看 NuGet 包依赖关系层次结构

    有没有一种方法 文本或图形 来查看 NuGet 包之间的依赖关系层次结构 如果您使用的是新的 csproj 您可以在此处获取所有依赖项 在项目构建后 项目目录 obj project assets json
  • C# 数据表更新多行

    我如何使用数据表进行多次更新 我找到了这个更新 1 行 http support microsoft com kb 307587 my code public void ExportCSV string SQLSyntax string L
  • 从客户端访问 DomainService 中的自定义对象

    我正在使用域服务从 Silverlight 客户端的数据库中获取数据 在DomainService1 cs中 我添加了以下内容 EnableClientAccess public class Product public int produ
  • unordered_map 中字符串的 C++ 哈希函数

    看起来 C 标准库中没有字符串的哈希函数 这是真的 在任何 c 编译器上使用字符串作为 unordered map 中的键的工作示例是什么 C STL提供模板专业化 http en cppreference com w cpp string
  • 启动时的 Excel 加载项

    我正在使用 Visual C 创建 Microsoft Excel 的加载项 当我第一次创建解决方案时 它包含一个名为 ThisAddIn Startup 的函数 我在这个函数中添加了以下代码 private void ThisAddIn
  • 识别 Visual Studio 中的重载运算符 (c++)

    有没有办法使用 Visual Studio 快速直观地识别 C 中的重载运算符 在我看来 C 中的一大问题是不知道您正在使用的运算符是否已重载 Visual Studio 或某些第三方工具中是否有某些功能可以自动突出显示重载运算符或对重载运
  • 为什么我的单选按钮不起作用?

    我正在 Visual C 2005 中开发 MFC 对话框应用程序 我的单选按钮是 m Small m Medium 和 m Large 它们都没有在我的 m Summary 编辑框中显示应有的内容 可能出什么问题了 这是我的代码 Pizz
  • 保护 APK 中的字符串

    我正在使用 Xamarin 的 Mono for Android 开发一个 Android 应用程序 我目前正在努力使用 Google Play API 添加应用内购买功能 为此 我需要从我的应用程序内向 Google 发送公共许可证密钥
  • 打印大型 WPF 用户控件

    我有一个巨大的数据 我想使用 WPF 打印 我发现WPF提供了一个PrintDialog PrintVisual用于打印派生的任何 WPF 控件的方法Visual class PrintVisual只会打印一页 因此我需要缩放控件以适合页面
  • WebBrowser.Print() 等待完成。 。网

    我在 VB NET 中使用 WebBrowser 控件并调用 Print 方法 我正在使用 PDF 打印机进行打印 当调用 Print 时 它不会立即启动 它会等到完成整个子或块的运行代码 我需要确保我正在打印的文件也完整并继续处理该文件
  • String.Empty 与 "" [重复]

    这个问题在这里已经有答案了 可能的重复 String Empty 和 有什么区别 https stackoverflow com questions 151472 what is the difference between string
  • 将数组作为参数传递

    如果我们修改作为方法内参数传递的数组的内容 则修改是在参数的副本而不是原始参数上完成的 因此结果不可见 当我们调用具有引用类型参数的方法时 会发生什么过程 这是我想问的代码示例 using System namespace Value Re
  • PHP条件,如果当前页面,则链接突出显示[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我有一个带
  • 如何减少具有多个单元的 PdfPTable 的内存消耗

    我正在使用 ITextSharp 创建一个 PDF 它由单个 PdfTable 组成 不幸的是 对于特定的数据集 由于创建了大量 PdfPCell 我遇到了内存不足异常 我已经分析了内存使用情况 我有近百万个单元格的 1 2 在这种情况下有
  • Objective-C / C 给出枚举默认值

    我在某处读到过关于给枚举默认值的内容 如下所示 typedef enum MarketNavigationTypeNone 0 MarketNavigationTypeHeirachy 1 MarketNavigationTypeMarke
  • 是否可以在不连接数据库的情况下检索 MetadataWorkspace?

    我正在编写一个需要遍历实体框架的测试库MetadataWorkspace对于给定的DbContext类型 但是 由于这是一个测试库 我宁愿不连接到数据库 它引入了测试环境中可能无法使用的依赖项 当我尝试获取参考时MetadataWorksp

随机推荐