I have written a small piece of code for a function that extracts certain elements from a matrix and then sum them and return the result. Although the uncompiled version works, when I try to switch to a compilable function something goes wrong:

microstep = Compile [{{matrix, _Integer, 2}, {arraydim, _Integer}},

tempmatrix = matrix,
randomtuple = {x , y } = RandomInteger[{1, arraydim}, 2], (*select a random element of  the matrix*)

down = {Mod[x + 1, arraydim, 1], y},  (*find the nearest neighbours  and *)
up = {Mod[x - 1, arraydim, 1], y},    (*impose periodic boundary conditions*)
left = {x, Mod[ y - 1, arraydim, 1]},
right = {x, Mod[y + 1, arraydim, 1]}, spindiff},

spindiff = Total[Extract[tempmatrix, #] & /@ {up, down, left, right}]

CompilationTarget -> "C", RuntimeOptions -> "Speed"]

microstep[confiniziale, 5]

where confiniziale is a 5x5 matrix whose elements are randomly chosen between -1 and 1.

confiniziale = RandomChoice[{-1, 1}, {lato, lato}];

The plan was to further develop her and implement a Metropolis algorithm. The errors i get are :

1) Extract: "Position specification {4.,2.} in Extract[*mymatrix,,{4.,2.}] is not applicable


2) CompiledFunction : " compiled expression Extract[*mymatrix,{4.,2.}] should be a rank 2 tensor of machine-size real numbers

and then the function continues using the uncompiled version giving the right result. what am I missing? any tips?

  • $\begingroup$ Does spindiff = Total[Compile`GetElement[tempmatrix, ##] & @@@ {up, down, left, right}] work? $\endgroup$
    – kglr
    Commented May 12, 2018 at 5:39
  • $\begingroup$ @kglr it says " Compilation of COmpileGetElement(tempmatrix,##1) &)@@CompileGetElement(SystemPrivateCompileSymbol(0),SystemPrivateCompileSymbol(1)) is not supported for the function argument CompileGetElement(tempmatrix,##1)&. The only function arguments supported are Times,Plus,or List. Evaluation will use the uncompiled function" $\endgroup$
    – Alucard
    Commented May 12, 2018 at 5:47
  • 2
    $\begingroup$ It's worth pointing out that randomtuple = {x , y } = RandomInteger[{1, arraydim}, 2] is also causing trouble here. x and y isn't localized. $\endgroup$
    – xzczd
    Commented May 12, 2018 at 6:46
  • $\begingroup$ @xzczd ah yes , thank you $\endgroup$
    – Alucard
    Commented May 12, 2018 at 6:52

1 Answer 1


This is how I would write your CompiledFunction:

microstep = Compile[{{matrix, _Integer, 2}},
  Module[{x, y, dimx, dimy},
   dimx = Compile`GetElement[Dimensions[matrix], 1];
   dimy = Compile`GetElement[Dimensions[matrix], 2];
   x = RandomInteger[{1, dimx}];
   y = RandomInteger[{1, dimy}];
    Compile`GetElement[matrix, Mod[x + 1, dimx, 1], y],
    Compile`GetElement[matrix, Mod[x - 1, dimx, 1], y],
    Compile`GetElement[matrix, x, Mod[y - 1, dimy, 1]],
    Compile`GetElement[matrix, x, Mod[y + 1, dimy, 1]]
  CompilationTarget -> "C",
  RuntimeOptions -> "Speed"

The major issue was that Extract is not compilable and Compile seems to be unable to build a reasonable call to the main evaluator. Anyway, you wouldn't have fun with a compiled function that has to call the main evaluator (slow).

Another mild issue:

You use quite a lot of tensor operations like left = {x, Mod[ y - 1, arraydim, 1]}, for vectors of length 2. That's very inefficient within Compile since each of these calls will involve a CopyTensor which is notoriously slow. And in the end, you have to retrieve the elements of these vectors again, undoing the whole costly process of putting things into vectors.

  • $\begingroup$ thanks ! where can i find the documentation for `GetElement ? i couldn't find it on the wolfram center. $\endgroup$
    – Alucard
    Commented May 12, 2018 at 6:43
  • 1
    $\begingroup$ There is not documentation for it, but it gets frequently used on this site. In a nutshell, it is a read-only variant of Part with the difference that does not check every time whether the indices are within the bounds of the array. That makes it considerably faster than Part but the programmer has to do the bound checks. Otherwise the kernel will quit when the function is called. $\endgroup$ Commented May 12, 2018 at 6:49
  • $\begingroup$ one last question : do you know if Mathematica speed up by a noteworthy amount if i switch to helical boundary conditions? or the Mod function is pretty much irrelevant for the absolute time? $\endgroup$
    – Alucard
    Commented May 12, 2018 at 6:50
  • 1
    $\begingroup$ Mod is very quick. No need to take pain for optimizing it away. $\endgroup$ Commented May 12, 2018 at 6:51
  • $\begingroup$ sorry to bother you again henrik but when i try to check whether the sum (spinsum= Plus[...]) is lesser than 0 i get a warning message that tells me that spinsum should be a machine-size real number. Do you know hw to solve this problem? $\endgroup$
    – Alucard
    Commented May 12, 2018 at 7:23

Your Answer

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

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