0

我必须在我的程序中使用随机数。知道 rand() 不是线程安全的,这就是为什么我尝试了几种方法:互斥锁,srand,drand48 ......但我的并行程序仍然比串行程序慢......有人可以帮忙吗?

我使用 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);


}
4

0 回答 0