BRL-CAD
many.c
Go to the documentation of this file.
1 /* M A N Y . C
2  * BRL-CAD
3  *
4  * Copyright (c) 1999-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @addtogroup librt */
21 /** @{ */
22 /** @file librt/many.c
23  *
24  * Wrapper routines to help fire multiple rays in parallel, without
25  * exposing the caller to the details of running in parallel.
26  *
27  */
28 /** @} */
29 
30 #include "common.h"
31 
32 #include <math.h>
33 #include "bio.h"
34 
35 
36 #include "bu/parallel.h"
37 #include "vmath.h"
38 #include "bn.h"
39 #include "raytrace.h"
40 
41 
42 /* For communication between interface routine and each of the threads */
44  uint32_t magic;
45  long cur_index; /* semaphored */
46  long max_index;
47  const struct application *proto_ap;
49  int (*callback)(struct application *, int index);
51  int sem_chunk;
52 };
53 #define RT_MANY_INTERNAL_MAGIC 0x526d6970 /* Rmip */
54 #define RT_CK_RMI(_p) BU_CKMAG(_p, RT_MANY_INTERNAL_MAGIC, "rt_many_internal")
55 
56 /**
57  * Internal helper routine for rt_shoot_many_rays().
58  *
59  * Runs in PARALLEL, one instance per thread.
60  *
61  * In order to reduce the traffic through the critical section, a
62  * multiple pixel block may be removed from the work queue at once.
63  */
64 void
65 rt_shoot_many_rays_worker(int cpu, void *arg)
66 {
67  struct application app;
68  struct rt_many_internal *rmip = (struct rt_many_internal *)arg;
69 
70  if (cpu >= MAX_PSW) {
71  bu_log("rt_shoot_many_rays_worker() cpu %d > MAX_PSW %d, array overrun\n", cpu, MAX_PSW);
72  bu_bomb("rt_shoot_many_rays_worker() cpu > MAX_PSW, array overrun\n");
73  }
74 
75  RT_CK_RMI(rmip);
76  RT_CK_RESOURCE(&rmip->resources[cpu]);
78 
79  app = *rmip->proto_ap; /* struct copy */
80  app.a_resource = &rmip->resources[cpu];
81 
82  while (1) {
83  register long index;
84  register long lim;
85 
86  if (rmip->stop_worker) break;
87 
89  index = rmip->cur_index;
90  rmip->cur_index += rmip->sem_chunk;
92 
93  lim = index + rmip->sem_chunk;
94  for (; index < lim; index++) {
95  if (index >= rmip->max_index) return;
96 
97  /*
98  * a_x is set here to get differentiated LIBRT debugging
99  * messages even from a trivial callback. The callback
100  * may, of course, override it.
101  */
102  app.a_x = index;
103 
104  /* Allow our user to do per-ray init of application struct */
105  if ((*rmip->callback)(&app, index) < 0) {
106  rmip->stop_worker = 1;
107  break;
108  }
109 
110  (void)rt_shootray(&app);
111  }
112  }
113 }
114 
115 
116 /**
117  * A convenience routine for application developers who wish to fire a
118  * large but fixed number of rays in parallel, without wanting to
119  * create a parallel "self dispatcher" routine of their own.
120  *
121  * Basic setup of the application structure is done by the caller, and
122  * provided via the proto_ap pointer.
123  *
124  * Per-ray setup of the application structure is done by the callback
125  * routine, which takes an index in the range 0..(nrays-1) and uses
126  * that to fill in each specific instance of application structure as
127  * required.
128  *
129  * The a_hit() and a_miss() routines must save any results; their
130  * formal return codes, and the return code from rt_shootray(), are
131  * ignored.
132  *
133  * a_x is changed by this wrapper, and may be overridden by the
134  * callback.
135  *
136  * Note that the cost of spawning threads is sufficiently expensive
137  * that 'nrays' should be at least dozens or hundreds to get a real
138  * benefit from parallelism.
139  *
140  * Return codes expected from the callback() -
141  * -1 End processing before all nrays have been fired.
142  * 0 Normal return, proceed with firing the ray.
143  *
144  * Note that bu_parallel() is not re-entrant, so you can't have an
145  * a_hit() routine which is already running in parallel call into this
146  * routine and expect to get even more parallelism. This is not a
147  * limitation, as you usually can't construct more CPUs.
148  *
149  * resources[ncpus]
150  */
151 void
152 rt_shoot_many_rays(const struct application *proto_ap, int (*callback) (struct application *, int), int ncpus, long int nrays, struct resource *resources)
153 {
154  struct rt_many_internal rmi;
155  int i;
156 
157  RT_CK_APPLICATION(proto_ap);
158  for (i=0; i < ncpus; i++) {
159  RT_CK_RESOURCE(&resources[i]);
160  }
161  rmi.resources = resources;
162 
164  rmi.stop_worker = 0;
165  rmi.cur_index = 0;
166  rmi.max_index = nrays;
167  rmi.proto_ap = proto_ap;
168  rmi.callback = callback;
169  rmi.sem_chunk = ncpus;
170 
171  if (!RTG.rtg_parallel || ncpus <= 1) {
172  /* The 1-cpu case is supported for testing & generality. */
173  rt_shoot_many_rays_worker(0, (void *)&rmi);
174  } else {
175  bu_parallel(rt_shoot_many_rays_worker, ncpus, (void *)&rmi);
176  }
177 }
178 
179 
180 /*
181  * Local Variables:
182  * mode: C
183  * tab-width: 8
184  * indent-tabs-mode: t
185  * c-file-style: "stroustrup"
186  * End:
187  * ex: shiftwidth=4 tabstop=8
188  */
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
struct resource * resources
Definition: many.c:48
#define RT_CK_APPLICATION(_p)
Definition: raytrace.h:1675
#define RT_CK_RMI(_p)
Definition: many.c:54
int stop_worker
Definition: many.c:50
long cur_index
Definition: many.c:45
void bu_semaphore_acquire(unsigned int i)
Definition: semaphore.c:180
int8_t rtg_parallel
!0 = trying to use multi CPUs
Definition: raytrace.h:1697
Header file for the BRL-CAD common definitions.
struct resource * a_resource
dynamic memory resources
Definition: raytrace.h:1591
int(* callback)(struct application *, int index)
Definition: many.c:49
#define RT_MANY_INTERNAL_MAGIC
Definition: many.c:53
int sem_chunk
Definition: many.c:51
int a_x
Screen X of ray, if applicable.
Definition: raytrace.h:1596
void rt_shoot_many_rays_worker(int cpu, void *arg)
Definition: many.c:65
const struct application * proto_ap
Definition: many.c:47
void bu_semaphore_release(unsigned int i)
Definition: semaphore.c:218
#define MAX_PSW
Definition: parallel.h:48
void bu_parallel(void(*func)(int func_ncpu, void *func_data), int ncpu, void *data)
#define RT_SEM_WORKER
Definition: raytrace.h:1730
#define RT_CK_RESOURCE(_p)
Definition: raytrace.h:1490
long max_index
Definition: many.c:46
int rt_shootray(struct application *ap)
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91
void rt_shoot_many_rays(const struct application *proto_ap, int(*callback)(struct application *, int), int ncpus, long int nrays, struct resource *resources)
Definition: many.c:152
uint32_t magic
Definition: many.c:44
struct rt_g RTG
Definition: globals.c:39