【发布时间】:2018-03-22 07:51:58
【问题描述】:
我正在 Clojure 中计算 3d 点云的边界框。点云表示为 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 代码一样快?如果您测试了您的代码并测量了加速,则可以加分。
如果你想重现实验和published on my Github repository here。
【问题讨论】:
标签: performance clojure geometry clojure-java-interop