Linux下使用POSIX Thread作多核多线程并行计算
POSIX线程库根据处理器、操作系统等特性封装了一台线程处理的接口。对于目前基于x86处理器架构的Linux系统来说,它往往会默认地将新创建的一个线程调度到与主线程不同的核中执行,如果这样能更好地平衡负荷的话。因此,在使用POSIX线程时,开发者不能断言当前创建的线程是否运行在与主线程相同的核心下,也不能断言一定运行在与主线程不同的核心下。当然,由于POSIX线程具有时间片轮询调度(Round-Robin),因此即便与主线程处于一个核心,使用旋锁的话,性能影响也不会太大。不过多核多线程其实最好还是使用类似于OS X以及iOS中的Grand Central Dispatch机制,显式给出线程的调度队列。
在Linux下使用POSIX线程时应当先得加上libpthread.so动态库,因此在连接器选项中加上-lpthread。
以下代码在联想Z475,AMD APU A6-3420M,4GB DDR3,Ubuntu12.04系统下完成测试。
C代码:
/* ============================================================================ Name : ThreadTest.c Author : Zenny Chen Version : Copyright : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> #define TOTAL_CALC_ITEMS 1000000 extern unsigned long getRealtimeCycles(void); static volatile _Bool isFinished = 0; static volatile int sum4Core2 = 0; static void* threadProc(void *param) { int sum = 0; int *pSrc = (int*)param; for(int i = TOTAL_CALC_ITEMS / 2; i < TOTAL_CALC_ITEMS; i++) sum += pSrc[i]; sum4Core2 = sum; isFinished = 1; return NULL; } static int sourceArray[TOTAL_CALC_ITEMS]; static void testOpt(void) { // Initialize the array for(int i = 0; i < TOTAL_CALC_ITEMS; i++) sourceArray[i] = i + 1; pthread_t threadHandle; pthread_attr_t attr; if(pthread_attr_init(&attr) != 0) { puts("Attribute failed to create!"); return; } pthread_attr_setschedpolicy(&attr, SCHED_OTHER); if(pthread_create(&threadHandle, &attr, &threadProc, sourceArray) != 0) { puts("Thread failed to create!"); return; } int polacy = -1; pthread_attr_getschedpolicy(&attr, &polacy); printf("Current sched polacy is: %d\n", polacy); int sum = 0; unsigned long ticks = getRealtimeCycles(); for(int i = 0; i < TOTAL_CALC_ITEMS / 2; i++) sum += sourceArray[i]; while(!isFinished) __asm__("pause"); sum += sum4Core2; ticks = getRealtimeCycles() - ticks; printf("The number of cycles is: %lu\n", ticks); printf("The sum is: %d\n", sum); pthread_attr_destroy(&attr); } static void testNaive(void) { // Initialize the array for(int i = 0; i < TOTAL_CALC_ITEMS; i++) sourceArray[i] = i + 1; int sum = 0; unsigned long ticks = getRealtimeCycles(); for(int i = 0; i < TOTAL_CALC_ITEMS; i++) sum += sourceArray[i]; ticks = getRealtimeCycles() - ticks; printf("The number of cycles is: %lu\n", ticks); printf("The sum is: %d\n", sum); } int main(void) { testOpt(); testNaive(); testOpt(); testNaive(); return EXIT_SUCCESS; // 1784293664 }
汇编代码:
.text .align 2 .globl getRealtimeCycles getRealtimeCycles: rdtsc shl $32, %rdx or %rdx, %rax ret