C 并行操作执行时间因分配动态内存和静态内存而异
我已经编写了一个代码,使用openmp parallel for(对于外部循环)将两个n乘n矩阵相乘。我已经在编译时给出了数组大小。我希望给出n作为2000。然而,作为第二个版本,我编写了相同的代码,为三个矩阵动态分配空间,并将n(2000)的大小作为参数。当n=2000时,我得到的两个版本的执行时间相差很大。对于第1版(静态分配)约为13秒,对于第2版(动态分配)约为32秒。但两者给出的n时间大致相同,动态分配有三个主要差异:C 并行操作执行时间因分配动态内存和静态内存而异,c,memory-management,parallel-processing,openmp,C,Memory Management,Parallel Processing,Openmp,我已经编写了一个代码,使用openmp parallel for(对于外部循环)将两个n乘n矩阵相乘。我已经在编译时给出了数组大小。我希望给出n作为2000。然而,作为第二个版本,我编写了相同的代码,为三个矩阵动态分配空间,并将n(2000)的大小作为参数。当n=2000时,我得到的两个版本的执行时间相差很大。对于第1版(静态分配)约为13秒,对于第2版(动态分配)约为32秒。但两者给出的n时间大致相同,动态分配有三个主要差异: 数据不是连续分配的,因为每一行是单独分配的。这会导致内存访问效率降
N
在编译时不再为人所知,因此编译器必须为N
上的循环生成更多通用代码第一个版本分配一个数组数组(即常用的2-D数组),而第二个版本分配一个指针数组,每个指针指向另一个数组。第二个版本中有更多的间接内存访问(通过指针差异),“为NxN大小的矩阵声明指针”-没有指向矩阵(也称为2D数组)的指针。指针不是数组@IanAbbott这就是为什么第二个版本由于间接内存访问而花费更多时间的原因吗?部分原因是间接内存访问,尽管如果编译器进行了合理的优化工作,并且能够在外循环的完整迭代期间将指针数组的当前元素保存在寄存器中,那么它应该只会使外环慢一点。剩下的速度减慢可能是由于第二个版本中由于非连续数据而导致更多缓存未命中,也可能是因为编译器在编译时不知道维度,因此需要在运行时进行更多计算。明白了,谢谢@IanAbbott
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <omp.h>
#define N 1000
double A[N][N], B[N][N], C[N][N]; // declaring matrices of NxN size
int main ()
{
/* DECLARING VARIABLES */
int i, j, m; // indices for matrix multiplication
double t_1; // Execution time measures
/* FILLING MATRICES WITH RANDOM NUMBERS */
srand ( time(NULL) );
for(i=0;i<N;i++) {
for(j=0;j<N;j++) {
A[i][j]= (rand()%10);
B[i][j]= (rand()%10);
}
}
double st=omp_get_wtime();
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
for(m=0;m<N;m++)
{
C[i][j]+=A[i][m]*B[m][j];
}
}
}
/* TIME MEASURE + OUTPUT */
double en=omp_get_wtime();
printf("Serial: %lf\n",en-st);
}
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <omp.h>
int N = 0; // no of columns and rows of a matrix
double **A, **B, **C; // declaring pointers for matrices of NxN size
void getArguments(int argc, char *argv[]);
int main (int argc, char *argv[])
{
/* DECLARING VARIABLES */
int i, j, m; // indices for matrix multiplication
double t_1; // Execution time MEASURES
getArguments(argc,argv);
/* ALLOCATE MEMORY FOR MATRIX A */
A = (double **) malloc( sizeof(double *) * N);
for(i = 0;i < N; i++)
{
A[i] = (double *) malloc(sizeof(double *) * N);
}
/* ALLOCATE MEMORY FOR MATRIX B */
B = (double **) malloc( sizeof(double *) * N);
for(i = 0;i < N; i++)
{
B[i] = (double *) malloc(sizeof(double *) * N);
}
/* ALLOCATE MEMORY FOR MATRIX C */
C = (double **) malloc( sizeof(double *) * N);
for(i = 0;i < N; i++)
{
C[i] = (double *) malloc(sizeof(double *) * N);
}
/* FILLING MATRICES WITH RANDOM NUMBERS */
srand ( time(NULL) );
for(i = 0;i < N;i++) {
for(j = 0;j < N;j++) {
A[i][j] = (rand() % 10);
B[i][j] = (rand() % 10);
}
}
double st = omp_get_wtime();
#pragma omp parallel for private(m,j)
for(i = 0;i < N;i++) {
for(j = 0;j < N;j++) {
C[i][j] = 0.; // set initial value of resulting matrix C = 0
for(m = 0;m < N;m++) {
C[i][j] = A[i][m] * B[m][j] + C[i][j];
}
}
}
/* TIME MEASURE */
double en = omp_get_wtime();
printf("Parallel: %lf\n",en - st);
/* FREE MEMORY */
for(i = 0;i < N; i++){
free(A[i]);
}
free(A);
for(i = 0;i < N; i++){
free(B[i]);
}
free(B);
for(i = 0;i < N; i++){
free(C[i]);
}
free(C);
}
void getArguments(int argc, char *argv[]){
// Check the N
if (argc != 2) {
printf("Please give a valid number for N\n");
exit(0);
}
N = (int) strtol(argv[1], (char **) NULL, 10);
if (N == 0) {
printf("Please give a number for N more than 0\n");
exit(0);
}
}