まあ、私は遊びに抵抗できませんでした。単精度と倍精度のペアワイズ ユークリッド距離を実装するという名前の Matlab mex C ファイルを作成しました。pdistc
私のマシンでは、Matlab R2012b および R2015a を使用しており、大きな入力 (たとえば、60,000 x 300) の場合よりも 20 ~ 25% 高速ですpdist
(および基礎となるヘルパー関数)。pdistmex
指摘されているように、この問題は基本的にメモリによって制限されており、多くのメモリを要求しています。私の mex C コードは、出力に必要な量を超える最小限のメモリを使用します。そのメモリ使用量を のメモリ使用量と比較するとpdist
、2 つが実質的に同じであるように見えます。つまり、pdist
余分なメモリを大量に使用していません。メモリの問題は、呼び出す前にメモリを使い果たしている可能性があります (大きな配列を削除するためにpdist
使用できますか?)、または単に小さなハードウェアで大きな計算上の問題を解決しようとしているからです。clear
したがって、私のpdistc
関数はメモリ全体を節約できない可能性がありますが、組み込みの別の機能を使用できる可能性があります。全体的なペアワイズ距離ベクトルのチャンクを計算できます。このようなもの:
m = 6e3;
n = 3e2;
X = rand(m,n);
sz = m*(m-1)/2;
for i = 1:m:sz-m
D = pdistc(X', i, i+m); % mex C function, X is transposed relative to pdist
... % Process chunk of pairwise distances
end
これはかなり遅く (10 倍程度)、私の C コードのこの部分は最適化されていませんが、配列全体を一度に必要としないと仮定すると、メモリの使用量ははるかに少なくなります。pdist
(または) を使用して、すべてではなくpdistc
サブセットを直接渡したループを作成することで、同じことをはるかに効率的に実行できることに注意してください。X
64 ビットの Intel Mac を使用している場合は、.mexmaci64
バイナリが含まれているのでコンパイルする必要はありませんが、それ以外の場合は、マシンのコードをコンパイルする方法を理解する必要があります。私はそれを手伝うことはできません。コンパイルできない可能性や、コードを自分で編集して解決する必要がある互換性の問題が発生する可能性があります。バグがあり、コードが Matlab をクラッシュさせる可能性もあります。pdist
また、マシン イプシロン ( ) の範囲内で 2 つの間の違いに関連して、わずかに異なる出力が得られる場合があることに注意してくださいeps
。pdist
大規模な入力やその他の数値の問題のオーバーフローを回避するために、派手なことをする場合としない場合がありますが、私のコードはそうではないことに注意してください。
さらに、単純な純粋な Matlab 実装を作成しました。これは mex コードよりも大幅に低速ですが、単純な実装や にあるコードよりも高速ですpdist
。
すべてのファイルはここにあります。ZIP アーカイブには、すべてのファイルが含まれています。BSDライセンスです。自由に最適化してください (C コードで BLAS 呼び出しと OpenMP を試してみましたが、うまくいきませんでした。ポインター マジックまたは GPU/OpenCL でさらに高速化できる可能性があります)。あなたや他の誰かに役立つことを願っています。