Skip to content

Add examples of efficient numerics #1

Open
@dcnorris

Description

@dcnorris

Thanks for this wonderful project. In under 24h, never having written any Rust code before, I have achieved a 2.5x speedup of an objective function that is invoked by base::integrate().

FYI, here is the original function from package dfcrm ...

crmh = function(a,x,y,w,s) {  ## posterior
  v = exp(-a^2/2/s^2) 
  for (i in 1:length(x)) {
	v = v * ((x[i]^exp(a))^y[i])*(((1-w[i]*x[i]^exp(a))^(1-y[i])))
  }
  return(v)
}

and here is my initial direct translation into Rust:

/// A Rust implementation of the dfcrm::crmh posterior,
/// which I hope will prove faster to integrate().
/// @export
#[extendr]
fn rcrmh(a: &[f64],
	 x: &[f64],
	 y: &[f64],
	 w: &[f64],
	 s: &[f64]) -> Robj {
    // TODO: Assert that x, y and w all have same length?
    let v = a.iter().map(|a| {
	let mut v_ = (-0.5*a/s[0]).exp();
	for i in 0 .. y.len() {
	    let p_i = x[i].powf(a.exp()); // 'power model' CRM
	    v_ = v_ * if y[i] == 0.0 { 1.0 - w[i] * p_i } else { p_i };
	}
	v_
    });
    v.collect_robj()
}

Speaking from the POV of the Rust novice, the sort of example I would find most helpful would show a cascade of performance improvements that start with 'elegant' or 'default' wrappings and proceed step-wise through a series of tuning steps that exploit language features like borrowing, etc. Alluding to equivalent constructs in C would help orient users who are familiar with performance-tuning tricks in that language.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions