\documentclass[twocolumn]{article}
% \documentclass{article}

\setlength{\oddsidemargin}{-0.5in}
\setlength{\evensidemargin}{-0.5in}
\setlength{\topmargin}{0.0in}
\setlength{\headheight}{0in}
\setlength{\headsep}{0in}
\setlength{\textwidth}{7.0in}
\setlength{\textheight}{9.5in}
\setlength{\parindent}{0in}
\setlength{\parskip}{0.05in}
\setlength{\columnseprule}{0.3pt}

\setlength\columnsep{25pt}

\usepackage{fancyvrb}
\usepackage{relsize}
\usepackage{hyperref}

\usepackage{listings}
\usepackage{amsmath}

\begin{document}

\lstset{xleftmargin=5mm,framexleftmargin=10mm,basicstyle=\footnotesize}

Name: \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_

Directions: {\bf \Large Work only on this sheet} (on both sides, if
needed).  MAKE SURE TO COPY YOUR ANSWERS TO A SEPARATE SHEET FOR SENDING
ME AN ELECTRONIC COPY LATER.

{\bf Important note:}  Remember that in problems calling for R code, you
are allowed to use any built-in R function, e.g. {\bf choose()}, {\bf
sum()}, {\bf combn()} etc.  

{\bf 1.} (10) In a certain line in some MPI program, we wish to receive a
message from node 0, consisting of an array of 10000 integers, placing
it in {\bf y}.  The message type will be XTYPE.  We have declarations

\begin{lstlisting}
int *y; 
MPI_Status stat;
\end{lstlisting}

and have called {\bf malloc()}, assigning the result to {\bf y.}  Give
the call needed to receive the data.

{\bf 2.} A military commander in old Egypt, Amr ibn al-As, once wrote to
a Caliph Umar, ``I will send to Medina a camel train so long that the
first camel will reach you before the last one has left me.''  (True
story.) Fill in the blanks with terms from our course:

\begin{itemize}

\item [(a)] (10) An increase in camel walk speed would reduce the
\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_.

\item [(b)] (10) An increase in the time it takes to load a camel and
start it on its journey would reduce the 
\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_.

\end{itemize}

{\bf 3.} This problem concerns the function {\bf bsort()} in Section
1.3.2.6 of our book.

\begin{itemize}

\item [(a)] (10) Briefly---in just one line in your electronic Quiz
submission---discuss this algorithm in terms of the load balance
issue.

\item [(b)] (10) Give a single C statement, to go between lines 92 and
93, that will be executed by the last thread, that is, the thread with
the numerically largest thread number.  The code with print out the
index (i.e. subscript) within {\bf x} at which the chunk written by
thread 1 begins.  If for example thread 1 writes to {\bf x[12]} through
{\bf x[28]}, then 12 will be printed out.

\item [(c)] (10) Internally, the pragma on line 43 likely makes multiple
calls to which {\bf pthreads} function?

\end{itemize}

{\bf 4.} (40) This will be a variant of the matrix-multiply Snow code in
our text.  The two main differences are that (a) we send each worker
its assigned rows of the multiplier, rather than sending the full matrix
and assigned row numbers, and (b) the multiplier matrix is
upper-diagonal.

Concerning (a), say we have two workers and the multiplier has 6 rows.
Then in {\bf uv()}, {\bf uchunks[[1]]} will be the submatrix of {\bf u}
consisting of the first 3 rows of the latter.  Concerning (b), we want
to avoid wasteful multiplication by the 0s below the diagonal in {\bf
u}, but they are there, i.e. the matrix is not stored in compressed
form.

Fill in the blanks (only one line or partial line each):

\begin{lstlisting}
uv <- function(cls,u,v) {
   rownums <- splitIndices(nrow(u),length(cls))
   # tack on row numbers to u
   u1 <- cbind(u,1:nrow(u))  
   uchunks <- list()  
   for (i in 1:length(cls)) {
      uchunks[[i]] <- blank (a)
   }
   res <- clusterApply(cls,uchunks,chunkmul,v)
   Reduce(c,res)
}

chunkmul <- function(uchunk,v) {
   nr <- nrow(uchunk)
   nc <- ncol(uchunk)
   ncu <- nc - 1
   prod <- vector(length=nr)
   for (i in 1:nr) {
      urownum <- uchunk[i,nc]
      rng <- blank (b)
      prod[i] <- blank(c)
   }
   prod
}
\end{lstlisting}

\onecolumn

\newpage

{\bf Solutions:}

{\bf 1.}

\begin{lstlisting}
MPI_Recv(y,10000,MPI_INT,0,XTYPE,MPI_COMM_WORLD,&stat);
\end{lstlisting}

{\bf 2.a} latency

{\bf 2.b} bandwidth

{\bf 3.a} Load balance could be poor, say if the numbers are skewed
toward their lower range.

{\bf 3.b}

\begin{lstlisting}
if (me == nth-1) printf("%d\n",counts[0]);
\end{lstlisting}

{\bf 3.c}

\begin{lstlisting}
pthread_create()
\end{lstlisting}

{\bf 4.}

\begin{lstlisting}
uv <- function(cls,u,v) 
{ rownums <- splitIndices(nrow(u),length(cls))
   # tack on row numbers to U
   u1 <- cbind(u,1:nrow(u))  
   uchunks <- list()
   for (i in 1:length(cls)) {
      uchunks[[i]] <- u1[rownums[[i]],]
   }
   res <- clusterApply(cls,uchunks,chunkmul,v)
   Reduce(c,res)
}

chunkmul <- function(uchunk,v) {
   nr <- nrow(uchunk)
   nc <- ncol(uchunk)
   ncu <- nc - 1
   prod <- vector(length=nr)
   for (i in 1:nr) {
      urownum <- uchunk[i,nc]
      rng <- urownum:ncu
      prod[i] <- uchunk[i,rng] %*% v[rng]
   }
   prod
}
\end{lstlisting}

\end{document}

source("umul.R")

c2 <- makeCluster(2)

