【问题标题】:Program error that measures the parameters of matrix multiplication测量矩阵乘法参数的程序错误
【发布时间】:2019-11-29 11:05:51
【问题描述】:

我正在编写一个程序,用rdtsc(),读取时间戳计数器来测量矩阵乘法的性能。

但是,当我结合矩阵乘法程序和性能测量程序时,出现了错误。

如果您能告诉我如何更改当前代码以进行调试,我将不胜感激。

环境:macOS Mojave 版本 10.14.5,终端 2.9.5

当我执行矩阵乘法程序本身时,matrixmul.c,编译成功并且输出正确。但是,如果我添加性能测量,它就无法编译。

这里是matrixmul.c

#include<stdio.h>

#define N 3
int main(int argc, char *argv[])
{
    double A[N][N] = {
        {1.0, 3.0, 1.0},
        {3.0, 1.0, 3.0},
        {1.0, 1.0, 1.0}
    };

    double B[N][N] = {
        {6.0, 1.0, 0.0},
        {0.0, 1.0, 6.0},
        {6.0, 1.0, 1.0}
    };

    double C[N][N] = {
        {0.0, 0.0, 0.0},
        {0.0, 0.0, 0.0},
        {0.0, 0.0, 0.0}
    };
    int i, j, k;

    for(i=0; i<N; i++)
        for(j=0; j<N; j++)
            for(k=0; k<N; k++)
                C[i][j] += A[i][k]*B[k][j];

    for(i=0; i<N; i++)
        for(j=0; j<N; j++)
            printf("C[%d][%d] = %f\n", i, j, C[i][j]);
}

输出:

$ ./matrixmul
C[0][0] = 6.000000
C[0][1] = 5.000000
C[0][2] = 19.000000
C[1][0] = 18.000000
C[1][1] = 7.000000
C[1][2] = 9.000000
C[2][0] = 6.000000
C[2][1] = 3.000000
C[2][2] = 7.000000

这里是measurement.c

#include <stdio.h>
#include "rdtsc.h"

#define N 3
int main(int argc, char *argv[])
{
    unsigned long long start = rdtsc();

    double A[N][N] = {
        {1.0, 3.0, 1.0},
        {3.0, 1.0, 3.0},
        {1.0, 1.0, 1.0}
    };

    double B[N][N] = {
        {6.0, 1.0, 0.0},
        {0.0, 1.0, 6.0},
        {6.0, 1.0, 1.0}
    };

    double C[N][N] = {
        {0.0, 0.0, 0.0},
        {0.0, 0.0, 0.0},
        {0.0, 0.0, 0.0}
    };
    int i, j, k;

    for(i=0; i<N; i++)
        for(j=0; j<N; j++)
            for(k=0; k<N; k++)
                C[i][j] += A[i][k]*B[k][j];

    for(i=0; i<N; i++)
        for(j=0; j<N; j++)
            printf("C[%d][%d] = %f\n", i, j, C[i][j]);
        
    unsigned long long stop = rdtsc();
    printf("measured time : %I64d [clock]\n", stop - start);

    return 0;
}

这里是rdtsc.h(这个程序与measurement.c在同一个文件夹下):

#ifndef RDTSC_H_
#define RDTSC_H_

inline unsigned long long rdtsc() {
    unsigned long long ret;
    __asm__ volatile ("rdtsc" : "=A" (ret));
    return ret;
}

#endif /* RDTSC_H_ */

输出:

$ gcc -o measurement measurement.c
measurement.c:38:30: warning: length modifier 'I64' results in undefined
      behavior or no effect with 'd' conversion specifier [-Wformat]
    printf("measured time : %I64d [clock]\n", stop - start);
                            ~^~~~
1 warning generated.
Undefined symbols for architecture x86_64:
  "_rdtsc", referenced from:
      _main in measurement-510357.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

根据答案试用

我已经修复了我的代码并再次执行它,但我仍然有一个错误。 错误信息

$ gcc -o measurement measurement.c
measurement.c:38:53: error: use of undeclared identifier 'start'
    printf("measured time : %lld [clock]\n", stop - start);
                                                    ^
1 error generated.

测量.c

#include <stdio.h>
#include "rdtsc.h"

#define N 3
int main(int argc, char *argv[])
{
    //unsigned long long start = rdtsc();

    double A[N][N] = {
        {1.0, 3.0, 1.0},
        {3.0, 1.0, 3.0},
        {1.0, 1.0, 1.0}
    };

    double B[N][N] = {
        {6.0, 1.0, 0.0},
        {0.0, 1.0, 6.0},
        {6.0, 1.0, 1.0}
    };

    double C[N][N] = {
        {0.0, 0.0, 0.0},
        {0.0, 0.0, 0.0},
        {0.0, 0.0, 0.0}
    };
    int i, j, k;

    for(i=0; i<N; i++)
        for(j=0; j<N; j++)
            for(k=0; k<N; k++)
                C[i][j] += A[i][k]*B[k][j];

    for(i=0; i<N; i++)
        for(j=0; j<N; j++)
            printf("C[%d][%d] = %f\n", i, j, C[i][j]);
        
    unsigned long long stop = rdtsc();
    printf("measured time : %lld [clock]\n", stop - start);

    return 0;
}

rdtsc.h

#ifndef RDTSC_H_
#define RDTSC_H_

unsigned long long rdtsc() {
    unsigned long long ret;
    __asm__ volatile ("rdtsc" : "=A" (ret));
    return ret;
}

#endif /* RDTSC_H_ */

【问题讨论】:

    标签: c performance cpu clock rdtsc


    【解决方案1】:

    真的没有必要把rdtsc函数inline,它只会让编译器混淆是否导出函数。只需删除它或在它之前添加extern 以明确告诉编译器导出函数。这将起作用:

    #ifndef RDTSC_H_
    #define RDTSC_H_
    
    unsigned long long rdtsc() {
        unsigned long long ret;
        __asm__ volatile ("rdtsc" : "=A" (ret));
        return ret;
    }
    
    #endif /* RDTSC_H_ */
    

    另外,正如clang 所说,%I64d 是一个无效的格式修饰符。使用%lld 代替long long int

    【讨论】:

    • %I64d 表示法在 Windows 上使用;它不能移植到任何其他平台。
    • @MarcoBonelli 谢谢你的回答。我已在您对我的问题帖子的回答之后添加了试用版,如果您能给我额外的建议来解决它,我将不胜感激。
    猜你喜欢
    • 2021-04-25
    • 2021-08-30
    • 2018-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-21
    • 2022-06-10
    • 2012-10-25
    相关资源
    最近更新 更多