【问题标题】:Cblas_sgemm produces wrong resultsCblas_sgemm 产生错误的结果
【发布时间】:2016-01-29 23:17:28
【问题描述】:

我在使用 cblas 的 sgemm 函数时遇到问题。

代码如下:

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cblas.h>

#define MATRIX_DIM 5

int main(){

    float *a_mat = calloc(MATRIX_DIM*MATRIX_DIM, sizeof(float));
    float *b_mat = calloc(MATRIX_DIM, sizeof(float));
    float *c_mat = calloc(MATRIX_DIM, sizeof(float));
    int i,j;

    for(i=0; i<MATRIX_DIM*MATRIX_DIM; i++) {
        a_mat[i] = 1.0f;
        b_mat[i] = 1.0f;
        c_mat[i] = 0.0f;
    }

    cblas_sgemm(CblasRowMajor, CblasNoTrans,
                 CblasNoTrans, MATRIX_DIM, MATRIX_DIM,
                 MATRIX_DIM, 1.0, a_mat,
                 MATRIX_DIM, b_mat, MATRIX_DIM,
                 1.0, c_mat, MATRIX_DIM);

    //RESULT PRINTING
    printf("Printing A MATRIX: \n");
    for(i=0; i<MATRIX_DIM; i++) {
        for(j=0; j<MATRIX_DIM; j++){
                printf("%0.1f ", a_mat[i*MATRIX_DIM+j]);
        }
        printf("\n");
    }
    printf("Printing B MATRIX: \n");
    for(i=0; i<MATRIX_DIM; i++) {
            for(j=0; j<MATRIX_DIM; j++){
                printf("%0.1f ", b_mat[i*MATRIX_DIM+j]);
        }
        printf("\n");
    }

    printf("\nPrinting the Results: \n");
    for(i=0; i<MATRIX_DIM;i++){
        for(j=0; j<MATRIX_DIM; j++){
                printf("%0.1f ", c_mat[i*MATRIX_DIM+j]);
        }
        printf("\n");
    }

    free(a_mat);
    free(b_mat);
    free(c_mat);

    return 0;
}

我提出的一些论点是错误的,但我真的不知道是哪一个。结果应该是一个用 5.0 填充的 5x5 矩阵。相反,程序会这样回应:

6.0 6.0 6.0 16.0 86.0 
6.0 6.0 6.0 16.0 86.0 
16.0 36.0 6.0 46.0 86.0 
16.0 36.0 5.0 45.0 85.0 
20.0 80.0 5.0 45.0 85.0 

我知道 rowmajor 顺序或转置参数可能是错误的,我稍后会弄清楚,但在这个特定的乘法中,答案应该是 5.0。

【问题讨论】:

  • 嗯...你不应该用callocsizeof(float) 吗? sizeof(*a_mat) 是如何有效的?你的结果不应该是一个长度为 5、所有元素都等于 5 的 vector 吗?这个结果不应该写在向量c_mat吗?你怎么没有收到任何段错误?
  • @AndrasDeak 好吧,您可能对sizeof(float) 部分是正确的,但由于某种原因,它可以像这样工作得很好。尽管如此,我会改变它。由于它是矩阵-矩阵乘法,因此结果应该是 MxN 的矩阵(M 是第一个矩阵的行,N 是第二个矩阵的列),在这种情况下将是一个 5x5 矩阵。我认为您指的是矩阵向量乘法。
  • 在哪里可以看到第二个矩阵有 5 列? float *b_mat = calloc(MATRIX_DIM, sizeof(*b_mat)); 只是分配的一列值。因此,我很惊讶您稍后不会遇到段错误。一种可能性是sizeof(*a_mat)(不管是什么)比float 有更多的空间。而你的问题正是它 not 工作正常:)
  • 好吧,你是对的!问题是我忘记在 b_mat 和 c_mat 上再添加一个 *MATRIX_DIM。我从我之前的 sgemv 实现中复制粘贴了代码,然后完全忘记了它。顺便说一句,sizeof(*a_mat) 仍然有效,但我不确定这是否有问题,所以我也将其更改为您所说的。谢谢你指出! :)

标签: c cblas


【解决方案1】:

感谢 cmets 中的 @AndrasDeak,我所需要的只是在两个矩阵上分配更多空间,这是我之前忽略的。

所以基本上改变了:

float *b_mat = calloc(MATRIX_DIM, sizeof(float));
float *c_mat = calloc(MATRIX_DIM, sizeof(float));

收件人:

float *b_mat = calloc(MATRIX_DIM*MATRIX_DIM, sizeof(float));
float *c_mat = calloc(MATRIX_DIM*MATRIX_DIM, sizeof(float));

因为这些应该是二维矩阵而不是向量。

【讨论】:

  • 我仍然会将那些sizeof()s 更改为浮动:) 由于这本质上是代码中的错字,因此您应该考虑未来的用户是否会发现此问答有用。如果您这么认为,那么可能值得删除该问题。如果您决定继续进行问答,请在一段时间后接受您的回答(我认为是 24 或 48 小时)
  • 我将calloc 更改为像您说的那样浮动,我是否也应该更改*MATRIX_DIM 部分以使其充分发挥作用?我是stackoverflow的新手,所以我不熟悉这个过程。
  • 哦不不不,对不起,你误会了:)我的意思只是改变你的实际代码,而不是你上面的问题(你的回答不清楚你是否也改变了sizeof,这就是为什么我在评论中也提到了这一点)。该程序是“保留原样,除非添加说明”,并且任何修复都应包含在答案中。然后一切都只出现一次:一个明确的问题陈述和一个(或多个)明确的答案。
  • 好吧,那我把它留给更改后的sizeof(float)。谢谢! :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-25
  • 1970-01-01
  • 1970-01-01
  • 2021-10-08
  • 2014-07-29
  • 1970-01-01
相关资源
最近更新 更多