다음 코드로 인해 어려움을 겪고 있습니다. 중력장에서 움직이는 별 모델링에 사용되는 Forward-Euler algorithm의 F # 구현입니다.F #에서 중첩 루프의 래핑 취소
let force (b1:Body) (b2:Body) =
let r = (b2.Position - b1.Position)
let rm = (float32)r.MagnitudeSquared + softeningLengthSquared
if (b1 = b2) then
VectorFloat.Zero
else
r * (b1.Mass * b2.Mass)/(Math.Sqrt((float)rm) * (float)rm)
member this.Integrate(dT, (bodies:Body[])) =
for i = 0 to bodies.Length - 1 do
for j = (i + 1) to bodies.Length - 1 do
let f = force bodies.[i] bodies.[j]
bodies.[i].Acceleration <- bodies.[i].Acceleration + (f/bodies.[i].Mass)
bodies.[j].Acceleration <- bodies.[j].Acceleration - (f/bodies.[j].Mass)
bodies.[i].Position <- bodies.[i].Position + bodies.[i].Velocity * dT
bodies.[i].Velocity <- bodies.[i].Velocity + bodies.[i].Acceleration * dT
이 기능이 작동하는 것은 정확하게 "기능적"이지 않습니다. 또한 끔찍한 성능으로 인해 C# 코드보다 2.5 배 더 느립니다. 본문은 본문 유형의 구조체 배열입니다.
힘들다는 것은 고가의 함수이므로 대개 한 쌍씩 계산하면 Fij = -Fji라는 사실에 의존한다는 것입니다. 그러나 이것은 펼쳐지는 루프를 정말로 엉망으로 만듭니다.
감사의 말씀을드립니다! 없음이
감사합니다,
에이드 ... 숙제없는
업데이트 : 몸과 VectorFloat을 명확히하기 위해가 C#을 구조체로 정의됩니다. 이것은 프로그램이 F #/C#과 C++/CLI 사이에서 상호 작용하기 때문입니다. 결국 나는 BitBucket에서 코드를 얻으 려하지만, 진행중인 작업을하기 전에 정리할 문제가 있습니다.
[StructLayout(LayoutKind.Sequential)]
public struct Body
{
public VectorFloat Position;
public float Size;
public uint Color;
public VectorFloat Velocity;
public VectorFloat Acceleration;
'''
}
[StructLayout(LayoutKind.Sequential)]
public partial struct VectorFloat
{
public System.Single X { get; set; }
public System.Single Y { get; set; }
public System.Single Z { get; set; }
}
벡터는 표준 Vector 클래스에 대해 예상되는 연산자 종류를 정의합니다. 이 경우에는 .NET Framework에서 Vector3D 클래스를 사용할 수 있습니다. 실제로이 프레임 워크에 대한 조사가 진행 중입니다.
UPDATE 2 향상된 코드 아래의 처음 두 응답에 기초 :
for i = 0 to bodies.Length - 1 do
for j = (i + 1) to bodies.Length - 1 do
let r = (bodies.[j].Position - bodies.[i].Position)
let rm = (float32)r.MagnitudeSquared + softeningLengthSquared
let f = r/(Math.Sqrt((float)rm) * (float)rm)
bodies.[i].Acceleration <- bodies.[i].Acceleration + (f * bodies.[j].Mass)
bodies.[j].Acceleration <- bodies.[j].Acceleration - (f * bodies.[i].Mass)
bodies.[i].Position <- bodies.[i].Position + bodies.[i].Velocity * dT
bodies.[i].Velocity <- bodies.[i].Velocity + bodies.[i].Acceleration * dT
의 B1 == B2를 케이스를 덮도록 강제 함수의 분기 최악 범죄자이다. softeningLength가 매우 작 으면 (Epsilon) 항상 0이 아닌 경우에는 필요하지 않습니다. 이 최적화는 C# 코드에는 있지만 F # 버전에는 없었습니다 (doh!).
Math.Pow (x, -1.5)는 1/(Math.Sqrt (x) * x)보다 훨씬 느린 것 같습니다. 본질적으로이 알고리즘은 퍼포먼스가이 한 단계의 비용에 의해 결정된다는 점에서 약간 이상합니다.
강제 계산을 인라인으로 이동하고 일부 나누기를 제거하면 성능이 약간 향상되지만 성능은 실제로 분기에 의해 종료되고 Sqrt의 비용에 의해 좌우됩니다. 구조체를 통해
WRT 사용하여 클래스 : 내가 관리되지 않는 코드로 또는 GPU에 몸의 배열을 얻을 필요가 경우 (CUDA와이 코드의 네이티브 C++ 구현과 DX9 렌더러)이 있습니다. 이러한 시나리오에서 메모리를 연속적으로 memcpy 할 수있는 것처럼 보입니다. 내가 신체 계급의 배열로부터 얻을 것 인 무엇인가.
감사합니다. 이제는 C#과 비슷한 성능의 F # 통합자를 얻었습니다. 그러나 (rm ** -1.5)는 상당한 성능 저하를 나타냅니다. ((float32) (Math.Sqrt ((float) rm)) * rm)이 빠를 것 같습니다. –