#better way for doing this

46 messages ยท Page 1 of 1 (latest)

pearl compass
subtle notch
#

any help?

pearl compass
#

I haven't had too much chance to look at it yet, but at first glance the locate function could be re-written as:

pub fn locate(board: &[&[u8]], target_ch: u8) -> Option<(usize, usize)> {
    CACHE.with(|cache| {
        *cache.borrow_mut().entry(target_ch).or_insert_with(|| {
            board.iter().enumerate().find_map(|(i, row)| {
                row.iter().enumerate().find_map(|(j, elem)| {
                    if *elem == target_ch {
                        Some((i, j))
                    } else {
                        None
                    }
                })
            })
        })
    })
}

Which probably isn't much of a performance gain here (except being able to insert in place with the entry API) - but will allow for easy parallelisation using Rayon if you do desire by changing iter to par_iter, and find_map to find_map_any:

pub fn locate(board: &[&[u8]], target_ch: u8) -> Option<(usize, usize)> {
    CACHE.with(|cache| {
        *cache.borrow_mut().entry(target_ch).or_insert_with(|| {
            board.par_iter().enumerate().find_map_any(|(i, row)| {
                row.par_iter().enumerate().find_map_any(|(j, elem)| {
                    if *elem == target_ch {
                        Some((i, j))
                    } else {
                        None
                    }
                })
            })
        })
    })
}

Although usually parallelising that is probably only really worth it on large grid sizes

subtle notch
pearl compass
#

Yeah sure ๐Ÿ™‚

  1. cache.borrow_mut() gets the &mut to the HashMap as before
  2. HashMap::entry is a function that takes a key and returns an "Entry" type which might have something in it, or might not (if it doesn't exist in the HashMap)
  3. Entry::or_insert_with takes a function to call that produces an item to be placed into the HashMap under the key in the case that the key didn't exist in the map (won't be called if it was already)
  4. board.par_iter() produces a parallel iterator over the collection - Rayon provides many of the same iterator adapters as std::Iterator except that when they're run, they can run in parallel - Rayon handles that behind the scenes for you
  5. enumerate() exists in this case because the par_iter function of the collection produces an IndexedParallelIterator which supports random access and more adapters
  6. find_map_any is like your regular find_map except that Rayon can run it in parallel - so it can check multiple rows at the same time on different threads, and it'll stop whenever one of the invocations returns a Some
  7. We can just do the same for iterating the elements in a given row in parallel with a nested par_iter/enumerate/find_map_any
subtle notch
pearl compass
#

if you don't use par_iter (and just use regular iter) then none of that is parallel - it'll be using the std::Iterator API which is single threaded - using par_iter unlocks all the parallelisation that Rayon provides

subtle notch
#

and for this part

#

can u also suggest a better way of doing it

subtle notch
pearl compass
#

You'd just benchmark the parent function - whatever is visible, you wouldn't be able to benchmark the nbrs in isolation since it's not accessbile to call in your Criterion benchmarks

A quick-and-dirty method would be just to time portions of the code yourself like this

#

?play

use std::time::Instant;

fn main() {
    let start_time = Instant::now();
    // do some stuff
    for _ in 0..10 {
        println!("Doing Stuff...");
    }
    let duration = start_time.elapsed();
    println!("Took {} seconds", duration.as_secs_f32());
}
severe fieldBOT
#
Doing Stuff...
Doing Stuff...
Doing Stuff...
Doing Stuff...
Doing Stuff...
Doing Stuff...
Doing Stuff...
Doing Stuff...
Doing Stuff...
Doing Stuff...
Took 0.000022211 seconds```
subtle notch
pearl compass
#

You'll have to change the outer function to be able to time the inner function - if you want to benchmark without changing any function then you can only benchmark the outer function because that's all that's publicly visible

pearl compass
#

Yeah parallelizing isn't always a gain especially for small workloads, the benefits increase as the sizes get larger generally

subtle notch
subtle notch
#

@pearl compass sorry to bother but can i get some help with this one pls

left nexus
#

parallel != faster

subtle notch
left nexus
#

sometimes the answer to having faster code is to not make it parallel

subtle notch
#

or smthing

left nexus
#

have you benchmarked both code correctly

#

preferably using criterion

subtle notch
#

cargo criterion?

left nexus
#

you dont add that to the terminal. have you read the docs for criterion?

subtle notch
#

when i import it wont work

#

so have to add dependency

left nexus
#

have you read the criterion book

subtle notch
#

no

subtle notch
#

since ive never used that before

left nexus
#

how will you measure performance if you dont benchmark?

subtle notch
#

warning: sol (bin "sol" test) generated 2 warnings
Finished test [unoptimized + debuginfo] target(s) in 0.03s
Running unittests src/main.rs (target/debug/deps/sol-e7cd669814d3b4d7)

Process finished with exit code 0

#

do u mean reading it from here?

left nexus
#

...have you read the getting start page

#

specifically the part about making a benches folder

#

like... step 1 and 2?