I need to loop a big array, 2 Million elements, many many times. The structure of my code looks like:
loop_tag= 0;
// the ig1, ig2 loop will run many times,
// and N & M are about 30000
for(ig1=0; ig1<N; ig1++)
{
for(ig2=0; ig2<M; ig2++)
{
for(k=0;k<45;k++)
{
element_val = arr[loop_tag];
loop_tag ++;
// there're a few lines to calculate something
}
if(loop_tag == the end of arr){loop_tag=0;}
}
}
I will run the code more than 100 000 times, each time takes me about 200~1000 sec. Actually, I have used MPI to save time. But it still needs about 10 hours with 300 CPUs being used. I find that most of the time is spent on "element_val = arr[loop_tag];". If I just assign a value to element_val like "element_val = 0.01", the time of each running will be just about 30% of before. How can I accelerate this part? Thanks!
Here are some outputs in the log file:
expo pair: 0-0-0(20193) <-> 1-0-1(22275)
Finish in 1017.22 sec. 4.49795e+08 pairs. Expo pairs got now: 1
Now 0 buffers, 1 block in current buffer
expo pair: 23-5-2(18259) <-> 201-18-1(9704)
Finish in 70.86 sec. 3.17283e+07 pairs. Expo pairs got now: 2
Now 0 buffers, 2 block in current buffer
expo pair: 23-5-2(18259) <-> 559-47-1(15243)
Finish in 608.50 sec. 2.78322e+08 pairs. Expo pairs got now: 3
Now 0 buffers, 3 block in current buffer
Here is the code inside the ig1- &ig2-loop. The code reads data from two exposure files each time, then it loop the lines of them. I put all the data, arrays, in the structure, expo_info.
// if two galaxies come from the same CFHTLenS exposure, break
if(expo_info->obs_expo_label_1[ig1] == expo_info->obs_expo_label_2[ig2]){break;}
n = ig2*expo_info->expo_data_col;
ra_z2 = expo_info->expo_data[expo_label_1][n+expo_info->ra_idx];
dec_z2 = expo_info->expo_data[expo_label_1][n+expo_info->dec_idx];
cos_dec_z2 = expo_info->expo_data[expo_label_1][n+expo_info->cos_dec_idx];
// the seperation angle (arc minute)
delta_ra = (ra_z2 - ra_z1)*cos_dec_z1;
delta_dec = dec_z2 - dec_z1;
delta_radius = sqrt(delta_ra*delta_ra + delta_dec*delta_dec);
theta_tag = -1;
for(ir=0; ir<expo_info->theta_bin_num; ir++)
{
if(delta_radius > expo_info->theta_bin[ir] and delta_radius <= expo_info->theta_bin[ir+1]){theta_tag=ir;break;}
}
if(theta_tag > -1)
{
pairs+= 1;
// shear estimators rotation (position angle defined as East of North)
sin_theta = delta_ra/delta_radius;
cos_theta = delta_dec/delta_radius;
sin_2theta = 2*sin_theta*cos_theta;
cos_2theta = cos_theta*cos_theta - sin_theta*sin_theta;
sin_4theta = 2*sin_2theta*cos_2theta;
cos_4theta = cos_2theta*cos_2theta - sin_2theta*sin_2theta;
mg1_z2 = expo_info->expo_data[expo_label_1][n+expo_info->mg1_idx]*cos_2theta - expo_info->expo_data[expo_label_1][n+expo_info->mg2_idx]*sin_2theta;
mg2_z2 = expo_info->expo_data[expo_label_1][n+expo_info->mg1_idx]*sin_2theta + expo_info->expo_data[expo_label_1][n+expo_info->mg2_idx]*cos_2theta;
mnu1_z2 = expo_info->expo_data[expo_label_1][n+expo_info->mu_idx]*cos_4theta -expo_info->expo_data[expo_label_1][n+expo_infomv_idx]*sin_4theta;
mnu2_z2 = mnu1_z2;
mnu1_z2 = expo_info->expo_data[expo_label_1][n+expo_info->mn_idx] + mnu2_z2;
mnu2_z2 = expo_info->expo_data[expo_label_1][n+expo_info->mn_idx] - mnu2_z2;
// there're zbin_num *zbin_num blocks, iz1 is row, iz2 is the col, each block
// has a length of mg_bin_num*mg_bin_num*chi_guess_num*theta_bin_num.
iz2 = expo_info->expo_zbin_label[expo_label_1][ig2];
////////////////////// the key part of PDF_SYM //////////////////////////////
ic_len = theta_tag*ir_chi_block_len + (iz1 + iz2)*expo_info-iz_chi_block_len;
gg_1 = expo_info->gg_1[loop_label];
gg_2 = expo_info->gg_2[loop_label];
temp_tt[2] = mg1_z1 - gg_1*mnu1_z1;
temp_tt[3] = mg1_z2 - gg_2*mnu1_z2;
hist_2d_new(temp_tt[2], temp_tt[3], expo_info->mg_bin,
mg_bin_num,mg_bin_num1, mg_bin_num2, mg_bin_num3, ix_tt, iy_tt);
expo_info->expo_num_count_chit[ic_len + iy_tt*mg_bin_num+ix_tt] += 1;
temp_xx[2] = mg2_z1 - gg_1*mnu2_z1;
temp_xx[3] = mg2_z2 - gg_2*mnu2_z2;
hist_2d_new(temp_xx[2], temp_xx[3], expo_info->mg_bin,
mg_bin_num,mg_bin_num1, mg_bin_num2, mg_bin_num3, ix_xx, iy_xx);
expo_info->expo_num_count_chix[ic_len + iy_xx*mg_bin_num+ix_xx] += 1;
loop_label += 1;
for(ic=1; ic<chi_guess_num; ic++)
{
ic_len += chi_block_len;
// these two lines, gg_1 & gg_2, take a lot of time.
// expo_info->gg_1 & gg_2 are two big arrays, 2 Million elements
// if I just use something like gg_1 = 0.001; gg_2 == 0.001,
// it runs very fast
gg_1 = expo_info->gg_1[loop_label];
gg_2 = expo_info->gg_2[loop_label];
bin_para_tt[0] = ix_tt;
bin_para_tt[1] = iy_tt;
temp_tt[0] = temp_tt[2];
temp_tt[1] = temp_tt[3];
temp_tt[2] = mg1_z1 - gg_1*mnu1_z1;
temp_tt[3] = mg1_z2 - gg_2*mnu1_z2;
hist_2d_new(expo_info->mg_bin, mg_bin_num, temp_tt, bin_para_tt, ix_tt, iy_tt);
expo_info->expo_num_count_chit[ic_len + iy_tt*mg_bin_num+ix_tt] += 1;
bin_para_xx[0] = ix_xx;
bin_para_xx[1] = iy_xx;
temp_xx[0] = temp_xx[2];
temp_xx[1] = temp_xx[3];
temp_xx[2] = mg2_z1 - gg_1*mnu2_z1;
temp_xx[3] = mg2_z2 - gg_2*mnu2_z2;
hist_2d_new(expo_info->mg_bin, mg_bin_num, temp_xx, bin_para_xx, ix_xx, iy_xx);
expo_info->expo_num_count_chix[ic_len + iy_xx*mg_bin_num+ix_xx] += 1;
loop_label += 1;
}
if(loop_label >= gg_len){loop_label = 0;}
////////////////////// the key part of PDF_SYM -end //////////////////////////////
}
I find most of the time is spent on
gg_1 = expo_info->gg_1[loop_label];
gg_2 = expo_info->gg_2[loop_label];