代码片段有什么区别?
What is the difference in the Code Snippets?
我是操作系统的初学者,我正在尝试理解一些代码片段。你能给我解释一下这些代码片段之间的区别吗??
int sum_array_rows(int a[M][N])
{
int i,j,sum=0;
for(i=0;i<M;i++)
for(j=0;j<N;j++)
sum+=a[i][j];
return sum;
}
和
int sum_array_col(int a[M][N])
{
int i,j,sum=0;
for(i=0;i<N;i++)
for(j=0;j<M;j++)
sum+=a[i][j];
return sum;
}
不同的部分是双重的对于属性其中一个应该比另一个快吗??如果可以,请您解释一下原因,因为我不明白。
在第一个例子中:
i
将得到值 0, 1, 2, ..., M-1
j
将得到值 0, 1, 2, ..., N-1
所以sum
计算为
sum = a[0][0] + a[0][1] + a[0][2] + ... + a[0][N-1] +
a[1][0] + a[1][1] + a[1][2] + ... + a[1][N-1] +
a[2][0] + a[2][1] + a[2][2] + ... + a[2][N-1] +
...
...
a[M-1][0] + a[M-1][1] + a[M-1][2] + ... + a[M-1][N-1]
在第二个示例中,这已被切换,因此
i
将得到值 0, 1, 2, ..., N-1
j
将得到值 0, 1, 2, ..., M-1
所以现在
sum = a[0][0] + a[0][1] + a[0][2] + ... + a[0][M-1] +
a[1][0] + a[1][1] + a[1][2] + ... + a[1][M-1] +
a[2][0] + a[2][1] + a[2][2] + ... + a[2][M-1] +
...
...
a[N-1][0] + a[N-1][1] + a[N-1][2] + ... + a[N-1][M-1]
注意第二个版本是错误的,因为参数是int a[M][N]
,即合法的第一个索引是0..M-1
,合法的第二个索引是0..N-1
换句话说,如果 N 和 M 不同,则第二个版本越界访问数组。
使第二个例子正确。这一行 sum+=a[i][j];
应该是 sum+=a[j][i];
这样 sum
现在是:
sum = a[0][0] + a[1][0] + a[2][0] + ... + a[M-1][0] +
a[0][1] + a[1][1] + a[2][1] + ... + a[M-1][1] +
a[0][2] + a[1][2] + a[2][2] + ... + a[M-1][2] +
...
...
a[0][N-1] + a[1][N-1] + a[2][N-1] + ... + a[M-1][N-1]
有了这个改变,两个版本在功能上是相同的,即产生相同的结果。它们仅在添加元素的顺序上有所不同。
由于二维数组的内存布局和缓存系统的工作方式,第一个版本的性能可能优于第二个。另一方面,编译器可能会优化这两个版本以使其性能相同。
仅当 M
和 N
值为 equal
时,两个代码才相似,否则两个代码块不同。
Case-1 :- 看下面的代码块
int sum_array_rows(int a[M][N]) {
int i,j,sum=0;
for(i=0;i<M;i++)
for(j=0;j<N;j++)
sum+=a[i][j];
return sum;
}
此处 a
是一个包含 M
行和 N
列的数组,您正在对每个行-列元素求和 sum+=a[i][j]
。这是一个很好的代码,因为外循环旋转等于行数,内循环旋转等于列数。
Case-2 :- 现在看第二个代码块,它导致溢出。
int sum_array_rows(int a[M][N]) {
int i,j,sum=0;
for(i=0;i<N;i++)
for(j=0;j<M;j++)
sum+=a[i][j];
return sum;
}
这里 a
也是一个包含 M
行和 N
列的数组。您的第一个外部 for 循环从 0
旋转到 N
但您只有 M
行。当您执行 sum+=a[i][..]
时,如果 M
和 N
不相同,则会产生一个大问题。例如,M
是 2
和 N
是 5
即它像 int a[2][5]
和外循环从 0
迭代到 5
然后你继续做
sum+=a[0][j]
然后
sum+=a[1][j]
到此为止还好(bcz M=2),但什么时候可以
sum+=a[2][j]
和 sum+=a[3][j]
等然后出现问题,因为没有 a[2][j]
或 a[3][j]
出口,所以您正在尝试访问导致 未定义行为的边界 .
所以上面两个代码块只有当M
和N
相同时才相同,否则两者不同。
首先,第二个代码块是错误的,但是您可以通过 sum+=a[j][i]
而不是 sum+=a[i][j]
来更正它,因为
int sum_array_rows(int a[M][N]) {
int i,j,sum=0;
for(i=0;i<N;i++)
for(j=0;j<M;j++)
sum+=a[j][i];
return sum;
}
正如其他人所说,由于二维数组的内存布局和缓存系统的工作方式,第一个版本的性能可能优于第二个。另一方面,编译器可能会优化这两个版本以使其性能相同。
正如其他人所说,如果数组维度不同,第二个代码片段可能会导致溢出错误,因此需要修复此问题。
然而,由于多维数组的元素在内存中的存储方式和缓存架构,在最内层循环 中循环最后一个数组维度可以 比其他方式更快现代 CPU。
此处要搜索的字词是 'cache locality' 和 'stride of arrays'
我是操作系统的初学者,我正在尝试理解一些代码片段。你能给我解释一下这些代码片段之间的区别吗??
int sum_array_rows(int a[M][N])
{
int i,j,sum=0;
for(i=0;i<M;i++)
for(j=0;j<N;j++)
sum+=a[i][j];
return sum;
}
和
int sum_array_col(int a[M][N])
{
int i,j,sum=0;
for(i=0;i<N;i++)
for(j=0;j<M;j++)
sum+=a[i][j];
return sum;
}
不同的部分是双重的对于属性其中一个应该比另一个快吗??如果可以,请您解释一下原因,因为我不明白。
在第一个例子中:
i
将得到值 0, 1, 2, ..., M-1
j
将得到值 0, 1, 2, ..., N-1
所以sum
计算为
sum = a[0][0] + a[0][1] + a[0][2] + ... + a[0][N-1] +
a[1][0] + a[1][1] + a[1][2] + ... + a[1][N-1] +
a[2][0] + a[2][1] + a[2][2] + ... + a[2][N-1] +
...
...
a[M-1][0] + a[M-1][1] + a[M-1][2] + ... + a[M-1][N-1]
在第二个示例中,这已被切换,因此
i
将得到值 0, 1, 2, ..., N-1
j
将得到值 0, 1, 2, ..., M-1
所以现在
sum = a[0][0] + a[0][1] + a[0][2] + ... + a[0][M-1] +
a[1][0] + a[1][1] + a[1][2] + ... + a[1][M-1] +
a[2][0] + a[2][1] + a[2][2] + ... + a[2][M-1] +
...
...
a[N-1][0] + a[N-1][1] + a[N-1][2] + ... + a[N-1][M-1]
注意第二个版本是错误的,因为参数是int a[M][N]
,即合法的第一个索引是0..M-1
,合法的第二个索引是0..N-1
换句话说,如果 N 和 M 不同,则第二个版本越界访问数组。
使第二个例子正确。这一行 sum+=a[i][j];
应该是 sum+=a[j][i];
这样 sum
现在是:
sum = a[0][0] + a[1][0] + a[2][0] + ... + a[M-1][0] +
a[0][1] + a[1][1] + a[2][1] + ... + a[M-1][1] +
a[0][2] + a[1][2] + a[2][2] + ... + a[M-1][2] +
...
...
a[0][N-1] + a[1][N-1] + a[2][N-1] + ... + a[M-1][N-1]
有了这个改变,两个版本在功能上是相同的,即产生相同的结果。它们仅在添加元素的顺序上有所不同。
由于二维数组的内存布局和缓存系统的工作方式,第一个版本的性能可能优于第二个。另一方面,编译器可能会优化这两个版本以使其性能相同。
仅当 M
和 N
值为 equal
时,两个代码才相似,否则两个代码块不同。
Case-1 :- 看下面的代码块
int sum_array_rows(int a[M][N]) {
int i,j,sum=0;
for(i=0;i<M;i++)
for(j=0;j<N;j++)
sum+=a[i][j];
return sum;
}
此处 a
是一个包含 M
行和 N
列的数组,您正在对每个行-列元素求和 sum+=a[i][j]
。这是一个很好的代码,因为外循环旋转等于行数,内循环旋转等于列数。
Case-2 :- 现在看第二个代码块,它导致溢出。
int sum_array_rows(int a[M][N]) {
int i,j,sum=0;
for(i=0;i<N;i++)
for(j=0;j<M;j++)
sum+=a[i][j];
return sum;
}
这里 a
也是一个包含 M
行和 N
列的数组。您的第一个外部 for 循环从 0
旋转到 N
但您只有 M
行。当您执行 sum+=a[i][..]
时,如果 M
和 N
不相同,则会产生一个大问题。例如,M
是 2
和 N
是 5
即它像 int a[2][5]
和外循环从 0
迭代到 5
然后你继续做
sum+=a[0][j]
然后sum+=a[1][j]
到此为止还好(bcz M=2),但什么时候可以sum+=a[2][j]
和sum+=a[3][j]
等然后出现问题,因为没有a[2][j]
或a[3][j]
出口,所以您正在尝试访问导致 未定义行为的边界 .
所以上面两个代码块只有当M
和N
相同时才相同,否则两者不同。
首先,第二个代码块是错误的,但是您可以通过 sum+=a[j][i]
而不是 sum+=a[i][j]
来更正它,因为
int sum_array_rows(int a[M][N]) {
int i,j,sum=0;
for(i=0;i<N;i++)
for(j=0;j<M;j++)
sum+=a[j][i];
return sum;
}
正如其他人所说,由于二维数组的内存布局和缓存系统的工作方式,第一个版本的性能可能优于第二个。另一方面,编译器可能会优化这两个版本以使其性能相同。
正如其他人所说,如果数组维度不同,第二个代码片段可能会导致溢出错误,因此需要修复此问题。
然而,由于多维数组的元素在内存中的存储方式和缓存架构,在最内层循环 中循环最后一个数组维度可以 比其他方式更快现代 CPU。
此处要搜索的字词是 'cache locality' 和 'stride of arrays'