SHOGUN v0.9.0
|
00001 /* 00002 * This program is free software; you can redistribute it and/or modify 00003 * it under the terms of the GNU General Public License as published by 00004 * the Free Software Foundation; either version 3 of the License, or 00005 * (at your option) any later version. 00006 * 00007 * Written (W) 1999-2009 Christian Gehl 00008 * Copyright (C) 1999-2009 Fraunhofer Institute FIRST 00009 */ 00010 00011 #include "classifier/DistanceMachine.h" 00012 00013 using namespace shogun; 00014 00015 #ifndef DOXYGEN_SHOULD_SKIP_THIS 00016 struct D_THREAD_PARAM 00017 { 00018 CDistance* d; 00019 float64_t* r; 00020 int32_t idx_r_start; 00021 int32_t idx_start; 00022 int32_t idx_stop; 00023 int32_t idx_comp; 00024 }; 00025 #endif // DOXYGEN_SHOULD_SKIP_THIS 00026 00027 CDistanceMachine::CDistanceMachine() 00028 : CClassifier(), distance(NULL) 00029 { 00030 } 00031 00032 CDistanceMachine::~CDistanceMachine() 00033 { 00034 SG_UNREF(distance); 00035 } 00036 00037 void CDistanceMachine::distances_lhs(float64_t* result,int32_t idx_a1,int32_t idx_a2,int32_t idx_b) 00038 { 00039 int32_t num_threads=parallel->get_num_threads(); 00040 ASSERT(num_threads>0); 00041 00042 ASSERT(result); 00043 00044 if (num_threads < 2) 00045 { 00046 D_THREAD_PARAM param; 00047 param.d=distance; 00048 param.r=result; 00049 param.idx_r_start=idx_a1; 00050 param.idx_start=idx_a1; 00051 param.idx_stop=idx_a2+1; 00052 param.idx_comp=idx_b; 00053 00054 run_distance_thread_lhs((void*) ¶m); 00055 } 00056 #ifndef WIN32 00057 else 00058 { 00059 pthread_t* threads = new pthread_t[num_threads-1]; 00060 D_THREAD_PARAM* params = new D_THREAD_PARAM[num_threads]; 00061 int32_t num_vec=idx_a2-idx_a1+1; 00062 int32_t step= num_vec/num_threads; 00063 int32_t t; 00064 00065 pthread_attr_t attr; 00066 pthread_attr_init(&attr); 00067 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 00068 00069 for (t=0; t<num_threads-1; t++) 00070 { 00071 params[t].d = distance; 00072 params[t].r = result; 00073 params[t].idx_r_start=t*step; 00074 params[t].idx_start = (t*step)+idx_a1; 00075 params[t].idx_stop = ((t+1)*step)+idx_a1; 00076 params[t].idx_comp=idx_b; 00077 00078 pthread_create(&threads[t], &attr, CDistanceMachine::run_distance_thread_lhs, (void*)¶ms[t]); 00079 } 00080 params[t].d = distance; 00081 params[t].r = result; 00082 params[t].idx_r_start=t*step; 00083 params[t].idx_start = (t*step)+idx_a1; 00084 params[t].idx_stop = idx_a2+1; 00085 params[t].idx_comp=idx_b; 00086 00087 run_distance_thread_lhs(¶ms[t]); 00088 00089 for (t=0; t<num_threads-1; t++) 00090 pthread_join(threads[t], NULL); 00091 00092 pthread_attr_destroy(&attr); 00093 delete[] params; 00094 delete[] threads; 00095 } 00096 #endif 00097 } 00098 00099 void CDistanceMachine::distances_rhs(float64_t* result,int32_t idx_b1,int32_t idx_b2,int32_t idx_a) 00100 { 00101 int32_t num_threads=parallel->get_num_threads(); 00102 ASSERT(num_threads>0); 00103 00104 ASSERT(result); 00105 00106 if (num_threads < 2) 00107 { 00108 D_THREAD_PARAM param; 00109 param.d=distance; 00110 param.r=result; 00111 param.idx_r_start=idx_b1; 00112 param.idx_start=idx_b1; 00113 param.idx_stop=idx_b2+1; 00114 param.idx_comp=idx_a; 00115 00116 run_distance_thread_rhs((void*) ¶m); 00117 } 00118 #ifndef WIN32 00119 else 00120 { 00121 pthread_t* threads = new pthread_t[num_threads-1]; 00122 D_THREAD_PARAM* params = new D_THREAD_PARAM[num_threads]; 00123 int32_t num_vec=idx_b2-idx_b1+1; 00124 int32_t step= num_vec/num_threads; 00125 int32_t t; 00126 00127 pthread_attr_t attr; 00128 pthread_attr_init(&attr); 00129 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 00130 00131 for (t=0; t<num_threads-1; t++) 00132 { 00133 params[t].d = distance; 00134 params[t].r = result; 00135 params[t].idx_r_start=t*step; 00136 params[t].idx_start = (t*step)+idx_b1; 00137 params[t].idx_stop = ((t+1)*step)+idx_b1; 00138 params[t].idx_comp=idx_a; 00139 00140 pthread_create(&threads[t], &attr, CDistanceMachine::run_distance_thread_rhs, (void*)¶ms[t]); 00141 } 00142 params[t].d = distance; 00143 params[t].r = result; 00144 params[t].idx_r_start=t*step; 00145 params[t].idx_start = (t*step)+idx_b1; 00146 params[t].idx_stop = idx_b2+1; 00147 params[t].idx_comp=idx_a; 00148 00149 run_distance_thread_rhs(¶ms[t]); 00150 00151 for (t=0; t<num_threads-1; t++) 00152 pthread_join(threads[t], NULL); 00153 00154 pthread_attr_destroy(&attr); 00155 delete[] params; 00156 delete[] threads; 00157 } 00158 #endif 00159 } 00160 00161 void* CDistanceMachine::run_distance_thread_lhs(void* p) 00162 { 00163 D_THREAD_PARAM* params= (D_THREAD_PARAM*) p; 00164 CDistance* distance=params->d; 00165 float64_t* res=params->r; 00166 int32_t idx_res_start=params->idx_r_start; 00167 int32_t idx_act=params->idx_start; 00168 int32_t idx_stop=params->idx_stop; 00169 int32_t idx_c=params->idx_comp; 00170 00171 for (int32_t i=idx_res_start; idx_act<idx_stop; i++,idx_act++) 00172 res[i] =distance->distance(idx_act,idx_c); 00173 00174 return NULL; 00175 } 00176 00177 void* CDistanceMachine::run_distance_thread_rhs(void* p) 00178 { 00179 D_THREAD_PARAM* params= (D_THREAD_PARAM*) p; 00180 CDistance* distance=params->d; 00181 float64_t* res=params->r; 00182 int32_t idx_res_start=params->idx_r_start; 00183 int32_t idx_act=params->idx_start; 00184 int32_t idx_stop=params->idx_stop; 00185 int32_t idx_c=params->idx_comp; 00186 00187 for (int32_t i=idx_res_start; idx_act<idx_stop; i++,idx_act++) 00188 res[i] =distance->distance(idx_c,idx_act); 00189 00190 return NULL; 00191 }