379 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			379 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			C
		
	
	
	
| /*********************************************************************/
 | |
| /* Copyright 2009, 2010 The University of Texas at Austin.           */
 | |
| /* All rights reserved.                                              */
 | |
| /*                                                                   */
 | |
| /* Redistribution and use in source and binary forms, with or        */
 | |
| /* without modification, are permitted provided that the following   */
 | |
| /* conditions are met:                                               */
 | |
| /*                                                                   */
 | |
| /*   1. Redistributions of source code must retain the above         */
 | |
| /*      copyright notice, this list of conditions and the following  */
 | |
| /*      disclaimer.                                                  */
 | |
| /*                                                                   */
 | |
| /*   2. Redistributions in binary form must reproduce the above      */
 | |
| /*      copyright notice, this list of conditions and the following  */
 | |
| /*      disclaimer in the documentation and/or other materials       */
 | |
| /*      provided with the distribution.                              */
 | |
| /*                                                                   */
 | |
| /*    THIS  SOFTWARE IS PROVIDED  BY THE  UNIVERSITY OF  TEXAS AT    */
 | |
| /*    AUSTIN  ``AS IS''  AND ANY  EXPRESS OR  IMPLIED WARRANTIES,    */
 | |
| /*    INCLUDING, BUT  NOT LIMITED  TO, THE IMPLIED  WARRANTIES OF    */
 | |
| /*    MERCHANTABILITY  AND FITNESS FOR  A PARTICULAR  PURPOSE ARE    */
 | |
| /*    DISCLAIMED.  IN  NO EVENT SHALL THE UNIVERSITY  OF TEXAS AT    */
 | |
| /*    AUSTIN OR CONTRIBUTORS BE  LIABLE FOR ANY DIRECT, INDIRECT,    */
 | |
| /*    INCIDENTAL,  SPECIAL, EXEMPLARY,  OR  CONSEQUENTIAL DAMAGES    */
 | |
| /*    (INCLUDING, BUT  NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE    */
 | |
| /*    GOODS  OR  SERVICES; LOSS  OF  USE,  DATA,  OR PROFITS;  OR    */
 | |
| /*    BUSINESS INTERRUPTION) HOWEVER CAUSED  AND ON ANY THEORY OF    */
 | |
| /*    LIABILITY, WHETHER  IN CONTRACT, STRICT  LIABILITY, OR TORT    */
 | |
| /*    (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY WAY OUT    */
 | |
| /*    OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF ADVISED  OF  THE    */
 | |
| /*    POSSIBILITY OF SUCH DAMAGE.                                    */
 | |
| /*                                                                   */
 | |
| /* The views and conclusions contained in the software and           */
 | |
| /* documentation are those of the authors and should not be          */
 | |
| /* interpreted as representing official policies, either expressed   */
 | |
| /* or implied, of The University of Texas at Austin.                 */
 | |
| /*********************************************************************/
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include "common.h"
 | |
| #ifdef OS_LINUX
 | |
| #include <sys/sysinfo.h>
 | |
| #include <sched.h>
 | |
| #include <errno.h>
 | |
| #include <linux/unistd.h>
 | |
| #include <sys/syscall.h>
 | |
| #include <sys/time.h>
 | |
| #include <sys/resource.h>
 | |
| #endif
 | |
| 
 | |
| #ifdef OS_HAIKU
 | |
| #include <unistd.h>
 | |
| #endif
 | |
| 
 | |
| #if defined(OS_FREEBSD) || defined(OS_OPENBSD) || defined(OS_NETBSD) || defined(OS_DRAGONFLY) || defined(OS_DARWIN)
 | |
| #include <sys/sysctl.h>
 | |
| #include <sys/resource.h>
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #define FIXED_PAGESIZE 4096
 | |
| 
 | |
| 
 | |
| void *sa = NULL;
 | |
| void *sb = NULL;
 | |
| static double static_buffer[BUFFER_SIZE/sizeof(double)];
 | |
| 
 | |
| void *blas_memory_alloc(int numproc){
 | |
| 
 | |
|   if (sa == NULL){
 | |
| #if 0
 | |
|     sa = (void *)qalloc(QFAST, BUFFER_SIZE);
 | |
| #else
 | |
|     sa = (void *)malloc(BUFFER_SIZE);
 | |
| #endif
 | |
|     sb = (void *)&static_buffer[0];
 | |
|   }
 | |
| 
 | |
|   return sa;
 | |
| }
 | |
| 
 | |
| void blas_memory_free(void *free_area){
 | |
|   return;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| extern void openblas_warning(int verbose, const char * msg);
 | |
| 
 | |
| #ifndef SMP
 | |
| 
 | |
| #define blas_cpu_number 1
 | |
| #define blas_num_threads 1
 | |
| 
 | |
| /* Dummy Function */
 | |
| int  goto_get_num_procs  (void) { return 1;};
 | |
| void goto_set_num_threads(int num_threads) {};
 | |
| 
 | |
| #else
 | |
| 
 | |
| #if defined(OS_LINUX) || defined(OS_SUNOS)
 | |
| #ifndef NO_AFFINITY
 | |
| int get_num_procs(void);
 | |
| #else
 | |
| int get_num_procs(void) {
 | |
| 
 | |
|   static int nums = 0;
 | |
|   cpu_set_t cpuset,*cpusetp;
 | |
|   size_t size;
 | |
|   int ret;
 | |
| 
 | |
| #if defined(__GLIBC_PREREQ)
 | |
| #if !__GLIBC_PREREQ(2, 7)
 | |
|   int i;
 | |
| #if !__GLIBC_PREREQ(2, 6)
 | |
|   int n;
 | |
| #endif
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
|   if (!nums) nums = sysconf(_SC_NPROCESSORS_CONF);
 | |
| #if !defined(OS_LINUX)
 | |
|   return nums;
 | |
| #endif
 | |
| 
 | |
| /*
 | |
| #if !defined(__GLIBC_PREREQ)
 | |
|   return nums;
 | |
| #else
 | |
|  #if !__GLIBC_PREREQ(2, 3)
 | |
|   return nums;
 | |
|  #endif
 | |
| 
 | |
|  #if !__GLIBC_PREREQ(2, 7)
 | |
|   ret = sched_getaffinity(0,sizeof(cpuset), &cpuset);
 | |
|   if (ret!=0) return nums;
 | |
|   n=0;
 | |
|   #if !__GLIBC_PREREQ(2, 6)
 | |
|   for (i=0;i<nums;i++)
 | |
|      if (CPU_ISSET(i,&cpuset)) n++;
 | |
|   nums=n;
 | |
|   #else
 | |
|   nums = CPU_COUNT(sizeof(cpuset),&cpuset);
 | |
|   #endif
 | |
|   return nums;
 | |
|  #else
 | |
|   if (nums >= CPU_SETSIZE) {
 | |
|     cpusetp = CPU_ALLOC(nums);
 | |
|       if (cpusetp == NULL) {
 | |
|         return nums;
 | |
|       }
 | |
|     size = CPU_ALLOC_SIZE(nums);
 | |
|     ret = sched_getaffinity(0,size,cpusetp);
 | |
|     if (ret!=0) {
 | |
|       CPU_FREE(cpusetp);
 | |
|       return nums;
 | |
|     }
 | |
|     ret = CPU_COUNT_S(size,cpusetp);
 | |
|     if (ret > 0 && ret < nums) nums = ret;	
 | |
|     CPU_FREE(cpusetp);
 | |
|     return nums;
 | |
|   } else {
 | |
|     ret = sched_getaffinity(0,sizeof(cpuset),&cpuset);
 | |
|     if (ret!=0) {
 | |
|       return nums;
 | |
|     }
 | |
|     ret = CPU_COUNT(&cpuset);
 | |
|     if (ret > 0 && ret < nums) nums = ret;	
 | |
|     return nums;
 | |
|   }
 | |
|  #endif
 | |
| #endif
 | |
| */
 | |
|    return 1;
 | |
| }
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
| #ifdef OS_ANDROID
 | |
| int get_num_procs(void) {
 | |
|   static int nums = 0;
 | |
|   if (!nums) nums = sysconf(_SC_NPROCESSORS_CONF);
 | |
|   return nums;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #ifdef OS_HAIKU
 | |
| int get_num_procs(void) {
 | |
|   static int nums = 0;
 | |
|   if (!nums) nums = sysconf(_SC_NPROCESSORS_CONF);
 | |
|   return nums;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #ifdef OS_AIX
 | |
| int get_num_procs(void) {
 | |
|   static int nums = 0;
 | |
|   if (!nums) nums = sysconf(_SC_NPROCESSORS_CONF);
 | |
|   return nums;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #ifdef OS_WINDOWS
 | |
| 
 | |
| int get_num_procs(void) {
 | |
| 
 | |
|   static int nums = 0;
 | |
| 
 | |
|   if (nums == 0) {
 | |
| 
 | |
|     SYSTEM_INFO sysinfo;
 | |
| 
 | |
|     GetSystemInfo(&sysinfo);
 | |
| 
 | |
|     nums = sysinfo.dwNumberOfProcessors;
 | |
|   }
 | |
| 
 | |
|   return nums;
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| #if defined(OS_FREEBSD) || defined(OS_OPENBSD) || defined(OS_NETBSD) || defined(OS_DRAGONFLY)
 | |
| 
 | |
| int get_num_procs(void) {
 | |
| 
 | |
|   static int nums = 0;
 | |
| 
 | |
|   int m[2];
 | |
|   size_t len;
 | |
| 
 | |
|   if (nums == 0) {
 | |
|     m[0] = CTL_HW;
 | |
|     m[1] = HW_NCPU;
 | |
|     len = sizeof(int);
 | |
|     sysctl(m, 2, &nums, &len, NULL, 0);
 | |
|   }
 | |
| 
 | |
|   return nums;
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| #if defined(OS_DARWIN)
 | |
| int get_num_procs(void) {
 | |
|   static int nums = 0;
 | |
|   size_t len;
 | |
|   if (nums == 0){
 | |
|     len = sizeof(int);
 | |
|     sysctlbyname("hw.physicalcpu", &nums, &len, NULL, 0);
 | |
|   }
 | |
|   return nums;
 | |
| }
 | |
| /*
 | |
| void set_stack_limit(int limitMB){
 | |
|   int result=0;
 | |
|   struct rlimit rl;
 | |
|   rlim_t StackSize;
 | |
| 
 | |
|   StackSize=limitMB*1024*1024;
 | |
|   result=getrlimit(RLIMIT_STACK, &rl);
 | |
|   if(result==0){
 | |
|     if(rl.rlim_cur < StackSize){
 | |
|       rl.rlim_cur=StackSize;
 | |
|       result=setrlimit(RLIMIT_STACK, &rl);
 | |
|       if(result !=0){
 | |
|         fprintf(stderr, "OpenBLAS: set stack limit error =%d\n", result);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| */
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /*
 | |
| OpenBLAS uses the numbers of CPU cores in multithreading.
 | |
| It can be set by openblas_set_num_threads(int num_threads);
 | |
| */
 | |
| int blas_cpu_number  = 0;
 | |
| /*
 | |
| The numbers of threads in the thread pool.
 | |
| This value is equal or large than blas_cpu_number. This means some threads are sleep.
 | |
| */
 | |
| int blas_num_threads = 0;
 | |
| 
 | |
| int  goto_get_num_procs  (void) {
 | |
|   return blas_cpu_number;
 | |
| }
 | |
| 
 | |
| void openblas_fork_handler()
 | |
| {
 | |
|   // This handler shuts down the OpenBLAS-managed PTHREAD pool when OpenBLAS is
 | |
|   // built with "make USE_OPENMP=0".
 | |
|   // Hanging can still happen when OpenBLAS is built against the libgomp
 | |
|   // implementation of OpenMP. The problem is tracked at:
 | |
|   //   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60035
 | |
|   // In the mean time build with USE_OPENMP=0 or link against another
 | |
|   // implementation of OpenMP.
 | |
| #if !((defined(OS_WINDOWS) && !defined(OS_CYGWIN_NT)) || defined(OS_ANDROID)) && defined(SMP_SERVER)
 | |
|   int err;
 | |
|   err = pthread_atfork ((void (*)(void)) BLASFUNC(blas_thread_shutdown), NULL, NULL);
 | |
|   if(err != 0)
 | |
|     openblas_warning(0, "OpenBLAS Warning ... cannot install fork handler. You may meet hang after fork.\n");
 | |
| #endif
 | |
| }
 | |
| 
 | |
| extern int openblas_num_threads_env();
 | |
| extern int openblas_goto_num_threads_env();
 | |
| extern int openblas_omp_num_threads_env();
 | |
| 
 | |
| int blas_get_cpu_number(void){
 | |
| #if defined(OS_LINUX) || defined(OS_WINDOWS) || defined(OS_FREEBSD) || defined(OS_OPENBSD) || defined(OS_NETBSD) || defined(OS_DRAGONFLY) || defined(OS_DARWIN) || defined(OS_ANDROID)
 | |
|   int max_num;
 | |
| #endif
 | |
|   int blas_goto_num   = 0;
 | |
|   int blas_omp_num    = 0;
 | |
| 
 | |
|   if (blas_num_threads) return blas_num_threads;
 | |
| 
 | |
| #if defined(OS_LINUX) || defined(OS_WINDOWS) || defined(OS_FREEBSD) || defined(OS_OPENBSD) || defined(OS_NETBSD) || defined(OS_DRAGONFLY) || defined(OS_DARWIN) || defined(OS_ANDROID)
 | |
|   max_num = get_num_procs();
 | |
| #endif
 | |
| 
 | |
|   // blas_goto_num = 0;
 | |
| #ifndef USE_OPENMP
 | |
|   blas_goto_num=openblas_num_threads_env();
 | |
|   if (blas_goto_num < 0) blas_goto_num = 0;
 | |
| 
 | |
|   if (blas_goto_num == 0) {
 | |
|     blas_goto_num=openblas_goto_num_threads_env();
 | |
|     if (blas_goto_num < 0) blas_goto_num = 0;
 | |
|   }
 | |
| 
 | |
| #endif
 | |
| 
 | |
|   // blas_omp_num = 0;
 | |
|   blas_omp_num=openblas_omp_num_threads_env();
 | |
|   if (blas_omp_num < 0) blas_omp_num = 0;
 | |
| 
 | |
|   if (blas_goto_num > 0) blas_num_threads = blas_goto_num;
 | |
|   else if (blas_omp_num > 0) blas_num_threads = blas_omp_num;
 | |
|   else blas_num_threads = MAX_CPU_NUMBER;
 | |
| 
 | |
| #if defined(OS_LINUX) || defined(OS_WINDOWS) || defined(OS_FREEBSD) || defined(OS_OPENBSD) || defined(OS_NETBSD) || defined(OS_DRAGONFLY) || defined(OS_DARWIN) || defined(OS_ANDROID)
 | |
|   if (blas_num_threads > max_num) blas_num_threads = max_num;
 | |
| #endif
 | |
| 
 | |
|   if (blas_num_threads > MAX_CPU_NUMBER) blas_num_threads = MAX_CPU_NUMBER;
 | |
| 
 | |
| #ifdef DEBUG
 | |
|   printf( "Adjusted number of threads : %3d\n", blas_num_threads);
 | |
| #endif
 | |
| 
 | |
|   blas_cpu_number = blas_num_threads;
 | |
| 
 | |
|   return blas_num_threads;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| int openblas_get_num_procs(void) {
 | |
| #ifndef SMP
 | |
|   return 1;
 | |
| #else
 | |
|   return get_num_procs();
 | |
| #endif
 | |
| }
 | |
| 
 | |
| int openblas_get_num_threads(void) {
 | |
| #ifndef SMP
 | |
|   return 1;
 | |
| #else
 | |
|   // init blas_cpu_number if needed
 | |
|   blas_get_cpu_number();
 | |
|   return blas_cpu_number;
 | |
| #endif
 | |
| }
 |