12
$\begingroup$

I am writing a simulation for 2D random walk. I wrote several version of code, and found that the speed is like this (fastest to slowest): C++, Mathematica compiled procedural code, Mathematica functional code. However, the rand() in C is not good enough for the experiment, and it is said that Mathematica uses cellular automation to generate random numbers, which have better distribution, so I wish to use the latter one.

There are two cases, the first one is just plainCompile, the second one uses the option: CompilationTarget -> "C", which is about 4 times faster than the first one. But the documentation states something scary (for the second case): the function is converted to C, compiled to DLL and linked back. I am wondering that if the compiled program uses the wolfram random algorithm or the rand() provided by C in those cases.

PS: I am using RandomInteger and RandomReal for random number generation.

$\endgroup$
10
  • 3
    $\begingroup$ Why don't you use a C++ library, e.g. Boost.Random? It is not generally true that rand() from the C standard library is not good enough. Some implementations are good, some are not so good. The problem is that the implementation you get depends on the system/compiler you use. If you use Boost.Random or a similar library you'll know which precise implementation you have and you'll even have a choice of several different implementations. $\endgroup$
    – Szabolcs
    Jul 2, 2015 at 11:58
  • 2
    $\begingroup$ That said, your question is valid and interesting, but given your motivation for asking it: I'd just use a C++ library. $\endgroup$
    – Szabolcs
    Jul 2, 2015 at 11:59
  • 3
    $\begingroup$ What I sometimes do is generate a huge block of random number in Mathematica and send this (as a block) to a compiled Mathematica routine. This is quite often much faster than generating the random numbers one by one in the compiled routine. $\endgroup$ Jul 2, 2015 at 12:01
  • 1
    $\begingroup$ @Felix You can make C++ functions accessible from Mathematica through LibraryLink. This does take a bit of work, but once you've got used to it it's not so bad. This is now the usual way for me to call C++ code (I hate writing to files using newly invented formats and importing the data back). Of course if it's fast enough in pure Mathematica that's much less trouble. $\endgroup$
    – Szabolcs
    Jul 2, 2015 at 12:06
  • 2
    $\begingroup$ Or even use C++11 <random>? cplusplus.com/reference/random $\endgroup$ Jul 2, 2015 at 12:24

1 Answer 1

14
$\begingroup$

This is not a full answer, but too long for a comment.

We can try to look at the C code that Mathematica generates.

Needs["CCodeGenerator`"]

cf = Compile[{{n, _Integer}}, RandomReal[1, n]]
CCodeStringGenerate[cf, "fun"]

Excerpt from the output:

...
FP0 = funStructCompile->getFunctionCallPointer("RandomReals");
...
err = FP0(libData, 3, FPA, FPA[3]);/*  RandomReals  */
...

This is the function that's being called. What this is, we can only guess, but I'd be very surprised if it were simply using the C standard library's random number generator. It very likely uses a cross platform implementation contained within the Mathematica kernel.


Update

Here's proof that the same random number generator is being used regardless of whether the function is compiled and regardless of the compilation target.

cf = 
  Compile[{{n, _Integer}}, SeedRandom[123]; RandomReal[1, n]];

cf2 = 
  Compile[{{n, _Integer}}, SeedRandom[123]; RandomReal[1, n], 
   CompilationTarget -> "C"];

cf[5]
(* {0.45571914, 0.97782592, 0.94321464, 0.96221575, 0.3023479} *)

cf2[5]
(* {0.45571914, 0.97782592, 0.94321464, 0.96221575, 0.3023479} *)

SeedRandom[123]; RandomReal[1, 5]
(* {0.45571914, 0.97782592, 0.94321464, 0.96221575, 0.3023479} *)

I haven't tried other random number generation methods than the default. You might want to experiment with other options as well (the Method option of SeedRandom).

$\endgroup$
4
  • $\begingroup$ Thanks! And this proves what Sjoerd C. de Vries said: the uncompiled version is faster. $\endgroup$
    – vapor
    Jul 2, 2015 at 12:40
  • $\begingroup$ Seems to work with different method of random number generation... $\endgroup$ Jul 2, 2015 at 12:58
  • 2
    $\begingroup$ Try this with something other than a uniform distribution, e.g. cf = Compile[{{n, _Integer}}, RandomVariate[ChiSquareDistribution[5]]] and you see it calls back to Mathematica, $\endgroup$ Jul 2, 2015 at 13:27
  • 2
    $\begingroup$ @SjoerdC.deVries mathematica.stackexchange.com/questions/1124/… $\endgroup$ Jul 2, 2015 at 14:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.