Skip to content

Commit

Permalink
Remove old L15 flipped note and make a new one
Browse files Browse the repository at this point in the history
  • Loading branch information
h365chen committed Feb 9, 2024
1 parent 043c351 commit cd1652d
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 116 deletions.
124 changes: 31 additions & 93 deletions lectures/flipped/L15.md
Original file line number Diff line number Diff line change
@@ -1,114 +1,52 @@
# Lecture 15: Crossbeam and Rayon
# Lecture 15 — Rate Limits

## Scoped thread in std::thread
## Roadmap

We can use the Rust standard library (since Rust 1.63.0).
We will talk about if something is not under our control, what we can do.

```rust
/*
[dependencies]
thread-id = "4.0.0"
*/

use std::thread;
## Intro

fn main() {
let v = vec![1, 2, 3];
println!("main thread has id {}", thread_id::get());
Have you seen a response code of 429? Where and how did you see it?

thread::scope(|scope| {
scope.spawn(|| {
println!("Here's a vector: {:?}", v);
println!("Now in thread with id {}", thread_id::get());
});
});
Talk about the ideas in the lecture note.

println!("Vector v is back: {:?}", v);
}
```
Can we think more? What about if it happens anyway?

## Scoped thread in Crossbeam
## ratelimit::Ratelimiter

We can also use the Crossbeam library to do it.
https://docs.rs/ratelimit/latest/ratelimit/

```rust
/*
[dependencies]
crossbeam = "0.8.0"
thread-id = "4.0.0"
ratelimit = "0.9.0"
*/

fn main() {
let v = vec![1, 2, 3];
println!("main thread has id {}", thread_id::get());

crossbeam::scope(|scope| {
scope.spawn(|_| {
println!("Here's a vector: {:?}", v);
println!("Now in thread with id {}", thread_id::get());
});
}).unwrap();

println!("Vector v is back: {:?}", v);
}
```

## Multi-producer and Multi-consumer

See `live-coding/L15/producer-consumer-channel/`

## Data Parallelism with Rayon

### Parallelizing loops

use Rust explorer to run following code.

```rust
/*
[dependencies]
rayon = "1.6.1"
*/

use rayon::prelude::*;

fn main() {
println!("without rayon");
(0..10).for_each(|x| println!("{:?}", x));
println!("with rayon");
(0..10).into_par_iter().for_each(|x| println!("{:?}", x));
}
```

```rust
/*
[dependencies]
rayon = "1.6.1"
*/

use std::time::Instant;
use rayon::prelude::*;
use ratelimit::Ratelimiter;
use std::time::Duration;

fn main() {
let arr: Vec<i128> = (1..10_000_000).collect();
println!("sum = {}", sum_of_squares(&arr));
}

fn sum_of_squares(input: &[i128]) -> i128 {
let start = Instant::now();
let res = input.iter()
// ^ change iter() to par_iter() and check the elapsed time
.map(|i| i * i)
.sum();
println!("{:?}", Instant::now() - start);
res
// constructs a ratelimiter that generates 1 tokens/s with no burst
let ratelimiter = Ratelimiter::builder(1, Duration::from_millis(1000))
.build()
.unwrap();

for _ in 0..10 {
// a simple sleep-wait
if let Err(sleep) = ratelimiter.try_wait() {
std::thread::sleep(dbg!(sleep));
continue;
}

// do some ratelimited action here
// e.g.,
println!("I have a token!");
}
}
```

Exercise: make use of `for_each_with` to combine data parallelization with message passing

One example is provided on <https://docs.rs/rayon/latest/rayon/iter/trait.ParallelIterator.html#method.for_each_with>
How many prints do you see?

# After-action report, huanyi, 06Feb23 (substituting for Patrick)
## TODO

A producer-consumer live coding to show how to use the Crossbeam channel seems
slightly over. Changing it to a lighter example would be better.
Use `Ratelimiter` in multiple threads.
23 changes: 0 additions & 23 deletions lectures/flipped/L15_for_each_with.md

This file was deleted.

0 comments on commit cd1652d

Please sign in to comment.