已关闭。此问题需要更多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]
感谢您的支持!
1条答案
按热度按时间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明显小于完整的笛卡尔积,总体上可能会更快