0

I am writing a code for vector addition in C. I am getting a segmentation fault when I pass the arguments as 10 million.

I know segmentation fault occurs when we access memory address outside process address space.

But I don't think so here it is not the reason here.

My code is:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
struct timeval stop, start,start1,stop1;
void add(int a[], int b[],int N);

int main(int argc, char* argv[]){

    gettimeofday(&start1, NULL);

    if(argc<2){
        printf("Please enter the value of N(number of elements)\n");
    }else{
        int i,N;
        N=atoi(argv[1]);
        N=N*1024;   
        int a[N],b[N];
        for(i=0;i<=N;i++){
            a[i]=rand()%1000;
            b[i]=rand()%1000;
        }
        gettimeofday(&start, NULL);
        add(a,b,N);
        gettimeofday(&stop, NULL);
        printf("took %lu us\n", (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec);
    }
    gettimeofday(&stop1, NULL);
    printf("Total took %lu us\n", (stop1.tv_sec - start1.tv_sec) * 1000000 + stop1.tv_usec - start1.tv_usec);
    return 0;
}

void add(int a[], int b[], int N){
    int c,i;
    for(i=0;i<=N;i++){
        c=a[i]+b[i];
        // printf("%d + %d = %d\n",a[i],b[i],c);
    }
}

And output is as follows: (The command argument is the size of array)

$ ./vectorAdd 1
took 9 us
Total took 233 us

$ ./vectorAdd 10
took 93 us
Total took 918 us

$ ./vectorAdd 100
took 210 us
Total took 4974 us

$ ./vectorAdd 1000
took 2371 us
Total took 20277 us

$ ./vectorAdd 10000
Segmentation fault (core dumped)

EsmaeelE
  • 2,331
  • 6
  • 22
  • 31
  • 7
    Measuring execution time on a multi-tasking system together with other processes and threads is going to give unreliable results. For benchmarking, do the task you're measuring many times (thousands or perhaps even millions of times) and calculate an average or mean. And remember to always measure an optimized build. – Some programmer dude Feb 02 '20 at 19:29
  • 1
    How are you compiling your code? If it is not at least a `-O2` you are wasting your time as the assembler that gcc and most other compilers generate at default is worse than sub optimal – Adrian Cornish Feb 02 '20 at 19:33
  • 4
    Also you have a printf in add() so you are measuring the time to output to the console – Adrian Cornish Feb 02 '20 at 19:37
  • I compiled using -O2 and it worked and also Can you please tell how to convert us to ms@AdrianCornish – Bhavin Thakar Feb 02 '20 at 19:55
  • @BhavinThakar Why would you want ms :-) - but sure divide by 1000 – Adrian Cornish Feb 02 '20 at 20:03
  • 2
    `for(i=0;i<=N;i++)` causes arrays to ovreflow. This could cause the crash. use `i < N`; – Serge Feb 02 '20 at 21:24
  • 3
    All good comments, however, I suspect your Segmentation fault is because the arrays are getting allocated on the stack. Stacks typically aren't very big. – Frank Merrow Feb 02 '20 at 21:31
  • On Unix-like systems, the total stack size is typically 8 MiB by default; on Windows, it is 1 MiB by default. Since you multiply the given size by 1024, and you are allocating two arrays of integers, when you specify 1000, you are allocating just under 8 MiB and therefore get away without exceeding the default (Unix) stack size limit. When you use 10000, you are attempting to allocate just under 80 MiB, which is far too big and a segmentation fault is almost inevitable. Use `malloc()` for larger sizes of array (and perhaps for smaller sizes too). Or impose an upper limit on the given size. – Jonathan Leffler Feb 02 '20 at 22:59
  • Note that an optimizing compiler might eliminate the call to `add()` altogether as it has no detectable side effects. You need to do something like accumulate the sums of both vectors into `c` and return that from `add()` and print the result outside the timing code. `int add(int a[], int b[], int N) { int c = 0; for (int i = 0; i < N; i++) c += a[i] + b[i]; return c; }` or thereabouts. – Jonathan Leffler Feb 02 '20 at 23:03
  • You can increase stack size then run program. For example: `sudo ulimit -s 1658989` then run executable. – EsmaeelE Feb 02 '20 at 23:18
  • https://stackoverflow.com/a/28927490/7508077 – EsmaeelE Feb 02 '20 at 23:34
  • The Intention of writing code in this way because my goal is to compare time difference between CPU and GPU where kernel function add remains constant that means both the functions operate in same fashion @JonathanLeffler – Bhavin Thakar Feb 04 '20 at 20:27
  • I tried your solution but sorry doesn't work @Serge. Thankyou and appreciate for your answer – Bhavin Thakar Feb 04 '20 at 20:28
  • @BhavinThakar good to fix it in any case :-). Stack size is the the next then. – Serge Feb 04 '20 at 23:03
  • I wanted to ask I thought of a way to do this is to declare global variables and then use malloc(), memcopy() and free() functions to allocated memory for the process@Serge. Thankyou for your patience in answering the question. I wiill try and post the solution today – Bhavin Thakar Feb 05 '20 at 04:12

1 Answers1

0

I tried this and it works. Thank you for all your responses. It really helped me.If there are any optimization please let me know Output:

$ ./vectorAdd 10000
took 34853 us
Total took 246023 us

#include<stdio.h>
#include<stdlib.h>
#include <sys/time.h>
struct timeval stop, start,start1,stop1;
void add(int *a, int *b, int *c, int N);
int *a, *b ,*c;

int main(int argc,char* argv[]){
    gettimeofday(&start1, NULL);
    if(argc<2){
        printf("Please enter the value of N(number of elements)\n");
    }
    else
    {
        int i,N=0;
        N=atoi(argv[1]);
        N=N*1024;
        a=(int *)malloc(N * sizeof(int));
        b=(int *)malloc(N * sizeof(int));
        c=(int *)malloc(N * sizeof(int));
        for(i=0;i<N;i++){
            a[i]=rand()%1000;
            b[i]=rand()%1000;
        }
        gettimeofday(&start, NULL);
        add(a,b,c,N);
        gettimeofday(&stop, NULL);
        printf("took %lu us\n", (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec);
        free(a);
        free(b);
        free(c);
    }
    gettimeofday(&stop1, NULL);
    printf("Total took %lu us\n", (stop1.tv_sec - start1.tv_sec) * 1000000 + stop1.tv_usec - start1.tv_usec);
    return 0;
}

void add(int *a, int *b,int *c, int N){
    int i;
    for(i=0;i<=N;i++){
        c[i]=a[i]+b[i];
        // printf("%d + %d = %d\n",a[i],b[i],c[i]);
    }
}