您的位置:首页 > Web前端

__sync_fetch_and_add,pthread_mutex_lock

2017-07-10 18:00 246 查看
线程安全

#define _GNU_SOURCE

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <sched.h>
#include <linux/unistd.h>
#include <sys/syscall.h>
#include <errno.h>
#include <linux/types.h>
#include <time.h>

#define INC_TO 1000000 // one million...

__u64 rdtsc()
{
__u32 lo,hi;

__asm__ __volatile__
(
"rdtsc":"=a"(lo),"=d"(hi)
);

return (__u64)hi<<32|lo;
}

int global_int0 = 0;
int global_int1 = 0;
int global_int2 = 0;

pthread_mutex_t count_lock = PTHREAD_MUTEX_INITIALIZER;

pid_t gettid( void )
{
return syscall( __NR_gettid );
}

void *thread_routine0( void *arg )
{
int i;
int proc_num = (int)(long)arg;
__u64 begin, end;
struct timeval tv_begin,tv_end;
__u64 timeinterval;
cpu_set_t set;

CPU_ZERO( &set );
CPU_SET( proc_num, &set );

if (sched_setaffinity( gettid(), sizeof( cpu_set_t ), &set ))
{
perror( "sched_setaffinity" );
return NULL;
}

begin = rdtsc();
gettimeofday(&tv_begin,NULL);
for (i = 0; i < INC_TO; i++)
{
__sync_fetch_and_add( &global_int0, 1 );
}
gettimeofday(&tv_end,NULL);
end = rdtsc();
timeinterval =(tv_end.tv_sec - tv_begin.tv_sec) * 1000000 + (tv_end.tv_usec - tv_begin.tv_usec);
fprintf(stderr,"proc_num :%d,__sync_fetch_and_add cost %llu CPU cycle,cost %llu us\n", proc_num, end-begin, timeinterval);

return NULL;
}

void *thread_routine1( void *arg )
{
int i;
int proc_num = (int)(long)arg;
__u64 begin, end;
struct timeval tv_begin,tv_end;
__u64 timeinterval;
cpu_set_t set;

CPU_ZERO( &set );
CPU_SET( proc_num, &set );

if (sched_setaffinity( gettid(), sizeof( cpu_set_t ), &set ))
{
perror( "sched_setaffinity" );
return NULL;
}

begin = rdtsc();
gettimeofday(&tv_begin,NULL);
for (i = 0; i < INC_TO; i++)
{
global_int1++;
}
gettimeofday(&tv_end,NULL);
end = rdtsc();
timeinterval =(tv_end.tv_sec - tv_begin.tv_sec) * 1000000 + (tv_end.tv_usec - tv_begin.tv_usec);
fprintf(stderr,"proc_num :%d,__sync_fetch_and_add cost %llu CPU cycle,cost %llu us\n", proc_num, end-begin, timeinterval);

return NULL;
}

void *thread_routine2( void *arg )
{
int i;
int proc_num = (int)(long)arg;
__u64 begin, end;

struct timeval tv_begin,tv_end;
__u64 timeinterval;
cpu_set_t set;

CPU_ZERO( &set );
CPU_SET( proc_num, &set );

if (sched_setaffinity( gettid(), sizeof( cpu_set_t ), &set ))
{
perror( "sched_setaffinity" );
return NULL;
}

begin = rdtsc();
gettimeofday(&tv_begin,NULL);

for(i = 0;i<INC_TO;i++)
{
pthread_mutex_lock(&count_lock);
global_int2++;
pthread_mutex_unlock(&count_lock);
}

gettimeofday(&tv_end,NULL);
end = rdtsc();

timeinterval =(tv_end.tv_sec - tv_begin.tv_sec) * 1000000 + (tv_end.tv_usec - tv_begin.tv_usec);
fprintf(stderr,"proc_num :%d,pthread lock cost %llu CPU cycle,cost %llu us\n", proc_num, end-begin, timeinterval);

return NULL;
}

int main()
{
int procs = 0;
int i;
pthread_t *thrs;

// Getting number of CPUs
procs = (int)sysconf( _SC_NPROCESSORS_ONLN );
if (procs < 0)
{
perror( "sysconf" );
return -1;
}

thrs = malloc( sizeof( pthread_t ) * procs );
if (thrs == NULL)
{
perror( "malloc" );
return -1;
}

printf( "Starting %d threads...\n", procs );

for (i = 0; i < procs; i++)
{
if (pthread_create( &thrs[i], NULL, thread_routine0,
(void *)(long)i ))
{
perror( "pthread_create" );
procs = i;
break;
}
}

for (i = 0; i < procs; i++)
pthread_join( thrs[i], NULL );

printf("===== use automic method =====\n");
printf("After doing all the math, global_int value is: %d\n", global_int0);
printf("Expected value is: %d\n", INC_TO * procs );
printf("Correct rate: %f%\n\n", (double)(((double)global_int0)/((double)(INC_TO * procs)) * 100));

for (i = 0; i < procs; i++)
{
if (pthread_create( &thrs[i], NULL, thread_routine1,
(void *)(long)i ))
{
perror( "pthread_create" );
procs = i;
break;
}
}

for (i = 0; i < procs; i++)
pthread_join( thrs[i], NULL );

printf("===== don't use pthread mutex =====\n");
printf("After doing all the math, global_int value is: %d\n", global_int1 );
printf("Expected value is: %d\n", INC_TO * procs );
printf("Correct rate: %f%\n\n", (double)(((double)global_int1)/((double)(INC_TO * procs)) * 100));

for (i = 0; i < procs; i++)
{
if (pthread_create( &thrs[i], NULL, thread_routine2,
(void *)(long)i ))
{
perror( "pthread_create" );
procs = i;
break;
}
}

for (i = 0; i < procs; i++)
pthread_join( thrs[i], NULL );

printf("===== use pthread mutex =====\n");
printf("After doing all the math, global_int value is: %d\n", global_int2);
printf("Expected value is: %d\n", INC_TO * procs );
printf("Correct rate: %f%\n\n", (double)(((double)global_int2)/((double)(INC_TO * procs)) * 100));

free(thrs);
return 0;
}

jwwang@jwwang:~/test$ ./a.out
Starting 4 threads...
proc_num :2,__sync_fetch_and_add cost 201870083 CPU cycle,cost 74471 us
proc_num :1,__sync_fetch_and_add cost 216505929 CPU cycle,cost 79872 us
proc_num :0,__sync_fetch_and_add cost 221643287 CPU cycle,cost 81767 us
proc_num :3,__sync_fetch_and_add cost 202669487 CPU cycle,cost 74767 us
===== use automic method =====
After doing all the math, global_int value is: 4000000
Expected value is: 4000000
Correct rate: 100.000000%

proc_num :0,__sync_fetch_and_add cost 22410118 CPU cycle,cost 8267 us
proc_num :1,__sync_fetch_and_add cost 29147387 CPU cycle,cost 10752 us
proc_num :3,__sync_fetch_and_add cost 29398320 CPU cycle,cost 10845 us
proc_num :2,__sync_fetch_and_add cost 11182123 CPU cycle,cost 4124 us
===== don't use pthread mutex =====
After doing all the math, global_int value is: 1789149
Expected value is: 4000000
Correct rate: 44.728725%

proc_num :0,pthread lock cost 875600915 CPU cycle,cost 323023 us
proc_num :3,pthread lock cost 905362503 CPU cycle,cost 334003 us
proc_num :1,pthread lock cost 926347504 CPU cycle,cost 341745 us
proc_num :2,pthread lock cost 938705022 CPU cycle,cost 346304 us
===== use pthread mutex =====
After doing all the math, global_int value is: 4000000
Expected value is: 4000000
Correct rate: 100.000000%

1 不加锁的情况下,不能返回正确的结果
测试程序结果显示,正确结果为400万,实际为1789149
每台机器不一样,当时肯定结果不正确

2 线程锁和原子性自加都能返回正确的结果。

3 性能上__sync_fetch_and_add,完爆线程锁。
从测试结果上看, __sync_fetch_and_add,速度是线程锁的4倍
机器不一样,结果也不一样,当时可定比线程锁好
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: