0

我在一个 Android 应用程序中有一些代码,当我分析我的应用程序时,它会占用大部分时间。我试图优化它,但仍然占用了大部分 CPU 时间。我想知道是否有人对我如何加快速度有任何想法。这是我使用的代码的精简版本:

输入:
d 是浮点数数组
a 是浮点数数组
e 是浮点数数组

输出:
out 是一个包含 3 个浮点数的数组

代码:

float [] c=new float[3];
float [] b=new float[3];
float [] out=new float[3];

c[0] = a[0] - d[0 * 4 + 3];
c[1] = a[1] - d[1 * 4 + 3];
c[2] = a[2] - d[2 * 4 + 3];

b[0] = c[0]*d[0 * 4 + 0] + c[1]*d[1 * 4 + 0] + c[2]*d[2 * 4 + 0];
b[1] = c[0]*d[0 * 4 + 1] + c[1]*d[1 * 4 + 1] + c[2]*d[2 * 4 + 1];
b[2] = c[0]*d[0 * 4 + 2] + c[1]*d[1 * 4 + 2] + c[2]*d[2 * 4 + 2];           

out[0] = b[0] * e[0 * 4 + 0] + b[1] * e[0 * 4 + 1] + b[2] * e[0 * 4 + 2] + e[0 * 4 + 3];
out[1] = b[0] * e[1 * 4 + 0] + b[1] * e[1 * 4 + 1] + b[2] * e[1 * 4 + 2] + e[1 * 4 + 3];
out[2] = b[0] * e[2 * 4 + 0] + b[1] * e[2 * 4 + 1] + b[2] * e[2 * 4 + 2] + e[2 * 4 + 3];

对于那些对其 3D 模型动画的顶点变换感兴趣的人。'out' 是变换后的顶点,'a' 是原始顶点。其余的数组是骨架关节信息。

4

4 回答 4

1

其余的代码是做什么的?这看起来像一小段代码,所以它应该执行得非常快。你真的有性能问题,还是你想让你的程序完全不消耗 CPU?

也就是说,您可以简单地预先计算所有这些微不足道的算术运算:

c[0] = a[0] - d[3];
c[1] = a[1] - d[7];
c[2] = a[2] - d[11];

等等

我不明白您如何访问d[3],虽然,因为d[7]应该是一个由 3 个元素组成的数组。d[11]d

于 2012-10-29T20:11:14.913 回答
0

您对此无能为力..所有操作都是赋值和数学运算,您没有实现这些。此外,这些操作已经非常快了......在某种 for 循环中执行此操作会更节省内存,因为 java 必须在相乘之前存储所有这些数字。动态做会更有效率。

于 2012-10-29T20:11:29.313 回答
0

好吧,一个乘以零可以简化为零,然后删除加法,但我相信他们的编译器或热点已经这样做了。

您可以尝试记忆结果以防止重新计算。

此外,您可以尝试使用JCuda将这种数学运算卸载到 GPU,但我不知道 Android 是否支持此功能。

于 2012-10-29T20:11:50.187 回答
0

所有编译时常量都将(必须)由编译器进行常量折叠。您所能做的就是消除临时数组,无论如何您都不会将其用作数组。我试过这样:

public float[]  transform2(float[] a, float[] d, float[] e)
{
    float c0,c1,c2;
    float b0,b1,b2;
    float [] out=new float[3];

    c0 = a[0] - d[0 * 4 + 3];
    c1 = a[1] - d[1 * 4 + 3];
    c2 = a[2] - d[2 * 4 + 3];

    b0 = c0*d[0 * 4 + 0] + c1*d[1 * 4 + 0] + c2*d[2 * 4 + 0];
    b1 = c0*d[0 * 4 + 1] + c1*d[1 * 4 + 1] + c2*d[2 * 4 + 1];
    b2 = c0*d[0 * 4 + 2] + c1*d[1 * 4 + 2] + c2*d[2 * 4 + 2];           

    out[0] = b0 * e[0 * 4 + 0] + b1 * e[0 * 4 + 1] + b2 * e[0 * 4 + 2] + e[0 * 4 + 3];
    out[1] = b0 * e[1 * 4 + 0] + b1 * e[1 * 4 + 1] + b2 * e[1 * 4 + 2] + e[1 * 4 + 3];
    out[2] = b0 * e[2 * 4 + 0] + b1 * e[2 * 4 + 1] + b2 * e[2 * 4 + 2] + e[2 * 4 + 3];

    return out;
}

您的代码需要 35665 毫秒来运行10000000000L迭代。transform2()花了 20077 毫秒,所以它的速度略低于两倍。两种方法都先预热,a[]、d[] 和 e[] 包含随机浮点数。

我想知道是否可以通过创建out参数而不是在方法内部分配它来改进事情,如果out可以在外部保存,但这在您的调用代码中可能是不可能的。然而,将它作为第四个参数添加会使它变得更糟:它必须撤消一些 HotSpot 优化。但是,当您使用 Android 时,如果可行,您可能会考虑这样做。

这是很多迭代...

于 2012-10-29T23:39:06.633 回答