Home > Mobile >  CPU time sleep instead of wall-clock time sleep
CPU time sleep instead of wall-clock time sleep

Time:02-03

Currently, I have the following Rust toy program:

use rayon::prelude::*;
use std::{env, thread, time};

/// Sleeps 1 seconds n times parallely using rayon
fn rayon_sleep(n: usize) {
    let millis = vec![0; n];
    millis
        .par_iter()
        .for_each(|_| thread::sleep(time::Duration::from_millis(1000)));
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let n = args[1].parse::<usize>().unwrap();

    let now = time::Instant::now();
    rayon_sleep(n);
    println!("rayon: {:?}", now.elapsed());
}

Basically, my program accepts one input argument n. Then, I sleep for 1 second n times. The program executes the sleep tasks in parallel using rayon.

However, this is not exactly what I want. As far as I know, thread::sleep sleeps according to wall-clock time. However, I would like to keep a virtual CPU busy for 1 second in CPU time.

Is there any way to do this?

EDIT

I would like to make this point clear: I don't mind if the OS preempts the tasks. However, if this happens, then I don't want to consider the time the task spends in the ready/waiting queue.

EDIT

This is a simple, illustrative example of what I need to do. In reality, I have to develop a benchmark for a crate that allows defining and simulating models using the DEVS formalism. The benchmark aims to compare DEVS-compliant libraries with each other, and it explicitly says that the models must spend a fixed, known amount of CPU time. That is why I need to make sure of that. Thus, I cannot use a simple busy loop nor simply sleep.

CodePudding user response:

I followed Sven Marnach's suggestions and implemented the following function:

use cpu_time::ThreadTime;
use rayon::prelude::*;
use std::{env, thread, time};
/// Sleeps 1 seconds n times parallely using rayon
fn rayon_sleep(n: usize) {
    let millis = vec![0; n];
    millis.par_iter().for_each(|_| {
        let duration = time::Duration::from_millis(1000);
        let mut x: u32 = 0;
        let now = ThreadTime::now(); // get current thread time
        while now.elapsed() < duration { // active sleep
            std::hint::black_box(&mut x); // to avoid compiler optimizations
            x = x.wrapping_add(1);
        }
    });
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let n = args[1].parse::<usize>().unwrap();

    let now = time::Instant::now();
    rayon_sleep(n);
    println!("rayon: {:?}", now.elapsed());
}

If I set n to 8, it takes 2 seconds more or less. I'd expect a better performance (1 second, as I have 8 vCPUs), but I guess that the overhead corresponds to the OS scheduling policy.

  • Related