Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "cmtkThreads.h"
00034
00035
00036 #ifdef __APPLE__
00037 #include <sys/sysctl.h>
00038 #endif
00039
00040 #ifdef HAVE_UNISTD_H
00041 # include <unistd.h>
00042 #endif
00043
00044 #ifdef CMTK_USE_THREADS
00045 # include <pthread.h>
00046 # include <errno.h>
00047 #endif
00048
00049 #ifdef _OPENMP
00050 # include <omp.h>
00051 #endif // _OPENMP
00052
00053 #include <limits.h>
00054 #include <stdlib.h>
00055 #include <iostream>
00056
00057 #include <algorithm>
00058
00059 #ifndef _SC_NPROCESSORS_ONLN
00060 # ifdef _SC_NPROC_ONLN
00061 # define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN
00062 # endif
00063 #endif
00064
00065 #include <System/cmtkConsole.h>
00066
00067 namespace
00068 cmtk
00069 {
00070
00073
00074 int Threads::NumberOfThreads = 0;
00075
00076 int
00077 Threads::GetNumberOfThreads()
00078 {
00079 if ( !Threads::NumberOfThreads )
00080 Threads::CheckEnvironment();
00081
00082 if ( Threads::NumberOfThreads )
00083 {
00084 return Threads::NumberOfThreads;
00085 }
00086 else
00087 {
00088 return std::min( Threads::GetNumberOfProcessors(), Threads::GetMaxThreads() );
00089 }
00090 }
00091
00092 bool
00093 Threads::Available()
00094 {
00095 #ifndef CMTK_BUILD_SMP
00096
00097 return false;
00098 #else
00099
00100 #ifdef _MSC_VER
00101
00102 return true;
00103 #elif defined (__APPLE__)
00104
00105
00106
00107 #ifdef _POSIX_THREADS
00108 return true;
00109 #else
00110 return false;
00111 #endif
00112 #else
00113 return (sysconf(_SC_THREADS) == -1);
00114 #endif
00115 #endif
00116 }
00117
00118
00119 int
00120 Threads
00121 ::SetNumberOfThreads
00122 ( const int numberOfThreads, const bool force )
00123 {
00124 if ( numberOfThreads )
00125 {
00126 if ( force )
00127 {
00128 NumberOfThreads = std::min( numberOfThreads, Threads::GetMaxThreads() );
00129 }
00130 else
00131 {
00132 NumberOfThreads = std::min( numberOfThreads, Threads::GetNumberOfProcessors() );
00133 }
00134 }
00135 else
00136 NumberOfThreads = std::min( Threads::GetNumberOfProcessors(), Threads::GetMaxThreads() );
00137
00138 #ifdef _OPENMP
00139 omp_set_num_threads( NumberOfThreads );
00140 #endif
00141
00142 return NumberOfThreads;
00143 }
00144
00145 int
00146 Threads::GetMaxThreads()
00147 {
00148 #ifdef _MSC_VER
00149 return CMTK_MAX_THREADS;
00150 # elif defined(_POSIX_THREAD_THREADS_MAX)
00151 return _POSIX_THREAD_THREADS_MAX;
00152 # elif defined(PTHREAD_THREADS_MAX)
00153 return PTHREAD_THREADS_MAX;
00154
00155
00156
00157 #elif defined(__APPLE__) && defined(CMTK_USE_THREADS)
00158 return std::min( CMTK_MAX_THREADS, CMTK_MAX_THREADS );
00159 # elif defined(CMTK_USE_THREADS)
00160 const long sysconfNumThreads = sysconf( _SC_THREAD_THREADS_MAX );
00161 if ( sysconfNumThreads == -1 )
00162 return CMTK_MAX_THREADS;
00163 else
00164 return std::min( (int)sysconfNumThreads, CMTK_MAX_THREADS );
00165 # else
00166 return 1;
00167 # endif
00168 }
00169
00170 int
00171 Threads::GetNumberOfProcessors()
00172 {
00173 #ifdef _MSC_VER
00174 SYSTEM_INFO systemInfo;
00175 GetSystemInfo( &systemInfo );
00176 return std::min<int>( systemInfo.dwNumberOfProcessors, CMTK_MAX_THREADS );
00177 #elif defined(__APPLE__)
00178
00179
00180 char *name="hw.activecpu";
00181 int nproc; size_t len=4;
00182 sysctlbyname(name, &nproc, &len, NULL, 0);
00183 return nproc;
00184 #elif defined(CMTK_USE_THREADS)
00185 return sysconf( _SC_NPROCESSORS_ONLN );
00186 #else
00187 return 1;
00188 #endif
00189 }
00190
00191 void
00192 Threads::RunThreads
00193 ( ThreadFunction threadCall, const unsigned numberOfThreads, void *const parameters, const size_t parameterSize )
00194 {
00195 #ifdef _OPENMP
00196 const int nThreadsOMP = std::max<int>( 1, 1+GetNumberOfThreads()-numberOfThreads );
00197 omp_set_num_threads( nThreadsOMP );
00198 #endif
00199
00200 #ifdef CMTK_BUILD_SMP
00201 ThreadIDType Thread[CMTK_MAX_THREADS];
00202 #ifdef _MSC_VER
00203 HANDLE ThreadHandles[CMTK_MAX_THREADS];
00204 #endif
00205 #endif
00206
00207 #ifdef CMTK_USE_THREADS
00208 pthread_attr_t attr;
00209 pthread_attr_init(&attr);
00210 pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
00211 #endif
00212
00213 for ( unsigned threadIdx = 1; threadIdx < numberOfThreads; ++threadIdx )
00214 {
00215 void *threadParameters = ((char*) parameters) + threadIdx * parameterSize;
00216
00217
00218 int status = 0;
00219
00220
00221
00222
00223 #ifdef CMTK_BUILD_SMP
00224 #ifdef _MSC_VER
00225 ThreadHandles[threadIdx] = CreateThread( NULL , 0, (LPTHREAD_START_ROUTINE) threadCall, threadParameters, 0, &Thread[threadIdx] );
00226 if ( ThreadHandles[threadIdx] == NULL )
00227 {
00228 status = -1;
00229 }
00230 #else // _MSC_VER
00231 status = pthread_create( &Thread[threadIdx], &attr, threadCall, threadParameters );
00232 #endif // _MSC_VER
00233 #else
00234
00235 threadCall( threadParameters );
00236
00237 #endif
00238
00239 if ( status )
00240 {
00241 fprintf( stderr, "Creation of thread #%d failed with status %d.\n", threadIdx, status );
00242 #if defined(CMTK_BUILD_SMP) && defined(CMTK_USE_THREADS)
00243 Thread[threadIdx] = 0;
00244 #endif
00245 threadCall( threadParameters );
00246 }
00247 }
00248
00249
00250 threadCall( parameters );
00251
00252
00253
00254
00255
00256
00257 for ( int threadIdx = numberOfThreads-1; threadIdx; --threadIdx )
00258 {
00259 #ifdef CMTK_BUILD_SMP
00260 # ifdef _MSC_VER
00261 WaitForSingleObject( ThreadHandles[threadIdx], INFINITE );
00262 # else // _MSC_VER
00263 void *resultThread;
00264 if ( Thread[threadIdx] )
00265 {
00266 pthread_join( Thread[threadIdx], &resultThread );
00267 }
00268 # endif // _MSC_VER
00269 #endif
00270 }
00271
00272 #ifdef CMTK_BUILD_SMP
00273 #ifndef _MSC_VER
00274 pthread_attr_destroy(&attr);
00275 #endif
00276 #endif
00277
00278 #ifdef _OPENMP
00279 omp_set_num_threads( GetNumberOfThreads() );
00280 #endif
00281 }
00282
00283 void
00284 Threads::CheckEnvironment()
00285 {
00286 const char *env = getenv( "CMTK_NUM_THREADS" );
00287
00288 if ( ! env )
00289 env = getenv( "IGS_NUM_THREADS" );
00290
00291 if ( env )
00292 {
00293 const int numThreads = atoi( env );
00294 if ( numThreads )
00295 {
00296 SetNumberOfThreads( numThreads );
00297
00298 std::cerr << "INFO: number of threads set to " << numThreads << " according to environment variable CMTK_NUM_THREADS\n";
00299 }
00300 else
00301 {
00302
00303 std::cerr << "WARNING: environment variable CMTK_NUM_THREADS is set but does not seem to contain a number larger than 0.\n";
00304 }
00305 }
00306 }
00307
00308
00310
00311 }