规范化2d c数组列或行

时间:2013-07-23 02:36:14

标签: c linear-algebra dynamic-programming simd hidden-markov-models

我的问题很简单:在c中规范化2d双数组的最有效方法是什么,以便它的列(或其行)总和为1.下面是一个简单的例子来说明我想要做什么。如果重要的话,可以重新整形数组以标准化其行或列。我也愿意使用外部c线性代数库。只是不知道从哪里开始。感谢您提前提供任何帮助!

void normalize(double** array, int nrow) {
    int i;
    double sum = 0;
    for(i = 0; i < nrow; i++) {
        sum += array[i][0];
    }
    for(i = 0; i < nrow; i++) {
        array[i][0] /= sum;
    }
}

顺便说一句,这是隐马尔可夫模型动态规划算法的一部分,并且它被多次调用。所以我想让这部分尽可能高效。

1 个答案:

答案 0 :(得分:1)

我不知道您的示例代码与您的应用程序的匹配程度,但如果您循环遍历这样的行,您几乎肯定会遇到缓存问题。如果我以行主要和列主要顺序对循环进行编码,我会发现性能差异很大。

使用nrow=1000000ncol=1000,如果我使用array[i][0],我的运行时间大约为1.9秒。如果我使用array[0][i],则会降至0.05秒。

如果您可以通过这种方式转置数据,那么您应该会看到很大的性能提升。

#ifdef COL_MAJOR    

    array = (double **)malloc(nrow * sizeof(double *));
    for(i=0; i<nrow; i++) {
        array[i] = (double *)malloc(ncol * sizeof(double));
        array[i][0] = i;
    }

    for(i=0; i<nrow; i++) {
        sum += array[i][0];
    }
    for(i=0; i<nrow; i++) {
        array[i][0] /= sum;
    }

#else

    array = (double **)malloc(ncol * sizeof(double *));
    for(i=0; i<ncol; i++) {
        array[i] = (double *)malloc(nrow * sizeof(double));
    }
    for(i=0; i<nrow; i++) {
        array[0][i] = i;
    }

    for(i=0; i<nrow; i++) {
        sum += array[0][i];
    }
    for(i=0; i<nrow; i++) {
        array[0][i] /= sum;
    }

#endif

printf("%f\n", sum);
$ gcc -DCOL_MAJOR -O2 -o normed normed.c
$ time ./normed
499999500000.000000

real    0m1.904s
user    0m0.325s
sys 0m1.575s
$ time ./normed
499999500000.000000

real    0m1.874s
user    0m0.304s
sys 0m1.567s
$ time ./normed
499999500000.000000

real    0m1.873s
user    0m0.296s
sys 0m1.573s
$ gcc -O2 -o normed normed.c
$ time ./normed
499999500000.000000

real    0m0.051s
user    0m0.017s
sys 0m0.024s
$ time ./normed
499999500000.000000

real    0m0.050s
user    0m0.017s
sys 0m0.023s
$ time ./normed
499999500000.000000

real    0m0.051s
user    0m0.014s
sys 0m0.022s
$