Foster设计方法

1. Foster简介

Foster是一种设计并行计算程序的方法,分为四步(Partitioning、Communication、Agglomeration、Mapping)来进行并行计算程序的设计。此外还有一种设计方法Culler跟Foster大同小异。

作为例子问题是 1000 × 1000 1000 \times 1000 1000×1000的矩阵和向量相乘。使用了4个线程。

先打一下预防针。矩阵乘向量这个问题太简单了,一定要使用Foster设计方法反而觉得Foster有些累赘。例如信息传递、整合实际上完全可以没有操作,直接在划分的时候就一次性解决。但是,在后来解决n-body等问题的时候Foster设计方法才能更好的展现它的作用。

2. 设计过程

2.1 Partitioning

首先将问题划分为更细小的子任务。

在向量乘矩阵的大问题下可以把问题分解为 1 0 6 10^6 106次乘法和若干次加法。乘法的运算量远高于加法,因此只把乘法当作最小的子任务。

2.2.2 Communication

在信息传递的设计阶段,要考虑各个线程之间要传递的数据或者要用共享变量传递的数据。

之前划分过程得到的各个乘法子任务的计算结果要交给一个线程求和。

很明显这样的信息传递的过程比较繁琐,花费的代价也比较高,在下一个整合步骤会解决这个问题。

2.2.3 Agglomeration

整合步骤是将之前划分得到的子问题合并,目的是减少信息传递的代价或减少编程量。

在整合时可以将一行矩阵和向量的乘法合并为一个子问题,这样就完全消除了信息传递的代价。而且只要矩阵维度可以被线程数整除那么每个线程解决的问题量就是一样的。

实际上,正常思路都是就将计算一行乘法划分为一个子任务。这里只是为了突出Foster设计思路才将每一次乘法划分开。

2.2.4 Mapping

映射的过程是将线程(子问题)映射到处理器的过程。这个过程直接由操作系统或者硬件控制,程序员一般情况下不会通过代码控制。

3. 总设计方案

下表给出了Foster设计方法在每一步的设计

步骤名称 设计
Partitioning 将矩阵元素和向量元素每一次乘法划分为一个子问题
Communication 每次乘法的计算结果要汇总
Agglomeration 将一行的乘法合并成一个任务
Mapping 将线程分给不同的处理单元

附录:代码实现

#include 
#include 
#include 

#define DIMENSION 12

int **matrix;
int *vec;
int *result;
int thread = 4;

void *mul(void *r);

int main()
{
    // 初始化矩阵和向量
    long i, j;
    matrix = (int **)calloc(DIMENSION, sizeof(int *));
    for(i = 0; i < DIMENSION; ++i)
        matrix[i] = (int *)calloc(DIMENSION, sizeof(int));
    vec = (int *)calloc(DIMENSION, sizeof(int));
    result = (int *)calloc(DIMENSION, sizeof(int));
    for(i = 0; i < DIMENSION; ++i)
    {
        matrix[i][i] = 1;
        vec[i] = i;
    } 

    printf("Before mul vec:\n");
    for (i = 0; i < DIMENSION; ++i)
        printf("%d ", vec[i]);
    printf("\n");

    pthread_t *handles = (pthread_t *)malloc(thread * sizeof(pthread_t));
    for(i = 0; i < thread; ++i)
        pthread_create(&handles[i], NULL, mul,\
            (void *)i);

    for(i = 0; i < thread; ++i)
        pthread_join(handles[i], NULL);

    printf("After mul vec:\n");
    for(i = 0; i < DIMENSION; ++i)
        printf("%d ", result[i]);
    printf("\n");

    free(handles);
    free(vec);
    free(result);
    for(i = 0; i < DIMENSION; ++i)
        free(matrix[i]);
    free(matrix);

    return 0;
}

void *mul(void *r)
{
    long rank = (long)r;
    int len = DIMENSION / thread;
    int fir_dim = rank * len;
    int las_dim = (rank + 1) * len;

    int i, j;
    for(i = fir_dim; i < las_dim; ++i)
        for(j = 0; j < DIMENSION; ++j)
            result[i] += vec[j] * matrix[i][j];
    
    return NULL;
}

你可能感兴趣的:(Foster设计方法)