0

我需要使用稍微不同的类型在高级应用程序和低级子系统之间实现一个包装层:

该应用程序生成一个单向量数组:

unit unApplication
type

TVector = record
  x, y, z : single;
end;

TvectorArray = array of Tvector;

procedure someFunc(): tvectorArray;
[...]

而子系统需要一个双向量数组。我还实现了从 tvector 到 Tvectord 的类型转换:

unit unSubSystem
type

TVectorD = record
  x, y, z : double;
  class operator Implicit(value : t3dVector):t3dvectorD;inline;
end;

TvectorDArray = array of TvectorD;

procedure otherFunc(points: tvectorDArray);

implementation 
    class operator T3dVecTorD.Implicit(value : t3dVector):t3dvectorD;
begin
  result.x := value.x;
  result.y := value.y;
  result.z := value.z;
end;

我目前正在做的事情是这样的:

uses unApplication, unsubsystem,...
procedure ConvertValues
var
  singleVecArr : TvectorArray;
  doubleveArr :  TvectorDArray; 
begin
  singleVecArr := somefunc;
  setlength(doubleVecArray, lenght(singlevecArr));
  for i := 0 to length(singlevecArr) -1 do
    doubleVecArray[i] := singleVecArr[i];
end;

有没有更有效的方法来执行这些类型的转换?

4

3 回答 3

1

首先,我想说的是,如果没有第一次计时,您不应该尝试任何优化。在这种情况下,我不是指计时替代算法,我指的是计时有问题的代码并评估在那里花费的总时间的比例。

我的直觉告诉我,你展示的代码将只运行一小部分时间,因此优化它不会产生明显的好处。我认为如果你对这个数组的每个元素做任何有意义的事情,那么这一定是真的,因为与浮点运算相比,从单精度转换为双精度的成本会很小。

最后,如果这个代码可能是一个瓶颈,你应该考虑根本不转换它。我的假设是您正在使用映射到 8087 FPU 的标准 Delphi 浮点运算。所有此类浮点操作都发生在 8087 浮点堆栈中。值在输入时转换为 64 或更通常为 80 位精度。我不认为加载单张比加载双张要慢——事实上,由于内存读取性能,它甚至可能更快。

于 2011-02-01T08:24:10.147 回答
1

假设转换确实是瓶颈,那么加速转换的一种方法可能是使用 SSE# 而不是 FPU,前提是可以假设必要的指令集存在于运行此代码的计算机上。

例如,以下将一个单向量转换为一个双向量:

procedure SingleToDoubleVector (var S: TVector; var D: TVectorD);
// @S in EAX
// @D in EDX
asm
  movups    xmm0, [eax]     ;// Load S in xmm0
  movhlps   xmm1,  xmm0     ;// Copy High 2 singles of xmm0 into xmm1
  cvtps2pd  xmm2,  xmm0     ;// Convert Low two singles of xmm0 into doubles in xmm2
  cvtss2sd  xmm3,  xmm1     ;// Convert Lowes single in xmm1 into double in xmm1
  movupd   [edx],  xmm2     ;// Move two doubles in xmm2 into D (.X and .Y)
  movsd    [edx+16],xmm3    ;// Move one double from xmm3 into D.Z
end;

我并不是说这段代码是最有效的方法,一般使用汇编代码有很多注意事项,特别是这段代码。请注意,此代码对记录中字段的对齐方式进行了假设。(它不对整个记录的对齐方式做出假设。)

此外,为了获得最佳结果,您可以控制内存中数组/记录元素的对齐方式,并在汇编中编写整个转换循环,以减少开销。这是否是您想要/可以做的,是另一个问题。

于 2011-02-01T10:23:02.577 回答
0

如果修改源以产生双打而不是单打是不可能的,您可以尝试线程化该过程。尝试将 TArray 分成两个或四个大小相等的块(取决于处理器数量)并让每个线程进行转换。这样做将实现几乎两倍或四倍的速度。

另外,“长度”调用是否计算每个循环?也许将其放入变量中以避免计算。

于 2011-02-01T05:49:49.203 回答