Why does it stop working?

2

Good, I'm testing the execution time for different algorithms that solve the problem of matrix multiplication, but when I try to order arrays 417 up, the .exe stops working.

The program compiles without problems, but I would like to know why for high values of N the program no longer runs since I will also try other algorithms that possibly cause this problem.

I am using C in codeblocks, I leave the code I use:

#include<stdio.h>
#include<time.h>
#include<stdlib.h>

#define N 416

void llenarMat(long mat[][N]);
void multMat(long A[][N] , long B[][N] , long C[][N]);
void mostrarMat(long A[][N]);

int main()
{
    long A[N][N];
    long B[N][N];
    long C[N][N];

    clock_t start_t , end_t;
    double total_t;

    srand(time(NULL));

    llenarMat(A);
    llenarMat(B);

    start_t = clock();
    printf("El metodo empieza, start_t = %ld\n", start_t);
    multMat(A , B , C);
    end_t = clock();
    printf("El metodo termina, end_t = %ld\n", end_t);

    total_t = (double)(end_t - start_t) / CLOCKS_PER_SEC;
    printf("Tiempo total tomado por el CPU: %f\n", total_t);

    /*mostrarMat(A);
    mostrarMat(B);
    mostrarMat(C);*/

    return 0;
}

void llenarMat(long mat[][N])
{
    long i, j;

    for (i = 0 ; i < N ; i++)
    {
        for (j = 0 ; j < N ; j++)
            mat[i][j] = (rand() % 10 )+ 1;
    }
}

void multMat(long A[][N] , long B[][N] , long C[][N])
{
    long i , j , k;
    long sum;

    for(i = 0 ; i < N ; i++)
    {
        for (j = 0 ; j < N ; j++)
        {
            sum = 0;
            for(k = 0 ; k < N ; k++)
            {
                sum = sum + A[i][k] * B[k][j];
            }
            C[i][j] = sum;
        }
    }
}

void mostrarMat(long A[][N])
{
    long i, j;

    for (i = 0 ; i < N ; i++)
    {
        for (j = 0 ; j < N ; j++)
            printf(" %d", A[i][j]);
        printf("\n");
    }
    printf("\n");
}
    
asked by Rodfelje 02.09.2016 в 18:27
source

2 answers

2

When you run a program there are 3 memory areas, the stack (stack), data (data) and mound (heap).

Your problem is the stack overflow, caused by the declaration of the constant N, since you are reserving memory in a static way.

Generally, the stack has 8 MB and is used to save the state of the variables when invoking a function, it also stores the return address of the function and then continues its execution of the program.

One possible solution, although not correct, is to modify the type of the variable by a type that occupies less space in the stack, for example an integer.

This will depend on the accuracy you need for your matrix calculations

The correct solution to your problem is to use dynamic memory instead of static using the functions malloc and calloc .

#include<stdio.h>
#include<time.h>
#include<stdlib.h>

#define N 1000



void llenarMat(long *a);
void multMat(long *a , long *b , long *c);
void mostrarMat(long *a);

int main()
{

    long *A;
    long *B;
    long *C;
    A = malloc (N*N*sizeof(long));
    B = malloc (N*N*sizeof(long));
    C = malloc (N*N*sizeof(long));

    clock_t start_t , end_t;
    double total_t;

    srand(time(NULL));

    llenarMat(A);
    llenarMat(B);
    llenarMat(C);


    start_t = clock();
    printf("El metodo empieza, start_t = %ld\n", start_t);
    multMat(A, B , C);
    end_t = clock();
    printf("El metodo termina, end_t = %ld\n", end_t);

    total_t = (double)(end_t - start_t) / CLOCKS_PER_SEC;
    printf("Tiempo total tomado por el CPU: %f\n", total_t);


    return 0;
}

void llenarMat(long *v)
{
    long i, j;

    for (i = 0 ; i < N ; i++)
    {
        for (j = 0 ; j < N ; j++)
            v[i* N+j] = (rand() % 10 )+ 1;
    }
}



void multMat(long *a, long *b , long *c)
{
    int i, j, k;

    for (i = 0; i < N; i++){
        for (j = 0; j < N; j++){
            for (k = 0; k < N; k++){
                c[i*N + j] += a[ i*N +k ] * b[k * N + j];
            }

        }

    }
}

void mostrarMat(long *v)
{
    int i, j;

    for (i = 0; i < N; i++){
        printf("\n");
        for (j = 0; j < N; j++){
            printf(" %d \t", (int) v[i * N + j]);
        }
    }
}

Output with N = 1000

Output with N = 1500

Greetings!

    
answered by 03.09.2016 / 22:25
source
-1

The problem is the available stack size.

On my machine it does not fail with N = 417 but it fails with N = 1000, I get a segment violation.

But it works fine if I increase the size of the stack with the following code (for a Linux system):

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include <sys/resource.h>

#define N 1000

void llenarMat(long mat[][N]);
void multMat(long A[][N] , long B[][N] , long C[][N]);
void mostrarMat(long A[][N]);


// Devuelve 0 si tiene exito. 
// No hace nada si se pide un tamaño menor al actual
int aumentaTamPila(const rlim_t tamPilaBytes)
{
    struct rlimit rl;
    int result;

    result = getrlimit(RLIMIT_STACK, &rl);
    if (result == 0)
    {
        if (rl.rlim_cur < tamPilaBytes)
        {
            rl.rlim_cur = tamPilaBytes;
            return setrlimit(RLIMIT_STACK, &rl);
        }
    }

    return 0;
}

int testMatrices()
{
  // Poner aquí el código del main de la pregunta
}

int main()
{
  aumentaTamPila( 1024*1024*1024 ); // 1Gib de pila
  testMatrices();
}

// Poner el resto del código de la pregunta.

Note that I have put the original code in the function testMatrices , not in the main. It is very important that the variables A, B and C are not in the main because C has to reserve space in the stack for A, B and C when starting main, before the main code is executed, and then it still does not has run the stack size increase.

In other systems, for example in MAC, it is possible to specify the stack size when compiling. I imagine that in those systems it would be possible to put A, B and C in the main.

In linux you get a segment violation because the stack is separated from the heap (heap) and an operation on the stack can never overwrite the heap; an attempt to use more memory in the available stack causes the program to close in a predictable manner. In other systems, such as Toyota's disastrous ETCS, stack and heap share the same space and the stack can write in the heap causing the program to continue to run unpredictably.

A separate question. Use %ld for printf of long , not %d .

    
answered by 03.09.2016 в 00:25