1

我的问题很简单:在 c 中规范化二维双精度数组的最有效方法是什么,使其列(或其行)总和为 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;
    }
}

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

4

1 回答 1

1

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

使用nrow=1000000and ncol=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
$时间./规范
499999500000.000000

真正的 0m1.904s
用户 0m0.325s
系统 0m1.575s
$时间./规范
499999500000.000000

真正的 0m1.874s
用户 0m0.304s
系统 0m1.567s
$时间./规范
499999500000.000000

真实0m1.873s
用户 0m0.296s
系统 0m1.573s
$ gcc -O2 -o normed normed.c
$时间./规范
499999500000.000000

实际0m0.051s
用户 0m0.017s
系统 0m0.024s
$时间./规范
499999500000.000000

实际0m0.050s
用户 0m0.017s
系统 0m0.023s
$时间./规范
499999500000.000000

实际0m0.051s
用户 0m0.014s
系统 0m0.022s
$
于 2013-07-23T04:49:38.540 回答