【问题标题】:C++ API performance issue with tree structure树结构的 C++ API 性能问题
【发布时间】:2013-05-17 12:42:06
【问题描述】:

我正在为 C++ 模拟框架编写 API。我想在 C# 中使用这个 API。但是我在获取模拟中所有角色的位置时遇到了性能问题。我试图给你一个广泛的解释这个框架是如何工作的。

有一个模拟器类:

class Simulator
{
  /// A list of the characters that are currently in the simulation.
  std::vector<Character> characters;
  /// A list of the path planning results for the characters currently in the simulation.
  std::vector<PathPlanningResult*> pathPlanningResults;
  /// A mapping from character IDs (which can be set externally) to their positions in the 'characters' and 'PathPlanningResults' lists (which always number from 0).
  std::map<int, int> characterVectorPositions;

  /** Finds and returns a pointer to the character with the specified ID.
  * @param id       The ID of the character to find.
  * @return A pointer to the Character object that matches the given ID, or NULL if no such character exists.
  */
  inline Character* getCharacter(int id)
  { 
    std::map<int,int>::iterator findIt = characterVectorPositions.find(id);
    if(findIt == characterVectorPositions.end()) return NULL;
      return &characters[findIt->second];
    }

  /// Adds a character to the simulation, with the specified settings.
  bool Simulator::addCharacter(const Point& pos, short layer, const CharacterSettings& settings, int id)
  {
    Character newCharacter(id, pos, layer, settings);

    // add the character
    characters.push_back(newCharacter);
    // add an empty result
    pathPlanningResults.push_back(NULL);
    // add the ID mapping
    characterVectorPositions.insert(std::pair<int,int>(id, characters.size()-1));
  }
}

这个类保存了模拟中的所有角色对象。

有一个字符类,有一个获取位置的方法:

class Character
{
  /** Returns the current 2D position of the character on its current layer.
  * @return The current position of the character.
  */
  inline const Point& getPosition() const { return pos; }
}

Point 对象包含一个 X 和 Y 坐标

还有一个 API 类 API_simulator 有两种获取字符位置的方法:

class API_simulator 
{
  extern "C" EXPORT_API double GetCharacterX(int charid) {
    return simulator->getCharacter(charid)->getPosition().x;
  }

  extern "C" EXPORT_API double GetCharacterY(int charid) {
    return simulator->getCharacter(charid)->getPosition().y;
  }
}

当我在 C# 中使用此 API 时,一切正常。除非我在模拟器中添加了很多角色并且我需要获取所有角色的位置。这需要很长时间,因为每个字符的每个 X 和 Y 坐标都必须在树结构中找到。 有没有一种更快的方法来一次获取所有角色的位置? 共享内存是解决方案吗?

【问题讨论】:

    标签: c# c++ api tree shared-memory


    【解决方案1】:

    我不认为地图是瓶颈。它应该具有足够的可扩展性,因此通过地图查找每个字符的信息应该足够快,即使有几千个字符(这会导致 10 到 15 次查找)。
    但是,如果您想要所有字符的坐标,最好立即迭代正确的向量,而不是通过每个字符的 id 查找偏移量。

    【讨论】:

    • +1 OP 需要导出一组函数来迭代地图。
    • 你的意思是迭代“std::vector characters”向量吗?如果我这样做,我应该在 API 中使用哪种返回类型?包含 ID、X 和 Y 的结构数组?用 C 函数可以吗?
    • 是的,这是可能的。只需考虑到您需要进行一些内存管理。
    【解决方案2】:

    这实际上取决于数据库的大小与输入的大小相比。

    如果您要遍历输入中的所有字符(N 表示输入),并尝试每次在数据库映射中找到它们(D 表示数据库),那么您将花费 O(NlogD) 操作。

    您可以决定要数据库中的所有字符,然后您可以遍历 characters 向量,这将是 O(D)

    如果输入要大得多,您可以在地图或向量中对输入进行排序,然后遍历数据库,并将其与输入进行比较。 O(NlogN) 用于排序 + O(DlogN) 用于遍历数据库。

    【讨论】:

      【解决方案3】:
      1. 公开GetCharacterXY API 方法:这将需要一次对数时间查找来获取 (x,y) 位置,而不是执行两次相同的查找

        • 这仍可缩放为 O(n log n),但应该更快
      2. 尝试使用std::unordered_map 而不是std::map,除非您在某个地方需要按 id 对字符进行排序,因为这会提供恒定时间而不是对数时间查找

        • 这是O(n),但您仍在为每个 n 项进行哈希查找
      3. 公开一个返回所有 (id,x,y) 元组的方法,使用 characters 的线性扫描而不是按照 Yochai 的建议进行多次查找

        • 这是O(n),可能是最快的(因为您为每个项目做的多余工作最少)

      【讨论】:

        猜你喜欢
        • 2016-05-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多