Program za množenje matrice. Hodati kroz. Množenje matrice. Rješenje korištenjem paralelnog računanja

Naravno, matrice se mogu vratiti iz ulaznih podataka, pomnožiti na trivijalan način, a rezultat se može izvesti u datom obliku. Kao primjer lošeg stila programiranja: naivni algoritam dovodi do gotovo dvostruke prekomjerne upotrebe memorije i značajno je inferioran u performansama. Postoji još jedno rješenje do kojeg se može doći sukcesivnim prilagođavanjem standardnih matričnih operacija formatu ulaznih podataka.

Vežbe za predvorje sa šablonom

U tu svrhu, princip dinamičko programiranje. U ovom postu ćemo raspravljati o algoritmu množenja matrice zajedno sa njegovim dijagramom toka, koji se može koristiti za pisanje programskog koda za množenje matrice na bilo kojem jeziku visokog nivoa.

Ovo će vam pomoći da vizualizirate radni mehanizam množenja matrice i shvatite kako napisati kod, prateći koje korake. Budući da je matrica skup brojeva u pravokutnom obliku, njen postupak množenja nije isti kao množenje brojeva. Postoje određena različita pravila koja se moraju poštovati prilikom množenja matrice ručnom metodom i uz pomoć programiranja.

Najveća složenost, i računska i konceptualna, je množenje matrica, u ovom slučaju kvadriranje. Sljedeći niz koraka će vam omogućiti da pomnožite simetrične matrice koristeći njihovu linearnu reprezentaciju u originalnom formatu podataka.

Napomena 1

Podprostor simetričnih matrica nije zatvoren pod množenjem: proizvod dvije simetrične matrice može biti nesimetrična matrica.

Algoritam množenja matrice

Dakle, prije nego što pređemo na algoritam i dijagram toka množenja matrice, pogledajmo na brzinu kako se množenje matrice izvodi. Ako je broj redova prve matrice jednak broju stupaca druge matrice, idite na korak. Ispišite proizvod kao matricu kao izlaz na konzoli.

  • Provjerite broj redova i stupaca prve i druge matrice.
  • U suprotnom, množenje matrice ispisa je nemoguće i prijeđite na korak.
  • Pomnožite matrice koristeći ugniježđene petlje.
Algoritam i dijagram toka za rješavanje bilo kojeg problema daju osnovni trik koji se koristi tokom programiranja i osnovnu ideju koja stoji iza pisanja izvornog koda.

Primjer

\left(\begin(niz)(ccc) 1 & 1 & 3 \\ 1 & 4 & 5 \\ 3 & 5 & 0\end(niz) \desno) \cdot \left(\begin(array)(ccc ) 4 & 0 & 0 \\ 0 & 4 & 3 \\ 0 & 3 & 2 \end(niz) \desno) = \left(\begin(niz)(ccc) 4 & 13 & 9 \\ 4 & 31 & 22 \\ 12 & 20 & 15 \end(niz) \desno)

Napomena 2

Stepen simetrične matrice je također simetrična matrica. Dokaz se zasniva na reprezentaciji matrice kao reprezentaciji linearnog operatora i na svojstvima hermitskih operatora.

Ispitivanje dijagrama toka množenja matrice pomaže programeru da vizualizuje tok kontrole tokom izvršavanja programa. Gornji algoritam i dijagram toka mogu se koristiti za razumijevanje kako napisati program za množenje matrice u bilo kojem programskom jeziku visokog nivoa.

Matrice se mogu pomnožiti sa skalarnim konstantama na isti način na koji se bilo koji broj varijabli može pomnožiti sa skalarnom konstantom. Skalarna konstanta se odnosi na bilo koji broj; stvarne ili imaginarne; pozitivan ili negativan; cijeli broj ili razlomak, ali ne i varijabla.

U svim daljim proračunima pretpostavlja se da je matrica predstavljena linearnim nizom elemenata \frac(n(n+1))(2).

Za početak, imajte na umu da je element c_(i,j) matrice C=A^(2) jednak skalarnom proizvodu (kao vektori u standardnoj bazi) i-tog reda matrice A i njenog j-ti red (zbog činjenice da se u simetričnoj matrici j-ti red poklapa sa j-tom kolonom). Stoga je za podizanje simetrične matrice na stepen potrebno i dovoljno implementirati operaciju skalarnog množenja njena dva reda.

Svojstva množenja matrice

Osim množenja skalarnim konstantama, matrice se mogu množiti i drugim matricama. Međutim, množenje matrice nije tako jednostavno kao redovno množenje, moraju se poštovati određena pravila i ispuniti određeni uslovi. Postoji još nekoliko svojstava množenja matrice, a videćemo ih uskoro.

Pravilo za množenje matrica

Drugim riječima, prilikom množenja matrice, broj stupaca na lijevoj strani matrice mora biti jednak broju redova u matrici na desnoj strani. Ovo, kao što ćemo vidjeti u nekom trenutku, ima veze s načinom na koji se množe matrice. Ovo pravilo je razlog zašto množenje matrice nije komutativno. Optimalan način da provjerite da li se 2 matrice mogu pomnožiti njihovim veličinama jedna pored druge.

Tada bi trebalo da shvatite kako da dobijete njegov i-ti red iz datog prikaza matrice. Radi praktičnosti, ispisujemo dostupne elemente u obliku potpune matrice. Imajte na umu da će prvi element i-tog reda biti i-ti element prvog reda i generalizirajte ovo zapažanje. Označimo poziciju trenutnog elementa i-te linije koja nas zanima kao j. Ako j< i, то следует выбрать i-ый элемент j-ой строки, иначе следует выбрать все элементы j-ой строки, лежащие правее данного. Графически можно интерпретировать алгоритм таким образом: начиная с i-го элемента первой строки, спускаться вертикально вниз по матрице до тех пор, пока не будет достигнута i-ая строка, далее — двигаться вправо до конца строки. Наглядность алгоритма позволяет легко воплотить его программно.
Potrebno je samo uočiti kako se rastojanja između elemenata koji leže jedan ispod drugog mijenjaju pri pomicanju niz redove matrice, što će olakšati prenošenje algoritma na linearnu predstavu gornje trokutne matrice. Pozivamo čitaoca da uradi ovu jednostavnu, ali vizuelnu vežbu za bolje razumevanje algoritma.

Algoritam za množenje matrica

Ako nije, onda ne brinite o tome, samo recite da nije moguće. Množenje matrice slijedi isti algoritam kao i vektorsko množenje. Podsjetimo da vektor može biti red ili stupac, kao npr. Uvijek počnite postavljanjem matrica prema potrebi, nemojte miješati njihov redoslijed. Onda se postavlja pitanje šta dalje!

Množenje matrice se vrši množenjem redova po stupcima. U ovom slučaju imamo samo jedan red, ali imamo četiri kolone. Način na koji to radimo je da pomnožimo sve redove sa svim stupcima kao takvim. Dodajte jer je svaki unos u rezultirajućoj matrici zbir množenja unosa u retku i stupcu za tu poziciju.

Sada možemo preći direktno na implementaciju.

Dobar dan svima. Nedavno sam objavio kratki , a sada je vrijeme za implementacije paralelnih algoritama. Prvi na redu je jednostavan algoritam množenja matrice, vrlo je pogodan za paralelizaciju, jer se sastoji od tri ugniježđene petlje.

Dakle, sada možemo reći da kada pomnožite dvije matrice, njihov proizvod će imati isti broj redova kao matrice na lijevoj strani i isti broj stupaca kao matrica na desnoj strani. Ovo uvijek vrijedi za bilo koje množenje matrice. Dakle, sada imamo četiri reda i četiri kolone.

Svaki red množi svaku kolonu i daje jedan unos koji odgovara toj poziciji. Pogledajmo sada još jedan primjer kako bismo još jednom ilustrirali množenje matrice. Potrebno je neko vrijeme da se naviknete na cijeli proces množenja matrice, ali trik je u tome da napravite što više primjera. Ispod je nekoliko primjera.

Malo je vjerovatno da neko može bolje opisati algoritam množenja matrice od članka na Wikipediji. Stoga prilažem snimak ekrana i odmah prelazim na implementaciju.

Implementacija algoritma množenja matrice u C/C++

Neka matrica bude pohranjena u dvodimenzionalnom nizu int **matrix , a elementima se pristupa preko matrice dvostrukog indeksa[i][j] . Za početak ćemo napraviti jednostavnu provjeru da su matrice konzistentne, nakon toga možemo dodijeliti memoriju i izvršiti množenje po formuli.

Primjeri množenja matrice

Zatim radimo stvarno množenje. Ova dokumentacija se arhivira i ne obrađuje. Prikazana su dva algoritma, jedan bez pločica i jedan sa pločicama. U Solution Exploreru otvorite kontekstni meni izvorne datoteke i kliknite na Dodaj novu stavku. Pritisnite "Dalje". . Polaganje pločica je tehnika u kojoj se particije dijele na podskupove jednake veličine poznate kao pločice. Kada koristite pločicu, mijenjaju se tri stvari.

Ovdje se želimo pozabaviti isključivo drugim slučajem. Naravno, prva upotreba ove funkcije softver je kreiranje lepih radnih listova u prikazu, gde su formule takođe napisane na način na koji je uobičajeno u matematičkim tekstovima.

//Proizvodi množenje matrice n1 x m1 //sa matricom n2 x m2 int** matrixMulti(int **matrix1, int n1, int m1, int **matrix2, int n2, int m2) ( //If ne postoje matrice koje su konzistentne, onda nemojte izvoditi množenje if(m1 != n2) ( cout<< "Error! m1 != n2" << endl; return NULL; } //Выделяем память под результат умножения int **result; result = (int**)malloc(sizeof(int*)*n1); for(int i = 0; i < n1; i++) { result[i] = (int*)malloc(sizeof(int)*m2); } //Умножение по формуле for(int i = 0; i < n1; i++) { for(int j = 0; j < m2; j++) { result[i][j] = 0; for(int k = 0; k < m1; k++) { result[i][j] += (matrix1[i][k] * matrix2[k][j]); } } } return result; }

Ovdje, međutim, želimo iskoristiti ovu značajku softvera za kreiranje zanimljivih obrazovnih aplikacija. U suštini, dijelovi teksta moraju biti stavljeni u dvostruke navodnike, dinamički dijelovi moraju biti umetnuti sa svojim imenom bez navodnika; dijelovi teksta i dinamičke varijable su kombinirani sa znakom. Imajte na umu da su čak i razmak nakon dvije tačke i krajnje tačke rečenice umetnuti između dvostrukih navodnika, jer je ovo čist tekst.

Možemo birati hoćemo li izračunati zbroj ili proizvod koristeći nove varijable ili ih izvršiti direktno u tekstualnim poljima. Kao primjer, slijedit ćemo prvi put za proizvod, a drugi za iznos. \\ nalijevo.

Implementacija množenja paralelnih matrica u C/C++

Nećemo morati da pišemo puno koda jer ćemo raditi na nitima zajedničke memorije, a ne na procesima, kao u MPI. Cijela poenta paralelizacije je dodavanje #pragma omp paralele za direktivu prije vanjske petlje. Nakon toga, broj niti koji nam je potreban automatski će za sebe riješiti računske zadatke.

Uzimajući u obzir da moramo napisati dvije ulazne matrice razdvojene znakom sabiranja i izlaznu matricu čiji su elementi zbroj elemenata dvije ulazne matrice, dobijamo sljedeći kod. Kao što je već spomenuto, za proizvod ćemo izvršiti proračune sa novim varijablama kako bismo pojednostavili kod koji će biti upisan u tekstualno polje. Dakle, u prozoru za algebarski unos pisaćemo sekvencijalno.

U ovom trenutku, spremni smo da unesemo šifru proizvoda za dvije matrice. Determinanta niza \\ može se izračunati prema Laplaceovom pravilu, koje se razvija nad elementima prvog reda. Navodimo ga u nastavku radi potpunosti.

  • Zbroj matrica \\.
  • Matrični proizvod \\.
  • Skalarna višestruka matrica \\.
Ova dokumentacija je arhivirana i ne održava se.

Prilažem izvorni kod sa funkcijom generisanja slučajnih matrica i direktno po paralelnom algoritmu za njihovo množenje.

#include #include #include korištenje imenskog prostora std; void randomiseMatrix(int ​​**matrica, int n, int m) ( for(int i = 0; i< n; i++) { for(int j = 0; j < m; j++) { matrix[i][j] = rand() % 11; } } return; } int main(int argc, char** argv) { srand(time(NULL)); int n1 = 1000; int m1 = 500; int n2 = 500; int m2 = 1200; //Матрица n1 x m1 int **matrix1; //Матрица n2 x m2 int **matrix2; matrix1 = (int**)malloc(sizeof(int*)*n1); for(int i = 0; i < n1; i++) { matrix1[i] = (int*)malloc(sizeof(int)*m1); } matrix2 = (int**)malloc(sizeof(int*)*n2); for(int i = 0; i < n2; i++) { matrix2[i] = (int*)malloc(sizeof(int)*m2); } //Генерируем случайные матрицы для умножения randomiseMatrix(matrix1, n1, m1); randomiseMatrix(matrix2, n2, m2); int **result = (int**)malloc(sizeof(int*)*n1);; for(int i = 0; i < n1; i++) { result[i] = (int*)malloc(sizeof(int)*m2); } //Устанавливаем число потоков int threadsNum = 2; omp_set_num_threads(threadsNum); int i, j, k; #pragma omp parallel for shared(matrix1, matrix2, result) private(i, j, k) for (i = 0; i < n1; i++) { for (j = 0; j < m2; j++) { result[i][j] = 0; for (k = 0; k < m1; k++) { result[i][j] += (matrix1[i][k] * matrix2[k][j]); } } } return 0; }

Postojat će dva algoritma, jedan od njih ne koristi pločice, a drugi ne koristi pločice. U prozoru Solution Explorer otvorite iskačući meni u okviru Izvorne datoteke, a zatim izaberite Dodaj i novu stavku. Tiling je tehnika koja dijeli podatke u podskupove iste veličine, poznate kao pločice.

Da biste zaustavili sve niti u istom fragmentu na određenoj liniji koda, možete pozvati metodu. Korištenje lokalnog indeksa može učiniti vaš kod lakšim za čitanje i otklanjanje grešaka. U ovom primjeru, matrica je podijeljena na podmatrice iste veličine. Rezultat se izračunava množenjem podcasta.

Zaključak

Čini se da nisu učinili ništa, ali ako pažljivo pratite upravitelja zadataka () tijekom izvršavanja, postaje jasno kako se opterećenje raspoređuje između jezgri procesora. Uskoro ću objaviti još implementacija paralelnih algoritama koristeći OpenMP, pretplatiti se na ažuriranja putem e-pošte. I to je sve za danas, hvala na pažnji!

Matrice i njihov rezultat u ovom primjeru. Da biste brzo procijenili algoritam, izračunajte vrijednost elementa u prvom redu prve kolone rezultata. Kod za implementaciju ovog algoritma. Za izlazak iz aplikacije koristite razmaknicu. Matrica se najčešće piše kao tabela brojeva ograničenih zagradama.

Ovo je prvi element prvog reda, drugi element drugog reda i tako dalje. Matrica € e, gdje je € m = n^, naziva se kvadratna matrica. Matrica bilo kojeg tipa koja ima sve elemente svih redova jednake nuli naziva se nulta matrica. Neka je A matrica sa elementima e i €. Transponovanje matrice znači zamenu njenih redova i kolona. Matrica se množi konstantom, množeći svaki element istom konstantom.