首先介绍下多核并行计算的场景,及测试方法:
(1)并行计算运用在特定大型服务器之上,其硬件水平很高,可能有多几百到上千个cpu。
(2)这些cpu分成了2类,一类是控制cpu,作为主控,用于发起计算,与其他CPU交互,发起计算通知,分析并统计结果等作用;第二类是计算cpu(占大多数)。系统中绝大多数cpu属于计算cpu,因为整个系统就是为了高性能计算。由于计算量大,所以需要很多很多的cpu进行并行计算。每个cpu计算完后,将计算结果传回主控CPU。
(3)系统发起一次计算通知后,每个CPU核心会绑定一个进程开始进行实时运算。不同的CPU上运行着不同的实时进程,计算的通知和计算的结果,需要进程间通信,进行消息传递。并而且要求进程间通信的性能要足够的高,因为当cpu数量上涨到几百上千的时候,进程间通信的性能会影响到整个计算的结果收集。某些实时场景下,系统不允许某一次计算超期完成,这将导致整个业务的失败。
并行计算有知名的MPI库,如果不使用MPI,使用传统方式的linux IPC通信机制,比如管道,信号量,共享内存,消息队列等进程间通信方式。性能会是怎样的呢?下面对这几种IPC通信,进行性能研究。查看每种IPC之间的性能差距,及与MPI库做对比。形成性能分析报告。
首先采用管道方式来进行高性能密集并行计算。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <math.h>
#include <sys/time.h>
#include <sys/stat.h>
#define SHARE_RFIFO_PATH "/home/rfifo"
#define SHARE_WFIFO_PATH "/home/wfifo"
int on_cpu;
double dval = 1.23;
int create_process()
{
int ret;
pid_t pid;
pid = fork();
if(pid < 0) {
perror("fork");
return -1;
}
if(pid == 0) {
} else {
}
return ret;
}
int gettimeofday(struct timeval *tv, struct timezone *tz);
int do_calc(int loop)
{
int i;
for(i=0; i<loop; i++) {
dval *= sin(3.14159);
}
}
int do_simulation(int loop_num, int one_loop_num)
{
int i, count = 0;
struct timeval tv1, tv2;
long long us1, us2, ms1, ms2;
long long ms, us;
short skip = 2000;
int max=-1, min = 99999999, val;
for(i=0; i<loop_num; i++) {
gettimeofday(&tv1, NULL);
do_calc(one_loop_num);
gettimeofday(&tv2, NULL);
if(--skip < 0) {
us1 = (int64_t)tv1.tv_sec*1000*1000 + tv1.tv_usec;
us2 = (int64_t)tv2.tv_sec*1000*1000 + tv2.tv_usec;
ms1 = (int64_t)tv1.tv_sec*1000 + tv1.tv_usec/1000;
ms2 = (int64_t)tv2.tv_sec*1000 + tv2.tv_usec/1000;
us = us2 - us1;
ms = ms2 - ms1;
if(us > max)
max = us;
if(us < min)
min = us;
count++;
skip = 1000;
}
}
printf("on cpu %d count %d, Jitter %d, max %d, min %d\n", \
on_cpu, count, max-min, max, min);
}
int main(int argc, char **argv)
{
int i, ret = 0;
int rfd, wfd;
int len = 0;
char rbuffer[64], wbuffer[64];
pid_t pid;
do_simulation(300000, 20000);
return 0;
rfd = mkfifo(SHARE_RFIFO_PATH, O_RDONLY);
wfd = mkfifo(SHARE_WFIFO_PATH, O_WRONLY);
if(rfd < 0 || wfd < 0) {
perror("mkfifo:");
return rfd|wfd;
}
len = read(rfd, rbuffer, sizeof(rbuffer));
if(len < 0) {
perror("read:");
close(rfd);
close(wfd);
}
while(1) sleep(1);
return ret;
}