2017-11-20 3 views
0

Ich habe einen typischen Algorithmus für Matrixmultiplikation. Ich versuche, Loop Enrolling anzuwenden und zu verstehen, aber ich habe ein Problem mit der Implementierung des Algorithmus, wenn ich versuche, k mal abzuwickeln, wenn k kein Vielfaches der Matrizengröße ist. (Ich bekomme stattdessen sehr große Zahlen). Das bedeutet, dass ich nach dem Abwickeln nicht mit den restlichen Elementen umgehen kann. Hier ist, was ich habe:Loop Enrolling funktioniert nicht mit den restlichen Elementen

void Mult_Matx(unsigned long* a, unsigned long* b, unsigned long*c, long n) 
{ 
    long i = 0, j = 0, k = 0; 
    unsigned long sum, sum1, sum2, sum3, sum4, sum5, sum6, sum7; 

    for (i = 0; i < n; i++) 
    { 
     long in = i * n; 
     for (j = 0; j < n; j++) 
     { 
      sum = sum1 = sum2 = sum3 = sum4 = sum5 = sum6 = sum7 = 0; 

      for (k = 0; k < n; k += 8) 
      { 
       sum = sum + a[in + k] * b[k * n + j]; 
       sum1 = sum1 + a[in + (k + 1)] * b[(k + 1) * n + j]; 
       sum2 = sum2 + a[in + (k + 2)] * b[(k + 2) * n + j]; 
       sum3 = sum3 + a[in + (k + 3)] * b[(k + 3) * n + j]; 
       sum4 = sum4 + a[in + (k + 4)] * b[(k + 4) * n + j]; 
       sum5 = sum5 + a[in + (k + 5)] * b[(k + 5) * n + j]; 
       sum6 = sum6 + a[in + (k + 6)] * b[(k + 6) * n + j]; 
       sum7 = sum7 + a[in + (k + 7)] * b[(k + 7) * n + j]; 
      } 

      if (n % 8 != 0) 
      { 
       for (k = 8 * (n/8); k < n; k++) 
       { 
        sum = sum + a[in + k] * b[k * n + j]; 
       } 
      } 
      c[in + j] = sum + sum1 + sum2 + sum3 + sum4 + sum5 + sum6 + sum7; 
     } 
    } 
} 

Lasst uns sagen Größe aka n ist 12. Wenn ich es 4 mal entrollen, dieser Code funktioniert, was bedeutet, wenn es nie den Rest Schleife eintritt. Aber ich verliere den Überblick darüber, was passiert, wenn es passiert! Wenn mir jemand sagen kann, wo ich falsch liege, würde ich es sehr schätzen. Ich bin neu und habe es schwer, herauszufinden.

+2

manuelle Schleife entrolling ist so 80er ... (Ich würde sagen: nicht. Wenn Sie darauf bestehen, werfen Sie einen Blick auf [Duffs Gerät] (https://en.wikipedia.org/wiki/Duff%27s_device), den "Rest" handhabend, indem irgendwo innerhalb des entrollten Codes gesprungen wird) –

+0

@FelixPalmen lol. Ich nehme eine Intro-Betriebssystemklasse. So .... –

+0

Vielleicht sollten Sie sich etwas Zeit nehmen [lernen, wie Sie Ihre Programme debuggen] (https://ericlippert.com/2014/03/05/how-to-debug-small-programs/)? –

Antwort

2

Eine generische Art und Weise eine Schleife auf diese Form von Abrollen:

for(int i=0; i<N; i++) 
    ... 

ist

int i; 
for(i=0; i<N-L; i+=L) 
    ... 
for(; i<N; i++) 
    ... 

oder wenn Sie die Indexvariable im Rahmen der Schleifen halten:

for(int i=0; i<N-L; i+=L) 
    ... 
for(int i=L*(N/L); i<N; i++) 
    ... 

Hier verwende ich die Tatsache, dass Integer-Division abgerundet wird. L ist die Anzahl der Schritte, die Sie in der ersten Schleife ausführen.

Beispiel:

const int N=22; 
const int L=6; 
int i; 
for(i=0; i<N-L; i+=L) 
{ 
    printf("%d\n", i); 
    printf("%d\n", i+1); 
    printf("%d\n", i+2); 
    printf("%d\n", i+3); 
    printf("%d\n", i+4); 
    printf("%d\n", i+5); 
} 
for(; i<N; i++) 
    printf("%d\n", i); 

aber ich empfehle einen Blick auf Duff's device nehmen. Ich vermute jedoch, dass es nicht immer gut ist, es zu benutzen. Der Grund ist, dass Modulo eine ziemlich teure Operation ist.

Die Bedingung if (n % 8 != 0) sollte nicht benötigt werden. Der for Header sollte darauf achten, wenn er richtig geschrieben wird.

Verwandte Themen