所以我正在尝试优化一些代码。我有一个可变大小的循环函数。然而,为了提高效率,我想制作具有1,2和3大小的循环的特殊情况,这些特殊情况是完全展开的。到目前为止,我的方法是将循环大小声明为const参数,然后定义包装函数,该函数调用main函数,为const值处理文字。我已经包含了一个代码片段,它说明了我的想法。
inline void someFunction (const int a)
{
for (int i=0; i<a; i++)
{
// do something with i.
}
}
void specialCase()
{
someFunction (3);
}
void generalCase(int a)
{
someFunction (a);
}
所以我的问题是,我希望我的编译器(GCC)在specialCase中展开for循环是合理的。我的意思是显然我可以复制 - 将someFunction的内容粘贴到specialCase中并用3代替,但为了清楚起见,我宁愿只在代码中处理someFunction的一个定义。
答案 0 :(得分:2)
然而,为了提高效率,我想制作具有1,2和3大小的循环的特殊情况,这些特殊情况是完全展开的。
您是否测量过这实际上更快?我怀疑它会是什么(或者编译器不会自动展开循环)。
到目前为止,我的方法是将循环大小声明为const参数,然后定义调用main函数的包装函数,并将其作为const值的文字。
import React, {Component} from 'react';
import {connect} from 'react-redux'
import ReduxFormHelper from 'redux-form-helper'
class MyForm extends Component {
constructor(props) {
super(props);
this.helper = new ReduxFormHelper(props)
this.helper.resetForm();
}
onChange(e) {
this.helper.processField(e)
}
onSubmit(e) {
e.preventDefault()
let {onSubmitForm} = this.props
let ret = this.helper.processForm(e)
ret && onSubmitForm(ret)
}
render() {
let {formData, formErrors} = this.props
return (
<div>
{!!formErrors._flag &&
<div className="alert" role="alert">
Form has one or more errors.
</div>
}
<form onSubmit={this.onSubmit.bind(this)} >
<div className={'form-group' + (formErrors['field1']? ' has-error': '')}>
<label>Field 1 *</label>
<input type="text" name="field1" value={formData.field1} onChange={this.onChange.bind(this)} className="form-control" />
{!!formErrors['field1'] &&
<span className="help-block">
{formErrors['field1'] === 'invalid'? 'Must be a string of 2-50 characters' : 'Required field'}
</span>
}
</div>
...
<button type="submit" className="btn btn-default">Submit</button>
</form>
</div>
)
}
}
const formModel = {
field1: {
required: true,
validate: (value) => value.length >= 2 && value.length <= 50
},
...
}
function mapStateToProps (state) {
return {
formData: state.formData, formErrors: state.formErrors,
formModel
}
}
function mapDispatchToProps (dispatch) {
return {
onUpdateForm: (data, errors) => {
dispatch(doFormUpdate(data, errors))
},
onSubmitForm: (data) => {
// dispatch some action which somehow updates state with form data
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MyForm)
在这里没有任何意义。它不会影响编译器展开循环的能力。它只是意味着const
不能在函数体内变异,但它仍然是运行时参数。
如果您想确保展开,请强行退出。使用C ++ 17非常容易。
a
答案 1 :(得分:2)
如果您不喜欢模板并且不信任您的编译器,那么总会有这种方法,它受到手动展开称为“duff设备”的循环的过时方法的启发:
void do_something(int i);
void do_something_n_times(int n)
{
int i = 0;
switch(n)
{
default:
while(n > 3) {
do_something(i++);
--n;
}
case 3: do_something(i++);
case 2: do_something(i++);
case 1: do_something(i++);
}
}
但我认为值得一提的是,如果你不相信你的编译器会为你做一个像循环展开这么简单的事情,那么可能是时候考虑一个新的编译器了。
请注意,Duff的设备最初被发明为用编译器编译的程序的微优化策略,这些编译器不会自动应用循环展开优化。
它是由汤姆达夫于1983年发明的。
https://en.wikipedia.org/wiki/Duff%27s_device
它与现代编译器的使用是值得怀疑的。
答案 2 :(得分:1)
如果你愿意使用所有流行编译器的强制内联(非标准)功能,我宁愿这样做:
__attribute__((always_inline))
void bodyOfLoop(int i) {
// put code here
}
void specialCase() {
bodyOfLoop(0);
bodyOfLoop(1);
bodyOfLoop(2);
}
void generalCase(int a) {
for (int i=0; i<a; i++) {
bodyOfLoop(i);
}
}
注意:这是GCC / Clang解决方案。将__forceinline
用于MSVC。