Boxed Fn requires lifetime 'static only when testing? - closures

Using rustc 1.10.0, I'm trying to write some code which passes around boxed closures--the eventual goal is to procedurally generate an animation of fractals. Right now I have some function signatures like this:
pub fn interpolate_rectilinear(width: u32, height: u32, mut min_x: f64, mut max_x: f64, mut min_y: f64, mut max_y: f64)
-> Box<Fn(u32, u32) -> Complex64 + Send + Sync + 'static> { ... }
pub fn interpolate_stretch(width: u32, height: u32, mut min_x: f64, mut max_x: f64, mut min_y: f64, mut max_y: f64)
-> Box<Fn(u32, u32) -> Complex64 + Send + Sync + 'static> { ... }
pub fn parallel_image<F>(width: u32, height: u32, function: &F, interpolate: &Box<Fn(u32, u32) -> Complex64 + Send + Sync>, threshold: f64)
-> ImageBuffer<image::Luma<u8>, Vec<u8>>
where F: Sync + Fn(Complex64) -> Complex64
{ ... }
pub fn sequential_image<F>(width: u32, height: u32, function: &F, interpolate: &Box<Fn(u32, u32) -> Complex64>, threshold: f64)
-> ImageBuffer<image::Luma<u8>, Vec<u8>>
where F: Fn(Complex64) -> Complex64
{ ... }
Running this code for one image at a time in a binary works without problems:
let interpolate = interpolate_rectilinear(width, height, -1.0, 1.0, -1.0, 1.0);
let image = parallel_image(width * 2, height * 2, &default_julia, &interpolate, 2.0);
However, I wanted to ensure my serial and parallel image-production were both producing the same results, so I wrote the following test function:
#[test]
fn test_serial_parallel_agree() {
let (width, height) = (200, 200);
let threshold = 2.0;
let interpolate = interpolate_stretch(width, height, -1.0, 1.0, -1.0, 1.0);
assert!(parallel_image(width, height, &default_julia, &interpolate, threshold)
.pixels()
.zip(sequential_image(width, height, &default_julia, &interpolate, threshold)
.pixels())
.all(|(p, s)| p == s));
}
This refuses to compile, and I just can't figure it out. The error it gives is as follows:
> cargo test
Compiling julia-set v0.3.0
src/lib.rs:231:66: 231:78 error: mismatched types [E0308]
src/lib.rs:231 .zip(sequential_image(width, height, &default_julia, &interpolate, threshold)
^~~~~~~~~~~~
src/lib.rs:229:9: 233:36 note: in this expansion of assert! (defined in <std macros>)
src/lib.rs:231:66: 231:78 help: run `rustc --explain E0308` to see a detailed explanation
src/lib.rs:231:66: 231:78 note: expected type `&Box<std::ops::Fn(u32, u32) -> num::Complex<f64> + 'static>`
src/lib.rs:231:66: 231:78 note: found type `&Box<std::ops::Fn(u32, u32) -> num::Complex<f64> + Send + Sync>`
error: aborting due to previous error
Build failed, waiting for other jobs to finish...
error: Could not compile `julia-set`.
I really don't know what's going on there. I don't know why I'm required to manually mark Send and Sync in the boxed return types of the interpolation functions, when the compiler typically derives those traits automatically. Still, I just kept adding in markers that the compiler suggested until things worked.
The real problem is that, while I think I have a pretty good guess why you can't just mark a boxed closure 'static, I don't know what's requiring that lifetime in this case or how to fix it.
I did guess that possibly the issue was that I was trying to reference the closure from two read-borrows at once, (which should be ok, but I was desperate); at any rate, wrapping interpolate in an Rc gives the exact same error, so that wasn't the problem.

The problem is actually here:
pub fn sequential_image<F>(
...,
interpolate: &Box<Fn(u32, u32) -> Complex64>,
...) -> ...
The interpolate doesn't expect a &Box<Fn(u32, u32) -> Complex64 + Send + Sync>, and Rust is pretty bad at handling variance through all of this complexity.
One solution is to do the cast where it's called:
sequential_image(width, height, &default_julia,
&(interpolate as Box<Fn(u32, u32) -> Complex64>),
threshold)
but this requires a value case of sequential_image and is pretty damn ugly.
A nicer way is to just fix the parameter of sequential_image to something both more general and something easier for the compiler to reason about: basic pointers.
pub fn sequential_image<F>(
...,
interpolate: &Fn(u32, u32) -> Complex64,
...) -> ...
Now you can call it with just
sequential_image(width, height, &default_julia,
&*interpolate,
threshold)
and the compiler can do all of the variance magic itself.

Related

How to prevent destruction of references to local variables in Rust?

I have two structures. First is Point with two i32 coordinates, second is a Line with references to two Points. Structures have new and random constructors.
Required usage is:
use sandbox::{Point, Line};
fn main() {
let line = Line::new(&Point::new(1, 2),
&Point::new(1, 2));
line.from; // error[E0716]: temporary value dropped while borrowed
Line::random(10, 10); // error[E0515]: cannot return value referencing local variable `a`
}
And structs:
use rand::Rng;
pub struct Point {
pub x: i32,
pub y: i32,
}
pub struct Line<'line> {
pub from: &'line Point,
pub to: &'line Point,
}
impl Point {
pub fn new(x: i32, y: i32) -> Point {
Point { x, y }
}
pub fn random(x_max: i32, y_max: i32) -> Point {
let x = rand::thread_rng().gen_range(0..=x_max);
let y = rand::thread_rng().gen_range(0..=y_max);
return Point::new(x, y);
}
}
impl<'line> Line<'line> {
pub fn new<'a>(from: &'a Point, to: &'a Point) -> Line<'a> {
Line { from, to }
}
pub fn random<'a>(img_width: i32, img_height: i32) -> Line<'a> {
let a = Point::random(img_width, img_height);
let b = Point::random(img_width, img_height);
Line::new(&a, &b)
// error[E0515]: cannot return value referencing local variable `a`
// returns a value referencing data owned by the current function
}
}
Two errors occur. The first is related to the fact that the Point::new passed to Line is destroyed after Line::new is executed, so further usage is impossible. It would be possible to take it out into separate variable, but this does not meet the requirements of the usage.
The second error is related to the fact that the generated Point::random needed to build Line::random is local, which means that after Line::random is executed, it also become inaccessible.
One possible solution is to use a heap(Box<T>), but I haven't been able to figure out how to avoid destruction after the function completes.
I think your usage of references is misplaced here.
If Line must have references, I'd use a reference counted smartpointer instead.
The main problem is that if you store references in Line, Line does not own the Points. That means, you have to keep them alive externally.
This is the reason why your random constructor fails:
pub fn random(x_max: i32, y_max: i32) -> Point {
let x = rand::thread_rng().gen_range(0..=x_max);
let y = rand::thread_rng().gen_range(0..=y_max);
return Point::new(x, y);
}
As Point::new does not take ownership of x and y, the variables x and y cease to exist at the end of the random function.
Solution
There are two ways to solve this:
Use values instead of references (e.g. make Point cloneable)
Use reference counting smart pointers
In your case, as Point is a very trivial type, I'd go with the first option:
use sandbox::{Line, Point};
fn main() {
let line = Line::new(Point::new(1, 2), Point::new(1, 2));
println!("{:?}", line);
let line2 = Line::random(10, 10);
println!("{:?}", line2);
}
use rand::Rng;
#[derive(Clone, Debug)]
pub struct Point {
pub x: i32,
pub y: i32,
}
#[derive(Clone, Debug)]
pub struct Line {
pub from: Point,
pub to: Point,
}
impl Point {
pub fn new(x: i32, y: i32) -> Point {
Point { x, y }
}
pub fn random(x_max: i32, y_max: i32) -> Point {
let x = rand::thread_rng().gen_range(0..=x_max);
let y = rand::thread_rng().gen_range(0..=y_max);
return Point::new(x, y);
}
}
impl Line {
pub fn new(from: Point, to: Point) -> Line {
Line { from, to }
}
pub fn random(img_width: i32, img_height: i32) -> Line {
let a = Point::random(img_width, img_height);
let b = Point::random(img_width, img_height);
Line::new(a, b)
}
}
Output:
Line { from: Point { x: 1, y: 2 }, to: Point { x: 1, y: 2 } }
Line { from: Point { x: 9, y: 1 }, to: Point { x: 9, y: 1 } }
Solution #2 (with reference counters)
This solution is just for reference.
As previously mentioned, it is way overkill for simple data structures, which should rather derive the Clone trait.
If you are in a multi-threaded environment, replace Rc<RefCell<Point>> with Arc<Mutex<Point>>.
use std::{cell::RefCell, rc::Rc};
use sandbox::{Line, Point};
fn main() {
let line = Line::new(
Rc::new(RefCell::new(Point::new(1, 2))),
Rc::new(RefCell::new(Point::new(1, 2))),
);
println!("{:?}", line);
let line2 = Line::random(10, 10);
println!("{:?}", line2);
}
use std::{cell::RefCell, rc::Rc};
use rand::Rng;
#[derive(Debug)]
pub struct Point {
pub x: i32,
pub y: i32,
}
#[derive(Debug)]
pub struct Line {
pub from: Rc<RefCell<Point>>,
pub to: Rc<RefCell<Point>>,
}
impl Point {
pub fn new(x: i32, y: i32) -> Point {
Point { x, y }
}
pub fn random(x_max: i32, y_max: i32) -> Point {
let x = rand::thread_rng().gen_range(0..=x_max);
let y = rand::thread_rng().gen_range(0..=y_max);
return Point::new(x, y);
}
}
impl Line {
pub fn new(from: Rc<RefCell<Point>>, to: Rc<RefCell<Point>>) -> Line {
Line { from, to }
}
pub fn random(img_width: i32, img_height: i32) -> Line {
let a = Rc::new(RefCell::new(Point::random(img_width, img_height)));
let b = Rc::new(RefCell::new(Point::random(img_width, img_height)));
Line::new(a, b)
}
}
Output:
Line { from: RefCell { value: Point { x: 1, y: 2 } }, to: RefCell { value: Point { x: 1, y: 2 } } }
Line { from: RefCell { value: Point { x: 9, y: 1 } }, to: RefCell { value: Point { x: 4, y: 8 } } }
Well, this looks like you need for the points to be sometimes referenced and sometimes owned. Rust provides Cow which comes in handy for this cases:
use rand::Rng;
use std::borrow::Cow;
#[derive(Clone)]
pub struct Point {
pub x: i32,
pub y: i32,
}
pub struct Line<'line> {
pub from: Cow<'line, Point>,
pub to: Cow<'line, Point>,
}
impl Point {
pub fn new(x: i32, y: i32) -> Point {
Point { x, y }
}
pub fn random(x_max: i32, y_max: i32) -> Point {
let x = rand::thread_rng().gen_range(0..=x_max);
let y = rand::thread_rng().gen_range(0..=y_max);
return Point::new(x, y);
}
}
impl<'line> Line<'line> {
pub fn new(from: &'line Point, to: &'line Point) -> Line<'line> {
Line { from: Cow::Borrowed(from), to: Cow::Borrowed(to)}
}
pub fn random(img_width: i32, img_height: i32) -> Line<'line> {
let a = Point::random(img_width, img_height);
let b = Point::random(img_width, img_height);
Self {
from: Cow::Owned(a),
to: Cow::Owned(b)
}
}
}
Playground
One possible solution is to use a heap(Box), but I haven't been able to figure out how to avoid destruction after the function completes.
It does not, Box are still constrain to rust borrowing rules, and unless you leak it (making the references &'static) will complain about the temporary values droped after the function scope.
About the main, you just need to bind the Points to a variable, so they will live for the scope of main:
fn main() {
let (from, to) = (Point::new(1, 2), Point::new(1, 2));
let line = Line::new(&from, &to);
line.from;
Line::random(10, 10);
}
Playground

Binary Tree Maximum Path in Erlang

The Binary Tree Maximum Path problem can be solved in using DFS.
Here is a possible solution using this approach in Python.
def maxPathSum(self, root):
def maxSum(root):
if not root:
return 0
l_sum = maxSum(root.left)
r_sum = maxSum(root.right)
l = max(0, l_sum)
r = max(0, r_sum)
res[0] = max(res[0], root.val + l + r)
return root.val + max(l, r)
res = [-float('inf')]
maxSum(root)
return res[0]
I am trying to use the same approach in Erlang. Assuming a node would look like:
{Value, Left, Right}
I came up with:
max_sum(undefined) -> 0;
max_sum({Value, Left, Right}) ->
LeftSum = max(0, max_sum(Left)),
RightSum = max(0, max_sum(Right)),
%% Where to store the max? Should I use the process dictionary?
%% Should I send a message?
Value + max(LeftSum, RightSum).
max_path_sum(Root) ->
%% Bonus question: how to represent -infinity in Erlang?
max_sum(Root)
There are no global variables in Erlang. How can I keep track of the maximum during DFS? The only things that come to my mind are to use the process dictionary or an ETS table or maybe have a different process that can keep the maximum, but maybe I am overthinking and there is a more simple and idiomatic way?
The most "erlangish" way would be to pass the global maximum as a second parameter, and return it along with the local maximum:
max_sum(undefined, GlobalMax) -> {0, GlobalMax};
max_sum({Value, Left, Right}, GlobalMax0) ->
{LeftSum, GlobalMax1} = max(0, max_sum(Left, GlobalMax0)),
{RightSum, GlobalMax2} = max(0, max_sum(Right, GlobalMax1)),
NewGlobalMax =
case GlobalMax2 of
undefined ->
Value + LeftSum + RightSum
_ ->
max(GlobalMax2, Value + LeftSum + RightSum)
end,
{Value + max(LeftSum, RightSum), NewGlobalMax}.
max_path_sum(Root) ->
{_, GlobalMax} = max_sum(Root, undefined),
GlobalMax.
Erlang doesn't support infinity values in floats, so I used the atom undefined to represent a smallest value instead.

How can I `flatmap` streams in Rust?

I have a rusoto_core::ByteStream which implements futures' Stream trait:
let chunks = vec![b"1234".to_vec(), b"5678".to_vec()];
let stream = ByteStream::new(stream::iter_ok(chunks));
I'd like to pass it to actix_web's HttpResponseBuilder::streaming method.
use actix_web::dev::HttpResponseBuilder; // 0.7.18
use rusoto_core::ByteStream; // 0.36.0
fn example(stream: ByteStream, builder: HttpResponseBuilder) {
builder.streaming(stream);
}
When I try to do it I receive the following error:
error[E0271]: type mismatch resolving `<rusoto_core::stream::ByteStream as futures::stream::Stream>::Item == bytes::bytes::Bytes`
--> src/main.rs:5:13
|
5 | builder.streaming(stream);
| ^^^^^^^^^ expected struct `std::vec::Vec`, found struct `bytes::bytes::Bytes`
|
= note: expected type `std::vec::Vec<u8>`
found type `bytes::bytes::Bytes`
I believe the reason is that streaming() expects a S: Stream<Item = Bytes, Error> (i.e., Item = Bytes) but my ByteStream has Item = Vec<u8>. How can I fix it?
I think the solution is to flatmap my ByteStream somehow but I couldn't find such a method for streams.
Here's an example how streaming() can be used:
let text = "123";
let (tx, rx_body) = mpsc::unbounded();
let _ = tx.unbounded_send(Bytes::from(text.as_bytes()));
HttpResponse::Ok()
.streaming(rx_body.map_err(|e| error::ErrorBadRequest("bad request")))
How can I flatmap streams in Rust?
A flat map converts an iterator of iterators into a single iterator (or stream instead of iterator).
Futures 0.3
Futures 0.3 doesn't have a direct flat map, but it does have StreamExt::flatten, which can be used after a StreamExt::map.
use futures::{stream, Stream, StreamExt}; // 0.3.1
fn into_many(i: i32) -> impl Stream<Item = i32> {
stream::iter(0..i)
}
fn nested() -> impl Stream<Item = i32> {
let stream_of_number = into_many(5);
let stream_of_stream_of_number = stream_of_number.map(into_many);
let flat_stream_of_number = stream_of_stream_of_number.flatten();
// Returns: 0, 0, 1, 0, 1, 2, 0, 1, 2, 3
flat_stream_of_number
}
Futures 0.1
Futures 0.1 doesn't have a direct flat map, but it does have Stream::flatten, which can be used after a Stream::map.
use futures::{stream, Stream}; // 0.1.25
fn into_many(i: i32) -> impl Stream<Item = i32, Error = ()> {
stream::iter_ok(0..i)
}
fn nested() -> impl Stream<Item = i32, Error = ()> {
let stream_of_number = into_many(5);
let stream_of_stream_of_number = stream_of_number.map(into_many);
let flat_stream_of_number = stream_of_stream_of_number.flatten();
// Returns: 0, 0, 1, 0, 1, 2, 0, 1, 2, 3
flat_stream_of_number
}
However, this doesn't solve your problem.
streaming() expects a S: Stream<Item = Bytes, Error> (i.e., Item = Bytes) but my ByteStream has Item = Vec<u8>
Yes, this is the problem. Use Bytes::from via Stream::map to convert your stream Item from one type to another:
use bytes::Bytes; // 0.4.11
use futures::Stream; // 0.1.25
fn example(stream: ByteStream, mut builder: HttpResponseBuilder) {
builder.streaming(stream.map(Bytes::from));
}

Swit map: error: cannot invoke 'map' with an argument list of type '((_) -> _)'

I can't understand why this one works:
var arr = [4,5,6,7]
arr.map() {
x in
return x + 2
}
while this one not
arr.map() {
x in
var y = x + 2
return y
}
with error
Playground execution failed: MyPlayground.playground:13:5: error:
cannot invoke 'map' with an argument list of type '((_) -> _)'
arr.map() {
The problem here is there error message. In general, when you see something like cannot invoke .. with ... it means that the compiler's type inference has just not worked.
In this case, you've run up against one of the limitations of inference within closures. Swift can infer the type of single-statement closures only, not multiple-statement ones. In your first example:
arr.map() {
x in
return x + 2
}
There's actually only one statement: return x + 2. However, in the second:
arr.map() {
x in
var y = x + 2
return y
}
There's an assignment statement (var y = x + 2), and then the return. So the error is a little misleading: it doesn't mean you "can't invoke map() with this type of argument", what it means to say is "I can't figure out what type x or y is".
By the way, in single-statement closures, there are two other things that can be inferred. The return statement:
arr.map() {
x in
x + 2
}
And the variable name itself:
arr.map() { $0 + 2 }
It all produces the same compiled code, though. So it's really a matter of taste which one you choose. (For instance, while I think the inferred return looks clean and easier to read, I don't like the $0, so I generally always put x in or something, even for very short closures. It's up to you, though, obviously.)
One final thing: since this is all really just syntax stuff, it's worth noting that the () isn't needed either:
arr.map { x in x + 2 }
As #MartinR pointed out, the compiler can infer some types from outer context as well:
let b: [Int] = arr.map { x in
var y = x + 2
return y
}
Which is worth bearing in mind. (it seems that the "one-statement" rule only applies when there's no other type info available)
Swift can't infer type every time. Even though it should see that y = x + 2 means y is an Int too. My guess is that Swift parses the closure in a certain order that makes it not aware of the return type ahead of time in your case.
This works:
arr.map() {
x -> Int in
var y = x + 2
return y
}

using Array.Parallel.map for decreasing running time

Hello everyone
I have converted a project in C# to F# that paints the Mandelbrot set.
Unfortunately does it take around one minute to render a full screen so I am try to find some ways to speed it up.
It is one call that take almost all of the time:
Array.map (fun x -> this.colorArray.[CalcZ x]) xyArray
xyArray (double * double) [] => (array of tuple of double)
colorArray is an array of int32 length = 255
CalcZ is defined as:
let CalcZ (coord:double * double) =
let maxIterations = 255
let rec CalcZHelper (xCoord:double) (yCoord:double) // line break inserted
(x:double) (y:double) iters =
let newx = x * x + xCoord - y * y
let newy = 2.0 * x * y + yCoord
match newx, newy, iters with
| _ when Math.Abs newx > 2.0 -> iters
| _ when Math.Abs newy > 2.0 -> iters
| _ when iters = maxIterations -> iters
| _ -> CalcZHelper xCoord yCoord newx newy (iters + 1)
CalcZHelper (fst coord) (snd coord) (fst coord) (snd coord) 0
As I only use around half of the processor capacity is an idea to use more threads and specifically Array.Parallel.map, translates to system.threading.tasks.parallel
Now my question
A naive solution, would be:
Array.Parallel.map (fun x -> this.colorArray.[CalcZ x]) xyArray
but that took twice the time, how can I rewrite this to take less time, or can I take some other way to utilize the processor better?
Thanks in advance
Gorgen
---edit---
the function that is calling CalcZ looks like this:
let GetMatrix =
let halfX = double bitmap.PixelWidth * scale / 2.0
let halfY = double bitmap.PixelHeight * scale / 2.0
let rect:Mandelbrot.Rectangle =
{xMax = centerX + halfX; xMin = centerX - halfX;
yMax = centerY + halfY; yMin = centerY - halfY;}
let size:Mandelbrot.Size =
{x = bitmap.PixelWidth; y = bitmap.PixelHeight}
let xyList = GenerateXYTuple rect size
let xyArray = Array.ofList xyList
Array.map (fun x -> this.colorArray.[CalcZ x]) xyArray
let region:Int32Rect = new Int32Rect(0,0,bitmap.PixelWidth,bitmap.PixelHeight)
bitmap.WritePixels(region, GetMatrix, bitmap.PixelWidth * 4, region.X, region.Y);
GenerateXYTuple:
let GenerateXYTuple (rect:Rectangle) (pixels:Size) =
let xStep = (rect.xMax - rect.xMin)/double pixels.x
let yStep = (rect.yMax - rect.yMin)/double pixels.y
[for column in 0..pixels.y - 1 do
for row in 0..pixels.x - 1 do
yield (rect.xMin + xStep * double row,
rect.yMax - yStep * double column)]
---edit---
Following a suggestion from kvb (thanks a lot!) in a comment to my question, I built the program in Release mode. Building in the Relase mode generally speeded up things.
Just building in Release took me from 50s to around 30s, moving in all transforms on the array so it all happens in one pass made it around 10 seconds faster. At last using the Array.Parallel.init brought me to just over 11 seconds.
What I learnt from this is.... Use the release mode when timing things and using parallel constructs...
One more time, thanks for the help I have recieved.
--edit--
by using SSE assember from a native dll I have been able to slash the time from around 12 seconds to 1.2 seconds for a full screen of the most computational intensive points. Unfortunately I don't have a graphics processor...
Gorgen
Per the comment on the original post, here is the code I wrote to test the function. The fast version only takes a few seconds on my average workstation. It is fully sequential, and has no parallel code.
It's moderately long, so I posted it on another site: http://pastebin.com/Rjj8EzCA
I'm suspecting that the slowdown you are seeing is in the rendering code.
I don't think that the Array.Parallel.map function (which uses Parallel.For from .NET 4.0 under the cover) should have trouble parallelizing the operation if it runs a simple function ~1 million times. However, I encountered some weird performance behavior in a similar case when F# didn't optimize the call to the lambda function (in some way).
I'd try taking a copy of the Parallel.map function from the F# sources and adding inline. Try adding the following map function to your code and use it instead of the one from F# libraries:
let inline map (f: 'T -> 'U) (array : 'T[]) : 'U[]=
let inputLength = array.Length
let result = Array.zeroCreate inputLength
Parallel.For(0, inputLength, fun i ->
result.[i] <- f array.[i]) |> ignore
result
As an aside, it looks like you're generating an array of coordinates and then mapping it to an array of results. You don't need to create the coordinate array if you use the init function instead of map: Array.Parallel.init 1000 (fun y -> Array.init 1000 (fun x -> this.colorArray.[CalcZ (x, y)]))
EDIT: The following may be inaccurate:
Your problem could be that you call a tiny function a million times, causing the scheduling overhead to overwhelm that actual work you're doing. You should partition the array into much larger chunks so that each individual task takes a millisecond or so. You can use an array of arrays so that you would call Array.Parallel.map on the outer arrays and Array.map on the inner arrays. That way each parallel operation will operate on a whole row of pixels instead of just a single pixel.

Resources