I'm writing a program that measures the performance of matrix multiplication with rdtsc()
, Read Time Stamp Counter.
However, when I combined the matrix multiplication program and performance measurement program, errors appeared.
I would appreciate if you could let know me how to change my current code for debugging.
Environment: macOS Mojave version 10.14.5, terminal 2.9.5
When I execute the program for matrix multiplication itself, matrixmul.c
, the compilation succeeds and the output is correct. However, if I add the performance measurement it fails to compile.
Here's 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]);
}
Output:
$ ./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
Here's 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;
}
Here's rdtsc.h
(this program is located in the same folder of 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_ */
Output:
$ 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)
I have fixed my code and executed it again, but still I had one error. error message
$ 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.
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 : %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_ */
There's really no need to make the rdtsc
function inline
, it only confuses the compiler about whether or not to export the function. Just remove it or add extern
before it to explicitly tell the compiler to export the function. This will work:
#ifndef RDTSC_H_
#define RDTSC_H_
unsigned long long rdtsc() {
unsigned long long ret;
__asm__ volatile ("rdtsc" : "=A" (ret));
return ret;
}
#endif /* RDTSC_H_ */
Also, as clang
says, %I64d
is an invalid format modifier. Use %lld
instead for long long int
.