【问题标题】:normalize 2d c array column or row规范化 2d c 数组列或行
【发布时间】:2013-07-23 02:36:13
【问题描述】:

我的问题很简单:在 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;
    }
}

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

【问题讨论】:

  • 最有效的衡量标准是什么?给出的例子有什么问题?如果我不能证明我的答案在某种程度上是最有效的(你甚至没有给出平台和架构,所以我不知道有人怎么可能知道什么对你最有效),你不想是吗?
  • 嗯,我只是想知道是否有更好的方法来做到这一点,以经过的时间来衡量。代码将在 linux 和 intel xeon 上运行。
  • 存储每个可能组合的哈希值并查找标准化值。当然,它需要几乎无限量的内存。我的意思是.. 可能有一些 SIMD 指令您可以使用,但是否值得走那么远(另外,这需要知道哪个 xeon 平台)?你的目标是什么?为什么你认为你需要更快的东西?你分析过你的代码吗?
  • 当然,如果没有更快更好的方法,那可能不值得。这段代码大约需要五分之一的运行时间。我认为代码的其他部分更难加速。但是如果你有大量数据,并且你想通过迭代(EM 或 MCMC)来训练模型,五分之一的时间仍然很多。
  • 我会从这里开始阅读:en.wikipedia.org/wiki/Streaming_SIMD_Extensions 我猜你的第二个循环可能会从一些 SIMD 的爱中受益匪浅——但我从来没有做过这样的事情。此外,看起来使用 intel 编译器可能会自动为你做一些事情

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


【解决方案1】:

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

使用nrow=1000000ncol=1000,如果我使用array[i][0],我会得到大约1.9 秒的运行时间。如果我使用array[0][i],那么它会下降到0.05s。

如果您可以以这种方式转置数据,您应该会看到性能大幅提升。

#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 $

【讨论】:

  • 我猜行规范化和列规范化之间会有差异,但感谢基准!
猜你喜欢
  • 2016-06-04
  • 1970-01-01
  • 2021-03-22
  • 2013-08-21
  • 2010-12-29
  • 1970-01-01
  • 2013-01-18
  • 2020-12-13
  • 1970-01-01
相关资源
最近更新 更多