2016-12-30 488 views
0

我有一个矩阵Xn列数据向量在d维空间。 给定一个矢量XJv [j]的是其L1范数(所有ABS(XJI的总和)),W [j]的是其L2范数的平方(在所有XJI^2),和PJ [I]的总和是通过L1L2范数划分条目的组合。最后,我需要输出:pj,v,w for subsequet应用程序。如何在C++中快速计算矢量的归一化l1和l2范数?

// X = new double [d*n]; is the input. 
double alpha = 0.5; 
double *pj = new double[d]; 
double *x_abs = new double[d]; 
double *x_2 = new double[d]; 
double *v = new double[n](); 
double *w = new double[n](); 
for (unsigned long j=0; j<n; ++j) { 
     jm = j*m; 
     jd = j*d; 
     for (unsigned long i=0; i<d; ++i) { 
      x_abs[i] = abs(X[i+jd]); 
      v[j] += x_abs[i]; 
      x_2[i] = x_abs[i]*x_abs[i]; 
      w[j] += x_2[i];  
     } 
     for (unsigned long i=0; i<d; ++i){ 
      pj[i] = alpha*x_abs[i]/v[j]+(1-alpha)*x_2[i]/w[j];  
     } 

    // functionA(pj){ ... ...} for subsequent applications 
} 
// functionB(v, w){ ... ...} for subsequent applications 

我上面的算法需要O(ND)拖/时间的复杂性,任何一个可以帮助我通过使用建筑functoin或新的实现在C++加快呢?减少O(nd)中的常数值对我也很有帮助。

+2

是不是内存分配的瓶颈?你不能将预分配的数组传递给函数吗? – Bathsheba

+0

你可以尝试在第二个循环外计算'a = alpha/v [j]'和'b =(1-alpha)/ w [j]'然后计算'pj [i] = a * x_abs [i] + b * x_2 [i];'而是。然而,编译器可能已经为你做了这种优化,并且由于浮点错误,结果可能会稍微有所不同 – samgak

+0

@Bathsheba我对内存使用没有限制。请继续。谢谢。 – olivia

回答

1

让我猜测:既然你有与性能相关的问题,你的向量的维度是相当大的。
如果是这样的话,那么它值得考虑“CPU缓存局部性” - 关于这个in a cppcon14 presentation的一些有趣的信息。
如果数据在CPU高速缓存中不可用,那么在CPU刚刚等待数据之前,一旦可用,将其平方化即可。

有了这一点,你可能想尝试以下解决方案(没有保证,这将提高性能 - 编译器优化代码时,可以实际应用这些技术)

for (unsigned long j=0; j<n; ++j) { 
     // use pointer arithmetic - at > -O0 the compiler will do it anyway 
     double *start=X+j*d, *end=X+(j+1)*d; 

     // this part avoid as much as possible the competition 
     // on CPU caches between X and v/w. 
     // Don't store the norms in v/w as yet, keep them in registers 
     double l1norm=0, l2norm=0; 
     for(double *src=start; src!=end; src++) { 
      double val=*src; 
      l1norm+=abs(src); 
      l2norm+= src*src; 
     } 
     double pl1=alpha/l1norm, pl2=(1-alpha)*l2norm; 
     for(double *src=start, *dst=pj; src!=end; src++, dst++) { 
      // Yes, recomputing abs/sqr may actually save time by not 
      // creating competition on CPU caches with x_abs and x_2 
      double val=*src; 
      *dst = pl1*abs(val) + pl2*val*val; 
     }  
     // functionA(pj){ ... ...} for subsequent applications 

     // Think well if you really need v/w. If you really do, 
     // at least there are two values to be sent for storage into memory, 
     //meanwhile the CPU can actually load the next vector into cache 
     v[j]=l1norm; w[j]=l2norm; 
} 
// functionB(v, w){ ... ...} for subsequent applications