Look up BinCounts
and DistanceMatrix
.
Example
Here are 20,000 points in the unit square. As I understand, you want the histogram of their pairwise distances.
pts = RandomReal[1, {20000, 2}];
DistanceMatrix[pts]
would calculate pairwise distances. But the matrix it would produce will not fit in memory (for 20000 it might, but for 100000 it will not). So we need to compute the distance matrix block by block. Let one block be of size blockSize
by blockSize
.
blockSize = 1000;
parts = Partition[pts, blockSize, blockSize, {1, 1}, {}];
res = ConstantArray[0, 10];
Do[
res += BinCounts[
Flatten@DistanceMatrix[p1, p2], {0, 1, 0.1}],
{p1, parts}, {p2, parts}
] // AbsoluteTiming
res[[1]] -= Length[pts];
res /= 2;
This takes 7.5 seconds on my machine. For your size of data, it would take 5-6 minutes. If you have higher-than-2 dimensional data, it would take longer, but not significantly so.
The last two line of the code correct for counting the zero-distances on the diagonal of the matrix, and for double counting all other distances.
Parallel version
We can speed this up somewhat using parallelization. Here's how:
LaunchKernels[]
DistributeDefinitions[parts]
res = Total@ParallelMap[
BinCounts[Flatten@DistanceMatrix[parts[[First[#]]], parts[[Last[#]]]], {0, 1, 0.1}] &,
Tuples[Range@Length[parts], {2}]
]; // AbsoluteTiming
res[[1]] -= Length[pts];
res /= 2;
A trick I used here was to distribute parts
only once, and then index into it. A more straightforward solution would send a block of data with each evaluation. This would result in a lot of data transfer overhead.
With a block size of 5000 and 130000 points, this took 220 s on my 4-core laptop. It is not a huge speedup over 5-6 minutes (which I have extrapolated, not measured), but it is a useful speedup nevertheless. Once reason for the modest performance increase is that DistanceMatrix
already makes use of all CPU cores.