【问题标题】:Smart way to make efficient wrapper for a performance library为性能库制作高效包装器的智能方法
【发布时间】:2016-04-26 07:17:44
【问题描述】:

假设,我们有一个外部库,它可以对一个双精度浮点数数组进行非常快速的计算(大多数时候是多线程的)。为方便起见,我以面向对象的方式编写代码,以便获得一组对象。每个对象都有一个持有双精度值的属性。使用强大的外部库的天真方法是这样的:

double temp[N];
for i from 1 to N
   temp[i] = objectArray[i].property;
end

但是,这需要时间和额外的内存来保存 temp 数组。有没有更好的方法来做到这一点?

这是一个普遍的问题,但我基本上想在 C++ 中解决这个问题。

【问题讨论】:

  • 如果您的库在一个数组上执行算法并且一个数组,那么这是唯一的方法。如果您的库可以以其他方式执行它,那么我们需要更多地了解这个库。
  • 我能想到几个选项: 1. 在你的 objectArray 旁边放一个 double[] 成员,并确保它们始终同步。 2. 一个更好的选择是用指向 double[] 的 double* 替换您的 double 属性。这样你就不用写同步代码了
  • 不知道库API 很难提出建议。这就是为什么STL 接口风格如此强大的原因,他们将指针的概念概括为迭代器。如果你的库接受 iterators 这会容易得多。 API 有类似的东西吗?
  • @Galik “如果你的库接受迭代器,这会容易得多。”怎么会更容易?你能简要解释一下吗?我是 C++ 新手。
  • @ZoltánCsáti 然后您可以将该算法与对象数组中的迭代器一起使用。这些迭代器将返回带有operator* 的双精度值。

标签: c++ performance numerical-computing


【解决方案1】:

如果您确定您的对象仅包含 double 数据成员,没有添加数据成员的基础,也没有 virtual 函数 - 请检查 sizeof(*objectArray) == sizeof(double) 的静态断言 - 并假设您的外部库函数是离线,您可以将外部库a double* 传递给objectArray[0]

如果库函数内联在您包含的标头中,您可能会遇到别名问题,应查阅您的编译器文档以获取选项。

如果您的objectArray 元素每个只包含一个double,您必须将它们复制到一个压缩的如果这是外部库所期望的数组。 (您可能会考虑的一种选择是将 double 值保存在数组中,并让更复杂的对象存储对数组元素的引用)。

【讨论】:

  • 我的objectArray 也包含其他基本数据类型和其他类的对象通过组合。你是什​​么意思压缩数组?那么您是否建议将该双精度数组存储在类的属性中?
  • @ZoltánCsáti:通过“压缩数组”,我只是在强调数组的内存中连续元素方面。如果您只是创建数组以便可以将库应用于它然后将元素提取回objectArray 元素中,那么 "将双数组存储在类的属性中"我>。如果您发现自己想将数组视为对象并对其调用操作 - 那么您可能会费心创建一个存储或管理数组的类。抱歉,如果这没有帮助 - 需求的平衡决定了最佳选择。
  • "如果您只是创建数组,以便可以将库应用于它"。是的,这只是我需要的。因此,如果我理解得很好,您会说 1) 不要将该双数组存储在属性中 - 它没有用,2) 因为我不想对该数组进行任何操作(只需将其传递给现有库),请使用我在问题中看到的幼稚方法。
  • @ZoltánCsáti:听起来我的答案的最后一段已应用-您可以 1) 像在您的问题中那样复制它们,或者 2) 提前将一组双人坐在那里,然后直接操作objectArray 对象中的值。为了支持 2),objectArray 元素需要某种方式来知道它们控制数组中的哪个double - 引用、指针,甚至是指向数组开头的指针和索引号。
  • 我真的很喜欢你的第二种方法。我会这样做的。
【解决方案2】:

您可以为您的对象使用竞技场策略。基本上我们的对象将只包含一个索引和一个数据区的句柄。实际数据存储在正确索引的竞技场中。这样,当您需要创建 double 的向量时,它已经存在于竞技场中。

只有在您始终知道哪些对象是一起处理的并且它们几乎总是一起处理的情况下才有效。如果您每次都需要选择需要的对象,这不会给您带来任何性能提升(除非对象在数组中始终是连续的)。这也使常规对象访问速度稍慢一些,因此只有在每次复制值确实是您程序中的瓶颈时才有意义。

您的数据结构如下所示:

class Arena {
   vector<double> propertyX;
   vector<double> propertyY;
   int next_index;
};

class MyObject {
  int index;
  Arena& arena
  MyObject(Arena& arena_ref): arena(arena_ref) { index = arena.next_index++; }
  double getX() { return arena.propertyX[index]; }
};

你需要更多的代码来确保分配的东西等等,但你明白了。现在,当您需要调用外部库时,您可以直接从 Arena 对象获取数组。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-21
    相关资源
    最近更新 更多