问题标签 [visual-c++-2017]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
0 回答
112 浏览

c++ - 为什么 VS C++ 2017 编译器仅在迭代指针未存储在结构中时才使用 SSE 优化?

动机很简单:我遍历两个 uint64 数组、位和它们的值,并将结果存储在第三个数组中。然而,在我推广以结构形式接受输入的解决方案后,代码速度大大减慢,我发现生成的程序集完全不同。我的问题是为什么会这样,我该如何防止这种行为?(有关动机的更多详细信息,请参阅问题末尾的注释。)

最小化的代码如下所示:

FooBitAndExpression编译成:

whileFooBitAndRaw被编译成:

请注意,我对汇编程序的了解非常有限,我的结论是基于猜测。如果我正确理解生成的程序集,该FooBitAndRaw函数会使用 sse 指令循环遍历迭代数据。当剩余空间太小时,它会退回到对单个值的迭代。

然而,该FooBitAndExpression函数并没有这样做,而是立即迭代单个值。据我了解,除了两个内联的方法调用外,两种实现在高级指令中都是相同的。

已经发现C# 的 JIT 不会对用于迭代的局部结构变量中的变量使用寄存器,这会大大降低应用程序的速度。显然,MS Visual C++在类似的情况下使用了寄存器,但它让我想到了一个子问题:如果变量存储在本地结构中,是否有类似的限制不允许使用 sse 优化?

更多细节和注意事项:

  • 我相信这不是一个过早的优化。最初,我只是将布尔值存储为完全不同结构的成员变量,并在我想对这些字段运行逻辑操作时简单地迭代这些结构的数组。它被指定用于一定数量的元素。然而,输入的数量级增加了,代码非常慢。因此,作为一种优化,我实现了基于位域的结构来存储某些布尔值。我工作的大部分系统都是 O(N),但是使用这些位域技巧的部分是 O(M*N),所以即使是微小的变化也会对性能产生很大影响。
  • 当我尝试通过展开循环来优化实现时,我注意到了这种行为。FooBitAndExpression速度更快,而速度FooBitAndRaw却大大减慢,这是出乎意料的,所以我进行了调查-发现了这一点。
  • 我的主要动机/目标是什么:在分析之后,我发现了代码中最薄弱的部分并对其进行了优化(例如通过实现FooBitAndRaw)。但是,代码变得不那么可读了,所以现在我想在不影响性能的情况下返回一些可读性。我打算将一些源数据和操作封装在结构中。目前,使用优化位操作的代码必须在每行代码中注释以描述意图,因为从需要 6 个以上参数的函数调用中并不清楚。
  • 这只是一个例子。我还为逻辑或异或、某种比较等实现了类似的功能。这就是我实现FooBitAndExpression功能的原因。下一步是将其更改为模板以支持各种输入表达式。
  • 我在 Windows 10 上使用 Visual Studio C++ 2017。