这是检索和存储 QueryPerformanceCounter 检索值的最快方法吗?

如何解决这是检索和存储 QueryPerformanceCounter 检索值的最快方法吗?

我正在尝试用 VBA 编写一个基准测试程序。我的目标是尽可能多地排除延迟(基准)代码的因素。在测试中,LongLong 似乎比 Currency 快一点,但每个人都使用 UDT 或 Currency 数据类型。

我的主要问题是:检索到的 QPC 值的最佳数据类型是什么?

为了尽量减少调用基准程序的时间,最好的方法似乎是将检索到的 QueryPerformanceCounter (QPC) 值存储在一个数组中。然后在基准代码完成后处理存储的值。由于处理发生在之后,我不关心处理值本身所需的时间。 Windows API kernel32 函数 QPC 的返回类型为 LARGE_INTEGER:

typedef union _LARGE_INTEGER {
  struct {
    DWORD LowPart;
    LONG  HighPart;
  } DUMMYSTRUCTNAME;
  struct {
    DWORD LowPart;
    LONG  HighPart;
  } u;
  LONGLONG QuadPart;
} LARGE_INTEGER;

根据您使用的是 64 位系统,有两种或三种选择可以在 VBA 中捕获此数据类型:

  1. 具有两个 Long 值的用户定义类型 (UDT)(引导 u.LowPart 和 u.HighPart)
  2. Currency 捕获并转换 Quadpart ???
  3. LongLong 捕获 QuadPart(仅适用于 64 位 Office)

由于调用 QPC 函数比存储值本身花费更多的时间,我无法直接测试什么是最佳选择。但是,我确实测试了存储这些数据类型本身的值的最有效方法是什么。存储 UDT(设置其值之一 (usd.low = udt.low) 或仅将整个 UDT 实例设置为另一个实例 (udt1 = udt2))似乎比存储 LongLong、Currency 或任何其他数字花费两倍的时间数据类型相同。 因此,就速度而言,此选项已失效(假设差异不是因为 cpu 分支,而是因为 UDT 实际上必须存储 2 个单独的值而不是一个)。

这留下了两个选项,LongLong 和 Currency。 (或者你们中的一个人在 32 位系统上,但我不是)。 LongLongCurrency 都是 64 位(8 字节)整数数据类型,而货币据说是 VBA 提供的最准确的数据类型。它们都具有相同的范围,唯一的区别是 Currency 类型的逗号向左移动了 4 位。在测试 QPC 检索值时,货币似乎总是与放大的 LongLong 检索值相同(货币 = 10000 * LongLong)。只是为了清楚这两个值将返回什么(仅参数不同)。

Declare PtrSafe Function QueryPerformanceCounter Lib "kernel32" (tickLongLong As LongLong) As Long
Declare PtrSafe Function QueryPerformanceCounter Lib "kernel32" (tickCurrency As Currency) As Long

tickLongLong-->  3563633494792
tickCurrency-->  356363349,4792

我遇到了许多使用 UDTCurrency 数据类型的代码。它们都没有使用 LongLong 返回类型,但它似乎是最接近实际返回类型的 QuadPart,它也是 LongLong。

似乎在将 LongLong 转换为货币时,唯一需要做的就是将逗号移动 4 位。但这仍然需要一些额外的步骤。这让我认为以 LongLong 形式检索值应该(一点点)更快。我无法对其进行测试,因为调用 QPC 函数本身比将检索到的 LongLong 类型的值转换为货币花费更多的时间。

我唯一可以测试的是存储 LongLong 或将 LongLong 转换为货币所需的时间,反之亦然。乍一看似乎没有什么区别,而且 Currency 甚至更快,但最终测试表明 LongLong 类型(超过 1000 万次迭代的循环)实际上是。

Private Type Tudt
    low As Long
    high As Long
End Type
Private Sub test()
Dim i As Long,timer As Currency
Dim udt As Tudt: udt.low = 1000&: udt.high = 1000&
Dim lonlon As LongLong: lonlon = 1000^
Dim cur As Currency: cur = 1000@
Dim arUdt() As Tudt: ReDim arUdt(1 To 10000000)
Dim arLonlon() As LongLong: ReDim arLonlon(1 To 10000000)
Dim arCur() As Currency: ReDim arCur(1 To 10000000)

timer = MicroTimer
For i = 2 To 10000000 '10 million (63 milliseconds when empty)

''assigning the same value to each element in the array
arUdt(i).low = 1&      '165 milliseconds
arUdt(i) = udt         '215 milliseconds
arLonlon(i) = 1^       '103 milliseconds
arCur(i) = 1@          '103 milliseconds
'conclusion: setting only one of the UDT bounds
'already takes more then 50% more time. Setting
'a whole udt (what would be returned by the QPC)
'takes twice the time.

'assigning a random value in the array to exclude branching
arLonlon(i) = CLngLng(Int((1000 * Rnd) + 1))   '611-625 milliseconds
arCur(i) = CCur(Int((1000 * Rnd) + 1))         '580-595 milliseconds
'conclusion: assinging a random LongLong value
'takes longer,possibly because of Int conversion?

'excluding branching and int conveRSSion by assigning the value of the prevIoUs assigned value
If arLonlon(i - 1) = 2^ Then arLonlon(i) = 3^ Else arLonlon(i) = 2^ '270 milliseconds
If arCur(i - 1) = 2@ Then arCur(i) = 3@ Else arCur(i) = 2@          '380 milliseconds
'conclusion: excluding more cpu branching assigning
'a value to a LongLong datatype does seem to be a
'little faster.

Next i
Debug.Print MicroTimer - timer
End Sub

最后的测试表明,存储大量 LongLong 值比 Currency 快一点。

问题 1

我发现的所有代码片段都使用 Currency 或 UDT,没有一个使用 LongLong。但是LongLong要快一些。我假设选择 Currency 数据类型而不是 LongLong,因为 Currency 在 32 位系统上也可用。还有其他原因吗?

问题 2

货币不是 QPC docLargeInteger doc 中提到的数据类型之一。这意味着 VBA 将数据类型转换为货币,当它用作参数/检索值的数据类型时。我可以想象 VBA 只是存储所选数据类型的基数开始的数字(检索值的)(货币的基数是逗号右侧的第 4 个数字)。这是真的?如果是这样,它是否仍然可以命名为“转换”/是否需要更多步骤或时间让 cpu 将值放入货币数据类型?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?