How do I make Maple Code run faster after its conversion from C code?

We were wondering if you could help us with a question to Maple:

We have converted a C code directly into Maple code and have found
that Maple runs about a thousand times slower than the C version
(the code is a numerical simulation).

1) Why is this so?
2) How do we make it run faster?

jan's picture

How to make Maple code run faster.

I don't know enough about the Maple architecture to comment on speed of execution. However, here are a few things to make Maple go faster:

Use floating point where possible

Maple by default tries to keep results in exact form. For example the following expression

sin (Pi/2)

would be kept in its exact form, which is really slow. To speed things up you can make Maple evaluate the expression into a floating point number by

sin (Pi/2)

or

evalf (sin (Pi/2))

This can result is small improvement without doing a lot of work.

Use evalhf

Evalhf is a procedure that can execute another procedure or a statement using hardware floating point arithmetic. See ?evalhf for more details.

Here is an example from one of the samples in Maple 10.

WaveGen := proc(
		nc::posint,
		amps::Array(datatype=float[8]),
		freqs::Array(datatype=float[8]),
		Npoints::posint,
		SampleFreq::float,
		SigData::Array(datatype=float[8])
)
local i::posint, j::posint, tot::float, t::float, deltaT::float;

deltaT:=1/SampleFreq;
for i from 1 to Npoints do
	tot:=0.0;
	t := evalf (i/SampleFreq);
	for j from 1 to nc do
		tot:= tot + evalf (amps[j]*(sin(2*Pi*freqs[j]*t)));
	end do;
	SigData[i] := tot;
end do;

end proc:

This procedure can be called using evalhf as

evalhf (WaveGen (5, amps, freqs, Npoints, Fs, var(SigData)));

Compile the procedure

You can also use the compiler to compile the procedure. The above procedure would be compiled using:

c_WaveGen := Compiler:-Compile (WaveGen):

Then you can execute the c_WaveGen procedure, which calls the compiled code.

c_WaveGen (5, amps, freqs, Npoints, Fs, SigData));

Timing improvement

To get the sense of the possible speedup, here are timing for the SignalGeneration example in Maple 10.

  • Maple proc - 121 seconds
  • Evalhf - 0.484 seconds
  • Compile - 0.093 seconds

To see the example, go to the Help Menu, then Take a tour. From the worksheet, you can click on the Wave Generation link to bring up the example.

Hope this helps,

Jan Bakus
Applications Engineer, Maplesoft

Maple vs C

1) Why is this so?

Well, C is a compiled programming language, so the resulting binary executes directly on the CPU. Maple is an interpreted programming language, meaning that there is a piece of software that reads your code and decides how to execute it. In addtion, for numeric code, C works in hardware datatypes (floats and integers) whereas Maple works with software data types. A hardware float multiplication will take one CPU cycle, a software float multiplication may take hundreds or thousands (depending on the length of the float).

2) How do we make it run faster?

What was the point of taking C code and converting it into Maple? Did you want greater accuracy? Usually people would develop the code in Maple first, and then export it to C for greater performance.

If you don't need more accuracy than C, then check out ?evalhf and ?Compiler. Those will give you a lot of speed ups by executing the code at hardware precision. However the final results may not be very different that your results from C.

Without seeing your Maple code, I can only suggest areas for you to investigate.

The Maple functions map, seq, add, and mul are more efficient than for loops.

For example, this

# create the data
n := 10^6;
L := [ seq( i, i=1..n ) ];
s := 0;

for i from 1 to n
do
    s := s+L[i];
end do;

is slower than

# create the data
n := 10^6;
L := [ seq( i, i=1..n ) ];

s := add( L[i], i=1..n );

In this particular case you could just do this:

# create the data
n := 10^6;
s := add( i, i=1..n );

However often the data represented here by L won't be so simple.

As well, growing lists element by element is very slow.

This is bad code:


n := 10^6;

L := [];

for i from 1 to n
do
    L := [ op(L), i ]:
end do:

L;

This is far more efficient

n := 10^6;

L := [ seq( i, i=1..n ) ];

Maple also provides built in data structures with built in operations. Using them appropreately can greatly speed up your code. In particular, Maple's hash tables (?table) might be useful.

Darin

--
Kernel Developer
Maplesoft

External calling

Another option to consider is calling your compiled C routine directly from Maple (see ?define_external). This way you will be able to run your simulation as efficiently as possible and at the same time you will be able to use the results of your simulation in a Maple session to do any further analysis.

Thank You

Thank you Darin and Jan for your help!

When I am what I am where I am, I am who I am.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
}