我在这里有一个小循环,我想知道我是否犯了一个大错误。
例如,有没有办法以不同的方式重写部分内容,以使矢量化成为可能(假设启用了GCC4.8.1和所有的联合友好标志)?
这是传递列表数字的最佳方法(const float name_of_var [])吗?
代码的想法是采用(未经数字的)y
和两个绑定值(ox[0]<=ox[1]
)的向量(在数学意义上,而不是必需的std :: vector)和存储在整数向量rdx
中,i
条目的索引y
满足ox [0]&lt; = y [i]&lt; = ox [1]。
rdx
可以包含m
个元素,而y
可以包含n
和n>m
。如果超过m
值y[i]
满足ox [0]&lt; = y [i]&lt; = ox [1]然后代码应该返回第一个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;
}
}
答案 0 :(得分:1)
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;
}
}
}
答案 1 :(得分:1)
只是为了确保我是正确的:你试图找到[ox [0]范围内的第一个m + 1(如果它实际上是m,做j == m-1)值,牛[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;
}
答案 2 :(得分:1)
一个。是的,将float数组作为float []传递不仅有效,而且是唯一的方法(并且与float *参数相同)。
A1。 但是在C ++中,您可以使用更好的类型而不会丢失性能。访问向量或数组(标准库容器)不应该比访问纯C样式数组慢。我强烈建议你使用它们。在现代C ++中,还可以使用迭代器和函子;我不是那里的专家,但是如果你能通过更抽象地表达不同元素上的操作的独立性,你可以让编译器有机会生成更适合矢量化的代码。
B中。您应该用逻辑AND,运算符&amp;&amp;替换除法。第一个优点是,如果第一个条件为假,则根本不评估第二个条件 - 这可能是您最重要的性能提升。第二个优点是表现力和可读性。
℃。使用-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 []的数组传递。由于阵列访问是不必要的间接,因此可能带来开销,因此这里优选使用两个普通的浮点参数。保持它们像你的数组一样const。你也可以很好地命名它们。