10
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rustのfilter()について

Last updated at Posted at 2019-12-03

TL;DR

本稿で述べるような処理においてはループの中でifを使用した方が速いという話.

本題

filter()を用いた以下のコードは1以上100未満の偶数を出力する.

for i in (1..100).filter(|&x| x % 2 == 0) {
    println!("{}", i);
}

本稿では0 ... 10000という等差数列vecの要素のうち,偶数である要素を足し合わせる処理したい.

const MAX: u32 = 10000;

fn main() {
    let vec: Vec<u32> = (0..MAX).collect();
}

そこで,filter()を用いた/用いない場合についてその速度を比較する.

filter()を使わずにifを使用した場合

let mut result = 0;
for i in &vec {
  if i % 2 == 0{
    result += i;
  }
}

filter()を用いる

イテレータとしてループで使用した場合

let mut result = 0;
for i in vec.iter().filter(|&x| x % 2 == 0) {
  result += i;
}

ループ前に使用した場合

let mut result = 0;
let vec: Vec<u32> = vec.iter().cloned().filter(|&x| x % 2 == 0).collect();
for i in &vec {
  result += i;
}

数値解析

10000回繰り返すのにかかる時間を計測した.

ソースコード

use std::time::{Instant};

const TRIAL: u32 = 10000;
const MAX: u32 = 10000;

fn main() {
    let vec: Vec<u32> = (0..MAX).collect();

    // (a)
    let mut result = 0;
    let start = Instant::now();
    for _ in 0..TRIAL{
        for i in &vec {
            if i % 2 == 0{
                result += i;
            }
        }
    }
    println!("\n(a) Result: {}, elapsed:{:?}", result, start.elapsed());

    // (b)
    result = 0;
    let start = Instant::now();
    for _ in 0..TRIAL{
        for i in vec.iter().filter(|&x| x % 2 == 0) {
            result += i;
        }
    }
    println!("\n(b) Result: {}, elapsed:{:?}", result, start.elapsed());

    // (c)
    result = 0;
    let start = Instant::now();
    for _ in 0..TRIAL{
        let vec: Vec<u32> = vec.iter().cloned().filter(|&x| x % 2 == 0).collect();
        for i in &vec {
            result += i;
        }
    }
    println!("\n(c) Result: {}, elapsed:{:?}", result, start.elapsed());
}

結果

$ cargo run --release
   Compiling filter_if v0.1.0 (/Users/scstechr/Works/projects/filter_if)
    Finished release [optimized] target(s) in 1.88s
     Running `target/release/filter_if`

(a) Result: 841896832, elapsed:124.80438ms

(b) Result: 841896832, elapsed:130.393264ms

(c) Result: 841896832, elapsed:157.500689ms

結論

今回の場合においてはループの中でif分岐した方が速い.
(というよりfilter()は遅い?)

todo

cargoにはベンチマーク機能があるらしいので,そちらを記事に追加して更新する.

10
4
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?