Я вычисляю ограничивающую рамку трехмерного облака точек в Clojure. Облако точек представлено в виде примитивного массива с плавающей запятой Java, и каждая точка в облаке точек хранится с использованием 4 с плавающей запятой, где последняя с плавающей запятой не используется. Как это:
[x0 y0 z0 u0 x1 y1 z1 u1 .... ]
Размер облака точек 19200, то есть 4*19200 поплавков в массиве.
Некоторые из этих значений могут не быть конечными (либо они бесконечны, либо NaN). Таким образом, любая точка, которая содержит не конечное значение, должна быть полностью исключена из вычислений. Я реализовал это вычисление как на Java, так и на Clojure, но по какой-то причине версия Clojure все еще примерно в 4-5 раз медленнее.
Вот как выглядит код Clojure:
(defn good-compute-bbox [^floats data]
(let [n (alength data)]
(loop [i (int 0)
minx (float (aget data 0))
maxx (float (aget data 0))
miny (float (aget data 1))
maxy (float (aget data 1))
minz (float (aget data 2))
maxz (float (aget data 2))]
(if (< i n)
(let [x (float (aget data (unchecked-add i 0)))
y (float (aget data (unchecked-add i 1)))
z (float (aget data (unchecked-add i 2)))]
(if (and (Float/isFinite x)
(Float/isFinite y)
(Float/isFinite z))
(recur (unchecked-add-int i (int 4))
(min minx x)
(max maxx x)
(min miny y)
(max maxy y)
(min minz z)
(max maxz z))
(recur (unchecked-add-int i (int 4))
minx
maxx
miny
maxy
minz
maxz
))
)
[minx maxx miny maxy minz maxz]))))
и вот как выглядит код Java:
public class BBox {
public static float[] computeBBox(float[] data) {
long n = data.length;
float[] result = new float[6];
float minx = data[0];
float maxx = data[0];
float miny = data[1];
float maxy = data[1];
float minz = data[2];
float maxz = data[2];
for (int i = 0; i < n; i += 4) {
float x = data[i + 0];
float y = data[i + 1];
float z = data[i + 2];
if (java.lang.Float.isFinite(x) &&
java.lang.Float.isFinite(y) &&
java.lang.Float.isFinite(z)) {
minx = x < minx? x : minx;
maxx = x > maxx? x : maxx;
miny = y < miny? y : miny;
maxy = y > maxy? y : maxy;
minz = z < minz? z : minz;
maxz = z > maxz? z : maxz;
}
}
result[0] = minx;
result[1] = maxx;
result[2] = miny;
result[3] = maxy;
result[4] = minz;
result[5] = maxz;
return result;
}
};
У меня вопрос: какие изменения я могу внести в свой код Clojure, чтобы он работал так же быстро, как код Java? Бонусный балл, если вы протестировали свой код и измерили его ускорение.
Если вы хотите воспроизвести эксперимент и опубликовать его на моем Репозиторий Github здесь.