我必须在我的程序中使用随机数。知道rand()不是线程安全的,这就是为什么我尝试了几种方法:mutex来阻止它,srand,drand48 ......但是我的并行程序仍然比串行程序慢......有人可以帮忙吗? / p>
我使用带有2个核心的Mac book pro i5。
//
// main.cpp
// Dirihle_problem_monte_carlo_method (Posix threads)
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdint.h>
#include <math.h>
#include <mach/mach_time.h>
#include <sys/time.h>
// переменные
FILE *FileData, *FileResults;
int N = 200; // число равномерных случайных блужданий
int n = 51; // сетка n x n (шаг h=1)
int nInside; // сетка внутренних узлов (nInside-1) x (nInside-1)
float *presult;
int indexBegin, indexEnd;
int partSize;
int numOfLine;
#define NUM_THREADS 1
double conversion_factor;
//Raw mach_absolute_times going in, difference in seconds out
double subtractTimes( uint64_t endTime, uint64_t startTime );
float Monte_Carlo_Method(int N, int n, int i, int j);
bool borderLineNotReached(int i, int j, int n);
void *ParallelResultCalculation (void *threadid);
int indEnd(int treadID);
void Init() {
mach_timebase_info_data_t timebase;
mach_timebase_info(&timebase);
conversion_factor = (double)timebase.numer / (double)timebase.denom;
}
#pragma mark - main
/*****************************************************************/
int main(int argc, const char * argv[])
{
pthread_t threads[NUM_THREADS];
pthread_attr_t attr;
int rc;
uint64_t start,stop;
double duration = 0.0;
timeval beforeTime, afterTime;
// Init();
//инициализация системы и отправка необходимых данных остальным процессам
// FileData = fopen("DataFile.txt","r");
FileResults = fopen("FileResults.txt","w+");
// Initialize and set thread joinable
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
//fscanf(FileData,"%d",&n);
nInside = n - 1;
// fscanf(FileData,"%d",&N);
numOfLine = (nInside - 1);
partSize = numOfLine / NUM_THREADS;
presult = new float [n * n];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (i == 0 || j == 0)
{
presult[i * n + j] = 0.0f;
}
else if (i == nInside)
{
presult[i * n + j] = j;
}
else if (j == nInside)
{
presult[i * n + j] = i;
}
}
}
start = mach_absolute_time();
for (int i = 0; i < NUM_THREADS; i++)
{
// rc = pthread_create(&threads[i], NULL, ParallelResultCalculation, (void *)i);
rc = pthread_create(&threads[i], &attr, ParallelResultCalculation, (void *)i);
if (rc)
{
printf("Error:unable to create thread %d", rc);
exit(-1);
}
}
// free attribute and wait for the other threads
pthread_attr_destroy(&attr);
for (int i = 0; i < NUM_THREADS; i++)
{
rc = pthread_join(threads[i], NULL);
if (rc)
{
printf("Error:unable to join thread %d", rc);
exit(-1);
}
}
stop = mach_absolute_time();
duration = subtractTimes(stop,start);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
fprintf(FileResults, "u(%d,%d)= %lf\t", i, j, presult[i * n + j]);
}
fprintf(FileResults, "\n");
}
fprintf(FileResults, "\n\n Elapsed time(seconds) = %lf", duration);
delete [] presult;
// fclose(FileData);
fclose(FileResults);
pthread_exit(NULL);
return 0;
}
#pragma mark - function relative to time
/*****************************************************************/
double subtractTimes( uint64_t endTime, uint64_t startTime )
{
uint64_t difference = endTime - startTime;
static double conversion = 0.0;
if( conversion == 0.0 )
{
mach_timebase_info_data_t info;
kern_return_t err = mach_timebase_info( &info );
//Convert the timebase into seconds
if( err == 0 )
conversion = 1e-9 * (double) info.numer / (double) info.denom;
}
return conversion * (double) difference;
}
#pragma mark - last id
int indEnd(int treadID)
{
int index;
if(treadID == NUM_THREADS - 1)
{
index = nInside;
}
else
{
index = (partSize * (treadID + 1)) + 1;
}
return index;
}
#pragma mark - Monte-Carlo method
/*****************************************************************/
float Monte_Carlo_Method(int N, int n, int i, int j)
{
unsigned int rand_state;
int randomValueForStep;
// int minRandom = 0;
// int maxRandom = 10; // 10 not included in interval
do
{
// determine the direction of the step (look at "„исленные методы анализа", ƒемидович стр.272:
// определение шага частицы в зависимости от выпавшего случайного числа)
// algorithm http://iguania.ru/stati-po-programmirovaniiu/generatsiya-sluchaynich-chisel.html
// unsigned seed = getpid() * time(NULL) * (thrID + 1);
//
// randomValueForStep = rand_r(&seed) % 4;
// randomValueForStep = rand() % 4;
randomValueForStep = drand48() * 5.0;
// rand_state = rdtsc();
// randomValueForStep = rand_r(&rand_state) % 4;
if (randomValueForStep == 0) // шаг вправо
{
i++;
}
else if (randomValueForStep == 1) // шаг вверх
{
j++;
}
else if (randomValueForStep == 2)// шаг влево
{
i--;
}
else if (randomValueForStep == 3) // шаг вниз
{
j--;
}
}
while (borderLineNotReached(i, j, n));
// блуждание частицы завершено, т.к она вышла на границу
float res;
if (j == 0) // нижняя граница (x,border_y0)
{
res = 0.0;
}
else if(i == n - 1) // правая граница (border_xmax,y)
{
res = j;
}
else if(j == n - 1) // верхняя граница (x,border_ymax)
{
res = i;
}
else {
res = 0.0;
}
return res;
}
//bool borderLineNotReached(float i, float j, float border_x0, float border_y0, float border_xmax, float border_ymax)
bool borderLineNotReached(int i, int j, int n)
{
if (i <= 0 || j <= 0 || i >= (n - 1) || j >= (n - 1))
{
return false;
}
return true;
}
void *ParallelResultCalculation (void *threadid)
//void *ParallelResultCalculation (void *data)
{
int tid;
tid = *((int *)&threadid);
// struct thread_data *getData = (struct thread_data *)data;
// tid = getData->thread_id;
indexBegin = partSize * tid + 1;
indexEnd = indEnd(tid);
for (int i = indexBegin; i < indexEnd; i++)
{
for (int j = 1; j < nInside; j++)
{
float sum = 0.0;
float res;
for (int indexOfTrajectory = 0; indexOfTrajectory < N; indexOfTrajectory++)
{
res = Monte_Carlo_Method(N, n, i, j);
sum += res;
}
float uij = sum / (float)N;
presult[i * n + j] = uij; // a[i,j]= [i*m+j], где i = 0...n, j = 0...m
}
}
// pthread_exit(NULL);
}