1 /*************************************************************************
2  *                                                                       *
3  * Vega FEM Simulation Library Version 3.1                               *
4  *                                                                       *
5  * "distance field" library , Copyright (C) 2007 CMU, 2016 USC           *
6  * All rights reserved.                                                  *
7  *                                                                       *
8  * Code author: Jernej Barbic                                            *
9  * http://www.jernejbarbic.com/code                                      *
10  *                                                                       *
11  * Research: Jernej Barbic, Hongyi Xu, Doug L. James                     *
12  *                                                                       *
13  * Funding: National Science Foundation, Link Foundation,                *
14  *          Zumberge Research and Innovation Fund at USC                 *
15  *                                                                       *
16  * This library is free software; you can redistribute it and/or         *
17  * modify it under the terms of the BSD-style license that is            *
18  * included with this library in the file LICENSE.txt                    *
19  *                                                                       *
20  * This library is distributed in the hope that it will be useful,       *
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file     *
23  * LICENSE.TXT for more details.                                         *
24  *                                                                       *
25  *************************************************************************/
26 
27 /*
28   Multithreaded computation of the distance field. Main computational routines.
29 */
30 
31 #ifdef COMPUTE_SIGNED_FIELD
32   #ifdef COMPUTE_FLOOD_FIELD
33     #define COMPUTEFIELDMT_CLASSNAME DistanceFieldMT
34     #define COMPUTEFIELDMT_STRUCTNAME DistanceFieldMT_signed_flood_struct
35     #define COMPUTEFIELDMT_WORKERTHREADNAME DistanceFieldMT_signed_flood_WorkerThread
36     #define ZIGZAGROUTINE DistanceField::ZigZagFloodFillSigned
37   #else
38     #ifdef COMPUTE_CLOSEST_POINT
39       #define COMPUTEFIELDMT_CLASSNAME ClosestPointFieldMT
40       #define COMPUTEFIELDMT_STRUCTNAME ClosestPointFieldMT_signed_struct
41       #define COMPUTEFIELDMT_WORKERTHREADNAME ClosestPointFieldMT_signed_WorkerThread
42       #define ZIGZAGROUTINE ClosestPointField::ZigZagSigned
43     #else
44       #define COMPUTEFIELDMT_CLASSNAME DistanceFieldMT
45       #define COMPUTEFIELDMT_STRUCTNAME DistanceFieldMT_signed_struct
46       #define COMPUTEFIELDMT_WORKERTHREADNAME DistanceFieldMT_signed_WorkerThread
47       #define ZIGZAGROUTINE DistanceField::ZigZagSigned
48     #endif
49   #endif
50 #else
51   #ifdef COMPUTE_CLOSEST_POINT
52     #define COMPUTEFIELDMT_CLASSNAME ClosestPointFieldMT
53     #define COMPUTEFIELDMT_STRUCTNAME ClosestPointFieldMT_unsigned_struct
54     #define COMPUTEFIELDMT_WORKERTHREADNAME ClosestPointFieldMT_unsigned_WorkerThread
55     #define ZIGZAGROUTINE ClosestPointField::ZigZagUnsigned
56   #else
57     #define COMPUTEFIELDMT_CLASSNAME DistanceFieldMT
58     #define COMPUTEFIELDMT_STRUCTNAME DistanceFieldMT_unsigned_struct
59     #define COMPUTEFIELDMT_WORKERTHREADNAME DistanceFieldFieldMT_unsigned_WorkerThread
60     #define ZIGZAGROUTINE DistanceField::ZigZagUnsigned
61   #endif
62 #endif
63 
64 //#define USE_MULTICORE_LIBRARY
65 #ifdef USE_MULTICORE_LIBRARY
66   #include "multicore.h"
67 #endif
68 
69 struct COMPUTEFIELDMT_STRUCTNAME
70 {
71   COMPUTEFIELDMT_CLASSNAME * object;
72   void * objMeshOctree;
73   void * meshGraph;
74   int rank;
75   int startSlice;
76   int endSlice;
77 };
78 
COMPUTEFIELDMT_WORKERTHREADNAME(void * arg)79 void * COMPUTEFIELDMT_WORKERTHREADNAME(void * arg)
80 {
81   struct COMPUTEFIELDMT_STRUCTNAME * threadArgp = (struct COMPUTEFIELDMT_STRUCTNAME*) arg;
82   COMPUTEFIELDMT_CLASSNAME * object = threadArgp->object;
83   void * objMeshOctree = threadArgp->objMeshOctree;
84   void * meshGraph = threadArgp->meshGraph;
85   int rank = threadArgp->rank;
86   //int startSlice = object->GetStartSlice(rank);
87   //int endSlice = object->GetEndSlice(rank);
88   int startSlice = threadArgp->startSlice;
89   int endSlice = threadArgp->endSlice;
90   //printf("rank: %d startSlice: %d endSlice: %d\n", rank, startSlice, endSlice);
91 
92   int asterisk=0;
93   if (rank == 0)
94     asterisk = 1;
95 
96   object->ZIGZAGROUTINE(objMeshOctree, meshGraph, startSlice, endSlice-1, asterisk);
97 
98   return NULL;
99 }
100 
101 #ifdef COMPUTE_SIGNED_FIELD
102   #ifdef COMPUTE_CLOSEST_POINT
ZigZagSigned(void * objMeshOctree_,void * meshGraph_)103     int ClosestPointFieldMT::ZigZagSigned(void * objMeshOctree_, void * meshGraph_)
104   #else
105     #ifdef COMPUTE_FLOOD_FIELD
106       int DistanceFieldMT::ZigZagFloodFillSigned(void * objMeshOctree_, void * meshGraph_)
107     #else
108       int DistanceFieldMT::ZigZagSigned(void * objMeshOctree_, void * meshGraph_)
109     #endif
110   #endif
111 #else
112   #ifdef COMPUTE_CLOSEST_POINT
113     int ClosestPointFieldMT::ZigZagUnsigned(void * objMeshOctree_, void * meshGraph_)
114   #else
115     int DistanceFieldMT::ZigZagUnsigned(void * objMeshOctree_, void * meshGraph_)
116   #endif
117 #endif
118 {
119   Setup();
120 
121   struct COMPUTEFIELDMT_STRUCTNAME * threadArgv = (struct COMPUTEFIELDMT_STRUCTNAME*) malloc (sizeof(struct COMPUTEFIELDMT_STRUCTNAME) * numThreads);
122 
123   for(int i=0; i<numThreads; i++)
124   {
125     threadArgv[i].object = this;
126     threadArgv[i].objMeshOctree = objMeshOctree_;
127     threadArgv[i].meshGraph = meshGraph_;
128     threadArgv[i].rank = i;
129     threadArgv[i].startSlice = GetStartSlice(i);
130     threadArgv[i].endSlice = GetEndSlice(i);
131   }
132 
133   #ifdef USE_MULTICORE_LIBRARY
134     Multicore * multicore = new Multicore(numThreads);
135     for(int i=0; i<numThreads; i++)
136     {
137       multicore->SetThreadTask(i, COMPUTEFIELDMT_WORKERTHREADNAME);
138       multicore->SetThreadTaskParameter(i, &threadArgv[i]);
139     }
140 
141     //assigns equal z-range to every thread (weakness: can be non-even computational load)
142     //multicore->LaunchThreads(0, numThreads);
143 
144     int zSlice = zMin;
145     while (zSlice <= zMax)
146     {
147       int availableThread;
148       multicore->WaitForAvailableThread(&availableThread);
149       threadArgv[availableThread].startSlice = zSlice;
150       threadArgv[availableThread].endSlice = zSlice + 1;
151       multicore->LaunchThread(availableThread);
152       zSlice++;
153     }
154 
155     multicore->WaitForCompletionOfAllThreads();
156 
157     delete(multicore);
158   #else
159     printf("Launching %d threads...\n", numThreads);
160     pthread_t * tid = (pthread_t*) malloc (sizeof(pthread_t) * numThreads);
161     for(int i=0; i<numThreads; i++)
162     {
163       if (pthread_create(&tid[i], NULL, COMPUTEFIELDMT_WORKERTHREADNAME, &threadArgv[i]) != 0)
164       {
165         printf("Error: unable to launch thread %d.\n", i);
166         exit(1);
167       }
168     }
169 
170     for(int i=0; i<numThreads; i++)
171     {
172       if (pthread_join(tid[i], NULL) != 0)
173       {
174         printf("Error: unable to join thread %d.\n", i);
175         free(threadArgv);
176         free(tid);
177         free(startSlice);
178         free(endSlice);
179         return 1;
180       }
181     }
182     free(tid);
183   #endif
184 
185   free(threadArgv);
186   free(startSlice);
187   free(endSlice);
188 
189   return 0;
190 }
191 
192 #undef ZIGZAGROUTINE
193 #undef COMPUTEFIELDMT_CLASSNAME
194 #undef COMPUTEFIELDMT_STRUCTNAME
195 #undef COMPUTEFIELDMT_WORKERTHREADNAME
196 
197