I am trying to fine tune a procedure to reduce its running time. It involves two large arrays "data" and "positions":
size=10^6;
data=RandomReal[1,size];
positions=RandomInteger[{1,size},24*size];
Here, "positions" never changes. However, "data" is constantly changing along the procedure and every time this happens, I need to produce the array
evalData=data[[positions]];
My questions is, considering both the sizes and the fact that positions
is fixed, what would be the fastest way of refreshing evalData
every time data
changes?
I have tried compiling Part
but it takes about the same time as using Part
directly. Also, ParallelMap
and ParallelTable
are very slow (even when I tried it on a computer with 10 cores). I also thought about compiling Part
together with positions
but this seems to take too much memory. Any advice?
UPDATE 1:
Perhaps my first question was overly simplified. This is in the context of a gradient descent algorithm, and the array positions
actually has rank two.
size=10^6;
data=RandomReal[1,size];
positions=RandomInteger[{1,size},{6*size,4}];
I am trying to optimize the following code:
Do[
dataTemp = Transpose[Map[data[[#]] &, Transpose[positions]]];
dataDescent = compiledFunction[dataTemp];
data=data-0.5*dataDescent;
,1000]
where compiledFunction
is listable and performs a computation on each array of size 4 stored in dataTemp
, in parallel, and it is currently much faster than the line
dataTemp = Transpose[Map[data[[#]] &, Transpose[positions]]];
I could store transposedPositions=Transpose[positions];
and save some time by instead calling
dataTemp = Transpose[Map[data[[#]] &, transposedPositions]];
but it is not a huge improvement.
UPDATE 2:
Found the following related unanswered question
evalData
. $\endgroup$evalData=data[[positions]]
call takes about 0.5 seconds on my machine. For comparison, pure allocation of an array of this size usingevalData=ConstantArray[0.,24*size]
takes close to 0.1 seconds, a similar order of magnitude. Btw, I do wonder how this call can be the bottleneck of any computation. Unless of course you do not actually use most of the entries inevalData
, in which case, why construct it at all? $\endgroup$Extract
? $\endgroup$Extract
:data = RandomReal[1, 10^6]; positions = RandomInteger[{1, Length[data]}, 6*10^6]; AbsoluteTiming[data[[positions]];] // First positions = positions /. i_Integer :> {i}; AbsoluteTiming[Extract[data, positions];] // First
gives0.085491 0.554953
It is slower thanPart
. $\endgroup$