我需要高性能。如果我使用 C 或 C++ 会有区别吗?
我需要编写一个程序(大学项目)来解决(大约)一个 NP 难题。 它是线性排序问题的变体。 一般来说,我会有非常大的输入(如图表)并尝试找到最佳解决方案 (基于会对每个解决方案进行“评分”的函数)
如果我用 C 风格代码(一个主要的和函数)编写此代码,会有什么不同吗? 或者构建一个 Solver 类,创建一个实例并从 main 调用“run”方法(类似于 Java)
此外,每次迭代中都会进行大量浮点数学运算。
谢谢!
I need to write a program (a project for university) that solves (approx) an NP-hard problem.
It is a variation of Linear ordering problems.
In general, I will have very large inputs (as Graphs) and will try to find the best solution
(based on a function that will 'rate' each solution)
Will there be a difference if I write this in C-style code (one main, and functions)
or build a Solver class, create an instance and invoke a 'run' method from a main (similar to Java)
Also, there will be alot of floating point math going on in each iteration.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
不会。
最大的性能提升/缺陷将在于您实现的算法,以及您执行了多少不需要的工作(不需要的工作可能是从重新计算可能已缓存的先前值到使用太多的 malloc/free 与使用内存之间的一切)泳池、
按值而不是引用传递大型不可变数据)
No.
The biggest performance gains/flaws will be on the algorithm you implement, and how much unneeded work you perform (Unneeded work could be everything from recalculating a previous value that could have been cached, to using too many malloc/free's vs using memory pools,
passing large immutable data by value instead of reference)
实现最佳代码的最大障碍不再是语言(对于正确编译的语言),而是程序员。
The biggest roadblock to optimal code is no longer the language (for properly compiled languages), but rather the programmer.
不可以,除非您使用虚函数。
编辑:如果您需要运行时动态性,那么是的,虚拟函数与手动构造的
if-else
语句一样快或更快。但是,如果您在方法前面添加 virtual 关键字,但实际上并不需要多态性,那么您将付出不必要的开销。编译器不会在编译时优化它。我只是指出这一点,因为它是 C++ 的功能之一,打破了“零开销原则”(引用 Stroustrup)。作为旁注,由于您提到大量使用 fp 数学:
-mfpmath=sse
、-ffast- math
和-mrecip
(最后两个“有点危险”,这意味着它们可能会在边缘情况下为您提供奇怪的结果以换取速度。第一个会稍微降低精度-- 您有 64 位双精度数而不是 80 位双精度数 -- 但通常不需要这种额外的精度。)这些标志对于 C 和 C++ 编译器同样有效。INFINITY
必须由处理器作为特殊情况进行处理。No, unless you are using virtual functions.
Edit: If you have a case where you need run-time dynamism, then yes, virtual functions are as fast or faster than a manually constructed
if-else
statement. However, if you drop in thevirtual
keyword in front of a method, but you don't actually need the polymorphism, then you will be paying an unnecessary overhead. The compiler won't optimize it away at compile time. I am just pointing this out because it's one of the features of C++ that breaks the 'zero-overhead principle` (quoting Stroustrup).As a side note, since you mention heavy use of fp math:
-mfpmath=sse
,-ffast-math
and-mrecip
(The last two are 'slightly dangerous', meaning that they could give you weird results in edge cases in exchange for the speed. The first one reduces precision by a bit -- you have 64-bit doubles instead of 80-bit ones -- but this extra precision is often unneeded.) These flags would work equally well for C and C++ compilers.INFINITY
with a large-but-not-infinite value gives you a good speed boost. This is because trueINFINITY
has to be handled as a special case by the processor.经验法则 - 在知道要优化什么之前不要进行优化。因此,从 C++ 开始并拥有一些工作原型。然后对其进行分析并重写装配中的瓶颈。但正如其他人指出的那样,选择的算法将比语言产生更大的影响。
Rule of thumb - do not optimize until you know what to optimize. So start with C++ and have some working prototype. Then profile it and rewrite bottle necks in assembly. But as others noted, chosen algorithm will have much greater impact than the language.
说到性能,任何可以在 C 中完成的事情都可以在 C++ 中完成。
例如,众所周知,虚拟方法“慢”,但如果这确实是一个问题,您仍然可以求助于 C 语言。
C++ 还带来了模板,这比使用
void*
进行泛型编程具有更好的性能。When speaking of performance, anything you can do in C can be done in C++.
For example, virtual methods are known to be “slow”, but if it's really a problem, you can still resort to C idioms.
C++ also brings templates, which lead to better performance than using
void*
for generic programming.Solver
类将被构造一次,我认为,并且run
方法将执行一次......在那种环境中,您不会看到任何差异。相反,需要注意以下事项:内存管理非常昂贵。如果您需要执行大量的
malloc()
操作,操作系统就会吃掉您的午餐。如果您知道很快就会再次做同样的事情,请坚决努力重用您创建的任何数据结构!实例化类通常意味着...分配内存!同样,实例化一些对象并重新使用它们几乎不需要任何成本。但要注意,创建对象只是为了拆除它们并在不久后重建它们!
在问题允许的范围内,为您的架构选择正确的浮点风格。尽管
double
需要更多内存,但它最终可能会比float
更快。您应该尝试对此进行微调。理想情况下,您将使用#define
或typedef
来指定类型,以便您可以在一处轻松更改它。整数计算可能比浮点计算更快。根据数据的数值范围,您还可以考虑使用被视为定点小数的整数来执行此操作。如果您需要 3 位小数,您可以使用
int
并将它们视为“milli-somethings”。你必须记住在除法和乘法之后移动小数......但没什么大不了的。当然,如果您使用基本算术之外的任何数学函数,那当然会消除这种可能性。The
Solver
class will be constructed once, I take it, and therun
method executed once... in that kind of environment, you won't see a difference. Instead, here are things to watch out for:Memory management is hellishly expensive. If you need to do lots of little
malloc()
s, the operating system will eat your lunch. Make a determined effort to re-use whatever data structures you create if you know you'll be doing the same kind of thing again soon!Instantiating classes generally means... allocating memory! Again, there's practically no cost for instantiating a handful of objects and re-using them. But beware of creating objects only to tear them down and rebuild them soon after!
Choose the right flavor of floating point for your architecture, insofar as the problem permits. It's possible that
double
will end up being faster thanfloat
, although it will need more memory. You should experiment to fine-tune this. Ideally, you'll use a#define
ortypedef
to specify the type so you can change it easily in one place.Integer calculations are probably faster than floating point. Depending on the numeric range of your data, you may also consider doing it with integers treated as fixed-point decimals. If you need 3 decimal places, you could use
int
s and just consider them "milli-somethings". You'll have to remember to shift decimals after division and multiplication... but no big deal. If you use any math functions beyond the basic arithmetic, of course, that would of course kill this possibility.由于两者都是编译的,并且编译器现在非常擅长如何处理 C++,我认为唯一的问题来自于代码的优化程度。我认为用 C++ 编写较慢的代码会更容易,但这取决于您的模型最适合哪种风格。
归根结底,我怀疑是否会有任何真正的区别,假设两者都写得很好,您使用的任何库,它们写得有多好,如果您在同一台计算机上进行测量。
Since both are compiled, and the compilers now are very good at how to handle C++, I think the only problem would come from how well optimized your code is. I think it would be easier to write slower code in C++, but that depends on which style your model fits into best.
When it comes down to it, I doubt there will be any real difference, assuming both are well-written, any libraries you use, how well written they are, if you are measuring on the same computer.
与文件输入和算法本身相比,函数调用与成员函数调用开销不太可能成为限制因素。 C++ iostream 不一定是超高速。如果你真的在优化,C 有“限制”,在 C++ 中内联函数调用更容易。总的来说,C++ 提供了更多的选项来清晰地组织代码,但如果它不是一个大程序,或者您只是以类似的方式编写它,无论是 C 还是 C++,那么 C 库的可移植性就变得更加重要。
Function call vs. member function call overhead is unlikely to be the limiting factor, compared to file input and the algorithm itself. C++ iostreams are not necessarily super high speed. C has 'restrict' if you're really optimizing, in C++ it's easier to inline function calls. Overall, C++ offers more options for organizing your code clearly, but if it's not a big program, or you're just going to write it in a similar manner whether it's C or C++, then the portability of C libraries becomes more important.
只要您不使用任何虚拟函数等,您就不会注意到任何显着的性能差异。早期的 C++ 被编译为 C,因此只要您知道这会产生任何相当大的开销(例如虚函数),您就可以清楚地计算出差异。
此外,我想指出,如果您使用 STL 和 Boost 库,那么使用 C++ 可以给您带来很多好处。特别是STL提供了最重要的数据结构和算法的非常高效且经过验证的实现,因此您可以节省大量的开发时间。
实际上,它还取决于您将使用的编译器以及它将如何优化代码。
As long as you don't use any virtual functions etc. you won't note any considerable performance differences. Early C++ was compiled to C, so as long as you know the pinpoints where this creates any considerable overhead (such as with virtual functions) you can clearly calculate for the differences.
In addition I want to note that using C++ can give you a lot to gain if you use the STL and Boost Libraries. Especially the STL provides very efficient and proven implementations of the most important data structures and algorithms, so you can save a lot of development time.
Effectively it also depends on the compiler you will be using and how it will optimize the code.
首先,用C++编写并不意味着使用OOP,看看STL算法。
其次,C++ 在运行时甚至可以稍微快一些(与 C 相比,编译时间可能很糟糕,但这是因为现代 C++ 往往严重依赖抽象,这会给编译器带来负担)。
编辑:好的,请参阅 Bjarne Stroustrup 的 对 qsort 的讨论和 std::sort,以及 FAQ 提到的文章(学习标准C++ 作为一种新语言),他在其中展示了 C++ 风格的代码不仅可以更短、更易读(因为有更高的抽象),而且速度也更快。
first, writing in C++ doesn't imply using OOP, look at the STL algorithms.
second, C++ can be even slightly faster at runtime (the compilation times can be terrible compared to C, but that's because modern C++ tends to rely heavily on abstractions that tax the compiler).
edit: alright, see Bjarne Stroustrup's discussion of qsort and std::sort, and the article that FAQ mentions (Learning Standard C++ as a New Language), where he shows that C++-style code can be not only shorter and more readable (because of higher abstractions), but also somewhat faster.
另一方面:
C++ 模板可以成为生成特定类型/
优化的代码变体。
例如,C qsort 需要对比较器进行函数调用,而 std::sort 可以内联传递的函子。当比较和交换本身很便宜时,这可以产生显着的差异。
请注意,您可以使用一系列定义或代码生成器或手动生成针对各种类型进行优化的“自定义 qsorts” - 您也可以在 C 中进行这些优化,但成本要高得多。
(它不是通用武器,模板仅在特定情况下有帮助 - 通常将单个算法应用于不同的数据类型或注入不同的小代码片段。)
Another aspect:
C++ templates can be an excellent tool to generate type-specific /
optimized code variations.
For example, C
qsort
requires a function call to the comparator, whereasstd::sort
can inline the functor passed. This can make a significant difference when compare and swap themselves are cheap.Note that you could generate "custom qsorts" optimized for various types with a barrage of defines or a code generator, or by hand - you could do these optimizations in C, too, but at much higher cost.
(It's not a general weapon, templates help only in sepcific scenarios - usually a single algorithm applied to different data types or with differing small pieces of code injected.)
好的答案。我会这样说:
使算法在形式结构方面尽可能高效。
C++ 将和 C 一样快,除了它会诱惑你做一些愚蠢的事情,比如构造你不需要的对象,所以不要上当。像 STL 容器类和迭代器这样的东西可能看起来是最新、最伟大的东西,但它们会在热点中杀死你。
即便如此,请在反汇编级别单步执行它。您应该会看到它非常直接地解决您的问题。如果要花费大量周期进入和退出例程,请尝试一些内联(或宏)。如果大部分时间都在内存分配和释放中徘徊,请停止这种情况。如果它有内部循环,其中循环开销占很大比例,请尝试展开循环。
这样你就可以尽可能快地完成它。
Good answers. I would put it like this:
Make the algorithm as efficient as possible in terms of its formal structure.
C++ will be as fast as C, except that it will tempt you to do dumb things, like constructing objects that you don't have to, so don't take the bait. Things like STL container classes and iterators may look like the latest-and-greatest thing, but they will kill you in a hotspot.
Even so, single-step it at the disassembly level. You should see it very directly working on your problem. If it is spending lots of cycles getting in and out of routines, try some in-lining (or macros). If it is wandering off into memory allocation and freeing, for much of the time, put a stop to that. If it's got inner loops where the loop overhead is a large percentage, try unrolling the loop.
That's how you can make it about as fast as possible.
我肯定会选择 C++。如果您仔细设计并避免在热点内创建重对象,您不应该看到任何性能差异,但代码将更易于理解、维护和扩展。
明智地使用模板和类。通过引用传递对象来避免不必要的对象创建。避免过多的内存分配,如果需要,请在热点之前分配内存。在内存指针上使用限制关键字来告诉编译器指针是否重叠。
至于优化,请特别注意内存对齐。假设您正在使用英特尔处理器,则可以使用向量指令,前提是您通过编译指示告诉编译器有关内存对齐和别名指针的信息。您还可以通过内在函数直接使用向量指令。
您还可以使用模板自动创建热点代码,并让编译器优化它(如果您有不同大小的短循环之类的东西)。要了解性能并深入了解瓶颈,英特尔 vtune 或 oprofile 非常有帮助。
希望有帮助
I would go with C++ definitely. If you are careful about your design and avoid creating heavy objects inside hotspots you should not see any performance difference but the code is going to be much simpler to understand, maintain, and expand.
Use templates and classes judiciously. avoid unnecessary object creation by passing objects by reference. Avoid excessive memory allocation, if needed, allocate memory in advance of hotspots. Use restrict keyword on memory pointers to tell compiler whenever pointers overlap or not.
As far as optimization, pay careful attention to memory alignment. Assuming you are working on Intel processor, you can make use of vector instructions, provided you tell the compiler through pragma's about your memory alignment and aliased pointers. you can also use vector instructions directly via intrinsics.
you can also automatically create hotspot code using templates and let compiler optimize it out if you have things like short loops of different sizes. To find out performance and to drill down to your bottlenecks, Intel vtune or oprofile are extremely helpful.
hope that helps
我做了一些 DSP 编码,有时使用汇编语言仍然有好处。我建议使用 C 或 C++,无论其中一种,并准备在需要时使用汇编语言,尤其是利用 SIMD 指令。
I do some DSP coding, where it still pays off to go to assembly language sometimes. I'd say use C or C++, either one, and be prepared to go to assembly language when you need to, especially to exploit SIMD instructions.