如何使此代码更快(学习最佳实践)
How to make this code faster (learning best practices)?
我这里有一个小循环,我想知道我是否犯了一些大错误,性能明智。
例如,有没有办法以不同的方式重写其中的某些部分,使矢量化成为可能(假设GCC4.8.1和所有vecotrization友好标志都已启用)?
这是向列表传递数字(常量浮点数 name_of_var[])的最佳方法吗?
代码的思想是获取(未排序数)y
的向量(在数学意义上,不一定是 std::vector)和两个绑定值 (ox[0]<=ox[1]
),并将整数向量存储在整数向量中rdx
满足 ox[0]<=y[i]<=ox[1] y
条目的索引i
。
rdx
可以包含m
元素,y
具有容量n
和n>m
。如果超过 m
满足 ox[0]<=y[i]<=ox[1] y[i]
的值,则代码应返回第一个m
提前感谢,
void foo(const int n,const int m,const float y[],const float ox[],int rdx[]){
int d0,j=0,i=0;
for(;;){
i++;
d0=((y[i]>=ox[0])+(y[i]<=ox[1]))/2;
if(d0==1){
rdx[j]=i;
j++;
}
if(j==m) break;
if(i==n-1) break;
}
}
d0=((y[i]>=ox[0])+(y[i]<=ox[1]))/2;
if(d0==1)
我相信使用中间变量是没有用的,需要更多循环
这是我能想到的最优化的版本,但它完全不可读......
void foo(int n, int m, float y[],const float ox[],int rdx[])
{
for(int i = 0; i < n && m != 0; i++)
{
if(*y >= *ox && *y <= ox[1])
{
*rdx=i;
rdx++;
m--;
}
y++;
}
}
我认为以下带有体面优化标志的版本应该可以完成这项工作
void foo(int n, int m,const float y[],const float ox[],int rdx[])
{
for(int j = 0, i = 0; j < m && i < n; i++) //Reorder to put the condition with the highest probability to fail first
{
if(y[i] >= ox[0] && y[i] <= ox[1])
{
rdx[j++] = i;
}
}
}
只是为了确保我是正确的:您正在尝试找到第一个 m+1(如果它实际上是 m,j == m-1)值在 [ ox[0], ox[1] ] 范围内?
如果是这样,这样做不是更好吗:
for (int i=0, j=0;;++i) {
if (y[i] < ox[0]) continue;
if (y[i] > ox[1]) continue;
rdx[j] = i;
j++;
if (j == m || i == n-1) break;
}
- 如果 y[i] 确实在该范围内,您必须像我们一样执行这两个比较。
- 如果 y[i] 在 ox[0] 下,则无需执行第二次比较。
- 我避免使用除法。
A.是的,将浮点数组作为 float[] 传递不仅有效,而且是唯一的方法(并且与 float * 参数相同)。
回答 1.但在C++您可以使用更好的类型而不会降低性能。访问向量或数组(标准库容器)不应比访问纯 C 样式数组慢。我强烈建议您使用这些。在现代C++中,还可以使用迭代器和函子;我不是那里的专家,但如果您可以通过更抽象的方式来表达对不同元素的操作的独立性,您可能会让编译器有机会生成更适合矢量化的代码。
二.您应该将除法替换为逻辑 AND、运算符 &&。第一个优点是,如果第一个条件为假,则根本不评估第二个条件 - 这可能是您在这里最重要的性能提升。第二个优点是表现力,因此可读性。
三.当您使用 -O3 编译时,中间变量 d0 可能会消失,但它仍然是不必要的。
其余的在性能方面还可以。从习惯上讲,正如已经表明的那样,还有改进的余地。
D.我不确定是否有机会使用此处介绍的代码进行矢量化。编译器可能会在 -O3 处执行一些循环展开;尝试让它发出 SSE 代码(参见 http://gcc.gnu.org/onlinedocs/,特别是 http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/i386-and-x86-64-Options.html#i386-and-x86-64-Options)。谁知道呢。
哦,我刚刚意识到您的原始代码将常量间隔边界作为具有 2 个元素的数组 ox[] 传递。由于数组访问是不必要的间接寻址,因此可能会带来开销,因此此处首选使用两个正常的浮点参数。让它们像你的阵列一样持续存在。你也可以很好地命名它们。
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 在c代码之间共享数据的最佳方式
- 使用std::source_location报告错误的最佳实践
- 派生类销毁的最佳实践是什么
- 将寄存器设计成可由C和C++访问的外设的最佳实践
- 在两台机器之间进行时间戳的最佳c++chrono函数是什么
- 使用QQuickFramebufferObject时同步数据的最佳方式是什么
- 在C++中向零方向近似的最佳方法
- 使用不同的CRT将新的C++代码与旧的(二进制)组件隔离开来的最佳方法是什么
- 从嵌套在std::映射中的std::列表中删除元素的最佳方式
- 如果条件为TRUE(最佳方式?),则在do while循环中后置增量
- 学习多线程C++:添加线程不会使执行速度更快,即使它看起来应该
- 检测win32服务创建和删除的最佳方法
- 学习如何制作可以处理动画的程序的最佳方式
- 学习阅读 ISO C++ 标准所需的逻辑格式和词汇的最佳方法是什么?
- 学习C/C++的最佳资源
- 机器学习数据结构输入的最佳实践
- 如何使此代码更快(学习最佳实践)