Matrizen Multiplikation



  • Hallo Leute,

    Meine Aufgabe ist Matrix Multiplikation von verschiedenen Loop Orders in C++ zu schreiben und die Laufzeiten von diesen zu messen. Wir muessen die Multiplikation von general Matrizen ausrechnen und die Daten in Row Major Order speichern. Ich habe Programm geschrieben wenn ich z.B nur eine Dimension N habe aber Problem ist es dass bei general Matrizen die Anzahl der Spalten bzw. Zeilen unterschiedlich sein kann. Ich wollte jetzt fragen wie ich diese Sachen in Programm schreiben kann bzw. wie kann ich meine Daten in Row Major Order speichern. Mein Programm :

    #include <iostream>
    #include <stdlib.h>
    #include "stl.h"
    #include <time.h>      
    
    using namespace std;
    
    void arrayausleeren(int size, double *array)    
    {
        for (int i= 0 ; i < size * size ; i++)    
            array[i] = 0;
    }
    
    void foo1(int size, double *data1, double *data2, double *result)  
    {
        arrayausleeren(size,result);
        for (int i = 0 ; i < size; i++)
            for (int f = 0 ; f < size ; f++)
                for (int k = 0; k < size;k++)
                {
                    result[size*i+f] += data1[size*i+k] * data2[size*k+f];
                }
    
    }
    
    void foo2(int size, double *data1, double *data2, double *result)
    {
        arrayausleeren(size,result);
        for (int i = 0 ; i < size; i++)
            for (int k = 0 ; k < size ; k++)
                for (int f = 0; f < size;f++)
                {
                    result[size*i+f] += data1[size*i+k] * data2[size*k+f];
                }
    
    }
    
    void foo3(int size, double *data1, double *data2, double *result)
    {
        arrayausleeren(size,result);
        for (int f = 0 ; f < size; f++)
            for (int i = 0 ; i < size ; i++)
                for (int k = 0; k < size;k++)
                {
                    result[size*i+f] += data1[size*i+k] * data2[size*k+f];
                }
    }
    
    void foo4(int size, double *data1, double *data2, double *result)
    {
        arrayausleeren(size,result);
        for (int f = 0 ; f < size; f++)
            for (int k = 0 ; k < size ; k++)
                for (int i = 0; i < size;i++)
                {
                    result[size*i+f] += data1[size*i+k] * data2[size*k+f];
                }
    }
    
    void foo5(int size, double *data1, double *data2, double *result)
    {
        arrayausleeren(size,result);
        for (int k = 0 ; k < size; k++)
            for (int i = 0 ; i < size ; i++)
                for (int f = 0; f < size;f++)
                {
                    result[size*i+f] += data1[size*i+k] * data2[size*k+f];
                }
    }
    
    void foo6(int size, double *data1, double *data2, double *result)
    {
        arrayausleeren(size,result);
        for (int k = 0 ; k < size; k++)
            for (int f = 0 ; f < size ; f++)
                for (int i = 0; i < size;i++)
                {
                    result[size*i+f] += data1[size*i+k] * data2[size*k+f];
                }
    }
    
    void randomzahl(int size, double *array)
    {
        for(int i = 0 ; i< size * size ;i++)
        {
            array[i] = rand();
        }
    }
    
    int main(int argc,const char *argv[]) {
    
        int N = atoi(argv[1]);
    	int M = atoi(argv[2]);
    
    	if( N != M)
        {
            cout << "Die Spaltenanzahl der linken Matrizen muss mit der Zeilenanzahl der rechten Matrizen uebereinstimmen!!!";
            exit(1);
        }
        double * arr = new double[6];
        double *A = new double[N*N];
        double *B = new double[N*N];
        double *C = new double[N*N];
    
        for(;N<=1000;N=N+100){
            cout << "N : " << N << endl;
            A = new double[N*N];
            B = new double[N*N];
            C = new double[N*N];
    
            randomzahl(N,A);
            randomzahl(N,B);
    
        for(int i=0; i<6 ; i++)
            arr[i] = 0;
    
        for(int k=0;k<5;k++){
            clock_t executetime;
            executetime = clock();
            foo1(N,A,B,C);
            arr[0] +=(clock()-executetime) /(double)CLOCKS_PER_SEC;
    
            clock_t executetime1;
            executetime1 = clock();
            foo2(N,A,B,C);
            arr[1] +=(clock()-executetime1) /(double)CLOCKS_PER_SEC;
    
            clock_t executetime2;
            executetime2 = clock();
            foo3(N,A,B,C);
            arr[2] +=(clock()-executetime2) /(double)CLOCKS_PER_SEC;
    
            clock_t executetime3;
            executetime3 = clock();
            foo4(N,A,B,C);
            arr[3] +=(clock()-executetime3) /(double)CLOCKS_PER_SEC;
    
            clock_t executetime4;
            executetime4 = clock();
            foo5(N,A,B,C);
            arr[4] +=(clock()-executetime4) /(double)CLOCKS_PER_SEC;
    
            clock_t executetime5;
            executetime5 = clock();
            foo6(N,A,B,C);
            arr[5] +=(clock()-executetime5) /(double)CLOCKS_PER_SEC;
    
            }
            delete[] A;
            delete[] B;
            delete[] C;
    
            for(int i=0;i<6;i++)
                cout<<"Average: "<<(arr[i]/5)<<endl;
    
        }
    
        if (atoi(argv[2])==0)
            stl_v(N,A,B,C,2);
    
        return 0;
    }
    

  • Mod

    Kennt ihr benutzerdefinierte Datenstrukturen? Je nach Sprache die ihr lernt (ich bin nicht sicher, ob das hier C oder C++ sein soll) läuft das unter dem Stichwort struct und/oder class. Das wäre nämlich extremst nützlich, sich hier einen Matrixdatentypen zu erstellen.

    wie kann ich meine Daten in Row Major Order speichern

    Wo genau ist das Problem? Du weißt, was Row Major Order ist, oder? Du schreibst eine Funktion wie deine anderen Funktionen auch und gibst in dieser deine Matrizen aus.

    Dein Programm ist aus zwei Gründen schrecklich und wartet nur darauf, schwer zu findende Fehler zu entwickeln, falls dies nicht bereits der Fall sein sollte. Dies solltest du dringend abstellen, wenn du dir selber etwas gutes tun möchtest.
    Grund 1: Zeig diese Funktionsdeklaration einem Fremden:

    void foo3(int size, double *data1, double *data2, double *result);
    

    Was wird der Fremde antworten, wenn du ihn fragst, was diese Funktion tut?
    Zeig diesen Funktionsaufruf einem Fremden:

    foo2(N,A,B,C);
    

    Was wird dir der Fremde antworten, was hier wohl ungefähr passiert, wenn du ihn fragst?
    Dieselben Fragen könnte man fast zu jeder Zeile stellen und bekäme fast immer die gleiche Antwort. Selbst bei mehreren zusammenhängenden Zeilen. Das sollte nicht so sein. Stell dir dich selber in 2 Wochen vor. Würdest du dein Programm noch verstehen?

    Grund 2: Wie schon gesagt, bin ich nicht sicher, ob ihr C oder C++ macht. Das sollte nicht sein. Dein Programm benutzt C++ Schlüsselwörter (new, welches man in C++ aber eigentlich nie benutzt, besonders nicht für Felder), benutzt aber eine Programmstruktur (d.h. wie die Funktionsköpfe aussehen und wie die Programmlogik aufgebaut ist) wie (schlechtes) C.


Log in to reply