/*
* Nome: Antonio Ricardo Alexandre Brasil
Michelle Borges Botelho
Gustavo Grimaldi
Data: 03/07/2014
Objetivo: Implementar um algoritmo de geração e verificação de numeros primos
que realize uma comparação dessa verificação utilizando threads e no modo
serial.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <pthread.h>
// -------------- Cabeçalho
#define TAM_LINHA 20000 // Define o tamanho da linha da matriz
#define TAM_COLUNA 20000 // Define o tamanho da coluna da matriz
#define LIMITE 29999 // Limite da geração dos numeros na matriz
#define LMACRO 10000 // Macro bloco linha
#define CMACRO 10000 // Macro bloco coluna
#define NTHREADS 9 // Numero total de threads
#define SEMENTE 10 // Semente do srand()
int macroC = 0; // Utilizando para controlar o proximo macrobloco coluna inicio a ser atribuido a uma thread
int macroL = 0; // Utilizando para controlar o proximo macrobloco linha inicio a ser atribuido a uma thread
int qtNumerosPrimos; // Quantidade de numeros primos da matriz
int matriz[TAM_LINHA][TAM_COLUNA]; // matriz
pthread_mutex_t mutex_soma, mutex_macro; // Controle das regiões
void geraPrimos(void) {
/*
Objetivo: gerar os numeros primos na matriz.
Matriz[X][X];
*/
printf("Gerando numeros primos ...\n");
int i = 0, j = 0;
for(i = 0; i < TAM_LINHA; i++) {
for(j = 0; j < TAM_COLUNA; j++) {
matriz[i][j] = rand() % LIMITE; // Atribui um numero aleatorio iniciando do 0 até LIMITE.
}
}
}
int verificaPrimo(int num) {
/*
Objetivo: verificar se determinado numero é um numero primo.
*/
if (num == 2)
return 1;
if ((num % 2) == 0 || num < 2)
return 0;
int i = 3, raiz = (int)sqrt(num);
while (i <= raiz){
if ((num % i) == 0)
return 0;
i+=2;
}
return 1;
}
void checaPrimos() {
/*
Objetivo: identificar numeros primos na matriz de forma serial.
*/
printf("Verificando numeros primos sem thread...\n");
int i = 0, j = 0;
for(i = 0; i < TAM_LINHA; i++) {
for(j = 0; j < TAM_COLUNA; j++) {
if (verificaPrimo(matriz[i][j])) {
qtNumerosPrimos ++;
}
}
}
printf("Quantidade primos com thread: %d\n", qtNumerosPrimos);
}
void semThread()
{
/*
Objetivo:
Função principal. Nela contem a função checa primos que verifica de forma serial
os numeros primos e contabiliza a variavel quantidade de numeros primos.
*/
clock_t ti, tf;
ti = clock();
checaPrimos();
tf = clock();
printf("Tempo de verificacao sem thread: %lf\n", (float) (tf - ti) / CLOCKS_PER_SEC);
}
void proxMacro(int *lr, int *cr) {
/*
Objetivo: Determina o macrobloco a ser acessado pela thread.
Passando como parametros as linhas(linharesultante) e a coluna(colunaresultante).
*/
int l, c;
if (macroL == 0 && macroC == 0) {
/*
Se for a primeira execução, logo o macro bloco limite a ser atribuido é o LMACRO e o CMACRO.
*/
macroL = LMACRO;
macroC = CMACRO;
l = macroL;
c = macroC;
*lr = l;
*cr = c;
return;
}
/*
Como não é a primeira execução, o algoritmo verifica se ja chegou ao limite da coluna.
Se chegou eu adiciono mais LMACRO na linha e reseto para o inicio do macrobloco coluna.
*/
if (macroC >= TAM_COLUNA) {
macroL += LMACRO;
macroC = CMACRO;
}
else {
macroC += CMACRO;
}
l = macroL;
c = macroC;
*lr = l;
*cr = c;
/*
Retorno os valores e finalizo a função.
*/
}
void *contaPrimos(void* arg) {
/*
Objetivo: É a chamada "slave" é nessa função que as threads irão trabalhar.
*/
int tid = (int)arg;
while (1) {
/*
Irá pegar macroblocos enquanto não chegar no limite da linha.
*/
int i = 0, j = 0;
int lp = 0, cp = 0;
int temp_soma = 0;
/*
Controla a região que atribui os macroblocos a thread.
*/
pthread_mutex_lock(&mutex_macro);
proxMacro(&lp, &cp);
pthread_mutex_unlock(&mutex_macro);
if (lp > TAM_LINHA)
return(NULL);
/*
Ele irá iniciar na coluna:
LP - LMACRO
LP: macrobloco linha da thread a ser trabalhada.
CP - CMACRO
CP: macrobloco coluna da thread a ser trabalhada.
*/
for (i = (lp - LMACRO); i < lp; i++) {
for (j = (cp - CMACRO); j < cp; j++) {
if (verificaPrimo(matriz[i][j])) {
temp_soma++;
}
}
}
/*
Faz o controle da região da soma.
*/
pthread_mutex_lock(&mutex_soma);
qtNumerosPrimos += temp_soma;
pthread_mutex_unlock(&mutex_soma);
}
return(NULL);
}
void comThread() {
/*
Função "main" que irá chamar todas as outras funções da thread.
*/
pthread_t threads[NTHREADS];
int i = 0;
clock_t ti, tf;
printf("Verificando numeros primos com %d thread(s)...\n", NTHREADS);
ti = clock();
pthread_mutex_init(&mutex_soma, NULL);
pthread_mutex_init(&mutex_macro, NULL);
for (i = 0; i < NTHREADS; i++){
pthread_create(&(threads[i]), NULL, contaPrimos, NULL);
}
for (i = 0; i < NTHREADS; i++){
pthread_join(threads[i], NULL);
}
tf = clock();
printf("Quantidade primos com thread: %ld\n", qtNumerosPrimos);
printf("Tempo de verificacao com thread: %lf\n", (float)(tf - ti) / CLOCKS_PER_SEC);
}
int main() {
srand(SEMENTE);
geraPrimos();
semThread();
qtNumerosPrimos = 0;
comThread();
system("pause");
}