USER
逆行列の算出ですが、20000x20000 だと、倍精度が必要なようです。 11:53:46 2025 Matrix 20000x 20000 Generate an array of random numbers Elapsed time: 0h 0m 4s 311ms 888us 11:53:50 Inverse matrix size: 20000 X 20000 Elapsed time: 4h 7m 17s 946ms 212us 16:01:12 Generated matrix X Inverse matrix size: 20000 X 20000 Elapsed time: 2h 43m 33s 310ms 82us 18:44:48 E is an identity matrix 18:44:48
AI
USER
LU分解でも long double が必要ということです。
AI
USER
ただ、PC で 20000×20000 が半日もかからず解けるのは驚きでもあります。
AI
USER
BLAS を使って 20000×20000 の行列の逆行列 を解くと何秒ぐらいで解けますか?
AI
USER
// 動的メモリ確保 A = (double **)alloc2Darray(sizeof(double), n, n); A_inv = (double **)alloc2Darray(sizeof(double), n, n); E = (double **)alloc2Darray(sizeof(double), n, n); double start_time, end_time, date_Begin, date_i, date_e, date_v, date; date_Begin = date = *localtime(&timer); // ランダムな値で初期化されたnxn行列 start_time = get_micro_time(); for(int i=0; i<n; i++)for(int j=0; j<n; j++) A[i][j]=100.*(double)rand()/RAND_MAX; end_time = get_micro_time(); time(&timer); date_o = date = *localtime(&timer); //////////////////////////////////////////////////////////////////////////////////////////////// // 逆行列を計算 start_time = get_micro_time(); inverse_matrix_wrapping( A, A_inv, n ); end_time = get_micro_time(); time(&timer); date_i = date = *localtime(&timer); //////////////////////////////////////////////////////////////////////////////////////////////// start_time = get_micro_time(); multiplication_matrixEx(A, A_inv, E, n); end_time = get_micro_time(); time(&timer); date_e = date = *localtime(&timer); //////////////////////////////////////////////////////////////////////////////////////////////// fflush(stdout); if(ofname && fp)fflush(fp); long long flag=0; for(int y=0; y<n; y++)for(int x=0; x<n; x++){ int v = 100000*(E[y][x]+ 0.0000001); if( y==x ){if(v!=100000){if(perr)printf("ERROR: (% 6d,% 6d) %d\n", x, y, v); flag++; } } else if( v ){ flag++; if(perr)printf("ERROR: (% 6d,% 6d) %d\n", x, y, v); } } time(&timer); date_v = *localtime(&timer); //////////////////////////////////////////////////////////////////////////////////////////////// printf((flag?"\nE is not an identity matrix. %lld\n":"\nE is an identity matrix\n"),flag); void inverse_matrix_DoublePrecision(double** A, double** A_inv, int n) { long double** L = (long double**)malloc(n * sizeof(long double*)); long double** U = (long double**)malloc(n * sizeof(long double*)); long long* P = (long long*)malloc(n * sizeof(long long)); if( L && U && P ){ for(int i=0; i<n; i++) { L[i] = (long double*)calloc(n, sizeof(long double)); U[i] = (long double*)calloc(n, sizeof(long double)); if( !L[i] && !U[i] ){ perror("Memory allocation error L[i],U[i] in inverse_matrix\n"); exit(1); } } lu_decomposition_DoublePrecision(A, L, U, P, n); #pragma omp parallel for schedule(dynamic) for(int i=0; i<n; i++) { long double* e = (long double*)calloc(n, sizeof(long double)); long double* x = (long double*)calloc(n, sizeof(long double)); if( e && x ){ e[i] = 1.0; solve_LU_DoublePrecision(L, U, P, e, x, n); for(int j=0; j<n; j++) A_inv[j][i] = x[j]; } else { perror("Memory allocation error for solve_LU_DoublePrecision\n"); exit(1); } free(e); free(x); } } else { perror("Memory allocation error in inverse_matrix\n"); exit(1); } for(int i=0; i<n; i++){ free(L[i]); free(U[i]); } free(L); free(U); free(P); }
AI
USER
//////////////////////////////////////////////////////////////////////////////////////////////// fflush(stdout); if(ofname && fp)fflush(fp); long long flag=0; for(int y=0; y<n; y++)for(int x=0; x<n; x++){ int v = 100000*(E[y][x]+ 0.0000001); if( y==x ){if(v!=100000){if(perr)printf("ERROR: (% 6d,% 6d) %d\n", x, y, v); flag++; } } else if( v ){ flag++; if(perr)printf("ERROR: (% 6d,% 6d) %d\n", x, y, v); } } time(&timer); date_v = *localtime(&timer); //////////////////////////////////////////////////////////////////////////////////////////////// printf((flag?"\nE is not an identity matrix. %lld\n":"\nE is an identity matrix\n"),flag);
AI
USER
プラスに振れます。 マイナス0を消すのが目的で、100000 して整数にするので、さらにその1/10は無視できる値ということです
AI