【问题标题】:Large Data Set for Processing, need to maintain original data set处理的大数据集,需要维护原始数据集
【发布时间】:2013-05-29 21:30:06
【问题描述】:

这是我的问题定义:我有一个 七百万个索引 组成的数组,每个索引都包含一个标签。因此,为简单起见,这是我正在处理的示例数组:[1 2 3 3 3 5 2 1 7]。

我需要遍历这个数组,每次遇到标签时,将标签的位置输入到一个“集合”中,所有其他标签都相同。由于数组如此之大,我只想在任何给定点访问特定标签的位置,所以假设我只想访问 3 的位置并处理这些位置并将它们更改为 5,但我想做更多不仅是一项操作,而且不仅如此,我还想在所有标签上分别进行。在像我的示例中这样的小数组中,坚持使用数组似乎微不足道。但是,对于 700 万个点的数组,完成对所述标签的搜索然后对它们进行操作要花费更多的时间。

为了消除混淆,使用我的示例,我希望示例数组为我提供以下内容:

  • 1 映射到包含 0 和 7 的集合
  • 2 映射到包含 1 和 6 的集合
  • 3 映射到包含 2、3 和 4 的集合
  • 5 映射到包含 5 的集合

原来我是对原始数组进行处理,简单的对数组进行操作。这大约需要 30 秒来确定每个标签的对应索引的数量(所以我能够确定 1 的大小是 2,6 的大小是 2,3 的大小是 3,等等。但是,它没有使用此方法生成所述标签的位置。因此,在我的其余处理过程中也增加了时间来查找每个标签的位置,尽管它通过添加终端来加速,一旦它找到了引用标签的所有索引, 停止搜索。

下一步,我使用了map<int,set<int>>,但这最终导致时间增加至约 100 秒,但随后的处理时间减少了,但不足以证明时间大幅增加是合理的。

我还没有实现它,但作为一个额外的步骤,我计划尝试初始化一个集合数组,其索引对应于标签并尝试使用这种方法。

我也尝试过 hash_maps 也无济于事。 Visual Studio 2005 的 STL 中不包含 Unordered_sets 和 unordered_maps,所以我没有用这两个结构实现上述内容。

关键点: 我已经对数组进行了预处理,以便我知道最大标签,并且所有标签都是连续的(最小标签和最大值之间没有间隙)。但是,它们随机分散在原始阵列中。这可能证明在初始化一组大小的数据结构时很有用。 与标签对应的索引的顺序并不重要。标签在给定数据结构中的顺序也不重要。

编辑: 作为背景,该数组对应于一个二进制图像,我实现了二进制顺序标记以输出一个与 UINT16 的二进制图像大小相同的数组,所有二进制 blob 都被标记。我现在要做的是尽可能高效地获取构成每个 blob 的点的地图。

【问题讨论】:

  • 标签实际上是数字还是文本?
  • 它们将是无符号整数值。
  • 当您创建map 时,密钥类型是无符号整数吗?
  • 我还没有完全解决这个问题,但它开始感觉像是 Boost.MultiIndex 的工作。
  • 我会说用std::vector<std::vector<int>> 替换map<unsigned, set<int>>,它的工作方式应该几乎相同,但使用更少的内存并且速度更快。

标签: c++ image-processing visual-studio-2005 large-data


【解决方案1】:

您为什么要为这项任务使用如此复杂的数据结构?只需创建一个向量向量来存储每个标签的所有位置即可。您还可以通过预处理每个标签所需的空间来避免烦人的向量内存分配。类似的东西:

vector <int> count(N);
for(size_t i = 0; i < N; ++i)
    ++count[dataArray[i]];
vector < vector <int> > labels(N);
vector <int> last(N);
for(size_t i = 0; i < N; ++i)
    labels[i].resize(count[i]);
for(size_t i = 0; i < N; ++i) {
    labels[dataArray[i]][last[dataArray[i]]] = i;
    ++last[dataArray[i]];
}

它将在 O(N) 时间内工作,对于你的 700 万个整数来说,这看起来像是 1 秒。

【讨论】:

    【解决方案2】:

    我不一定会为此使用通用映射(或哈希表)。

    我最初的直觉是,我将创建第二个数组“位置”,其中包含 700 万个(或任何 N 个)位置,以及对应于范围 [min-label, max-label] 的第三个数组“last_position_for_index”。请注意,这几乎肯定会比任何类型的地图占用更少的存储空间。

    将 last_position_for_index 的所有条目初始化为某个保留值,然后您可以使用类似(未经测试)的内容循环遍历您的数组:

    for (std::size_t k = 0; k<N; ++k) {
      IndexType index = indices[k];
      positions[k] = last_position_for_index[index-min_label];
      last_position_for_index[index-min_label] = k;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多