home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume41 / parallel / part01 < prev    next >
Encoding:
Text File  |  1993-12-19  |  16.2 KB  |  487 lines

  1. Newsgroups: comp.sources.misc
  2. From: rlarkin@laurel.ocs.mq.edu.au (Rick Larkin)
  3. Subject: v41i049:  parallel - Parallelising routines, Part01/01
  4. Message-ID: <1993Dec19.220118.7050@sparky.sterling.com>
  5. X-Md4-Signature: 6b2a83eca73c642cd6bdab218b0a6792
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Macquarie University, Sydney Australia
  8. Date: Sun, 19 Dec 1993 22:01:18 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: rlarkin@laurel.ocs.mq.edu.au (Rick Larkin)
  12. Posting-number: Volume 41, Issue 49
  13. Archive-name: parallel/part01
  14. Environment: SunOS, MSDOS
  15.  
  16. Below are parallel.c, parallel.h and ptp.c.  They allow easy parallelisation 
  17. of loops on multiprocessor hardware.  Increases loop speed by up to 3 times 
  18. on a 4 processor SUN galaxy.
  19.  
  20. Works on SUNOS based SUNs and MSDOS PCs, don't know about any others.
  21. ----
  22. #! /bin/sh
  23. # This is a shell archive.  Remove anything before this line, then feed it
  24. # into a shell via "sh file" or similar.  To overwrite existing files,
  25. # type "sh file -c".
  26. # Contents:  Makefile parallel.c parallel.h ptp.c
  27. # Wrapped by kent@sparky on Sun Dec 19 15:55:57 1993
  28. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  29. echo If this archive is complete, you will see the following message:
  30. echo '          "shar: End of archive 1 (of 1)."'
  31. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  32.   echo shar: Will not clobber existing file \"'Makefile'\"
  33. else
  34.   echo shar: Extracting \"'Makefile'\" \(164 characters\)
  35.   sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  36. X#
  37. X#  Makefile file for parallel
  38. X#
  39. X#  Works on SUNOS based SUNs and MSDOS PCs, don't know about any others.
  40. X#
  41. X
  42. Xall: ptp
  43. X
  44. Xptp:
  45. X    gcc -o ptp ptp.c parallel.c -DSUN -lm
  46. END_OF_FILE
  47.   if test 164 -ne `wc -c <'Makefile'`; then
  48.     echo shar: \"'Makefile'\" unpacked with wrong size!
  49.   fi
  50.   # end of 'Makefile'
  51. fi
  52. if test -f 'parallel.c' -a "${1}" != "-c" ; then 
  53.   echo shar: Will not clobber existing file \"'parallel.c'\"
  54. else
  55.   echo shar: Extracting \"'parallel.c'\" \(6118 characters\)
  56.   sed "s/^X//" >'parallel.c' <<'END_OF_FILE'
  57. X/***************************************************************************
  58. X The following is...
  59. X      Copyright (C) 1993 by Macquarie University
  60. X      Released without ANY warranty to the public domain.
  61. X      Written by Richard Larkin. rlarkin@zen.efs.mq.edu.au
  62. X
  63. X      Thanks go to Mark Hahn for help with <sys/mman.h> functions.
  64. X
  65. X parallel.c - Code to achieve parallelism on multiprocessor architectures.
  66. X ***************************************************************************/
  67. X
  68. X#include "parallel.h"
  69. X
  70. X#ifndef MSDOS
  71. X
  72. X/***************************************************************************
  73. X Internally used structures.
  74. X ***************************************************************************/
  75. Xtypedef struct
  76. X{
  77. X  void *P;
  78. X  long int Size;
  79. X} PMAInfo;
  80. X
  81. X
  82. X/***************************************************************************
  83. X NumberProc number of processors available.
  84. X NumberProcUsed number of processors in use after last split.
  85. X ParentProcess true in the parent process.
  86. X ***************************************************************************/
  87. Xstatic long int NumberProc = 1;
  88. Xstatic long int NumberProcUsed = 1;
  89. Xstatic int ParentProcess = TRUE;
  90. X
  91. X
  92. X/***************************************************************************
  93. X Parallel memory details.
  94. X ***************************************************************************/
  95. Xstatic PMAInfo *PMA = NULL;
  96. Xstatic long int PMACnt = 0;
  97. X
  98. X
  99. X/***************************************************************************
  100. X ParallelProcessors tell parallel routines how many processors to assume.
  101. X Pre : none.
  102. X Post: Internal knowledge of number of processors set to maximum of N and 1.
  103. X ***************************************************************************/
  104. Xvoid ParallelProcessors(long int N)
  105. X{
  106. X  NumberProc = N < 1 ? 1 : N;
  107. X}
  108. X
  109. X
  110. X/***************************************************************************
  111. X ParallelSplit split into useful number of processes and return
  112. X interval of relevance to each process.
  113. X Calls to ParallelSplit cannot be nested.
  114. X Pre : Min, Max not NULL. NumberProcUsed == 1.
  115. X Post: NumberProcUsed is number of active processes.
  116. X       [Min..Max) will be interval of Range to use for each process.
  117. X ***************************************************************************/
  118. Xvoid ParallelSplit(long int Range, long int *Min, long int *Max)
  119. X{
  120. X  NumberProcUsed = Range < NumberProc ? Range : NumberProc;
  121. X
  122. X  /* Do we need to split?                                                  */
  123. X  if (NumberProcUsed > 1)
  124. X  {
  125. X    long int i;
  126. X
  127. X    /* Split into seperate processes.                                      */
  128. X    for (i = 0; i < NumberProcUsed - 1; i++)
  129. X      if (fork() == 0) break;                     /*ERROR fork() checks... */
  130. X
  131. X    /* Parent is only process that makes it through entire loop.           */
  132. X    ParentProcess = (i == NumberProcUsed-1);
  133. X
  134. X    /* Select the range for this process.                                  */
  135. X    *Min = i * (Range / NumberProcUsed);
  136. X    *Max = ParentProcess ? Range : (i+1) * (Range / NumberProcUsed);
  137. X  }
  138. X  else
  139. X  {
  140. X    /* Trivial range or number of processors.                              */
  141. X    *Min = 0; *Max = Range;
  142. X  }
  143. X}
  144. X
  145. X
  146. X/***************************************************************************
  147. X ParallelRegroup children all return to their parent who waits for them.
  148. X Pre : NumberProcUsed is number of active processes.
  149. X Post: One parent process. NumberProcUsed = 1;
  150. X ***************************************************************************/
  151. Xvoid ParallelRegroup(void)
  152. X{
  153. X  /* Nontrivial regroup?                                                   */
  154. X  if (NumberProcUsed > 1)
  155. X  {
  156. X    /* Children GO HOME!                                                   */
  157. X    if (!ParentProcess) exit(0);
  158. X
  159. X    /* Patient parent waits for children to arrive.                        */
  160. X    while (NumberProcUsed-- > 1) wait(NULL);
  161. X  }
  162. X}
  163. X
  164. X
  165. X/***************************************************************************
  166. X ParallelCalloc allocated a piece of memory to be globally accessible
  167. X throughout all processors.
  168. X Pre : none.
  169. X Post: Returns pointer to memory mapped parallel array file or
  170. X       in case of trivial processors returns normal Calloc result.
  171. X       Null returned on failure.
  172. X ***************************************************************************/
  173. Xvoid *ParallelCalloc(size_t nitems, size_t size)
  174. X{
  175. X  void *P;
  176. X
  177. X  if (NumberProc > 1)
  178. X  {
  179. X    PMA = Realloc(PMA, (PMACnt+1) * sizeof(PMA[0]));
  180. X    PMA[PMACnt].Size = nitems * size;
  181. X
  182. X    /* Set up the disk file to map into memory.                            */
  183. X    /* Map array and file together.                                        */
  184. X#ifdef SUN
  185. X    {
  186. X      int fd;
  187. X      if ((fd = open("/dev/zero", O_RDWR)) == -1) {/*ERROR*/};
  188. X
  189. X      P = mmap(0, PMA[PMACnt].Size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
  190. X      close(fd);      /*ERROR check P != -1 */
  191. X    }
  192. X#else
  193. X    P = mmap(0, PMA[PMACnt].Size, PROT_READ|PROT_WRITE, 
  194. X                MAP_SHARED|MAP_ANONYMOUS, fd, 0);
  195. X#endif
  196. X
  197. X    madvise(P, PMA[PMACnt].Size, MADV_WILLNEED);
  198. X
  199. X    /* Store so we can tidy up later.                                      */
  200. X    PMA[PMACnt].P = P;
  201. X    PMACnt++;
  202. X  }
  203. X  else
  204. X  {
  205. X    P = calloc(nitems, size);
  206. X  }
  207. X
  208. X  return P;
  209. X}
  210. X
  211. X/***************************************************************************
  212. X ParallelFree frees a piece of memory associated with a ParallelCalloc.
  213. X Pre : *P is pointer return from ParallelCalloc().
  214. X Post: Memory and possible file are freed.
  215. X ***************************************************************************/
  216. Xvoid _ParallelFree(void *P)
  217. X{
  218. X  if (NumberProc > 1 && P != NULL)
  219. X  {
  220. X    long int PMAi;
  221. X    int Last = TRUE;
  222. X
  223. X    for (PMAi = 0; PMAi < PMACnt; PMAi++)
  224. X    {
  225. X      if (PMA[PMAi].P == P)
  226. X      {
  227. X        munmap((caddr_t) P, PMA[PMAi].Size);
  228. X        PMA[PMAi].P = NULL;
  229. X      }
  230. X
  231. X      Last = Last && (PMA[PMAi].P == NULL);
  232. X    }
  233. X
  234. X    if (Last) {free(PMA); PMACnt = 0;}
  235. X  }
  236. X  else
  237. X    free(P);
  238. X}
  239. X
  240. X#endif 
  241. X
  242. X/***************************************************************************
  243. X End of parallel.c
  244. X ***************************************************************************/
  245. END_OF_FILE
  246.   if test 6118 -ne `wc -c <'parallel.c'`; then
  247.     echo shar: \"'parallel.c'\" unpacked with wrong size!
  248.   fi
  249.   # end of 'parallel.c'
  250. fi
  251. if test -f 'parallel.h' -a "${1}" != "-c" ; then 
  252.   echo shar: Will not clobber existing file \"'parallel.h'\"
  253. else
  254.   echo shar: Extracting \"'parallel.h'\" \(5398 characters\)
  255.   sed "s/^X//" >'parallel.h' <<'END_OF_FILE'
  256. X/***************************************************************************
  257. X The following is...
  258. X      Copyright (C) 1993 by Macquarie University
  259. X      Released without ANY warranty to the public domain.
  260. X      Written by Richard Larkin. rlarkin@zen.efs.mq.edu.au
  261. X
  262. X      Thanks go to Mark Hahn for help with <sys/mman.h> functions.
  263. X
  264. X parallel.h header for parallel.c
  265. X
  266. X Basic idea...
  267. X -------------
  268. X Somewhere call
  269. X ParallelProcessors(N)
  270. X with N the number of processors you have.
  271. X
  272. X For arrays that have to be globally written to within parallel loops,
  273. X use ParallelCalloc()/ParallelFree() instead of calloc()/free().
  274. X Also use for huge (non written) arrays to save on memory usage.
  275. X
  276. X For loops to parallelise of the form...
  277. X {Only nonrecurrent loops can be parallelised.}
  278. X        for (i = 0; i < MAXIMUM; i++) {do_somethings};
  279. X Change to...
  280. X        ParallelSplit(MAXIMUM, &min, &max);
  281. X        for (i = min; i < max; i++) {do_somethings};
  282. X        ParallelRegroup();
  283. X
  284. X NOTES: All variables that are not Parallelled,
  285. X        will be local to each processor.
  286. X
  287. X        Nested parallelising is not supported.
  288. X
  289. X        ParallelCalloc()/ParallelFree() should not be used within
  290. X        parallelled sections of code.
  291. X
  292. X Overheads: If do_somethings takes time enough to warrant being
  293. X            parallelised, the overheads are not worth mentioning.
  294. X
  295. X            Under MS-DOS the overhead is 2 redundant stores.
  296. X
  297. X            Any single processor machine will use normal calloc'ed
  298. X            memory and do approximately 4 simple conditional calculations
  299. X            and 2 redundant stores per Split/Regroup.
  300. X ***************************************************************************/
  301. X
  302. X#ifndef __PARALLEL_HEADER
  303. X#define __PARALLEL_HEADER
  304. X
  305. X#ifndef MSDOS
  306. X
  307. X#include <stddef.h>
  308. X#include <stdio.h>
  309. X#include <fcntl.h>
  310. X#include <sys/wait.h>
  311. X#include <sys/types.h>
  312. X#include <sys/mman.h>
  313. X
  314. X/* Until I find where they should be !!!! */
  315. X#define NULL  0
  316. X#define TRUE  (0==0)
  317. X#define FALSE (0!=0)
  318. X#define Realloc(P, s)  (P == NULL ? malloc((s)) : realloc((P), (size_t) (s)))
  319. Xint write(int fd, char *buf, int nbyte);
  320. Xint close (int fd);
  321. Xint fork(void);
  322. Xint munmap(caddr_t addr, int len);
  323. Xint madvise(caddr_t addr, size_t len, int advice);
  324. Xint unlink(char *path);
  325. Xvoid *malloc(size_t S);
  326. Xvoid *calloc(size_t N, size_t S);
  327. Xvoid *realloc(void *P, size_t S);
  328. X
  329. X/***************************************************************************
  330. X ParallelProcessors tell parallel routines how many processors to assume.
  331. X Pre : none.
  332. X Post: Internal knowledge of number of processors set to maximum of N and 1.
  333. X ***************************************************************************/
  334. Xvoid ParallelProcessors(long int N);
  335. X
  336. X
  337. X/***************************************************************************
  338. X ParallelSplit split into useful number of processes and return
  339. X interval of relevance to each process.
  340. X Calls to ParallelSplit cannot be nested.
  341. X Pre : Min, Max not NULL. NumberProcUsed == 1.
  342. X Post: NumberProcUsed is number of active processes.
  343. X       [Min..Max) will be interval of Range to use for each process.
  344. X ***************************************************************************/
  345. Xvoid ParallelSplit(long int Range, long int *Min, long int *Max);
  346. X
  347. X
  348. X/***************************************************************************
  349. X ParallelRegroup children all return to their parent who waits for them.
  350. X Pre : NumberProcUsed is number of active processes.
  351. X Post: One parent process. NumberProcUsed = 1;
  352. X ***************************************************************************/
  353. Xvoid ParallelRegroup(void);
  354. X
  355. X
  356. X/***************************************************************************
  357. X ParallelCalloc allocated a piece of memory to be globally accessible
  358. X throughout all processors.
  359. X Pre : none.
  360. X Post: Returns pointer to memory mapped parallel array file or
  361. X       in case of trivial processors returns normal Calloc result.
  362. X       Null returned on failure.
  363. X ***************************************************************************/
  364. Xvoid *ParallelCalloc(size_t nitems, size_t size);
  365. X
  366. X/***************************************************************************
  367. X ParallelFree frees a piece of memory associated with a ParallelCalloc.
  368. X Pre : P is pointer return from ParallelCalloc().
  369. X Post: Memory and possible file are freed.
  370. X ***************************************************************************/
  371. Xvoid _ParallelFree(void *P);
  372. X#define ParallelFree(P)           _ParallelFree((void *) P)
  373. X
  374. X#else
  375. X
  376. X/* Dummies for MSDOS                                                       */
  377. X#define ParallelProcessors(N)             {}
  378. X#define ParallelSplit(Range, Min, Max)    {*Min = 0; *Max = Range;}
  379. X#define ParallelRegroup()                 {}
  380. X#define ParallelCalloc(nitems, size)      calloc(nitems, size)
  381. X#define ParallelFree(P)                   free(P)
  382. X
  383. X#endif 
  384. X
  385. X/* Better access to parallel memory allocation.                            */
  386. X#define ParallelTypeMalloc(T, n)                                            \
  387. X          (T *) (ParallelCalloc((size_t)(n)*sizeof(T)), 1)
  388. X#define ParallelTypeCalloc(T, n)                                            \
  389. X          (T *) (ParallelCalloc((size_t)(n), sizeof(T)))
  390. X
  391. X#endif /* __PARALLEL_HEADER */
  392. X
  393. X/***************************************************************************
  394. X End of parallel.h
  395. X ***************************************************************************/
  396. END_OF_FILE
  397.   if test 5398 -ne `wc -c <'parallel.h'`; then
  398.     echo shar: \"'parallel.h'\" unpacked with wrong size!
  399.   fi
  400.   # end of 'parallel.h'
  401. fi
  402. if test -f 'ptp.c' -a "${1}" != "-c" ; then 
  403.   echo shar: Will not clobber existing file \"'ptp.c'\"
  404. else
  405.   echo shar: Extracting \"'ptp.c'\" \(1397 characters\)
  406.   sed "s/^X//" >'ptp.c' <<'END_OF_FILE'
  407. X/*
  408. X    ptp.c Parallel Test Program 
  409. X    (C) 1993 Macquarie University
  410. X    Released without ANY warranty to the public domain.
  411. X    Written by Richard Larkin. rlarkin@zen.efs.mq.edu.au
  412. X
  413. X    Demonstration of pseudo(?) parallel processing.
  414. X
  415. X    Calculates a total using however many processes are requested
  416. X    on the command line.
  417. X
  418. X    e.g
  419. X
  420. X    ptp, ptp 0    Crash and dump core.
  421. X    ptp 1        Use a single process.
  422. X            Does not use mapped file.
  423. X    ptp 2        2 processes used. This may make use of
  424. X            2 processors as well if the machine is parallel.
  425. X    ptp 128        Wish I had that many processors.
  426. X
  427. X    To compile...
  428. X            gcc -o ptp ptp.c parallel.c -DSUN -lm
  429. X
  430. X    Portability...
  431. X    Works on SUNOS based SUNs and MSDOS PCs, don't know about any others.
  432. X*/
  433. X
  434. X#include "parallel.h"
  435. X
  436. X#define ARRAYSIZE     80000
  437. X
  438. Xvoid main(int argc, char *argv[])
  439. X{
  440. X  long int i, Min, Max;
  441. X  float *t, s;
  442. X
  443. X  ParallelProcessors(atol(argv[1]));            
  444. X
  445. X  t = ParallelTypeCalloc(float, ARRAYSIZE);    
  446. X
  447. X  ParallelSplit(ARRAYSIZE, &Min, &Max);    
  448. X  puts("Processing");
  449. X  for (i = Min; i < Max; i++)
  450. X  {
  451. X    /* Nonsense calculation.                                               */
  452. X    s = (float) i / 10000.0 + 1.0;
  453. X    t[i] = log(abs(log((double) s) * log((double) s * s) + 1.0)) * 
  454. X           log(abs(log((double) s + 1.0) * log((double) s * s + 1.0) + 2.0));
  455. X  }
  456. X  ParallelRegroup();
  457. X
  458. X  for (i = 0, s = 0.0; i < ARRAYSIZE; s+=t[i++]);
  459. X  printf("Total is %f\n", s);
  460. X
  461. X  ParallelFree(t);
  462. X}
  463. X
  464. END_OF_FILE
  465.   if test 1397 -ne `wc -c <'ptp.c'`; then
  466.     echo shar: \"'ptp.c'\" unpacked with wrong size!
  467.   fi
  468.   # end of 'ptp.c'
  469. fi
  470. echo shar: End of archive 1 \(of 1\).
  471. cp /dev/null ark1isdone
  472. MISSING=""
  473. for I in 1 ; do
  474.     if test ! -f ark${I}isdone ; then
  475.     MISSING="${MISSING} ${I}"
  476.     fi
  477. done
  478. if test "${MISSING}" = "" ; then
  479.     echo You have the archive.
  480.     rm -f ark[1-9]isdone
  481. else
  482.     echo You still must unpack the following archives:
  483.     echo "        " ${MISSING}
  484. fi
  485. exit 0
  486. exit 0 # Just in case...
  487.