Hi Jaap,
thanks for the comments!
Of course, I should have known that passing an argument as non-const is
not a viable way to return something from a function (erhem...).
About the ones() thing, I see what you mean when you say that what I am
testing is the speed of the ones() function, and not how long it takes
to return a matrix.
I guess the main conclusion then about returning matrices is to try to
avoid allocating memory twice (which does seem to make a significant
difference), whether you do this in Ox or in C.
Regards,
Max
On Wed, 2003-11-26 at 15:04, Vries, J.J. de (Jaap) wrote:
> Dear Max,
>
> A few comments:
>
> The fact that the Ox methods use twice the time might be caused by the use of the function "ones". If first the function is evaluated and afterwards the result is assigned, there will be an extra matrix copy operation.
>
> The second Ox method should return "a" to be useful. A function argument that is not "const" is still passed by value.
>
> An alternative method in Ox would be
>
> somemethod4()
> {
> return ones(1000,1000);
> }
>
> This is more like the first "so" method. If the purpose is to test the speed of returning a matrix this is a relevant specification. A further alternative is to let a=ones(1000,1000) outside the test loop, and assign and/or return "a" in the test. Then the matrix return issue is isolated from the performance of the function "ones".
>
> Regards,
> Jaap
>
> > -----Original Message-----
> > From: Max Bruche [mailto:[log in to unmask]]
> > Sent: Tuesday, 25 November, 2003 13:14
> > To: [log in to unmask]
> > Subject: What's the fastest way to return a matrix from a function?
> >
> >
> > Hi Ox-Users,
> >
> > I have been profiling some of my code to see how to increase speed. I
> > thought that it might be useful to share my results. PLEASE COMMENT!
> >
> > --- output ---
> > Ox version 3.30 (Linux) (C) J.A. Doornik, 1994-2003
> > What's the fastest way to return a matrix from a function?
> >
> > C/C++ Shared Object/DLL (so):
> > Method 1 allocates memory for a matrix, fills it and
> > returns it.
> > Method 2 receives a pointer to a matrix and fills the
> > memory (no
> > checks).
> > Method 3 receives a pointer to a matrix and fills the
> > memory (with
> > checks).
> > Ox:
> > Method 1 creates matrix, returns it.
> > Method 2 receives a non-const matrix as argument.
> > Method 3 receives a const pointer to a matrix as argument.
> >
> > Time spent in routines
> > so::method1 so::method2 so::method3 ox::method1 ox::method2
> > ox::method3
> > 2.44 1.44 1.59 5.32 5.32
> > 2.60
> > 0.13 0.08 0.08 0.28 0.28
> > 0.14
> > --- end output ---
> >
> > My (tentative) conclusions/remarks/questions (please correct
> > me if I am
> > wrong!):
> > 1) For getting a matrix out of C/C++ code, the fastest way to
> > do it seems to
> > be to pass the matrix a non-const matrix into the function
> > (which in C/C++
> > is handled as a pointer to a non-const matrix).
> >
> > 2) In Ox, passing a matrix out of a function via an argument that is a
> > pointer to a matrix for which memory has already been allocated seems
> > significantly faster than anything else.
> >
> > 3) The overhead for checking matrix dimensions and type in C/C++ seems
> > relatively small and is probably worth it.
> >
> > 4) If my C/C++ functions essentially do something like the
> > ones() function
> > then I am surprised that the C/C++ DLL that does the same
> > thing is faster,
> > given that I compiled it with standard CFLAGS, and a standard
> > compiler (gcc
> > 3.2.3) (???)
> >
> > --- the code ---
> >
> > --- ox ---
> > #include <oxstd.h>
> > #include <packages/oxutils/oxutils.h>
> >
> > namespace so
> > {
> > extern "testso,FnSomeMethod1" somemethod1();
> > extern "testso,FnSomeMethod2" somemethod2(a);
> > extern "testso,FnSomeMethod3" somemethod3(a);
> > }
> >
> > namespace ox
> > {
> > somemethod1()
> > {
> > decl a;
> > return a = ones(1000,1000);
> > }
> >
> > somemethod2(a)
> > {
> > a = ones(1000,1000);
> > }
> >
> > somemethod3(const pa)
> > {
> > pa[0] = ones(1000,1000);
> > }
> > }
> >
> > main()
> > {
> > decl a = ones(1000,1000);
> >
> > print("What's the fastest way to return a matrix from
> > a function?
> > \n\n");
> > print("C/C++ Shared Object/DLL (so):\n");
> > print("\tMethod 1 allocates memory for a matrix, fills it and
> > returns it.\n");
> > print("\tMethod 2 receives a pointer to a matrix and fills the
> > memory (no checks).\n");
> > print("\tMethod 3 receives a pointer to a matrix and fills the
> > memory (with checks).\n");
> > print("Ox:\n");
> > print("\tMethod 1 creates matrix, returns it.\n");
> > print("\tMethod 2 receives a non-const matrix as
> > argument.\n");
> > print("\tMethod 3 receives a const pointer to a
> > matrix as argument.
> > \n");
> > print("\n");
> > TrackTime({"so::method1", " so::method2",
> > "so::method3", " ox::
> > method1", " ox::method2", " ox::method3"});
> >
> > decl n = 100;
> > for(decl i=0; i<n; i++)
> > {
> > TrackTime(0);
> > a = so::somemethod1();
> > TrackTime(1);
> > so::somemethod2(a);
> > TrackTime(2);
> > so::somemethod3(a);
> > TrackTime(3);
> > ox::somemethod1();
> > TrackTime(4);
> > ox::somemethod2(a);
> > TrackTime(5);
> > ox::somemethod3(&a);
> > TrackTime(-1);
> > }
> > TrackReport();
> >
> > }
> > --- end ox ---
> >
> > --- C/C++ ---
> > #include <oxexport.h>
> >
> > extern "C" void OXCALL FnSomeMethod1(OxVALUE *rtn, OxVALUE
> > *pv, int cArg);
> > extern "C" void OXCALL FnSomeMethod2(OxVALUE *rtn, OxVALUE
> > *pv, int cArg);
> > extern "C" void OXCALL FnSomeMethod3(OxVALUE *rtn, OxVALUE
> > *pv, int cArg);
> >
> > static int rows = 1000;
> > static int columns = 1000;
> >
> > // create the matrix and return it
> > void OXCALL FnSomeMethod1(OxVALUE *rtn, OxVALUE *pv, int cArg)
> > {
> > OxLibValMatMalloc(rtn, rows, columns);
> >
> > for(int r=0;r<rows;r++)
> > for(int c=0;c<columns;c++)
> > OxMat(rtn, 0)[r][c] = 1;
> > }
> >
> > // have the matrix passed in as an argument and return it (no checks)
> > void OXCALL FnSomeMethod2(OxVALUE *rtn, OxVALUE *pv, int cArg)
> > {
> > for(int r=0;r<rows;r++)
> > for(int c=0;c<columns;c++)
> > OxMat(pv, 0)[r][c] = 1;
> > }
> >
> > // have the matrix passed in as an argument and return it
> > (with checks)
> > void OXCALL FnSomeMethod3(OxVALUE *rtn, OxVALUE *pv, int cArg)
> > {
> > OxLibCheckMatrixSize(pv, 0, 0, 1000, 1000);
> > for(int r=0;r<rows;r++)
> > for(int c=0;c<columns;c++)
> > OxMat(pv, 0)[r][c] = 1;
> > }
> > --- end C/C++ ---
> >
> > --- Makefile ---
> > SONAME = testso
> >
> > CC = g++
> > CFLAGS = -I/opt/ox3.3/dev -Wall -O2 -D__cdecl= -c
> > LIBNAME = $(SONAME).so
> > LIBDIR = /home/max/lib
> > CPATH = .
> >
> > all : compile
> >
> > %.o : $(CPATH)/%.cpp
> > $(CC) $(CFLAGS) -fPIC $<
> >
> > OBJECTS_SO = $(SONAME).o
> >
> > compile : $(OBJECTS_SO)
> > $(CC) -shared -o $(LIBNAME) $^
> > mv $(LIBNAME) $(LIBDIR)
> >
> > clean:
> > rm *.o
> > rm *.so
> > --- end Makefile ---
> >
>
|