насколько медленная синхронизация мьютекса, чем отсутствие синхронизации в 2 потоках - PullRequest
0 голосов
/ 23 февраля 2020

У меня есть два потока, которые должны работать в разных ядрах. Когда я не предоставляю синхронизацию в коде, для выполнения потоков в коде требуется всего ~ 0,6 секунды (для итерации N = 100000000). Когда я запускаю тот же код с синхронизацией мьютексов, время между потоками составляет ~ 3 секунды. Я не уверен, что это то, что он должен показать. Должно ли это быть так медленно? или я делаю ошибку в своем коде.

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/time.h>
#include <time.h>
#include <sched.h>


int x=0;
long long i;
long long count=0;
pthread_mutex_t mutex;


double getsecs(void)
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec + tv.tv_usec / 1.0e6;
}


void* changetoone(void *arg)
        { 

  pthread_mutex_lock(&mutex);

         for (i=0; i<10000000; i++){

            count2=i;
            while(x!=1)


            { count= count+1;
                x=1;

              //printf("%d", x);


            }
            pthread_mutex_unlock(&mutex);

         }
         return NULL;

        }


void* changetozero(void *arg){
        pthread_mutex_lock(&mutex);//we can set one or more bits here, each one representing a single CPU

 for (i=0; i<10000000; i++){
            while(x!=0)
            {count= count+1;
             x=0;


          printf("%d", x);


             }
          pthread_mutex_unlock(&mutex);   
        } 

        return 0;           
       } 


int main()
{


    double t1 = getsecs();

    pthread_t thread1;

    pthread_create(&thread1, NULL, changetoone, &x);

    pthread_t thread2;
    pthread_create(&thread2, NULL, changetozero, &x);    

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    double t2 = getsecs();


    printf("elapsed seconds: %f, %f  uS/iteration\n", t2-t1,1000000*(t2-t1)/100000000);
   printf("%lld\n", count);

}

1 Ответ

1 голос
/ 23 февраля 2020

Ну, если честно, это действительно не имеет значения насколько медленнее. Либо вам нужна синхронизация, либо нет.

Неиспользование, когда это необходимо, может привести к неверным результатам. Вы бы предпочли иметь медленный код или неправильный код?

Сказав это, я вижу, что ваши потоки блокируют мьютекс на все время итерации в десять миллионов l oop. Это практически то же самое, что последовательный вызов двух функций. Если вы хотите истинный параллелизм, операции блокировки и разблокировки будут внутри l oop, что-то вроде (псевдокод):

do 10,000,000 times:
    lock mutex
    do operation
    unlock mutex

Но имейте в виду, что многопоточность полезно только тогда, когда разногласия относительно низкие . Если двум потокам нужна блокировка в 99% случаев (как, кажется, имеет место в вашем коде, даже с перемещением блокировки в пределах l oop), вы не увидите такого большого улучшения , если таковые имеются.

Вы можете даже увидеть деградацию, поскольку потоки по-прежнему в основном взаимоисключающие, но с добавленными мьютексами для замедления всего этого.

...