Re: compile speed

*To*: mathgroup at smc.vnet.net*Subject*: [mg74459] Re: compile speed*From*: "Szabolcs" <szhorvat at gmail.com>*Date*: Thu, 22 Mar 2007 01:09:58 -0500 (EST)*References*: <etqnm3$nf$1@smc.vnet.net>

On Mar 21, 8:42 am, "Boson" <sandro.romani at gmail.com> wrote: > dear mathematica users, > > i've written a simple function that works on a pair of binary > matrices: > (mathematica 5.2 linux, on a 32 bit platform) > > tab[nx_, ny_, frac_] := Table[If[Random[] < frac, 1, 0], {nx}, {ny}] > > nx = 25; ny = 50; frac1 = 0.1; frac2 = 0.5; > p1 = 0.4; p2 = 0.2; > tabrect = tab[nx, ny, frac1]; > tabsq = tab[ny, ny, frac2]; > > testnocomp[mat1_, mat2_, n1_, n2_, pp1_, pp2_] := Module[{tmp, sum, > val}, > tmp = mat2; Do[sum = mat1[[k,j]] + mat2[[k,i]]; > val = Which[sum == 2, If[Random[] < pp1, 1, tmp[[i,j]]], sum == > 1, > If[Random[] < pp2, 0, tmp[[i,j]]], sum == 0, tmp[[i,j]]]; > tmp[[i,j]] = val, > {k, n1}, {i, n2}, {j, n2}]; tmp]; > > Timing[resnc = testnocomp[tabrect, tabsq, nx, ny, p1, p2]; ] > > the result of the timing is > {0.7558840000000013*Second, Null} > > since i need high values of nx,ny (~5000) and the loop scales as > nx*ny^2, > i tried to implement a compiled version of the previous function: > > test := Compile[{{mat1, _Integer, 2}, {mat2, _Integer, 2}, {n1, > _Integer}, {n2, _Integer}, > {pp1, _Real}, {pp2, _Real}}, Module[{tmp, sum, val}, > tmp = mat2; Do[sum = mat1[[k,j]] + mat2[[k,i]]; > val = Which[sum == 2, If[Random[] < pp1, 1, tmp[[i,j]]], sum > == 1, > If[Random[] < pp2, 0, tmp[[i,j]]], sum == 0, tmp[[i,j]]]; > tmp[[i,j]] = val, > {k, n1}, {i, n2}, {j, n2}]; tmp], {{Random[_], _Real}}]; > > Timing[res = test[tabrect, tabsq, nx, ny, p1, p2]; ] > > results are a disaster: > {14.814747999999996*Second, Null} > > i'm sure this is related to my poor mathematica programming > experience.. > > could you suggest me a faster version to solve this problem? > > regards, > sandro Unfortunately I don't understand why the compiled version is so slow. But here are two (uncompiled) faster versions: In[1]:= tab[nx_,ny_,frac_]:=Table[If[Random[]<frac,1,0],{nx},{ny}] nx=50;ny=100; tabsq=tab[ny,ny,.5]; tabrect=tab[nx,ny,.1]; * This is your original version (the reference for the Timing value): In[5]:= testnocomp1[mat1_, mat2_, n1_, n2_, pp1_, pp2_]:= Module[{tmp, sum, val}, tmp = mat2; Do[ sum = mat1[[k,j]] + mat2[[k,i]]; val=Which[ sum == 2, If[Random[]<pp1, 1, tmp[[i,j]] ], sum == 1, If[Random[]<pp2, 0, tmp[[i,j]] ], sum == 0, tmp[[i,j]] ]; tmp[[i,j]] = val, {k,n1}, {i,n2}, {j,n2}]; tmp] In[6]:= Timing[testnocomp1[tabrect,tabsq,nx,ny,.4,.2];] Out[6]= {6.094 Second,Null} * Here's my first try at improving performance: In[7]:= testnocomp2[mat1_,mat2_,n1_,n2_,pp1_,pp2_]:= Module[{tmp}, tmp=mat2; Do[ Switch[ mat1[[k,j]] + mat2[[k,i]], 2, If[Random[] < pp1, tmp[[i,j]]=1], 1, If[Random[] < pp2, tmp[[i,j]]=0] ];, {k,n1}, {i,n2}, {j,n2}]; tmp] In[8]:= Timing[testnocomp2[tabrect,tabsq,nx,ny,.4,.2];] Out[8]= {3.297 Second,Null} * Second try: In[9]:= testnocomp3[mat1_,mat2_,n1_,n2_,pp1_,pp2_]:= Inner[Plus, Transpose[mat1], Take[mat2,n1], Fold[ Switch[#2, 2, If[Random[]<pp1, 1, #1], 1, If[Random[]<pp2, 0, #1], 0, #1] &, -1, {##}] & ] In[10]:= Timing[testnocomp3[tabrect,tabsq,nx,ny,.4,.2];] Out[10]= {2.453 Second,Null} But here you still need to replace all -1's in the result with the corresponding elements from tabsq. The compiled versions of testnocomp2 and testnocomp3 do not work and if I compile only the Switch or the Fold part from testnocomp3, performance becomes much worse.