Bilgisayar Özelliklerinin İncelenmesi ve Matris Çarpma İşlemine Etkisi.
Karadeniz Teknik Üniversitesi
Bilgisayar Mühendisliği Bölümü
Paralel Bilgisayarlar
Ad&Soyad: Nurullah Demirci
Sistem Bilgileri
~? Bilgisayarımızın FLOP/s kapasitesi nedir. ?~
FLOP/s Nedir? -> Saniyedeki kayan noktalı sayı ile yapılan (floating-point number) işlem sayısıdır. Mikroişlemcilerin hız performansını göstermek için kullanılan bir ölçüdür. Özellikle aşırı derecede kayan noktalı sayı işlemleri içeren bilimsel işlemlerde bu ölçüt kullanılır. Kayan noktalı işlemler kesirli sayılarla yapılan işlemleri içerir ve bu işlemler tam sayılar ile yapılan işlemlerden daha uzun sürer ve daha zordur. Çoğu modern işlemci kayan noktalı sayı işlemlerini yapmak için özel FPU (Floating Point Unit) birimini içerir.
Bilgisayarımızın İşlemcisi İntel(R) Core i5 3210M 2.5Ghz - 3.1Ghz
FLOP/s HESABI: Soket Sayısı * Soket Başına Çekirdek Sayısı * Saniye Başına Saat Döngü Sayısı * Döngü Başına Kayan Nokta İşlemi Sayısı
FLOP/s => 1 * 2 * 3.1Ghz * 4 = 24.8 GFLOPS
Bilgisayarımızın Grafik Kartı NVIDIA GeForce GT 635M
FP32 (float) performance: 388.8 GFLOPS
FP64 (double) performance: 32.40 GFLOPS
Bilgisayarımızın 2. Grafik Kartı Intel(R) HD Graphics 4000
FP32 (float) performance: 256.0 GFLOPS
FP64 (double) performance: 64.0 GFLOPS
~? Sistemindeki Cache belleğin özelliklerini açıklayınız, I-Cache, D-Cache kapasiteleri nedir. ?~
Cache Bellek (Önbellek)? -> CPU çok hızlıdır ve sürekli olarak hafızadan veri okur. Sistem belleğinden gelen veriler ise çoğunlukla CPU’nun hızına yetişemez ve işlemci verinin ulaşmasını beklemek zorunda kalır. Bu problemi çözmek için CPU içinde yüksek hızlı hafızalar bulunur, buna önbellek(cache) denir. Ön bellek çalışmakta olan programa ait komutların, verilerin geçici olarak saklandığı yüksek hızlı hafızalardır.
♦ L1 ön bellek (cache) : Önemli kodlar ve veriler bellekten buraya kopyalanır ve işlemci bunlara daha hızlı ulaşabilir. Kodlar için olan Code cache ve veriler için olan Data cache olmak üzere ikiye ayrılır. Kapasitesi 2 KB ile 256 KB arasında değişir.
L1 I-Cache: Instruction Cache, yani işlemcinin desteklediği komut setlerinin saklandığı ön bellektir.
L1 D-Cache: Data Cache, yani verilerin saklandığı ön bellek.
♦ L2 ön bellek (cache) : L1 belleklerine göre kapasiteleri 256 KB ile 2 MB arasında değişir. Başlangıçta L2 önbellek anakart üzerinde işlemciye yakın bir yerde yer almaktaydı. Daha sonra slot işlemciler ortaya çıkınca işlemci çekirdeğinin üzerinde kartuş şeklindeki paketlerde yer aldı. Bununla beraber çekirdeğin dışında ve işlemciyle aynı yapıda kullanılmaya başlandı. Bu kısa geçiş döneminden sonraysa L2 önbellek işlemci çekirdeklerine entegre edildi.
♦ L3 ön bellek (cache): L3 ön belleklerinin kapasiteleri 2MB ile 256 MB arasında değişir. Yeni bir teknolojidir. Çok çekirdekli işlemcilerde bütün çekirdeklere tek bir bellekle hizmet vermek akıllıca bir yaklaşım olacağı düşüncesiyle geliştirilmiştir.
Bilgisayarımın I-Cache Kapasitesi: 32 KByte x 2
Bilgisayarımın D-Cache Kapasitesi: 32 KByte x 2
~? Tampon bellekler için 4-yönlü (4-way) ne demektir. ?~
Cache’de, Ana hafızada bulunan adres bloklarından daha az 'line' olduğu için bir haritalama fonksiyonuna ihtiyaç vardır.
Kullanılabilecek 3 teknik var:
Doğrudan
Asosyatif
Küme Asosyatif
4-yönlü(4-way) küme asosyatif'e dahildir. Cache belirli bir sayıda küme içerir. Her küme belirli bir sayıda line içerir. Bir ana hafıza bloğu, belirli bir küme içerisindeki herhangi bir line ile eşleştirilebilir.
Ör: Bir kümede 4 line olsun. 4-way asosyatif Bir ana hafıza bloğu, belirli olan bir küme içerisindeki 4 line’dan biri ile eşleşir.
Kodlama Bölümü
~~ Projede nxn boyutlu 2 matrisin çarpımı yapılmıştır. Ayrıca proje hem seri hem de paralel kodlanmıştır. Kodlar aşağıdaki gibidir. ~~
#define WHITE SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
#define RED SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
#define GREEN SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
#define BLUE SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_BLUE);
#define YELLOW SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
#define MAGENTA SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE);
#define CYAN SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE);
#define GRAY SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY);
#define HAVE_STRUCT_TIMESPEC
#include <pthread.h>
#include <windows.h>
#include <iostream>
#include <iomanip>
#include <ctime>
#define SIZE 1000 // 1K 2K 3K 4K 5K
#define PRINT_SIZE 10 // JUST PRINT_SIZE ELEMENT WILL PRINT OUTPUT SCREEN
#define THREAD 10 // THREAD COUNT
//using namespace std;
pthread_t threads[THREAD]; // CREATE THREADS
pthread_mutex_t mutex; // = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond; // = PTHREAD_COND_INITIALIZER;
int core;
template <typename T> T** A;
template <typename T> T** B;
template <typename T> T** S;
// STRCUT FOR MATRIX(2D ARRAY)
template <class Type>
struct TypeMatrix {
Type** Mtrx;
};
// Matrix CLASS SPECIFIED
template <class Type>
class Matrix {
private:
Type _X, _Y;
struct TypeMatrix<Type> X; // nxn <TYPE> MATRIX X (n = SIZE)
struct TypeMatrix<Type> Y; // nxn <TYPE> MATRIX Y (n = SIZE)
struct TypeMatrix<Type> R; // nxn <TYPE> MATRIX RESULT (n = SIZE)
public:
Matrix(Type _x = (Type)1., Type _y = (Type)2.); // CONSTRUCTOR
void Create_Matrix(); // MATRIX CREATE METHOD
void Multiply_Matrix(); // MATRIX ELEMENTWISE MULTIPLICATION METHOD
void Multiply_Matrix_With_Threads(std::string); // THREADS CREATE AND JOIN METHOD
static void *Block_Mutiply_Matrix(void *); // BLOCK THREAD METHOD
static void *Squential_Mutiply_Matrix(void *); // SQUENTIAL THREAD METHOD
void Print(); // MATRIX PRINT METHOD
~Matrix();
};
// CONSTRUCTOR <TYPE> MATRIX CREATING (X && Y && R)
template <class Type>
Matrix<Type>::Matrix(Type _x, Type _y) {
this->_X = _x;
this->_Y = _y;
Create_Matrix();
}
// <TYPE> MATRIX CREATE METHOD (X && Y && R)
template <class Type>
void Matrix<Type>::Create_Matrix() {
X.Mtrx = new Type*[SIZE];
Y.Mtrx = new Type*[SIZE];
R.Mtrx = new Type*[SIZE];
for (int i = 0; i < SIZE; i++) {
X.Mtrx[i] = new Type[SIZE];
Y.Mtrx[i] = new Type[SIZE];
R.Mtrx[i] = new Type[SIZE];
for (int j = 0; j < SIZE; j++) {
X.Mtrx[i][j] = (Type)_X;
Y.Mtrx[i][j] = (Type)_Y;
R.Mtrx[i][j] = (Type)0.;
}
}
}
// <TYPE> MATRIX ELEMENTWISE MULTIPLICATION METHOD
template <class Type>
void Matrix<Type>::Multiply_Matrix() {
Type Total = (Type)0.;
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
for (int k = 0; k < SIZE; k++) {
Total += X.Mtrx[i][k] * Y.Mtrx[k][j];
}
R.Mtrx[i][j] = Total;
Total = (Type)0.;
}
}
}
// THREADS CREATE AND JOIN METHOD
template <class Type>
void Matrix<Type>::Multiply_Matrix_With_Threads(std::string DataShareType){
A<Type> = new Type*[SIZE];
B<Type> = new Type*[SIZE];
S<Type> = new Type*[SIZE];
for (int i = 0; i < SIZE; i++){
A<Type>[i] = new Type[SIZE];
B<Type>[i] = new Type[SIZE];
S<Type>[i] = new Type[SIZE];
for (int j = 0; j < SIZE; j++){
A<Type>[i][j] = X.Mtrx[i][j];
B<Type>[i][j] = Y.Mtrx[i][j];
S<Type>[i][j] = R.Mtrx[i][j];
}
}
core = 0;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
for (int i = 0; i < THREAD; i++){
if (DataShareType == "BlockDataShare")
pthread_create(&threads[i], NULL, Block_Mutiply_Matrix, NULL);
else if (DataShareType == "SquentialDataShare")
pthread_create(&threads[i], NULL, Squential_Mutiply_Matrix, NULL);
else
std::cout << " UNDEFINE DATA SHARE TYPE \n";
}
for (int i = 0; i < THREAD; i++)
pthread_join(threads[i], NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
R.Mtrx[i][j] = S<Type>[i][j];
}
}
for (int i = 0; i < SIZE; i++) {
delete A<Type>[i];
delete B<Type>[i];
delete S<Type>[i];
}
delete[] A<Type>;
delete[] B<Type>;
delete[] S<Type>;
//std::cout << "~~~ A && B && S MATRIX DELETED ~~~\n";
}
// BLOCK DATA SHARE <TYPE> MATRIX ELEMENTTWISE MULTIPLICATION MATRIX WITH PTHREAD
template <class Type>
void *Matrix<Type>::Block_Mutiply_Matrix(void *) {
Type Total = (Type)0.;
int _core = core++;
for (int i = _core * SIZE / THREAD; i < (_core + 1) * SIZE / THREAD; i++) {
for (int j = 0; j < SIZE; j++) {
for (int k = 0; k < SIZE; k++) {
Total += A<Type>[i][k] * B<Type>[k][j];
}
S<Type>[i][j] = Total;
Total = (Type)0.;
}
}
pthread_exit(NULL);
return 0;
}
// SQUENTIAL DATA SHARE <TYPE> MATRIX ELEMENTTWISE MULTIPLICATION MATRIX WITH PTHREAD
template <class Type>
void *Matrix<Type>::Squential_Mutiply_Matrix(void *) {
Type Total = (Type)0.;
int _core = core++;
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
for (int k = _core * SIZE / THREAD; k < (_core + 1) * SIZE / THREAD; k++) {
Total += A<Type>[i][k] * B<Type>[k][j];
}
pthread_mutex_lock(&mutex);
S<Type>[i][j] += Total;
pthread_mutex_unlock(&mutex);
Total = (Type)0.;
}
}
pthread_exit(NULL);
return 0;
}
// <TYPE> MATRIX PRINT METHOD (DEBUG OUTPUT SCREEN)
template <class Type>
void Matrix<Type>::Print() {
for (int i = 0; i < PRINT_SIZE; i++) {
std::cout << "[";
for (int j = 0; j < PRINT_SIZE; j++) {
if (j != PRINT_SIZE - 1)
std::cout << std::fixed << std::setprecision(2) << R.Mtrx[i][j] << ", ";
else
std::cout << std::fixed << std::setprecision(2) << R.Mtrx[i][j];
}
std::cout << "]\n";
}
}
// DESTRUCTOR
template <class Type>
Matrix<Type>::~Matrix(){
for (int i = 0; i < SIZE; i++) {
delete X.Mtrx[i];
delete Y.Mtrx[i];
delete R.Mtrx[i];
}
delete[] X.Mtrx;
delete[] Y.Mtrx;
delete[] R.Mtrx;
//std::cout << "~~~ X && Y && R MATRIX DELETED ~~~\n";
}
// MAIN METHOD
int main() {
double time; // TIME VARIABLE
CYAN; std::cout << "\n~~ " << SIZE << "*" << SIZE << " Iki Matris Carpimi Sonuclari ~~\n\n"; WHITE;
// DOUBLE MATRIX ELEMENTWISE MULTIPLICATION OPERATIONS (SERIAL EXCUTE)
Matrix<double> D__EMUL; // OBJECT SPECIFIED
clock_t start__1 = clock(), finish__1; // EXCUTE TIME START
D__EMUL.Multiply_Matrix(); // EXCUTE METHOD
finish__1 = clock(); // EXCUTE TIME FINISH
//D__EMUL.Print(); // DEBUG OUTPUT SCREEN
time = (double)(finish__1 - start__1) / CLOCKS_PER_SEC; // TIME CALCULATION
GREEN;
std::cout << "~~~ DOUBLE MULTIPLICATION MATRIX EXCUTE TIME (SERIAL): " << time << " ~~~\n\n";
WHITE;
// FLOAT MATRIX ELEMENTWISE MULTIPLICATION OPERATIONS (SERIAL EXCUTE)
Matrix<float> F__EMUL; // OBJECT SPECIFIED
clock_t start__11 = clock(), finish__11; // EXCUTE TIME START
F__EMUL.Multiply_Matrix(); // EXCUTE METHOD
finish__11 = clock(); // EXCUTE TIME FINISH
//F__EMUL.Print(); // DEBUG OUTPUT SCREEN
time = (double)(finish__11 - start__11) / CLOCKS_PER_SEC; // TIME CALCULATION
YELLOW;
std::cout << "~~~ FLOAT MULTIPLICATION MATRIX EXCUTE TIME (SERIAL): " << time << " ~~~\n\n";
WHITE;
// BLOCK DATA DOUBLE MATRIX ELEMENTWISE MULTIPLICATION OPERATIONS (PARALLELISM EXCUTE WITH pThread)
Matrix<double> DB__EMUL; // OBJECT SPECIFIED
clock_t start__2 = clock(), finish__2; // EXCUTE TIME START
DB__EMUL.Multiply_Matrix_With_Threads("BlockDataShare"); // MUST BE DEFINE ( "BlockDataShare" || "SquentialDataShare" )
finish__2 = clock(); // EXCUTE TIME FINISH
//DB__EMUL.Print(); // DEBUG OUTPUT SCREEN
time = (double)(finish__2 - start__2) / CLOCKS_PER_SEC; // TIME CALCULATION
GREEN;
std::cout << "~~~ BLOCK DATA DOUBLE MULTIPLICATION MATRIX WITH THREADS EXCUTE TIME (PARALLEL): " << time << " ~~~\n\n";
WHITE;
// SQUENTIAL DATA DOUBLE MATRIX ELEMENTWISE MULTIPLICATION OPERATIONS (PARALLELISM EXCUTE WITH pThread)
Matrix<double> DS__EMUL; // OBJECT SPECIFIED
clock_t start__3 = clock(), finish__3; // EXCUTE TIME START
DS__EMUL.Multiply_Matrix_With_Threads("SquentialDataShare");// MUST BE DEFINE ( "BlockDataShare" || "SquentialDataShare" )
finish__3 = clock(); // EXCUTE TIME FINISH
//DS__EMUL.Print(); // DEBUG OUTPUT SCREEN
time = (double)(finish__3 - start__3) / CLOCKS_PER_SEC; // TIME CALCULATION
YELLOW;
std::cout << "~~~ SQUENTIAL DATA DOUBLE MULTIPLICATION MATRIX WITH THREADS EXCUTE TIME (PARALLEL): " << time << " ~~~\n\n";
WHITE;
// BLOCK DATA FLOAT MATRIX ELEMENTWISE MULTIPLICATION OPERATIONS (PARALLELISM EXCUTE WITH pThread)
Matrix<float> FB__EMUL; // OBJECT SPECIFIED
clock_t start__22 = clock(), finish__22; // EXCUTE TIME START
FB__EMUL.Multiply_Matrix_With_Threads("BlockDataShare"); // MUST BE DEFINE ( "BlockDataShare" || "SquentialDataShare" )
finish__22 = clock(); // EXCUTE TIME FINISH
//FB__EMUL.Print(); // DEBUG OUTPUT SCREEN
time = (double)(finish__22 - start__22) / CLOCKS_PER_SEC; // TIME CALCULATION
GREEN;
std::cout << "~~~ BLOCK DATA FLOAT MULTIPLICATION MATRIX WITH THREADS EXCUTE TIME (PARALLEL): " << time << " ~~~\n\n";
WHITE;
// SQUENTIAL DATA FLOAT MATRIX ELEMENTWISE MULTIPLICATION OPERATIONS (PARALLELISM EXCUTE WITH pThread)
Matrix<float> FS__EMUL; // OBJECT SPECIFIED
clock_t start__33 = clock(), finish__33; // EXCUTE TIME START
FS__EMUL.Multiply_Matrix_With_Threads("SquentialDataShare");// MUST BE DEFINE ( "BlockDataShare" || "SquentialDataShare" )
finish__33 = clock(); // EXCUTE TIME FINISH
//FS__EMUL.Print(); // DEBUG OUTPUT SCREEN
time = (double)(finish__33 - start__33) / CLOCKS_PER_SEC; // TIME CALCULATION
YELLOW;
std::cout << "~~~ SQUENTIAL DATA FLOAT MULTIPLICATION MATRIX WITH THREADS EXCUTE TIME (PARALLEL): " << time << " ~~~\n\n";
WHITE;
return 0;
}
~~ Kodların Görsel Olarak Görünümü ve Bazı Testlerin Sonuçları Aşağıdaki Gibidir. ~~
Projede nxn boyutlu 2 matrisin çarpımını yapılmaktadır. Proje hem seri hem de paralel kodlanmıştır. Matrisler '1.0' ve '2.0' değerleri ile doldurulmuştur. Matrisler dinamik tanımlanmıştır. Bu sayede n = 1K, 2K, 3K, 4K, 5K (K: Bin) sadece n değeri değiştirilerek oluşturulabilir. Kodlamada C++ ve pThread Kullanılmıştır. Hem Float, hem de Double matrix çarpımları için C++ template özelliği kullanılmıştır.
~~ Kodumuzu Seri ve 10 Thread ile Test Edip Sonuçlarını Görelim ~~
1K x 1K Matris Çarpımı:
Double Değer Tanımlı Matrisler Seri Çalışma Süresi: 15.088sn Float Değer Tanımlı Matrisler Seri Çalışma Süresi: 11.09sn Double Değer Tanımlı Matrisler Blok Veri Paylaşımı Paralel Çalışma Süresi: 5.688sn Double Değer Tanımlı Matrisler Ardışıl Veri Paylaşımı Paralel Çalışma Süresi: 4.868sn Float Değer Tanımlı Matrisler Blok Veri Paylaşımı Paralel Çalışma Süresi: 4.813sn Float Değer Tanımlı Matrisler Ardışıl Veri Paylaşımı Paralel Çalışma Süresi: 4.105sn
2K x 2K Matris Çarpımı:
Double Değer Tanımlı Matrisler Seri Çalışma Süresi: 164.172sn Float Değer Tanımlı Matrisler Seri Çalışma Süresi: 123.37sn Double Değer Tanımlı Matrisler Blok Veri Paylaşımı Paralel Çalışma Süresi: 67.969sn Double Değer Tanımlı Matrisler Ardışıl Veri Paylaşımı Paralel Çalışma Süresi: 38.381sn Float Değer Tanımlı Matrisler Blok Veri Paylaşımı Paralel Çalışma Süresi: 48.979sn Float Değer Tanımlı Matrisler Ardışıl Veri Paylaşımı Paralel Çalışma Süresi: 29.042sn
3K x 3K Matris Çarpımı:
Double Değer Tanımlı Matrisler Seri Çalışma Süresi: 450.104sn Float Değer Tanımlı Matrisler Seri Çalışma Süresi: 379.546sn Double Değer Tanımlı Matrisler Blok Veri Paylaşımı Paralel Çalışma Süresi: 205.727sn Double Değer Tanımlı Matrisler Ardışıl Veri Paylaşımı Paralel Çalışma Süresi: 134.64sn Float Değer Tanımlı Matrisler Blok Veri Paylaşımı Paralel Çalışma Süresi: 226.329sn Float Değer Tanımlı Matrisler Ardışıl Veri Paylaşımı Paralel Çalışma Süresi: 121.95sn
4K x 4K Matris Çarpımı:
Double Değer Tanımlı Matrisler Seri Çalışma Süresi: 1130.25sn Float Değer Tanımlı Matrisler Seri Çalışma Süresi: 967.517sn Double Değer Tanımlı Matrisler Blok Veri Paylaşımı Paralel Çalışma Süresi: 537.798sn Double Değer Tanımlı Matrisler Ardışıl Veri Paylaşımı Paralel Çalışma Süresi: 367.762sn Float Değer Tanımlı Matrisler Blok Veri Paylaşımı Paralel Çalışma Süresi: 563.506sn Float Değer Tanımlı Matrisler Ardışıl Veri Paylaşımı Paralel Çalışma Süresi: 358.041sn
5K x 5K Matris Çarpımı:
Double Değer Tanımlı Matrisler Seri Çalışma Süresi: 2307.59sn Float Değer Tanımlı Matrisler Seri Çalışma Süresi: 1543.79sn Double Değer Tanımlı Matrisler Blok Veri Paylaşımı Paralel Çalışma Süresi: 1546.54sn Double Değer Tanımlı Matrisler Ardışıl Veri Paylaşımı Paralel Çalışma Süresi: 819.667sn Float Değer Tanımlı Matrisler Blok Veri Paylaşımı Paralel Çalışma Süresi: 880.656sn Float Değer Tanımlı Matrisler Ardışıl Veri Paylaşımı Paralel Çalışma Süresi: 676.106sn
~~ Kodların Görsel Olarak Görünümü ve Bazı Testlerin Sonuçları Aşağıdaki Gibidir. ~~
1K x 1K Matris Çarpımı Hızlanma && Verimlilik:
(Double Seri - Blok Veri Paylaşımı) Hızlanma = 15.088 / 5.688 = 2.65 (Double Seri - Blok Veri Paylaşımı) Verimlilik = (2.65 x 100) / 10 = 26.5% (Double Seri - Ardışıl Veri Paylaşımı) Hızlanma = 15.088 / 4.868 = 3.09 (Double Seri - Ardışıl Veri Paylaşımı) Verimlilik = (3.09 x 100) / 10 = 30.9% (Float Seri - Blok Veri Paylaşımı) Hızlanma = 11.09 / 4.813 = 2.30 (Float Seri - Blok Veri Paylaşımı) Verimlilik = (2.30 x 100) / 10 = 23% (Float Seri - Ardışıl Veri Paylaşımı) Hızlanma = 11.09 / 4.105 = 2.70 (Float Seri - Ardışıl Veri Paylaşımı) Verimlilik = (2.70 x 100) / 10 = 27%
2K x 2K Matris Çarpımı Hızlanma && Verimlilik:
(Double Seri - Blok Veri Paylaşımı) Hızlanma = 164.172 / 67.969 = 2.41 (Double Seri - Blok Veri Paylaşımı) Verimlilik = (2.41 x 100) / 10 = 24.1% (Double Seri - Ardışıl Veri Paylaşımı) Hızlanma = 164.172 / 38.381 = 4.27 (Double Seri - Ardışıl Veri Paylaşımı) Verimlilik = (4.27 x 100) / 10 = 42.7% (Float Seri - Blok Veri Paylaşımı) Hızlanma = 123.37 / 48.979 = 2.51 (Float Seri - Blok Veri Paylaşımı) Verimlilik = (2.51 x 100) / 10 = 25.1% (Float Seri - Ardışıl Veri Paylaşımı) Hızlanma = 123.37 / 29.042 = 4.24 (Float Seri - Ardışıl Veri Paylaşımı) Verimlilik = (4.24 x 100) / 10 = 42.4%
3K x 3K Matris Çarpımı Hızlanma && Verimlilik:
(Double Seri - Blok Veri Paylaşımı) Hızlanma = 450.104 / 205.727 = 2.18 (Double Seri - Blok Veri Paylaşımı) Verimlilik = (2.18 x 100) / 10 = 21.8% (Double Seri - Ardışıl Veri Paylaşımı) Hızlanma = 450.104 / 134.64 = 3.34 (Double Seri - Ardışıl Veri Paylaşımı) Verimlilik = (3.34 x 100) / 10 = 33.4% (Float Seri - Blok Veri Paylaşımı) Hızlanma = 379.546 / 226.329 = 1.67 (Float Seri - Blok Veri Paylaşımı) Verimlilik = (1.67 x 100) / 10 = 16.7% (Float Seri - Ardışıl Veri Paylaşımı) Hızlanma = 379.546 / 121.95 = 3.11 (Float Seri - Ardışıl Veri Paylaşımı) Verimlilik = (3.11 x 100) / 10 = 31.1%
4K x 4K Matris Çarpımı Hızlanma && Verimlilik:
(Double Seri - Blok Veri Paylaşımı) Hızlanma = 1130.25 / 537.798 = 2.10 (Double Seri - Blok Veri Paylaşımı) Verimlilik = (2.10 x 100) / 10 = 21.0% (Double Seri - Ardışıl Veri Paylaşımı) Hızlanma = 1130.25 / 367.762 = 3.07 (Double Seri - Ardışıl Veri Paylaşımı) Verimlilik = (3.07 x 100) / 10 = 30.7% (Float Seri - Blok Veri Paylaşımı) Hızlanma = 967.517 / 563.506 = 1.71 (Float Seri - Blok Veri Paylaşımı) Verimlilik = (1.71 x 100) / 10 = 17.1% (Float Seri - Ardışıl Veri Paylaşımı) Hızlanma = 967.517 / 358.041 = 2.70 (Float Seri - Ardışıl Veri Paylaşımı) Verimlilik = (2.70 x 100) / 10 = 27.0%
5K x 5K Matris Çarpımı Hızlanma && Verimlilik:
(Double Seri - Blok Veri Paylaşımı) Hızlanma = 2307.59 / 1546.54 = 1.49 (Double Seri - Blok Veri Paylaşımı) Verimlilik = (1.49 x 100) / 10 = 14.9% (Double Seri - Ardışıl Veri Paylaşımı) Hızlanma = 2307.59 / 819.667 = 2.81 (Double Seri - Ardışıl Veri Paylaşımı) Verimlilik = (2.81 x 100) / 10 = 28.1% (Float Seri - Blok Veri Paylaşımı) Hızlanma = 1543.79 / 880.656 = 1.75 (Float Seri - Blok Veri Paylaşımı) Verimlilik = (1.75 x 100) / 10 = 17.5% (Float Seri - Ardışıl Veri Paylaşımı) Hızlanma = 1543.79 / 676.106 = 2.28 (Float Seri - Ardışıl Veri Paylaşımı) Verimlilik = (2.28 x 100) / 10 = 22.8%
~? Sistemimizdeki Float ve Double Sürümlerinde Farklılık Var mıdır? Neden: ?~
Yukarıda da belirtildiği gibi test sonuçlarına bakıldığında Float veri tipi tanımlı matris çarpımları daha hızlı çalışmıştır. Double veri tipi tanımlı matris çarpımımız daha yavaş kaldı. Çünkü Float tipi kayan nokta sayısı, Double tipine göre daha azdır. Böylece işlemcilerin veya oluşturulan threadlerin yükleri daha az olur. Float hızlı sonuç vermiş olur.
~? Sistemimizde Belirtilen Flop/s Performans Limitinin Yüzde Kaçına Ulaşılabildi. ?~
Sistemimizi çalıştırdığımızda CPU çalışma hızımız 2.89Ghz kadar çıkıyor. Yani 1 * 2 * 2.89 * 4 = 23.12GFLOPS 93% performans limitine ulaşabildik.
~? Veri paylaşım türlerine göre uygulamamız geliştirilmiştir. Performans değişimleri vardır. Nedeni: ?~
Yukarıda da belirtildiği gibi test sonuçlarına bakıldığında Ardışıl veri paylaşım türü matris çarpım işlemi, Blok veri paylaşım türü matris çarpım işlemine göre daha hızlı çalışmıştır. Ardışıl veri paylaşım işleminde veri dağılım dengesi ve yük dağılımı daha iyi yapılıyor. Böylece threadler birbirini daha az bekliyor. Bunun sonucunda da daha hızlı sonuç veriyor.
~~ Matrix Çarpım İşlemlerinin Yorumu: ~~
Sistemin seri çalışması ile paralel çalışması 2 ile 4 arasında hızlanma ve 20% ile 40% arasında verimlilik sağlanmıştır. Küçük boyutlu matris çarpımlarında gereksiz görülebilir fakat eğer boyutumuz büyük verilerse zamandan tasarruf açısından çok önemli bir hızlanma değeri ortaya çıkmıştır.
