Hi, so if my interpretation of the above is correct the timings shouldn't be changing (i.e. one shouldn't be expecting the timings to improve)? The benchmarks seem to indicate this. I modified the second benchmark in http://lists.inf.ed.ac.uk/pipermail/polyml/2015-October/001673.html [the one with "(* This uses new FFI *)" at the top] to the following, and the time to compute was roughly the same :
*************************************************************************** *************************************************************************** open Foreign;
val mylib = loadLibrary "./intArray.so";
val c1 = buildCall1((getSymbol mylib "createIntArray"),cInt,cPointer)
val c2 = buildCall1((getSymbol mylib "destroyIntArray"),cPointer,cVoid)
val c3 = buildCall3((getSymbol mylib "setIntArray"),(cPointer,cInt,cInt),cVoid)
val c4 = buildCall2((getSymbol mylib "getIntArray"),(cPointer,cInt),cInt)
val c5 = buildCall1((getSymbol mylib "getSumIntArray"),(cPointer),cInt)
fun c_createIntArray (size) = c1 (size); fun c_destroyIntArray (p) = c2 (p); fun c_setIntArray (p,elem,value) = c3 (p,elem,value); fun c_getIntArray (p,elem) = c4 (p,elem); fun c_getSumIntArray (p) = c5 (p);
val size:int = 50000; val loops:int = 30; val cap:int = 50000;
fun loop (pData2) = let fun loopI i = if i = size then let val _ = () in c_setIntArray(pData2,0,c_getIntArray(pData2,size-1)); () end else let val previous = c_getIntArray(pData2,i-1); val use = if previous > cap then 0 else previous in c_setIntArray(pData2,i,use+1); loopI (i+1) end in loopI 1 end
fun benchmarkRun (pData2) = let fun bench i = if i = loops then () else let val _ = () in loop (pData2); bench (i+1) end in bench 1 end
fun main () = let val pData = c_createIntArray(size); in benchmarkRun(pData); print (Int.toString (c_getSumIntArray (pData))); print "\n" end *************************************************************************** ***************************************************************************
Thanks
On Wed, Dec 16, 2015 at 6:05 PM, David Matthews < David.Matthews at prolingua.co.uk> wrote:
There have been a few changes to the Foreign structure. The callN functions have been renamed as buildCallN and the way functions are passed as arguments has been changed.
The reason for the changes is to make clear that the expensive operations are creating the C functions and closures and that calling a C function or passing a constructed closure are comparatively cheap.
It is important to call the buildXXX functions at the top-level e.g. in a structure, so that the C function is created once. The old callN functions were curried and it wasn't apparent that the partial application to the conversions was quite different to the application of this to the arguments. For that reason the buildXXX take a tuple.
David
polyml mailing list polyml at inf.ed.ac.uk http://lists.inf.ed.ac.uk/mailman/listinfo/polyml