首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我的矩阵乘法不像BLAS那样精确

我的矩阵乘法不像BLAS那样精确
EN

Stack Overflow用户
提问于 2015-04-04 05:10:10
回答 1查看 454关注 0票数 0

我用C++编写了一个矩阵乘法例程,并在特征解算器中使用了它。然后我意识到我的实现有精度问题,即使我已经使用了双精度浮点。我的实现结果似乎不够精确。我用BLAS测试了它,发现它的结果与BLAS的不匹配。下面的简单代码说明了这个问题,输出如下。

代码语言:javascript
复制
0: 0
1: 0
2: -1.42109e-14
test: test.cpp:59: int main(): Assertion `C1[i] == C2[i]' failed.

我可以简单地调用BLAS例程进行矩阵乘法,但我想知道为什么会发生这种情况。我不知道这是否是与架构相关的问题。我使用Intel Xeon E5-4620。

顺便说一句,我试着用"long double“定义sum,仍然得到了不同的结果。

谢谢你,爸爸

代码语言:javascript
复制
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <cblas.h>
#include <assert.h>

#include <vector>

void init_vec(std::vector<double> &vec)
{
    for (size_t i = 0; i < vec.size(); i++)
        vec[i] = ((double) random()) / ((double) random());
}

void mv(const std::vector<double> &A, const std::vector<double> &B,
        std::vector<double> &C)
{
    size_t num_rows = A.size() / B.size();
    size_t num_cols = B.size();
    for (size_t i = 0; i < num_rows; i++) {
        double sum = 0;
        for (size_t j = 0; j < num_cols; j++)
            sum += A[j * num_rows + i] * B[j];
        C[i] = sum;
    }
}

int main()
{
    std::vector<double> A(100 * 10);
    std::vector<double> B(10);
    std::vector<double> C1(100);
    std::vector<double> C2(100);
    init_vec(A);
    init_vec(B);

    mv(A, B, C1);
    cblas_dgemv(CblasColMajor, CblasNoTrans, 100, 10, 1, A.data(), 100, B.data(), 1, 0, C2.data(), 1);
    for (size_t i = 0; i < C1.size(); i++) {
        printf("%ld: %g\n", i, C1[i] - C2[i]);
        assert(C1[i] == C2[i]);
    }
}
EN

回答 1

Stack Overflow用户

发布于 2015-04-06 03:43:46

我意识到现在的问题所在。BLAS确实使用了80位浮点进行乘法运算。下面代码的结果与BLAS匹配。

代码语言:javascript
复制
void mv(const std::vector<double> &A, const std::vector<double> &B,
       std::vector<double> &C)
{
    size_t num_rows = A.size() / B.size();
    size_t num_cols = B.size();
    for (size_t i = 0; i < num_rows; i++) {
        double sum = 0;
        for (size_t j = 0; j < num_cols; j++) {
            long double tmp1 = A[j * num_rows + i];
            long double tmp2 = B[j];
            sum += tmp2 * tmp1;
        }
        C[i] = sum;
    }
}

80位浮点似乎只用于乘法运算。求和仍然使用64位。我希望这能在未来帮助到一些人。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29439719

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档