# Tag Info

37

The code as it is now looks very much FORTRAN style, which is fine. But Mathematica offers you a wide range of ways to make your code more readable, faster and easier to spot potential bugs. So let's go through through some of the possible ways to improve your code: Variable Naming I know that in languages like C and FORTRAN it's common to give variables ...

34

A bit late to the discussion but I had the chance to ask Wolfram's North America sales manager about this. I had forwarded him the list of compilable functions "CompileCompilerFunctions[]". He asked one of his engineers about this. They came back with some information that I thought would add to this question. I don't think that is the correct ...

33

Leonid Shifrin has already given an excellent answer for the question but it's so… long and may be frustrating for someone just beginning to learn the usage of Compile so I decided to post this as an answer. Recently (OK… actually it's more than a year ago) I found that Ted Ersek's Mathematica tricks(.nb version can be found here) contains a brief but ...

33

Use pure functions (Function) and "InlineExternalDefinitions" -> True: g = #^2 &; f = # + 1 &; compiledFunction = Compile[{{x, _Real, 0}}, f@g[x], CompilationOptions -> {"InlineExternalDefinitions" -> True}]; CompilePrint[compiledFunction] 1 argument 1 Integer register 4 Real registers Underflow ...

32

Okay, this is a bit of an embarassment. Here is a very small modification of the original code. I simply made explicit option settings, made a denominator to Sin explicitly real, that kind of thing. My tests show the same timing as the original, give or take an iota. ie = 200; ez = ConstantArray[0., {ie + 1}]; hy = ConstantArray[0., {ie}]; fdtd1d = ...

31

Yes there is a way to use functions that use external non compiled functions. It uses the step function of Mr.Wizard defined in the post How do I evaluate only one step of an expression?, in order to recursively expand the code that we want to compile until it uses only functions that Mathematica can compile. The technique discussed in the post How to ...

31

This is because Table automatically compiles its argument above a certain length limit. SystemOptions["CompileOptions" -> "TableCompileLength"] (* {"CompileOptions" -> {"TableCompileLength" -> 250}} *) It does not seem to realize that the code modifies global variables because that behaviour is hidden behind code. Notice that the following both ...

28

Here is another compiled implementation: hammingDistanceCompiled = Compile[{{nums, _Integer, 1}}, Block[{x = BitXor[nums[[1]], nums[[2]]], n = 0}, While[x > 0, x = BitAnd[x, x - 1]; n++]; n ], RuntimeAttributes -> Listable, Parallelization -> True, CompilationTarget -> "C", RuntimeOptions -> "Speed" ]; This appears to ...

27

First off, your function is very simple without any hard number-crunching, so it will always be hard to get a large speedup for the compiled version. Secondly, your Parallelization option for Compile is useless because it doesn't do any parallelization this way. Let me give slightly changed versions of your examples and explain how you can achieve a large ...

26

The default SumCompileLength is 250. You can increase this number for example to 500 using SetSystemOptions["CompileOptions" -> {"SumCompileLength" -> 500}] or to infinity using SetSystemOptions["CompileOptions" -> {"SumCompileLength" -> ∞}] What is "SumCompileLength" for? For sums with a finite number of at least "SumCompileLength" elements ...

26

One of the biggest differences between main kernel evaluation and compiled evaluation in the "Wolfram Virtual Machine" (WVM) is that in the kernel, arbitrary expressions are allowed that are rewritten according to pattern-matching rules and in the WVM things are much more restricted and predictable. For instance, the types of all variables are ...

24

It is important to Compile that it has always the same return type, no matter what happens at runtime. Note that Which returns Null as default value. Since the return value of the function is meant to be a 4-vector in some cases, we have to assign also a 4-vector (e.g., {0., 0., 0., 0.}) as default return value of Which. So this should work: ...

22

There are much faster ways to generate Pythagorean triples. Update: Now twice as fast. genPTunder[lim_Integer?Positive] := Module[{prim}, prim = Join @@ Table[ If[CoprimeQ[m, n], {2 m n, m^2 - n^2, m^2 + n^2}, ## &[]], {m, 2, Floor @ Sqrt @ lim}, {n, 1 + m ~Mod~ 2, m, 2} ]; Union @@ (Range[lim ~Quotient~ Max@#] ~...

22

Maybe two advises for the start: Use the fact that Sin is Listable and you can call Sin[{1,2,3,4,..}] to get a list of results. Don't calculate the sum twice. Calculate the sine part only once and make the multiplication with i in the first sum as vectorized multiplication. Taking this into account give in a first try something like fHal = Compile[{{n, ...

21

This is a tricky case indeed, because what you basically ask for is compile-time evaluation (macro-style). Generally, the answer is to use meta-programming, to assemble the compiled expression at run-time. The reason your attempt did not work is that the expression you want to evaluate is too deep for Evaluate to be effective. Solution using in-place ...

21

The Wolfram Virtual Machine's CompiledFunctionCall opcode is a fast way to let one compiled function call another. The speed advantage is largely because the call can be made without leaving the virtual machine. Sometimes inlining can be fast, especially for functions with very small function bodies, but you would simply need to test both ways to know ...

21

Yes, there is! Mathematica creates a LibraryFunction when compiling to C, but puts it in a temporary directory. If you can recover the library, you can load it as often as you like! First let's define the function as in the question: generatef[opt_] := Compile[{}, Module[{j = 0}, Do[j++, {i, 10^8}]; j], CompilationTarget -> opt]; f2 = generatef["C"]; ...

19

The following additional functions are compilable in Mathematica 9. {Gamma, LogGamma, InternalReciprocalSqrt}

19

Another option to the answer posted by Andy Ross cropped up in a recent question of mine about corrupting an image with Poisson noise. In my own answer, I made use of LibraryLink to utilise the distributions built into C++. This was especially useful in my case because Poisson noise in an image otherwise relies on a call to RandomVariate for each pixel (...

19

This is awful. It is one very typical example of "how to use Mathematica the wrong way*. OK, enough complaining. Let me give you one hint. Lets say you have a 500x500 and a 1000x1000 matrix and you want to copy the smaller one in the upper left corner of the larger one. We do this step 100 times. In your style this would go like m1 = RandomReal[{0, 1}, {...

19

It's because FFc is being passed x and Ef symbolically, at first. To cure the problem, add an intermediate function between FFc and NIntegrate, such as f[x_?NumericQ, Ef_?NumericQ] := FFc[x,Ef] then foo[Ef_?NumericQ] := NIntegrate[f[x, Ef] , {x, -EBoundary, EBoundary}]

19

Looking at CompilePrint[compiledGlynnAlgorithm], there are some lines with CopyTensor in it which aren't really needed. There's also a few CoerceTensor lines in there when it might be faster to just coerce the integer matrix once at the beginning. By slightly adjusting the function, all instances of CopyTensor and CoerceTensor go away, giving a small ...

18

It's not you, it's Mathematica. You are not expected to know this, but basically, in compiled code, ReplacePart merely acts as syntactic sugar for setting a part, i.e.: l = Range[3]; ReplacePart[l, 2 -> 0] (* -> {1, 0, 3} *) would be compiled (but see below) into exactly the same bytecode as l = Range[3]; Block[{l = l}, l[[2]] = 0; l] (* -> {1, 0,...

18

If you look at the generated code (CompilePrint, for example), the procedure is as follows: All the program's constants are placed into separate registers (regardless of their location in the program, they can be in the r.h.s.of variable initialization in scoping constructs, or they can be statements in their bodies. Actually, same constants found in ...

18

Congratulations! You find one of subnormal positive double :) Another example f = Compile[{{t, _Real}}, 2.0^t]; f[-1074] f[-1075] 5.*10^-324 0 MachineNumberQ@f[-1074] True This doesn't mean that CompiledFunction can work with arbitrary-precision numbers. Update Normally Mathematica prevents such numbers 2.^-1074. % // MachineNumberQ 4.940656458413*...

18

No, it is not possible. With code converted to a LibraryLink library by way of Compile you are limited to using functions that either can be expressed directly in C, or exist in the runtime library; unfortunately, FindFit is not included in either category. When present in code passed to Compile, FindFit results in a call back to the top level, and it is ...

18

Based on the experience obtained here: friction = Compile[{{v, _Real}, {vt, _Real}}, If[v > vt, -v*3.0, -vt*3.0*Sign[v]]]; simulateSpring = Compile[{{x0, _Real}, {t, _Real}, {dt, _Real}, {vt, _Real}}, Module[{τ, times, positions, v = 0.0, a = 0.0, x = x0}, τ = t; times = Range[0.0, t, dt]; positions = Table[0.0, {Length@times}]; ...

17

First, if you use := in your assignment, then the compilation is not done instantly but every time you call winding2. That's btw the reason why you get the error message when you try to call the function because it is not compiled until then and the error is a compilation error. Secondly, as the error messages sais, @@ can only be used with Times, Plus or ...

17

Using Compile with CompilationTarget->"C" does generate C-Code to be compiled in a generalized way, the resulting code will contain some overhead due to that compared to hand-written code which can easily explain any difference in runtimes. Even for cases where that overhead is minimal or non-existent automatic code generation will always produce ...

16

In version 8, the callback into the interpreter (also known as MainEvaluate or WolframCompileLibrary_Functions->evaluateFunctionExpression) looks like Function[{iCompile$1}, Block[{i = iCompile$1}, {Print[i], i}]][register] where register is the (integer, scalar) register that contains the value of i. This looks correct to me, although I'll admit that I ...

Only top voted, non community-wiki answers of a minimum length are eligible