rust 如何使函数更有效:字符串元组向量笛卡尔积和搜索排序[已关闭]

qgelzfjb  于 2022-12-04  发布在  其他
关注(0)|答案(1)|浏览(128)

已关闭。此问题需要更多focused。当前不接受答案。
**想要改进此问题吗?**更新问题,使其仅关注editing this post的一个问题。

昨天关门了。
Improve this question
我开发了两个函数。笛卡尔积取集合并生成一个包含所有可能组合的元组向量。然后我对该向量进行一个小样本。第二个函数Searchsorted将两个元组向量作为输入,以获得与样本元组相关的较大向量的索引。

问题是我的函数太慢了(参见下面的基准测试)

我将非常感谢您的反馈。我能做些什么来改善执行时间?请记住,这是我的第一个生 rust 的项目;我是一个生 rust 的新手:)

  • 方法详情:*

准备运行-〉代码库在这里:https://github.com/cdgaete/searchsorted
其思路如下:我们有一个长格式表(示例):
| 尺寸1|尺寸2|尺寸3|价值|
| - -|- -|- -|- -|
| 'a1'|'b2'|'c1'| 10个|
| 'a2'|'b3'|'c2'|二十个|
每个维度都有一个已知的域:
尺寸1 ={'a1','a2'}
尺寸2 ={'b1','b2','b3'}
维度3 ={'c1','c2'}
我想创建一个包含所有可能组合的表(完整表),然后将示例表的值分配到完整表中。
所以,我的做法是:
第一步,我想创建一个元组数组(看起来像一个长格式表),包含所有可能的组合(这里,我使用了笛卡尔积函数)。第二步,我想找到元组数组示例的位置(上表),以便稍后将值插入到整个表中。
第1步:笛卡尔积(全)
| | 尺寸1|尺寸2|尺寸3|
| - -|- -|- -|- -|
| 一个|'a1'|'b1'|'c1'|
| 2个|'a1'|'b1'|'c2'|
| 三个|'a1'|'b2'|'c1'|
| 四个|'a1'|'b2'|'c2'|
| 五个|'a1'|'b3'|'c1'|
| 六个|'a1'|'b3'|'c2'|
| 七个|'a2'|'b1'|'c1'|
| 八个|'a2'|'b1'|'c2'|
| 九个|'a2'|'b2'|'c1'|
| 10个|'a2'|'b2'|'c2'|
| 十一|'a2'|'b3'|'c1'|
| 十二|'a2'|'b3'|'c2'|
步骤2:搜索排序
| 尺寸1|尺寸2|尺寸3|价值|索引全表|
| - -|- -|- -|- -|- -|
| 'a1'|'b2'|'c1'| 10个|三个|
| 'a2'|'b3'|'c2'|二十个|十二|
总结:

  • 笛卡尔积输入:维度集合
  • 笛卡尔积返回:具有元组的数组
  • 搜索排序输入:完整表(包含元组的数组)和示例表(包含元组的数组)
  • 搜索排序返回:整数数组

函数

笛卡尔积:

type TS3 = (String,String,String);

pub fn cartesian_3d(l1: Vec<String>, l2: Vec<String>, l3: Vec<String>) -> Vec<TS3> {
    let mut collector = Vec::new();
    for tuple in iproduct!(l1,l2,l3) {
        collector.push(tuple);
    };
    collector
}

搜索排序:

type TS3 = (String,String,String);

pub fn searchsorted_3d(dense_list: Vec<TS3>, index_list: Vec<TS3>) -> Vec<i64> {
    let mut htbl = HashMap::new();
    let mut i: i64 = 0;
    for key in dense_list.iter() {
        htbl.insert(key, i);
        i += 1i64
    };
    let mut location: Vec<i64> = Vec::new();
    for tuple in index_list.iter() {
        let value = htbl.get(tuple).unwrap();
        location.push(*value);
    };
    location
}

基准测试

在示例文件夹eg2.py和eg2.rs中包含基准代码:

  • 全矢量:一百万个五串元组。
  • 样本向量:1000元组
  • 元组中的每个字符串都有两个字符

结果:
笛卡尔积:

Rust-python   eTime: 1342697 μs.
Pure Rust     eTime   246470 μs.
Pure Rust     eTime   140097 μs. cargo --release
Pure python   eTime:   84879 μs.

搜索排序:

Rust-python   eTime: 2599270 μs.
Pure Rust     eTime  2015062 μs.
Pure Rust     eTime   678256 μs.  cargo --release
Pure python   eTime:  103814 μs.

纯Python代码:

笛卡尔积:迭代工具包

list(itertools.product(lst1,lst2,lst3,lst4,lst5))

搜索排序:字典和列表理解

def pysearchsorted(full_list, sample_list):
    fullhashtable = {tupl: idx for idx, tupl in enumerate(full_list)}
    return [fullhashtable[tupl] for tupl in sample_list]

感谢您的支持!

a64a0gku

a64a0gku1#

这里有两个问题。
1.如何改进现有的实现以使其比Python更快
1.如何实现更快的整体性能
几个想法:
关于1)。而不是let mut collector = Vec::new();。首先计算容量--乘以三个输入列表的len。然后执行Vec::with_capacity。这样就可以避免调整大小。
let mut htbl = HashMap::new();let mut location: Vec<i64> = Vec::new();的逻辑相同
关于2)。我发现首先计算全表时有很多冗余。笛卡尔积增长很快,所以内存也会受到影响。为什么不直接进入最终结果。首先将域列表list_1、list_2收集到hashmap中,以获得值的索引。然后针对索引列表的每一行,从hashmap中计算列值的索引(index_1,index_2,index_3,...),然后将最终值计算为index_n + index_{n-1} * len_{n} + index_{n-2} * len_{n} * len_{n-1} +...,其中len_n -是list_n的长度。len_n,len_n*len_{n-1},...应该在循环之前预先计算。我想如果我们计算值的index_list明显小于完整的笛卡尔积,总体上可能会更快

相关问题