[英]Rust function as slow as its python counterpart
我正在嘗試使用 Rust 加速 Python 程序,這是一種我完全是初學者的語言。 我寫了一個 function 來計算每個可能的長度為n
的字符串在較大字符串中的出現次數。 例如,如果主字符串是"AAAAT"
並且n=3
,則結果將是 hashmap {"AAA":2,"AAT":1}
。 我使用 pyo3 從 Python 調用 Rust function。 Rust function的代碼是:
fn count_nmers(seq: &str, n: usize) -> PyResult<HashMap<&str,u64>> {
let mut current_pos: usize = 0;
let mut counts: HashMap<&str,u64> = HashMap::new();
while current_pos+n <= seq.len() {
//print!("{}\n", &seq[current_pos..current_pos+n]);
match counts.get(&seq[current_pos..current_pos+n]) {
Some(repeats) => counts.insert(&seq[current_pos..current_pos+n],repeats+1),
None => counts.insert(&seq[current_pos..current_pos+n],1)
};
current_pos +=1;
}
//print!("{:?}",counts)
Ok(counts)
}
當我對n
( n<10
) 使用較小的值時,Rust 比 Python 快大約一個數量級,但是隨着 n 的長度增加,間隙趨於零,兩個函數具有相同的速度n=200
。 (見圖)計算不同 n-mer 長度的時間(Python 黑色,rust 紅色)
我一定是對字符串做錯了,但我找不到錯誤。
python 代碼為:
def nmer_freq_table(sequence,nmer_length=6):
nmer_dict=dict()
for nmer in seq_win(sequence,window_size=nmer_length):
if str(nmer) in nmer_dict.keys():
nmer_dict[str(nmer)]=nmer_dict[str(nmer)]+1
else:
nmer_dict[str(nmer)]=1
return nmer_dict
def seq_win(seq,window_size=2):
length=len(seq)
i=0
while i+window_size <= length:
yield seq[i:i+window_size]
i+=1
您正在計算 hash function 多次,這對於較大的 n 值可能很重要。 嘗試使用條目function 而不是手動插入:
while current_pos+n <= seq.len() {
let en = counts.entry(&seq[current_pos..current_pos+n]).or_default();
*en += 1;
current_pos +=1;
}
接下來,確保您正在運行--release
編譯代碼,例如cargo run --release
。
這里還討論了另一件事,Rust 可能會為您的案例使用非最佳 hash function 您可以更改。
最后,在大數據上,大部分時間都花在 HashMap/dict 內部,它們不是 python,而是編譯代碼。 所以不要指望它能夠很好地擴展。
可能是因為隨着 n 變大,循環中的迭代次數會變小嗎?
更少的循環迭代會降低使用 Rust 所獲得的性能增益。 我確定從 Python 轉換/編組到 Rust 的每個 function 調用性能成本很小。 這將解釋純 Python 和 Python/Rust 的性能最終如何變得相同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.