这是刷面试题17.26遇到的问题。
相同的算法,python能过,Rust超时
(能忍吗……)
13 小时前 超出时间限制 N/A N/A Rust
13 小时前 通过 1692 ms 37 MB Python3
在本地试了一下,是Rust的优化出了问题。
代码
#![feature(test)]
use std::time::Instant;
use std::collections::HashSet;
//#[cfg(codegen = "opt-level=2")]试过这么写,但是不行
fn compute_similarities(docs: Vec<Vec<i32>>) -> Vec<String> {
let now = Instant::now();
let mut ans:Vec<String>=Vec::with_capacity(64);
let mut set:Vec<HashSet<_>>=Vec::with_capacity(docs.len());
set.push(docs[0].iter().collect());
for i in 1..docs.len(){
set.push(docs[i].iter().collect());
for j in 0..i{
let n=set[i].intersection(&set[j]).fold(0,|s,_x|s+1) as f64;
if n>0.5{
let t=set[i].union(&set[j]).fold(0,|s,_x|s+1) as f64;
ans.push(format!("{id1},{id2}: {similarity:.4}",id1=j,id2=i,similarity=n/t+1e-9));
}
}
}
println!("{}", now.elapsed().as_nanos() as f64/1e9);
ans
}
fn data()->Vec<Vec<i32>>{
vec![vec![...],...]//大概800KB的样子
}
extern crate test;
fn main(){
println!("Program Start!");
println!("{:?}",(compute_similarities(test::black_box(data()))).get(0..5));
}
不使用优化,编译超快,但需要20+秒才能执行完毕
打开rustc的优化,需要编译十多秒钟(因为data实在太大),然后~1秒出结果。
显而易见的,我们其实只需要对函数compute_similarities进行优化,然后就能得到~1s的执行速度
想问一下Rust里面有没有什么对单个函数打开优化指令的方法。
或者如何在debug模式下高效计算两个HashSet的交/并的元素个数
(如果并没有类似的办法,我只能用出疫情期间学到的新型检测方法,给人分组,然后检测组与组之间有没有公共元素,以此减少计算了……)
1
共 6 条评论, 1 页
评论区
写评论试着优化了一下内存占用
现在小于200秒的程序,已经可以做到内存占用11MB了
.drain(..)是个好函数
--
👇
lagudomeze:
用了类似倒排东西
执行用时:208 ms 内存消耗:20.1 MB
用了类似倒排东西
执行用时:208 ms 内存消耗:20.1 MB
感谢指导。
现在这个方法已经通过了
就是算得太慢
我准备用疫情检测算法重做一遍
不知道用时会不会更少
(给doc分trunk,每个trunk里面的全部元素做union,之后比较trunk与trunk之间是否存在公共元素,如果有就比较doc与trunk之间是否存在公共元素,最后筛选出存在相似元素的两doc)
(这么做理应更快)
(过几天再试试吧)
--
👇
gwy15: 1. 你的 set 是 Vec<HashSet<&i32>>,肯定慢,而且缓存不友好,用 into_iter()。 2. 不需要 fold,直接 count() 就行了。 3. 不需要重新算 union。充分利用集合的性质。
原来有个函数叫count
话说count用了什么黑科技吗?
我明明试图使用过fold的
但仍然慢了不少
(当然,没用into_iter是我以为所有权会出问题的锅)
(以及,忘记可以不算union了……)
(我的锅)
--
👇
gwy15: 1. 你的 set 是 Vec<HashSet<&i32>>,肯定慢,而且缓存不友好,用 into_iter()。 2. 不需要 fold,直接 count() 就行了。 3. 不需要重新算 union。充分利用集合的性质。
执行用时:1256 ms, 在所有 Rust 提交中击败了 100.00% 的用户 内存消耗:7.9 MB, 在所有 Rust 提交中击败了 100.00% 的用户
不能更6。
--
👇
gwy15: 1. 你的 set 是 Vec<HashSet<&i32>>,肯定慢,而且缓存不友好,用 into_iter()。 2. 不需要 fold,直接 count() 就行了。 3. 不需要重新算 union。充分利用集合的性质。
执行用时:1256 ms, 在所有 Rust 提交中击败了 100.00% 的用户 内存消耗:7.9 MB, 在所有 Rust 提交中击败了 100.00% 的用户
执行用时:1256 ms, 在所有 Rust 提交中击败了 100.00% 的用户 内存消耗:7.9 MB, 在所有 Rust 提交中击败了 100.00% 的用户