0

The all task is: Implement the deterministic mass ranking algorithm.

The task should be prepared using the MPI standard in C programming language. Run times should be measured during runs on 1, 2, and 4 threads and plotted on a graph. The input N should always be 2 powers and this should be given on the horizontal x-axis, but only the exponents. For example, in the case of 1024, the scale is 10, because the 10th power of 2 is 1024. This is the so-called logarithmic scale. Thus, the scale of the x-axis remains linear, and the result can be easily plotted even with larger inputs. In all cases, the malloc function must be used, otherwise they will get a segmentation error! Whenever possible, input should be generated randomly.

My problem is, how can I measure the MPI threads, without the following error: MPI_Init_thread(517): Cannot call MPI_INIT or MPI_INIT_THREAD more than once

My second problem is, how can I visualize the measured numbers?

My code is following:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <dos.h>
#include <conio.h>
#include <graphics.h>
#include <math.h>
#include <mpi.h>
#include <string.h>
#include <omp.h>
#include "mpi.h"
 
int egyszal(int szomsz[], int rang[], int p, int x);
int ketszal(int szomsz[], int rang[], int p, int x);
int negyszal (int szomsz[], int rang[], int p, int x);
 
int egyszal(int szomsz[], int rang[], int p, int x)
{
    int i, j;
 
    MPI_Init_thread( 0, 0, MPI_THREAD_MULTIPLE, &x );
 
    for(i = 0; i < p; ++i)
    {
        if(szomsz[i] == 0)
        {
            rang[i] = 0;
        }
        else
        {
            rang[i] = 1;
        }
    }
 
    for(j = 0; j < log10(p); ++j)
    {
        //printf("j valtozo erteke: %d\n", j);
        for(i = 0; i < p; ++i)
        {
            //printf("i valtozo erteke: %d\n", i);
            if( szomsz[i] != 0)
            {
                rang[i] = rang[i] + rang[szomsz[i]];
                szomsz[i] = szomsz[szomsz[i]];
            }
        }
    }
 
    double ido_1 = MPI_Wtime();
 
    MPI_Finalize();
    MPI_Abort;
 
 
    return ido_1;
}
 
int ketszal(int szomsz[], int rang[], int p, int x)
{
    int i, j;
 
    MPI_Init_thread( 0, 0, MPI_THREAD_MULTIPLE, &x );
 
    for(i = 0; i < p; ++i)
    {
        if(szomsz[i] == 0)
        {
            rang[i] = 0;
        }
        else
        {
            rang[i] = 1;
        }
    }
 
    for(j = 0; j < log10(p); ++j)
    {
        //printf("j valtozo erteke: %d\n", j);
        for(i = 0; i < p; ++i)
        {
            //printf("i valtozo erteke: %d\n", i);
            if( szomsz[i] != 0)
            {
                rang[i] = rang[i] + rang[szomsz[i]];
                szomsz[i] = szomsz[szomsz[i]];
            }
        }
    }
 
    double ido_1 = MPI_Wtime();
 
    MPI_Finalize();
    MPI_Abort;
 
    return ido_1;
}
 
int negyszal(int szomsz[], int rang[], int p, int x)
{
    int i, j;
 
    MPI_Init_thread( 0, 0, MPI_THREAD_MULTIPLE, &x );
 
    for(i = 0; i < p; ++i)
    {
        if(szomsz[i] == 0)
        {
            rang[i] = 0;
        }
        else
        {
            rang[i] = 1;
        }
    }
 
    for(j = 0; j < log10(p); ++j)
    {
        //printf("j valtozo erteke: %d\n", j);
        for(i = 0; i < p; ++i)
        {
            //printf("i valtozo erteke: %d\n", i);
            if( szomsz[i] != 0)
            {
                rang[i] = rang[i] + rang[szomsz[i]];
                szomsz[i] = szomsz[szomsz[i]];
            }
        }
    }
 
    double ido_1 = MPI_Wtime();
 
    MPI_Finalize();
    MPI_Abort;
 
    return ido_1;
}
 
int main(int argc, char** argv)
{
    int i, j;
    int x = 1;
 
    int szomsz[] = {5, 4, 2, 0, 3, 1};
    int rang[] = {1, 1, 1, 0, 1, 1};
 
    int seged_1 = sizeof(szomsz);
    int seged_2 = sizeof(int);
    int p = seged_1/seged_2;
 
    egyszal(szomsz, rang, p, x);
 
    x = 2;
    ketszal(szomsz, rang, p, x);
 
    x = 4;
    negyszal(szomsz, rang, p, x);
 
   return 0;
}

1 Answers1

1

You can visualize with Gnuplot, considering the stdout prints, you can grab the stdout in a bash script file, and based on the input data, and the stdout you can visualize nice figures.

here is the example of collecting the "execution time" and then plot it then with Gnuplot:

In the following, based on the experiment, I will write results in a "CSV" file, then plot them.

FILENAME=MEASUREMENT
wdir=`pwd`
toolname=`pwd | awk -F/ '{print $NF}'`
cpath="run_mpi.sh" #command path of your executable
irange="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25" # input range

mstring="EXECUTION TIME" # matching string
mcolumn="5" # matching column
nrep="10" #number of repetition of the test
#-----------------------------------
if [ ! -d "$wdir" ]; then
    echo "ERROR: cannot find '$wdir'"; exit 1
fi

if [ ! -s "$wdir/$cpath" ]; then
    echo "ERROR: cannot find '$cpath' in '$wdir'"; exit 1
fi

cd $wdir
FILENAME=$FILENAME
re='^[0-9]+$'
echo "pwd=`pwd`"
echo "create log and plot file name: $FILENAME.csv"
echo "logs and plots will store into $wdir/logs/"
echo ""
for i in $irange; do
        a="0"; min=""; max="0"
        for r in `seq $nrep`; do

      output=`./$cpath $i 2>error.log`
      val=`echo "$output"|awk "/$mstring/{print \\$5}" c=$mcolumn`
      if ! [[ $val =~ $re ]] ; then echo "ERROR: The output is not a number! (input=$i,output='$val')" >&2; exit 1; fi
      if [ 1 = `echo "$val > $max"|bc` ]; then max="$val"; fi
      if [ "$min" = "" ]; then
         min="$val"; a="$val"
      else
         if [ 1 = `echo "$val < $min"|bc` ]; then min="$val"; fi
      fi
      i1=`expr $i - 1`
      a=`echo "define trunc(x) { auto s; s=scale; scale=0; x=x/1; scale=s; return x } trunc($a * $i1 / $i + $val / $i)"|bc -l`
#      echo "$i -- $val -- $a -- $min -- $max"

        done
        echo "$i,$a,$min,$max"
        printf %s'\n' "$i,$a,$min,$max" >> $FILENAME.csv
done



### plot the collected CSV file
for FILE in ${FILENAME}.csv; do
    gnuplot <<- EOF
        set xlabel "Fib Index"
        set ylabel "Execution time (ns)"
        set key left
        set term png
        set style histogram cluster gap 1
        set style fill solid 0.5
        set boxwidth 0.9
        set style histogram errorbars linewidth 1
        set errorbars linecolor black 
red = "#FF0000"; green = "#00FF00"; blue = "#0000FF"; skyblue = "#87CEEB" ; violet = "#FF00FF"; purple = "#440154" ;
        set grid ytics
        set format y '10^{%L}'
        set logscale y
        set autoscale x
        set yrange [1:]
        set output "${FILENAME}.png"
        set datafile separator ","
        set style data histogram
        plot "${FILENAME}.csv" using 2:3:4:xtic(1) title "Execution time (ns)" linecolor rgb purple linewidth 0
        EOF
done

You can also search about how to embed this script in your code, is possible to have Gnuplot in your C code. Look at here for instance: Making C code plot a graph automatically

Elephant88
  • 117
  • 1
  • 12