总的来说,我更喜欢使用Java编程而不是C++,主要是因为库的链接更容易(没有“依赖地狱”),并且有很多功能强大的包可以直接使用。我也喜欢像jMonkey和Processing这样的Java工具。
然而,我经常需要进行一些物理方面的操作,需要快速计算3D向量的数学运算。我没有找到任何方便的方法在Java中实现性能高效且易于阅读的解决方案(C++构造,例如宏、重载运算符、结构体和通过引用传递变量等都是非常有帮助的工具)。
例如,对于一个质点在中心力场中的跳跃积分器,在C++中我可以使用类似以下代码(使用类型float3的重载运算符):
另一种避免即时分配临时对象的策略是将这些临时变量定义为静态全局变量(这不是良好的编码风格),或者作为封闭类的属性,例如:
在这两种情况下,解引用指针会产生性能开销,同时使得星体对象消耗更多内存。
调用对象方法也会有性能惩罚(即使我尝试将它们设为“final”和“static”,以便JIT可以有效地内联它们)。根据我的测试,使用float3.mult()比仅乘以3个float要慢2-3倍。
因此,我经常只使用float进行复杂的向量代数计算,以避免这些性能惩罚。但是这样做完全不可读。这种方式在刚体动力学和空气动力学计算中非常痛苦。这就像40年前的Fortran77程序一样糟糕!(只是出于好奇,可以查看Xfoil的代码)
您建议在Java中执行矢量数学的策略既能提高性能又方便(可读性)?
然而,我经常需要进行一些物理方面的操作,需要快速计算3D向量的数学运算。我没有找到任何方便的方法在Java中实现性能高效且易于阅读的解决方案(C++构造,例如宏、重载运算符、结构体和通过引用传递变量等都是非常有帮助的工具)。
例如,对于一个质点在中心力场中的跳跃积分器,在C++中我可以使用类似以下代码(使用类型float3的重载运算符):
float ir2 = 1.0f/dot(vec_pos,vec_pos);
float ir = sqrt(ir2);
float3 vec_G = -vec_pos / (ir2*ir);
vec_v += vec_G*dt;
vec_pos += vec_v*dt;
Java中易读的代码应该长这样:
float ir2 = 1.0f/vec_pos.mag2();
float ir = sqrt(ir2);
float3 vec_G = vec_pos.mult( -ir2*ir);
vec_v .addLocal( vec_G.multLocal( dt ) );
vec_pos .addLocal( vec_v.mult ( dt ) );
这样做对性能不是很好,因为它会分配新的对象作为临时变量,而在无法使用“Local”方法的情况下。我可以通过定义新的融合乘加方法来进行优化,例如:
float ir2 = 1.0f/vec_pos.mag2();
float ir = sqrt(ir2);
float3 vec_G = vec_pos.mult( -ir2*ir);
vec_v .addLocal_vec_times_scalar( vec_G, dt );
vec_pos .addLocal_vec_times_scalar( vec_v, dt );
但是为所有可能的float3向量算术运算定义专门的方法并不是很方便,比如:
float3.addLocal_vec1_times_vec2_times_scalar()
另一种避免即时分配临时对象的策略是将这些临时变量定义为静态全局变量(这不是良好的编码风格),或者作为封闭类的属性,例如:
class asteroide{
// state variables
float3 vec_pos;
float3 vec_v;
// temporary variables
float3 vec_G,vec_dpos;
void update_leapfrog(float dt){
float ir2 = 1.0f/vec_pos.mag2();
float ir = sqrt(ir2);
vec_G .set_mult( vec_pos, -ir2*ir );
vec_v .addLocal( vec_G.multLocal( dt ) );
dpos .set_mult( vec_v, dt );
vec_pos .addLocal( dpos );
}
}
在这两种情况下,解引用指针会产生性能开销,同时使得星体对象消耗更多内存。
调用对象方法也会有性能惩罚(即使我尝试将它们设为“final”和“static”,以便JIT可以有效地内联它们)。根据我的测试,使用float3.mult()比仅乘以3个float要慢2-3倍。
因此,我经常只使用float进行复杂的向量代数计算,以避免这些性能惩罚。但是这样做完全不可读。这种方式在刚体动力学和空气动力学计算中非常痛苦。这就像40年前的Fortran77程序一样糟糕!(只是出于好奇,可以查看Xfoil的代码)
您建议在Java中执行矢量数学的策略既能提高性能又方便(可读性)?