I'd like to create a distance matrix with an expensive distance function.
To explore how to do this for a simpler case, consider these three ways of creating a Euclidean distance matrix:
- Using a DistanceFunction in DistanceMatrix
- Using EuclideanDistance in Outer
- Using DistanceMatrix directly
The second method is 2.3 times faster than the first. The third method is 880 times faster than the first.
pts = RandomReal[{0, 1}, {1000, 3}];
RepeatedTiming[DistanceMatrix[pts, DistanceFunction -> (EuclideanDistance[#1, #2] &)];]
RepeatedTiming[Outer[EuclideanDistance[#1, #2] &, pts, pts, 1];]
RepeatedTiming[DistanceMatrix[pts];]
I'm trying to use FunctionCompile to speed up the second method and can't find a way to do it.
Here is what I've tried:
Creating a compiled version of EuclideanDistance
distance = FunctionCompile@
Function[
{Typed[x, TypeSpecifier["NumericArray"]["Real64", 1]], Typed[y, TypeSpecifier["NumericArray"]["Real64", 1]]},
Module[{dx = x - y}, Sqrt[dx . dx]]
]
which works and has code signature:
codeSignature = {TypeSpecifier["NumericArray"]["Real64", 1],
TypeSpecifier["NumericArray"]["Real64", 1]} -> "Real64"
I can't figure out how to compile Outer:
outer = FunctionCompile@
Function[{Typed[x, TypeSpecifier["NumericArray"]["Real64", 1]]},
Module[{outer},
outer = Typed[KernelFunction[Outer],
{codeSignature,
TypeSpecifier["NumericArray"]["Real64", 1],
TypeSpecifier["NumericArray"]["Real64", 1],
Typed[level, "Integer16"]} ->
TypeSpecifier["NumericArray"]["Real64", 2]
];
outer[distance, x, x, 1]
]
]
I get a TypeError, no matching candidate, and something about Unintialized.
Can anyone give me a working example so I can compile a different distance function?