Skip to content

Instantly share code, notes, and snippets.

@seddi
Created April 9, 2011 01:17
Show Gist options
  • Save seddi/911007 to your computer and use it in GitHub Desktop.
Save seddi/911007 to your computer and use it in GitHub Desktop.
n x n 'lik 2 matrisin carpmının sonuc matrısının degerlerinin toplamını belirli aralıkta gosteren paralel ve seri olarak hesaplama kodları
/* Evrelerle gerçekleştirilen nokta çarpımı */
/*
* POSIX Thread'leriyle ilgili okunabilecek bazı kaynaklar:
*
* http://randu.org/tutorials/threads/
* http://www.ibm.com/developerworks/linux/library/l-posix1.html
* http://www.ibm.com/developerworks/library/l-pthred.html
* http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h> /* uintptr_t için */
#include <pthread.h> /* pthread_* işlevleri için */
/*
* Test amaçlı olarak kullanacağımız vektörlerin boyu.
*/
#define VECTOR_LENGTH 1000
/*
* Tamsayılar hangi aralıkta olsun?
*/
#define RANDOM_RANGE 1000
/*
* Kaç evre (thread) kullanılsın?
*/
#define NTHREAD 10 /* VECTOR_LENGTH x VECTOR_LENGTH matrisinin satırlarını hesaplamak icin 4 thread kullan*/
/*
* Test matrisini her evre başına bir aralık düşürecek şekilde bölüyoruz.
* İlgili aralık uzunluğu ne olmalı?
*/
#define VECTOR_LENGTH_PER_THREAD (VECTOR_LENGTH/NTHREAD)
/*
* Test matrisleri.
*/
static int *vector_a[VECTOR_LENGTH]; /* a matris vektoru */
static int *vector_b[VECTOR_LENGTH]; /* b matris vektoru */
/*
* Sonuç.
*/
static long dot_product;
/*
* Tüm evreler arasında paylaşılan karşılıklı dışlayıcı.
*/
static pthread_mutex_t mutex_dot_product;
/* Test vektörlerini ilkle. */
static void init(void) {
long i, j;
/*
* VECTOR_LENGTH x VECTOR_LENGTH uzunluğunda iki tamsayı matrisi oluştur ve matrisleri
* test amaçlı olarak [0, RANDOM_RANGE] aralığında rastgele tamsayı
* değerleriyle doldur.
*/
for (i = 0; i < VECTOR_LENGTH; i++){
vector_a[i] = (int *) malloc(VECTOR_LENGTH * sizeof(int)); /* ixj matrisi icin her i satırına j = VECTOR_LENGTH kadar yer tahsis et*/
vector_b[i] = (int *) malloc(VECTOR_LENGTH * sizeof(int)); /* ixj matrisi icin her i satırına j = VECTOR_LENGTH kadar yer tahsis et*/
}
for (i = 0; i < VECTOR_LENGTH; i++)
for (j = 0; j < VECTOR_LENGTH; j++){
vector_a[i][j] = vector_b[i][j] = random() % RANDOM_RANGE;
//~ printf("matris a[%ld][%ld] : %d\n",i,j,vector_a[i][j]);
}
}
/* Test vektörlerinin nokta çarpımını al (bu bir evre). */
static void *process(void *arg)
{
/*
* Evre oluşturulurken ilgili evre sırası bir void işaretçide taşınarak
* bu işleve iletiliyor. Sıra numarasını kullanarak vektörlerin hangi
* aralığında çalışacağımızı belirleyeceğiz. Tabii önce void
* işaretçiden pozitif tamsayıya döünştürmek için uygun bir tip
* tanımlıyoruz.
*/
uintptr_t offset;
long i, j, k, start, end;
long sum;
/*
* Tip dönüşümü. Örneğin 4 kanallı çalışıyorsak offset değeri sırayla
* 0, 1, 2, 3 olacak.
*/
offset = (uintptr_t) arg;
/*
* Bu evrenin çalışacağı vektör aralığını, yani başlangıç ve bitiş
* indislerini hesapla.
*/
start = offset * VECTOR_LENGTH_PER_THREAD;
end = start + VECTOR_LENGTH_PER_THREAD;
/*
* İşlemi yap. Burada her evre kendi vektör aralığında bağımsız şekilde
* çalışıyor. Örnek olarak basit bir işlem yapıyoruz: elemanları çarp,
* topla ve ilgili aralığa düşür. Bir tür "nokta çarpımı".
*/
for (i = start, sum = 0; i < end; i++) /* her thread icin baslangıc ve bitis satır numarası arasında dongu kur */
for(k = 0; k < VECTOR_LENGTH; k++)
for (j = 0; j < VECTOR_LENGTH; j++) /* her satır uzunlugu kadar dongu */
sum += (vector_a[i][k] * vector_b[k][j]) % RANDOM_RANGE;
/*
* Bu evre bir sonuç üretti ("nokta çarpımı"). Bu sonucu toplam sonuca
* ekleyeceğiz. Fakat aynı anda bir başka evre de bu işlemi yapıyor
* olabilir. Dolayısıyla sonuç değişkenine yazarken diğer evrelerin
* bu değişkene erişmesini engellemeliyiz. Nasıl? Bir "kardış"
* kullanarak. Karşılıklı kilitlemeyi mümkün olan en dar aralıkta, yani
* "kiritk bölge"de yapıyoruz.
*/
pthread_mutex_lock(&mutex_dot_product);
//~ printf("ara sonuc : %ld \n", dot_product);
dot_product += sum;
pthread_mutex_unlock(&mutex_dot_product);
/*
* Evre tamamlandı. pthread_join bu çağrıyı bekliyor.
*/
pthread_exit(NULL);
}
/* Sonucu raporla. */
static void report(void)
{
printf("Toplam: %ld\n", dot_product);
}
/* Test vektörlerini yoket. */
static void shutdown(void)
{
long i;
for (i = 0; i < VECTOR_LENGTH; i++){
free(vector_a[i]);
free(vector_b[i]);
}
}
int main(void)
{
/*
* Daha sonra void işaretçiye dönüştürülecek bir pozitif tamsayı
* gerekiyor. int veya uint kullanmamalıyız, taşınabilir değil ve uyarı
* üretir. Bunun yerine stdint.h başlığında tanımlı olan özel bir
* veritipi kullanıyoruz. Bu basitçe bir pozitif tamsayı, öyle ki
* sorunsuz şekilde void bir işaretçiye dönüştürülebilir.
*/
uintptr_t i;
/*
* Evre dizisi.
*/
pthread_t threads[NTHREAD];
/*
* Vektörleri oluştur.
*/
init();
/*
* Karşılıklı dışlayıcıyı ("kardış") hazırla.
*
* Kardışı bu işlevle ilklendirmek yerine (alternatif bir yöntem olarak)
* mutex_dot_product değişkeni tanımlandığı yerde ilklendirilebilirdi:
*
* mutex_dot_product = PTHREAD_MUTEX_INITIALIZER;
*/
pthread_mutex_init(&mutex_dot_product, NULL);
/*
* Evreleri oluştur ve ilgili işleve bağla.
*/
for (i = 0; i < NTHREAD; i++)
pthread_create(&threads[i], NULL, process, (void *) i); /* tip dönüşümüne dikkat */
/*
* Evrelerin tamamlanmasını bekle.
*
* Her evre kendi işlemini yapıyor. Sonucu almamız için katılımcı tüm
* evrelerin tamamlanmasını beklemeliyiz. Evreleri görevlendirildikleri
* işler için bir yere gönderilen ulaklar gibi düşünün. Bu ulaklar
* görevleri tamamlandığında bir noktada buluşuyorlar ("join").
*/
for (i = 0; i < NTHREAD; i++)
pthread_join(threads[i], NULL);
/*
* Sonucu raporla.
*/
report();
/*
* Oluşturulan vektörleri yoket.
*/
shutdown();
/*
* Karşılıklı dışlayıcıyı yoket.
*/
pthread_mutex_destroy(&mutex_dot_product);
exit(EXIT_SUCCESS);
}
/* Evrelerle gerçekleştirilen nokta çarpımının seri (klasik) gerçeklemesi */
#include <stdio.h>
#include <stdlib.h>
#define VECTOR_LENGTH 10000
#define RANDOM_RANGE 10000
static int *vector_a[VECTOR_LENGTH];
static int *vector_b[VECTOR_LENGTH];
static long dot_product;
static void process(void)
{
long i, j;
long sum;
for (i = 0, sum = 0; i < VECTOR_LENGTH; i++)
for (j = 0; j < VECTOR_LENGTH; j++)
sum += (vector_a[i][j] * vector_b[i][j]) % RANDOM_RANGE;
dot_product = sum;
}
static void init(void)
{
long i, j;
for (i = 0; i < VECTOR_LENGTH; i++){
vector_a[i] = (int *) malloc(VECTOR_LENGTH * sizeof(int));
vector_b[i] = (int *) malloc(VECTOR_LENGTH * sizeof(int));
}
for (i = 0; i < VECTOR_LENGTH; i++)
for (j = 0; j < VECTOR_LENGTH; j++)
vector_a[i][j] = vector_b[i][j] = random() % RANDOM_RANGE;
}
static void report(void)
{
printf("Toplam: %ld\n", dot_product);
}
static void shutdown(void)
{
long i;
for (i = 0; i < VECTOR_LENGTH; i++){
free(vector_a[i]);
free(vector_b[i]);
}
}
int main(void)
{
init();
process();
report();
shutdown();
exit(EXIT_SUCCESS);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment