我有一个相当简单的问题,但我找不到一个简单的解决方案。
事情是这样的,我有一个信号让我们说x长度是32。x[32]
。这个数组在每一步都得到了实时信号的值。在第一步,我得到[0:31]值,步骤2 [1:32],步骤3 [2:33],依此类推。要获得我想要重叠的最终信号,请添加此值并将它们存储到数组中。我试图这样做的方式是声明一个特定长度的数组,比方说150. xfinal[150]
。
然后,为了填补xfinal,我就这样做了。
Step 1. xfinal[0:31] = x[0:31].
Step 2. xfinal[1:31] = xfinal[1:31] + x[0:30].
xfinal[32] = x[31];
Step 3. xfinal[2:32] = xfinal[2:32] + x[0:30].
xfinal[33] = x[31];
等等。这样,在33个信号之后,x_final中的每个值都将是32的总和。
我用C编写的代码是(它有点复杂,因为x是一个帧,所以我必须逐个像素地复制。
void Overlapadd ( float **final_X, float **all_frames_X, int add_index,int w, int h)
{
for (int i=0; i< frame_size ; i++) { // for every pixel
for( int j=add_index; j<add_index+32; j++){
final_X[j][i] += all_frames_S[j-add_index][i];
}
}
add_index++;
}
此代码的问题在于,当我运行它很长一段时间后,final_X
数组将填充,final_X[add_index+32]
将从内存中消失。这就是为什么我想以循环方式存储它。所以当我到达终点时,我会回到0.问题是,当我到达final_X
中的某个点时,让我们说add_index = 60。因此final_X[add_index]
将是32帧的总和,但final_X[add_index+1]
将只是31帧中的一些,final_X[add_index+2]
将是仅30帧中的一些,依此类推。这个值对我很重要,因为它们通过添加新的x来帮助我获得新值。
我不知道自己是否清楚,可能不是,但我希望得到一些帮助。所以问题是我如何重叠添加信号并将它们存储在矢量中很长一段时间。
答案 0 :(得分:0)
您可以使用模运算,最内层循环中的一个额外变量用作计数器,而另一个变量用作位置索引。
#define FINAL_X_LEN 150
void Overlapadd(float **final_X, float **all_frames_X, int add_index)
{
for (int i = 0; i < frame_size; i++)
for(int j = add_index, int k = 0; k < 32; j = (j+1)%FINAL_X_LEN)
final_X[j][i] += all_frames_S[k][i];
}
此处,k
用于计算迭代次数,j
是您要编制索引的实际位置。
在add_index++;
的末尾小心使用Overlapadd
,这很可能不会像您期望的那样发挥作用。值是按副本传递的,因此add_index++
仅增加add_index
的本地副本,调用者将无法看到此更改。如果要模拟传递引用,则必须将add_index
作为指针传递。
另外,请注意您组织代码的方式对缓存不是很友好。 final_X[j][i] += ...
很糟糕,因为j
在最内层循环的每次迭代中都会发生变化,这会破坏空间局部性并增加缓存未命中率。如果访问阵列中的附近位置,则可以增加缓存命中时间和整体程序性能。我建议复制每个位置j
的每一帧,而不是每次复制一个帧j
(这就是你现在所做的)。在这种情况下,这就像交换循环的顺序一样简单:
void Overlapadd(float **final_X, float **all_frames_X, int add_index)
{
for(int j = add_index, int k = 0; k < 32; j = (j+1)%FINAL_X_LEN)
for (int i = 0; i < frame_size; i++)
final_X[j][i] += all_frames_S[k][i];
}
答案 1 :(得分:0)
我不完全明白你的目标是什么,但是对于循环添加,你必须使用模数连续索引变量:
int x[32];
int xfinal[32];
for (int i=0; i<32; i++) // initialize xfinal with 0
xfinal[i] = 0;
int iter = 100; // doing additions e.g. 100 times
for (int i=0; i<iter; i++)
for (int j=0; j<32; j++)
xfinal[(j+i)%32] += x[j]; // index of xfinal remains inside 0-31
另请注意,add_index++
中的Overlapaddd()
没有剩余效果!
修改强>
这就是我的解决方案:
外圈是xfinal,内圈是x。内圈随时钟转动,i
运行到iter
,外圈+=
基础单元格。在第一次迭代中,内圆相对于完全0初始化外圆未旋转,因此外圆变为=内圆(=步骤1)。等等...
答案 2 :(得分:0)
好的,我想到的一件事就是这个。
在每次迭代的第33帧到目前为止,我得到了一个很好的x_final值。所以我想在获得足够的x_final值后复制该位置之后的帧并将它们放在向量的开头。
所以我们假设x_final有170个长度。 x_final[170]
int curr_pos;
// if I reached frame 132 it means that values from 32-131 already have a 32 frame sum in them
if(add_index == 132) // I have 100 good values of x_final already - x_final[32:131]
{
for( int j=add_index; j<add_index+32; j++){
for (int i=0; i< (w*h) ; i++) {
x_final[add_index-132][i] = x_final[j][i]; //copy the rest at the beginning of the vector
}
}
curr_pos = 0;
}
else
curr_pos = add_index;
//Overlap add the new 32 frames
for( int j=curr_pos; j<curr_pos+32; j++){
for (int i=0; i< (w*h) ; i++) {
x_final[j][i] += all_frames_S[j-curr_pos][i];
}
}
// prepare vector for next iteration
for (int i=0; i< (w*h) ; i++) {
x_final[curr_pos+32][i] = 0;
}
这种方法有什么缺陷吗?