哪种方法更快且编译器/缓存更友好,在处理矩阵时使用M [a] [b]或M [a * b]?
我尝试在分配,初始化和返回矩阵的函数中在编译器资源管理器上编写两种方式,但我不知道汇编以及每条指令花费多少时间
int **M = malloc(sizeof(int*)*m)
for(i=0; i<m; ++i) {
*M = malloc(sizeof(int)*n);
for(int j = 0; j < n; ++j){
M[j] = j;
}
vs
int *M = malloc(m*n*sizeof(int));
for(i = 0; i < m*n; ++i) M[i] = i;
我希望第二种方法更快。
答案 0 :(得分:1)
带有malloc调用的代码将变慢。更有趣的是如何快速访问特定单元格
void foo(int * const * const M, const size_t x, const size_t y, const int val)
{
M[x][y] = val;
}
void foo2(int * const M, const size_t x, const size_t y, const size_t rowsize, const int val)
{
M[x + rowsize * y] = val;
}
foo:
mov rax, QWORD PTR [rdi+rsi*8]
mov DWORD PTR [rax+rdx*4], ecx
ret
foo2:
imul rcx, rdx
add rcx, rsi
mov DWORD PTR [rdi+rcx*4], r8d
ret
结果很明显;
答案 1 :(得分:0)
如果您的问题(以及相应的解决方案)需要2D数组,则只需使用2D数组:M [a] [b]。
您必须记住,存储器无论如何都是线性寻址的。多维数组的概念只是在线性内存之上实现的一层。
如今,编译器已进行了高度优化,因此它们将比您可以更好地“线性化”二维数组。此外,如果您这样做,则代码将很难编写和维护。
答案 2 :(得分:-1)
您可以使用clock_t跟踪代码块的时间。
这是经过一些更新的代码。
#include<stdio.h>
#include<time.h>
int main()
{
int i = 0, j = 0;
int m, n;
scanf("%d %d", &m, &n);
clock_t start, end;
double time_used;
start = clock();
int **M = malloc(sizeof(int*)*m);
for (i = 0; i < m; ++i) {
*M = malloc(sizeof(int)*n);
for (int j = 0; j < n; ++j) {
M[j] = j;
}
}
end = clock();
time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
printf("Time used for fisrst code is : %f \n ", time_used);
start = clock();
M = malloc(m*n * sizeof(int));
for (i = 0; i < m*n; ++i) M[i] = i;
end = clock();
time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
printf("Time used for second code is : %f \n ", time_used);
return 0;
}
,此代码的输出是在输入10000 * 10000矩阵时
用于第一个代码的时间为:0.001000
用于第一个代码的时间为:0.686000