2

与仅使用托管代码相比,在 c# 中使用指针是否具有显着的性能优势?指针的最佳用例在 c# 中是什么?我真的没有任何具体的例子,而且我以前从来不需要使用它们。似乎使用指针可以更快地操作数据,但最终可能一切都只是微不足道的。我什至考虑它们的唯一原因是因为我正在创建一个 Matrix 类(仅用于学习目的)并且我想尝试使所有计算尽可能高效。

4

6 回答 6

11

与仅使用托管代码相比,在 c# 中使用指针是否具有显着的性能优势?

有时。

指针的最佳用例在 c# 中是什么?

对性能极为敏感的代码,以及与现有非托管代码的互操作性。

我真的没有任何具体的例子,而且我以前从来不需要使用它们。

我已经编写 C# 代码大约十年了,我不记得曾经需要在实际的“业务线”代码中使用指针。测试用例,当然。但不适用于生产。

我想尝试使所有计算尽可能高效。

我在 StackOverflow 上听到了很多。不,你实际上不想那样。在给定一定预算的情况下,您希望使它们尽可能高效。例如,您可能不愿意在新的数学芯片制造上投资数十亿美元。 有些人愿意这样做,但你不是其中之一。有些人有那么多钱可以花,如果他们有技术,他们可以解决问题并从中获利。给定一组现有技术,并愿意投入一定的时间和精力,您可能愿意使其尽可能高效。因为您的目标实际上并不是编写快速数学,所以您的目标是学习如何优化程序。

在这种情况下,学习如何优化程序。优化程序的方式是使用分析工具识别代码中的问题点,然后根据数据决定是否探索不安全代码解决方案的成本和收益。例如,您的大部分成本可能是由于缓存未命中,而您真正需要的是更好的局部性,而不是更少的数组范围检查。或者,也许您会发现对于您的问题空间,记忆是一种更好的技术。有很多方法可以让程序更快,但如果没有数据,你无法知道自己是否会变得更好。

于 2013-05-01T00:03:36.723 回答
3

这个问题没有明确的答案,但是使用unsafe带有固定结构的代码(你称之为“指针”)可以带来性能优势,例如,当你在一个非常紧凑的循环中循环一个数组时,需要尽可能高的速度,但是不需要边界检查。您的里程将根据您在循环中所做的事情而有所不同,但我已经看到通过简单地声明一个方法来提高 10% 的速度unsafe

于 2013-04-30T21:54:03.037 回答
1

C# 中的指针有两个主要用例:

  1. 必须: 对于本机互操作或非托管内存数据结构。
  2. 您想摆脱数组边界检查或做一些其他无法验证的事情。

在其他情况下,它没有帮助。对于无论如何都消除了边界检查的数组,它也无济于事。

它还可能损害当前 JIT 的代码质量,因为它没有特别针对原始指针进行优化。

无论如何:重要的是要了解它为什么会有所帮助,这样您就可以预测它在哪些方面会有所帮助,在哪些方面会无用。

与 C 编译器所做的相比,在 C# 中变得不安全并不算什么。AC 编译器执行 JIT 从未听说过的事情。它不是“C 模式”。(当前的 JIT 不好,也无济于事)。

于 2013-04-30T22:00:14.390 回答
1

使用非托管代码总是会更快地运行;使用托管代码总是会更快上市。决定需要多少非托管代码以使您的应用程序足够快以随后依靠硬件改进是一个工程权衡。

标准方法主要是为了“更快上市”,然后在事后调整关键的已知问题领域。这具有显着的优势:

  1. 编写干净的托管代码所获得的时间是“在银行中”,并且可以根据需要有效地重新集中以解决已知问题。
  2. 重写干净的托管代码以获得更好的性能比恢复编写不必要的高度调整代码所花费的时间更容易。

这里明确的推论是倾向于编写更多托管代码比相反更安全。

于 2013-04-30T22:03:37.170 回答
0

当您不受管理时,几乎所有事情都会更快。快多少,取决于许多因素。选择最关键的部分并进行一些测试。

于 2013-04-30T21:56:22.687 回答
0

这完全取决于您如何在 unsafe 块中编写代码。非托管代码具有更高的性能上限,但是,如果您没有正确编写它,性能可能会比 C# 默认提供的性能差得多。例如,如果您使用指针来更有效地访问数组中的元素,那么性能提升将会很大。如果您只是将它们用作对通常分配给Obj myObj = new Obj()它的对象的引用,则可能不会有任何不同。

于 2013-04-30T22:01:32.507 回答