DeviceReduceModule throws an OverflowException - aleagpu

let absoluteSumModule = (new DeviceReduceModule<float32>(GPUModuleTarget.Worker(worker), fun a b -> a+b)).Create(128000)
I've tried various maxNumItems settings but no mater what it throws the same exception. Unlike last time I have no idea what the error could even possibly be so I've included the whole dump here.
Failure
(Description "$f0(sm52,64)",
Exception
System.OverflowException: Value was either too large or too small for a UInt16.
at Alea.CUDA.UsageByInstanceUtil.f#1-46(Object clrModuleInstance, IRModuleBuildingContext ctx, FieldInfo fieldInfo)
at Alea.CUDA.UsageByInstanceUtil.cudafy#104.Invoke(IRModuleBuildingContext ctx)
at <StartupCode$Alea-CUDA>.$Compilation.compile#490[T](Template`1 template, FSharpOption`1 bitcodeCache, IRModuleBuildingContext ctx, Unit unitVar0)
at <StartupCode$Alea-CUDA>.$Compilation.compile#515-7[T](Template`1 template, FSharpOption`1 bitcodeCache, IRModuleBuildingContext ctx, Unit unitVar0),
System.OverflowException: Value was either too large or too small for a UInt16.
at Alea.CUDA.UsageByInstanceUtil.f#1-46(Object clrModuleInstance, IRModuleBuildingContext ctx, FieldInfo fieldInfo)
at Alea.CUDA.UsageByInstanceUtil.cudafy#104.Invoke(IRModuleBuildingContext ctx)
at <StartupCode$Alea-CUDA>.$Compilation.compile#490[T](Template`1 template, FSharpOption`1 bitcodeCache, IRModuleBuildingContext ctx, Unit unitVar0)
at <StartupCode$Alea-CUDA>.$Compilation.compile#515-7[T](Template`1 template, FSharpOption`1 bitcodeCache, IRModuleBuildingContext ctx, Unit unitVar0))
System.Exception: Compiling failed.
at Alea.CUDA.Worker.LoadProgram[T](Template`1 template, CompileOptions options)
at <StartupCode$Alea-CUDA>.$UsageByInstance.-ctor#271-215.Invoke(Unit _arg1)
at System.Lazy`1.CreateValue()
at System.Lazy`1.LazyInitValue()
at <StartupCode$Alea-CUDA>.$UsageByInstance.-ctor#77-214.Invoke(Unit _arg1)
at System.Lazy`1.CreateValue()
at System.Lazy`1.LazyInitValue()
at Alea.CUDA.Unbound.DeviceReduceModule`1.Create(Int32 maxNumItems)
at <StartupCode$FSI_0002>.$FSI_0002.main#() in C:\Users\Marko\Documents\Visual Studio 2015\Projects\Load MNIST\Load MNIST\utils.fsx:line 28
Stopped due to error

Well, I checked that, looks like it is a bug. Will have to check this. It works if you code it in normal F# file, but doesn't work in F# interactive.
In the mean time, in F#, we encourge you to use quotations for the operator, so you can try this:
> let worker = Worker.Default;;
val worker : Worker = [0|5.2|GeForce GTX 970|7]
> let m = new DeviceReduceModule<float32>(GPUModuleTarget.Worker(worker), <# (+) #>);;
Binding session to 'C:\Users\Xiang\Documents\Inbox\Library3\packages\Alea.CUDA.IL.2.1.2.3274\lib\net40\Alea.CUDA.IL.dll'...
val m : DeviceReduceModule<float32>
> m.GPUForceLoad();;
Binding session to 'C:\Users\Xiang\Documents\Inbox\Library3\packages\Alea.CUDA.2.1.2.3274\lib\net40\Alea.CUDA.dll'...
val it : unit = ()
> let x = m.Create(128000);;
val x : DeviceReduce<float32>
>
So, instead of using fun a b -> a + b you can try <# fun a b -> a + b #>, or simply <# (+) #>.

Related

How to construct a loop in ATS over a given string?

For instance, how can I write code in ATS that traverses a given string as is done by the following C code:
while ((c = *str++) != 0) do_something(c);
Well, there is always a combinator-based solution:
(str).foreach()(lam(c) => do_something(c))
The following solution is easy, accessible and doesn't require any unsafe features (but it does use one advanced feature: indexed string type).
fun
loop {n:int}(p0: string(n)): void =
if string_isnot_empty (p0) then let
val c = (g0ofg1)(string_head(p0))
val p0 = string_tail(p0)
in
do_something(c); loop(p0)
end
Full code: https://glot.io/snippets/ejpwxk2xzx
The following solution makes use of UNSAFE but it should be really easy to access:
staload
UNSAFE =
"prelude/SATS/unsafe.sats"
fun
loop(p0: ptr): void = let
val c = $UNSAFE.ptr_get<char>p0)
in
if isneqz(c) then (do_something(c); loop(ptr_succ<char>(p0)) else ()
end
val () = loop(string2ptr(str))

Why don't I get output on OSX with this F# code but I do on Windows

I'm trying to execute the following F# script code on my macbook pro using FSI in visual studio code and the ionide plugin.
#r "packages/Newtonsoft.Json.9.0.1/lib/net40/Newtonsoft.Json.dll"
#r "System.Net.Http"
open System
open System.Net.Http
open Newtonsoft.Json
let client = new HttpClient()
type AlbumInfo = { userId:int; id:int; title:string }
let url = "https://jsonplaceholder.typicode.com/albums/1"
async {
let! res = Async.AwaitTask <| client.GetAsync(url)
let! content = Async.AwaitTask <| res.Content.ReadAsStringAsync()
let x = JsonConvert.DeserializeObject<AlbumInfo>(content)
printfn "%s" x.title
} |> Async.Start
printfn "Please wait..."
But I don't get any output apart from Please wait.... However, when I put https://jsonplaceholder.typicode.com/albums/1 into the browser I get the expected Json response. So I know there's no problem reaching the API.
Also, when I run the same code in Visual Studio 2013 on my Windows 10 PC. The code produces the expected result. i.e. Please wait... and the title of the album.
Any ideas why it doesn't work correctly on my macbook?
In Visual Studio there is a process hosting FSI and keeping the thread (pool) for the async computation alive. In FSI on the command line or VS Code, FSI will just terminate as soon as the main thread has finished writing Please wait... (which typically is before the computation was even started on the thread pool).
If you want to observe the side effects of an async computation you have to await its result (in this example unit):
let computation = async {
printfn "Starting async"
let! res = Async.AwaitTask <| client.GetAsync(url)
let! content = Async.AwaitTask <| res.Content.ReadAsStringAsync()
let x = JsonConvert.DeserializeObject<AlbumInfo>(content)
printfn "Downloaded %s" x.title
}
async {
let! started = computation |> Async.StartChild
let! _ = Async.Sleep 1 // only here to get interleaved ouput
printfn "Please wait..."
let! res = started
printfn "Got result %A" res
} |> Async.RunSynchronously
will likely print:
Starting async
Please wait...
Downloaded quidem molestiae enim
Got result <null>

XCTest'ing a tuple

I am trying to build a unit test like so:
// region is a (Double, Double) tuple
XCTAssertEqual(region, (0.0, 200.0))
But Xcode is giving me an error: Cannot invoke 'XCTAssertEqual' with an argument list of type ((Double, Double), (Double, Double))
Is there a different way to test tuples without extracting their members and testing individually?
XCTAssertEqual requires that the two parameters passed to it are Equatable, which you can see from the method signature. Note that expression1 returns T?, and T must be Equatable:
func XCTAssertEqual<T : Equatable>(_ expression1: #autoclosure () throws -> T?, _ expression2: #autoclosure () throws -> T?, _ message: #autoclosure () -> String = default, file: StaticString = #file, line: UInt = #line)
But Swift tuples aren't Equatable, so you can't use them with XCTAssertEqual.
Tuples do have an == method — they just don't conform to the protocol — so you could do something like this:
let eql = region == (0.0, 200.0)
XCTAssertTrue(eql)
Or even:
XCTAssertTrue(region == (0.0, 200.0))
Edit: I've expanded on this answer in a blog post, How to Make Specialized Test Assertions in Swift
A disadvantage of using
XCTAssertTrue(region == (0.0, 200.0))
is the inadequate reporting it gives upon failure:
XCTAssertTrue failed -
Now you have to track down what the actual values are, to understand what went wrong.
But you can add diagnostic information to the assertion like this:
XCTAssertTrue(region == (0.0, 200.0), "was \(region)")
For example:
XCTAssertTrue failed - was (1.0, 2.0)
If you plan to have several tests that compare this tuple, I wouldn't want to have to repeat this everywhere. Instead, create a custom assertion:
private func assertRegionsEqual(actual: (_: Double, _: Double), expected: (_: Double, _: Double), file: StaticString = #file, line: UInt = #line) {
if actual != expected {
XCTFail("Expected \(expected) but was \(actual)", file: file, line: line)
}
}
Now the test assertion is
assertRegionsEqual(actual: region, expected: (0.0, 200.0))
Upon failure, this yields a message like
failed - Expected (0.0, 200.0) but was (1.0, 2.0)

Is it possible to use a member instead of let for an F# Event?

In this code, EventL uses a let binding and EventM (is an attempt to) use a member:
type MyType() =
let EventL = new Event<_>()
member this.EventM = new Event<_>()
member this.AddHandlers() =
Event.add (fun string1 -> printfn "EventL: %s" string1) EventL.Publish
Event.add (fun string1 -> printfn "EventM: %s" string1) this.EventM.Publish
member this.Trigger(message) =
EventL.Trigger(message)
this.EventM.Trigger(message)
let myMyType = MyType()
myMyType.AddHandlers()
myMyType.Trigger("Event arg.")
When run, this outputs only EventL: Event arg. while EventM's handler is not called.
Am I making a silly mistake or missing some piece of logic regarding members?
Your EventM is a computed property that gets evaluated every time it's called. This results in different Event objects being created throughout the rest of your code (2 times, once in AddHandlers, next in Trigger).
Checkout the member val syntax. That creates a backing field and still gives public accessibility.
The fixed version would be:
type MyType() =
member val EventM = new Event<_>()
If you don't have a primary constructor then you will need to use val instead and assign it in your constructor:
type MyType =
val EventM : Event<string>
new () = { EventM = new Event<_>() }
Note that in this case, you will have to give the type argument to Event.

Unintuitive empty formatted string

I want to add a listener mechanism to a Format-based logging facility, and I ended up in a situation where my program is typed by OCaml and compiles, but the formatted string just disappeared, and I don't understand exactly why this happens (it's related to formatters returning unit when they should return something else, but I expected the program not to type-check in that case).
This comes from a real use case; its simplification may however have led into a somewhat contrived program.
The basic need is this: to devise a Format.printf-like function (with variadic arguments) that is easy to use but also allows other formatters to be notified (e.g. duplicating their outputs).
I've been told this is not possible due to typing constraints, and indeed if I further simplify my example below, I do get typing errors, but for some reason the program below does type-check but does not produce the expected result.
open Format
let observers : formatter list ref = ref []
let add_observer o : unit =
observers := o :: !observers
let print_to_fmt (fmt: formatter) (text: ('a, formatter, unit) format) : unit =
Format.fprintf fmt "<";
Format.fprintf fmt text;
Format.fprintf fmt ">#."
let notify text : unit =
List.iter (fun fmt ->
Format.printf "MESSAGE: {";
Format.printf text;
Format.printf "}#.";
print_to_fmt fmt text
) !observers
let buffer = ref ""
let append text _ _ = buffer := text
let print text =
let fmt = Format.make_formatter append (fun () -> ()) in
Format.kfprintf (fun f -> ()) fmt text
let log text =
notify text;
print text
let () =
add_observer (Format.err_formatter);
log "this works";
log "this does not %d" 42;
log "this also works"
Any help on how to (1) change the program to display this does not 42, or (2) an explanation on why the program type-checks when it seems it shouldn't, would be much appreciated.
You're trying to do a very strange magic with formatters, that I would classify as an abuse, honestly. Formatter is a formatted channel, not data, so they impose all problems of channels, like non-persistent data that disappear suddenly.
If you want to have a log function, that will dispatch data between registered formatters, then the following will work:
open Format
let observers : formatter list ref = ref []
let add_observer o : unit =
observers := o :: !observers
let notify (text : string) : unit =
List.iter (fun fmt ->
fprintf fmt "MESSAGE: {%s}#." text) !observers
let log text = ksprintf notify text
let () =
add_observer Format.err_formatter;
log "this works";
log "this does not %d" 42;
log "this also works"
Will rend the following output:
MESSAGE: {this works}
MESSAGE: {this does not 42}
MESSAGE: {this also works}

Resources