【问题标题】:Efficiently chunk large vector into a vector of vectors有效地将大向量分块为向量的向量
【发布时间】:2019-01-29 05:11:22
【问题描述】:

我想将一个大向量分块成一个向量向量。我知道chunks(),但不确定从迭代器到二维Vec 的最佳方式。我发现以下方法可行,但有没有更好的方法来编写它?

let v: Vec<i32> = vec![1, 1, 1, 2, 2, 2, 3, 3, 3];
let v_chunked: Vec<Vec<i32>> = v.chunks(3).map(|x| x.to_vec()).collect();

println!("{:?}", v_chunked); // [[1, 1, 1], [2, 2, 2], [3, 3, 3]]

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=5031d4d0e43470242b8304d483967a25

类似的操作是我的程序分析后最慢的部分之一,我想知道如何改进它。

【问题讨论】:

  • 我没有发现问题。
  • 您可以创建切片向量或编写/使用跨步数组类型。 有更好的方法吗? 是一个相当开放的问题。你能具体说明为什么这种方法不够好吗?
  • 问题的范围很广。我想真正的问题是:表示二维向量的最佳方式是什么?恕我直言,解决方案是包装单个向量并添加一些方法将其抽象为 2D。
  • 您将有 N + 2 个分配,其中 N 是 v_chuncked 的元素数。通过返回 Vec 而不是 Vec>。见godbolt.org/z/4Z2iww
  • 作为一个新的 Rust 用户,我倾向于用 vec 的 vec 定义我的结构,因为我不知道在编译时要分块到其中的集合的确切大小。我知道它会有数百万个元素,但我需要执行数百次。我将探索切片方法的 vec。谢谢!

标签: vector rust iterator slice


【解决方案1】:

如果Vec&lt;Vec&lt;i32&gt;&gt; 是您真正想要的,那么这是一个非常好的方法。任何其他方法(不包括unsafe 代码,见下文)不太可能明显更快或使用明显更少的内存。无论实际代码如何,每个嵌套的 Vec 都是一个新的内存分配,所有数据都需要复制 - 这基本上就是您的代码所做的一切。

表示像这样的 2D 结构的更“生锈”的方式是对原始数据进行切片的Vec。这样您就不会进行任何复制,也不会进行新的分配。

let v_slices: Vec<&[i32]> = v.chunks(3).collect();

println!("{:?}", v_slices); // [[1, 1, 1], [2, 2, 2], [3, 3, 3]]

编辑: 我这里确实有一个 extra bit 和一些 unsafe 代码,可以将 Vec&lt;i32&gt; 转换为 Vec&lt;Vec&lt;i32&gt;&gt; 而无需重新分配。不过已经指出它还是有Undefined Behaviour,根本就是问题出在not fixable

【讨论】:

  • 如果对任何人都有帮助,请附加说明:如果v.len() % chunk_length != 0,最后一个块的大小可以小于定义的块大小。我想要大小完全相同的块(在频道上收听),并等待下一批完成以完成为我工作。
【解决方案2】:

在 cmets 的帮助下,我发现将数据存储为一维 Vec 效率更高。然后为了方便地处理它,我使用chunks 并使用数据在函数体内根据需要使用切片的Vec

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-20
    • 2018-08-23
    • 1970-01-01
    相关资源
    最近更新 更多