I have a simple operation that I'd like to apply to an n×n matrix. My problem (well, one of them...) is that it runs in, say, 4 seconds for a 100×100 matrix, but it took five and a half minutes to run on a 300×300 matrix. It's a simple function I'm applying to each entry so I have no idea why this is happening, but I'm also pretty new to having to do anything efficiently.
The setup is this: I start with a random array of an equal number of 1s and -1s. I apply something like a Hamiltonian operator that looks at each element, does a calculation, and returns a number—namely, H[array]
gives a matrix of the same dimensions of array.
All H
does is look at the [[i,j]]
entry of our input array ar
, then multiplies that entry by all of its neighbors and takes the sum of those products. That sum is the [[i,j]]
the entry in H[array]
.
H[ar_] := -ParallelTable[
ArrayPad[ar, 1][[i, j]]*
Sum[ArrayPad[ar, 1][[i + m, j + n]],
{m, -1, 1}, {n, -1, 1}] - 1,
{i, 2, Length[ar] + 1}, {j, 2, Length[ar] + 1},
];
I use ArrayPad
on the input to pad the matrix with 0s on all sides—this way, the entries on the edge (which have fewer than 8 neighbors) don't throw errors, and the "non-existent" entries contribute 0s to the sum.
Because I calculate the product of one value with 9 other values, I sped up the algorithm by just factoring out the first value and multiplying that by the sum instead of calculating the sum of 9 products. I subtract 1 from the final sum because this method includes a term comprising the product of the [[i,j]]
entry of ar
with itself, which is either 1×1=1 or -1×-1=1.
So, it's not particularly complicated—but I can't, for the life of me, figure out how this scales with size of this matrix. I would expect a ~9× increase in time when going from 100×100 to 300×300, but instead got an ~80× increase. Could anybody help me to figure out why this is and how to help optimize it?
Thank you!