From: Hanissalwan Mobidin (hanis9136.10_at_[hidden])
Date: 2014-06-04 04:07:45

Hello,
I am student from Malaysia that currently studying Parallel Computing
subject. I got problem to code for the collective MPI. My program
requirement is as follows:

1. Generate a random array of numbers on the root process (process 0).
2. Scatter the numbers to all processes, giving each process an equal
amount of numbers.
3. Each process computes the average of their subset of the numbers.
4. Gather all averages to the root process. The root process then
computes the average of these numbers to get the final average.

I manage to found the code for the program but it run using c/c++ as below:

// Author: Wes Kendall
// This code is provided freely with the tutorials on mpitutorial.com. Feel
// free to modify it for your own use. Any distribution of the code must
// either provide a link to www.mpitutorial.com or keep this header in tact.
//
// Program that computes the average of an array of elements in parallel
using
// MPI_Scatter and MPI_Gather
//
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include <assert.h>

// Creates an array of random numbers. Each number has a value from 0 - 1
float *create_rand_nums(int num_elements) {
float *rand_nums = (float *)malloc(sizeof(float) * num_elements);
assert(rand_nums != NULL);
int i;
for (i = 0; i < num_elements; i++) {
rand_nums[i] = (rand() / (float)RAND_MAX);
}
return rand_nums;
}

// Computes the average of an array of numbers
float compute_avg(float *array, int num_elements) {
float sum = 0.f;
int i;
for (i = 0; i < num_elements; i++) {
sum += array[i];
}
return sum / num_elements;
}

int main(int argc, char** argv) {
if (argc != 2) {
fprintf(stderr, "Usage: avg num_elements_per_proc\n");
exit(1);
}

int num_elements_per_proc = atoi(argv[1]);
// Seed the random number generator to get different results each time
srand(time(NULL));

MPI_Init(NULL, NULL);

int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);

// Create a random array of elements on the root process. Its total
// size will be the number of elements per process times the number
// of processes
float *rand_nums = NULL;
if (world_rank == 0) {
rand_nums = create_rand_nums(num_elements_per_proc * world_size);
}

// For each process, create a buffer that will hold a subset of the entire
// array
float *sub_rand_nums = (float *)malloc(sizeof(float) *
num_elements_per_proc);
assert(sub_rand_nums != NULL);

// Scatter the random numbers from the root process to all processes in
// the MPI world
MPI_Scatter(rand_nums, num_elements_per_proc, MPI_FLOAT, sub_rand_nums,
num_elements_per_proc, MPI_FLOAT, 0, MPI_COMM_WORLD);

// Compute the average of your subset
float sub_avg = compute_avg(sub_rand_nums, num_elements_per_proc);

// Gather all partial averages down to the root process
float *sub_avgs = NULL;
if (world_rank == 0) {
sub_avgs = (float *)malloc(sizeof(float) * world_size);
assert(sub_avgs != NULL);
}
MPI_Gather(&sub_avg, 1, MPI_FLOAT, sub_avgs, 1, MPI_FLOAT, 0,
MPI_COMM_WORLD);

// Now that we have all of the partial averages on the root, compute the
// total average of all numbers. Since we are assuming each process
computed
// an average across an equal amount of elements, this computation will
if (world_rank == 0) {
float avg = compute_avg(sub_avgs, world_size);
printf("Avg of all elements is %f\n", avg);
// Compute the average across the original data for comparison
float original_data_avg =
compute_avg(rand_nums, num_elements_per_proc * world_size);
printf("Avg computed across original data is %f\n", original_data_avg);
}

// Clean up
if (world_rank == 0) {
free(rand_nums);
free(sub_avgs);
}
free(sub_rand_nums);

MPI_Barrier(MPI_COMM_WORLD);
MPI_Finalize();
}

I want to code the program sing c#. But i don't really understand to use
the method in c#. I manage to code in point-to-point communication, but it
does not fit with the requirement to code using collective communication.
My code for the point-to-point is as follows:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MPI;

class Program
{
static void Main(string[] args)
{

using (new MPI.Environment(ref args))
{
Intracommunicator comm = MPI.Communicator.world;
if (comm.Size < 4)
{
Console.WriteLine("At least 4 processes needed");
return;
}
ArrayList tempArray = new ArrayList();

int num = 0;
//Distribute Array
Random rnd = new Random();
if (comm.Rank == 0)//Master or root process
{
//initiliaze array
System.Console.WriteLine("INITIAL LIST: ");

for (int i = 0; i < 30; i++)
{
num = rnd.Next(1, 200);
System.Console.Write(tempArray[i] + " ");
}
System.Console.WriteLine();

int split_size = tempArray.Count / 3;
System.Console.WriteLine("Splitsize: " + split_size);

int[] array1 = new int[split_size];
int[] array2 = new int[split_size];
int[] array3 = new int[split_size];

//copy tempArray to array1 (startIndex tempArray,
array1, startIndex array1, how many element from tempArray to be copied)
tempArray.CopyTo(0, array1, 0, split_size);
PrintValues(array1, ' ');

//copy tempArray to array2 (startIndex tempArray,
array3, startIndex array2, how many element from tempArray to be copied)
tempArray.CopyTo(split_size, array2, 0, split_size);
PrintValues(array2, ' ');

//copy tempArray to array3 (startIndex tempArray,
array3, startIndex array3, how many element from tempArray to be copied)
tempArray.CopyTo(split_size * 2, array3, 0, split_size);
PrintValues(array3, ' ');

comm.Send(array1, 1, 99);
comm.Send(array2, 2, 98);
comm.Send(array3, 3, 97);

int[] result = new int[3];
int finalAve = 0;
int sumTotal = 0;
System.Console.WriteLine("Receive Ave1 : " + result[0]);
System.Console.WriteLine("Receive Ave2 : " + result[1]);
System.Console.WriteLine("Receive Ave3 : " + result[2]);

for (int i = 0; i < result.Length; i++)
{
//if (finalAve < result[i])
// finalAve = result[i];
sumTotal += result[i];
finalAve = sumTotal /result.Length;
}
System.Console.WriteLine("The total sum of average is:
" + sumTotal);
System.Console.WriteLine("The average value is : " +
finalAve);
}

else
if (comm.Rank == 1)
{
int sum = 0;
int ave = 0;
int[] a = new int[30];
for (int i = 0; i < a.Length; i++)
{

//if (max < a[i])
//max = a[i];
sum += a[i];
ave = sum / a.Length;

}
//System.Console.WriteLine("Sum for Process 1 : " +
sum);
System.Console.WriteLine("Ave for Process 1 : " +
ave);
comm.Send(ave, 0, 96);
}

else
if (comm.Rank == 2)
{
int sum = 0;
int ave = 0;
int[] b = new int[30];
for (int i = 0; i < b.Length; i++)
{
//if (max < b[i])
//max = b[i];
sum += b[i];
ave = sum / b.Length;

}
// System.Console.WriteLine("Sum for Process 2:
" + sum);
System.Console.WriteLine("Ave for Process 2 : "
+ ave);
comm.Send(ave, 0, 95);
}
else
if (comm.Rank == 3)
{
int sum = 0;
int ave = 0;
int[] c = new int[30];
for (int i = 0; i < c.Length; i++)
{
//if (max < c[i])
//max = c[i];
sum += c[i];
ave = sum / c.Length;
}
//System.Console.WriteLine("Sum for Process
3: " + sum);
System.Console.WriteLine("Ave for Process
3: " + ave);
comm.Send(ave, 0, 94);
}

}

}
public static void PrintValues(int[] myArr, char mySeparator)
{
for (int i = 0; i < myArr.Length; i++)
Console.Write("{0}{1}", mySeparator, myArr[i]);
Console.WriteLine();
}

}

I hope that someone can help me to code in collective communication. I run
my program using Microsoft Visual Studio 2010 Professional.

Thank you and Regards,
Hanis Salwan Binti Mobidin