Я не могу выделить память для больших матриц, тогда ~200x200 Lapack Visual Studio в C Вот мой код
Я измеряю время выполнения решения матриц, и я не могу получить больше чем ~200x200, я должен идти, вероятно, 1500x1500 или близко к этому. Я запускаю это на VS .
#include <stdlib.h>
#include <stdio.h>
#include "lapacke.h"
#include "lapacke_config.h"
#include <time.h>
/* Auxiliary routines prototypes */
extern void print_matrix(lapack_complex_double *a, int m, int n);
extern void generate_matrix(lapack_complex_double * matrix, int w, int h);
/* Parameters */
#define N 179
/* Main program */
int main() {
clock_t t;
/* Locals */
lapack_int n = N,info;
lapack_int ipiv[N];
lapack_complex_double a[N*N];
lapack_complex_double b[N*N];
FILE* fp1 = fopen("complexNumsLog.txt", "w");
int w = 1, h = 1, h2 = 1, i = 0, j = 0;
for(i = 1; i <= N; i++){
for(j = 1; j <= N; j++){
w = i;
h = i;
h2 = j;
generate_matrix(a, w, h);
generate_matrix(b, w, h2);
// print_matrix(a, w, h);
// print_matrix(b, w, h2);
// getchar();
t = clock();
info = LAPACKE_zgesv(LAPACK_ROW_MAJOR, w, h2, a, h, ipiv, b, h2);
t = clock() - t;
fprintf(fp1, "Matrix A: %3dx%3d ", w, h);
fprintf(fp1, "Matrix B: %3dx%3d ", w, h2);
fprintf(fp1, "%3d milliseconds %2.3f seconds\n",t,((float)t)/CLOCKS_PER_SEC);
/* Check for the exact singularity */
if( info > 0 ) {
printf( "The diagonal element of the triangular factor of A,\n" );
printf( "U(%i,%i) is zero, so that A is singular;\n", info, info );
printf( "the solution could not be computed.\n" );
getchar();
exit( 1 );
}
}
printf("%d\n", i);
}
getchar();
exit( 0 );
}
void print_matrix(lapack_complex_double* a, int m, int n) {
int i, j;
for( i = 0; i < m; i++ ) {
for( j = 0; j < n; j++ )
printf( " (%6.2f,%6.2f)", a[i*m+j].real, a[i*m+j].imag );
printf( "\n" );
}
printf( "********************************************\n" );
}
void generate_matrix(lapack_complex_double * matrix, int w, int h){
int i,j;
double r;
for(i = 0; i < w; i++){
for(j = 0; j < h; j++){
r = (rand()%1000 - 500)/100.0;
matrix[i*w+j].real = r;
r = (rand()%1000 - 500)/100.0;
matrix[i*w+j].imag = r;;
}
}
}
2 ответа
Вы дуете свой стек. Ваша программа обычно выделяет всего несколько МБ стекового пространства, и вы пытаетесь выделить все свои данные в стеке. Когда вы превышаете 200x200, вы очень быстро исчерпываете пространство стека.
Чтобы это исправить, вам нужно либо выделить память в глобальной области видимости или в куче, где размер ограничен только вашим виртуальным адресным пространством и / или общим объемом доступной физической памяти. Поскольку размер известен во время компиляции, его проще всего выделить в глобальной области видимости:
/* Parameters */
#define N 179
lapack_int ipiv[N];
lapack_complex_double a[N*N];
lapack_complex_double b[N*N];
/* Main program */
int main() {
...
}
Это вполне нормально. У вас есть этот блок объявлений в вашем коде:
lapack_int ipiv[N];
lapack_complex_double a[N*N];
lapack_complex_double b[N*N];
что, я думаю, является доминирующим распределением памяти. Я полагаю, что двойной комплекс Лапака представлен парой double
и Lapack Int как int
, но даже если это не так, конечный результат не сильно изменится.
Давайте возьмем некоторые стандартные значения (в байтах) для sizeof (double)
, 8, и sizeof (int)
4.
Хорошо, мы готовы рассчитать, сколько памяти вам нужно
Memory occupation = 2*(8*2)*N² + 4*N = 32N² + 4N Bytes
Что это значит?
| N | Memory occupation |
|--------|-------------------|
| 50 | 80kb |
| 100 | 320kb |
| 150 | 721kb |
| 500 | 8MB |
| 1000 | 32MB |
| 1500 | 72MB |
Поскольку это локальные переменные, они размещаются в стеке и... вау! 72 МБ стека! Это довольно много, учитывая, что стандартный размер стека составляет 1 МБ в Windows с MSVC.
Вы можете выделить их динамически с malloc
:
lapack_int *ipiv = malloc(N * sizeof (lapack_int));
lapack_complex_double *a = malloc(N * N * sizeof (lapack_complex_double);
lapack_complex_double *b = malloc(N * N * sizeof (lapack_complex_double);
но не забудьте освободить ресурсы перед выходом из функции, иначе вы потеряете (много) памяти. Делать:
free(ipiv);
free(a);
free(b);
как раз перед return
,