Changeset 3301

Show
Ignore:
Timestamp:
11/06/09 20:05:35 (2 weeks ago)
Author:
kraftche
Message:

More refactoring of get_adjacencies code:

o split common template code into separate union and intersect versions
o combine vector->vector with other cases for intersect
o copy blocked optimziation from specialized vertex case to general

union case

Reduces skin time for 100x100x100 hex mesh form 7.88s to 5.01s

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • MOAB/trunk/MBCore.cpp

    r3299 r3301  
    10471047} 
    10481048 
     1049 
     1050template <typename ITER> static  
     1051MBErrorCode get_adjacencies_union( MBCore* gMB, 
     1052                                   ITER begin, ITER end, 
     1053                                   int to_dimension, 
     1054                                   bool create_if_missing, 
     1055                                   MBRange& adj_entities ) 
     1056{  
     1057  const size_t DEFAULT_MAX_BLOCKS_SIZE = 4000; 
     1058  const size_t MAX_OUTER_ITERATIONS = 100; 
     1059 
     1060  std::vector<MBEntityHandle> temp_vec, storage; 
     1061  std::vector<MBEntityHandle>::const_iterator ti; 
     1062  MBErrorCode result = MB_SUCCESS, tmp_result; 
     1063  ITER i = begin; 
     1064  MBRange::iterator ins; 
     1065  const MBEntityHandle* conn; 
     1066  int conn_len; 
     1067 
     1068    // Just copy any vertices from the input range into the output 
     1069  size_t remaining = end - begin; 
     1070  assert(begin + remaining == end); 
     1071   
     1072    // How many entities to work with at once? 2000 or so shouldn't require 
     1073    // too much memory, but don't iterate in outer loop more than a 
     1074    // 1000 times (make it bigger if many input entiites.)  
     1075  const size_t block_size = std::max( DEFAULT_MAX_BLOCKS_SIZE, remaining/MAX_OUTER_ITERATIONS ); 
     1076  while (remaining > 0) { 
     1077    const size_t count = remaining > block_size ? block_size : remaining; 
     1078    remaining -= count; 
     1079    temp_vec.clear(); 
     1080    for (size_t j = 0; j < count; ++i, ++j) { 
     1081      if (MBCN::Dimension(TYPE_FROM_HANDLE(*i)) == to_dimension) { 
     1082        temp_vec.push_back(*i); 
     1083      } 
     1084      else if (to_dimension == 0 && TYPE_FROM_HANDLE(*i) != MBPOLYHEDRON) { 
     1085        tmp_result = gMB->get_connectivity( *i, conn, conn_len, false, &storage ); 
     1086        if (MB_SUCCESS != tmp_result) { 
     1087          result = tmp_result; 
     1088          continue; 
     1089        } 
     1090        temp_vec.insert( temp_vec.end(), conn, conn + conn_len ); 
     1091      } 
     1092      else { 
     1093        tmp_result = gMB->a_entity_factory()->get_adjacencies( *i, to_dimension,  
     1094                                                   create_if_missing, temp_vec); 
     1095      } 
     1096    } 
     1097 
     1098    std::sort( temp_vec.begin(), temp_vec.end() ); 
     1099    ins = adj_entities.begin(); 
     1100    ti = temp_vec.begin(); 
     1101    while (ti != temp_vec.end()) { 
     1102      MBEntityHandle first = *ti; 
     1103      MBEntityHandle second = *ti; 
     1104      for (++ti; ti != temp_vec.end() && (*ti - second <= 1); ++ti) 
     1105        second = *ti; 
     1106      ins = adj_entities.insert( ins, first, second ); 
     1107    } 
     1108  } 
     1109  return result; 
     1110} 
     1111 
     1112template <typename ITER> static  
     1113MBErrorCode get_adjacencies_intersection( MBCore* mb, 
     1114                             ITER begin, ITER end, 
     1115                             const int to_dimension, 
     1116                             const bool create_if_missing, 
     1117                             std::vector<MBEntityHandle>& adj_entities ) 
     1118{ 
     1119  const size_t SORT_THRESHOLD = 200; 
     1120  std::vector<MBEntityHandle> temp_vec; 
     1121  std::vector<MBEntityHandle>::iterator adj_it, w_it; 
     1122  MBErrorCode result = MB_SUCCESS; 
     1123 
     1124  for (ITER from_it = begin; from_it != end; from_it++)  
     1125  { 
     1126      // running results kept in adj_entities; clear temp_vec, which is working space 
     1127    temp_vec.clear(); 
     1128 
     1129      // get the next set of adjacencies 
     1130    MBEntityType type = TYPE_FROM_HANDLE(*from_it); 
     1131    if (to_dimension == MBCN::Dimension(type))  
     1132      temp_vec.push_back(*from_it);  
     1133    else if(to_dimension == 0 && type != MBPOLYHEDRON) 
     1134      result = mb->get_connectivity(&(*from_it), 1, temp_vec); 
     1135    else 
     1136      result = mb->a_entity_factory()->get_adjacencies(*from_it, to_dimension,  
     1137                                                   create_if_missing, temp_vec); 
     1138    if (MB_SUCCESS != result) 
     1139      return result; 
     1140   
     1141      // If first iteration and input is empty, begin with first set of adjacencies 
     1142    if (from_it == begin && adj_entities.empty()) { 
     1143      adj_entities.swap( temp_vec ); 
     1144      continue; 
     1145    } 
     1146   
     1147      // otherwise intersect with the current set of results 
     1148    w_it = adj_it = adj_entities.begin(); 
     1149    if (temp_vec.size()*adj_entities.size() < SORT_THRESHOLD) { 
     1150      for (; adj_it != adj_entities.end(); ++adj_it) 
     1151        if (std::find(temp_vec.begin(), temp_vec.end(), *adj_it) != temp_vec.end()) 
     1152          { *w_it = *adj_it; ++w_it; } 
     1153    } 
     1154    else { 
     1155      std::sort( temp_vec.begin(), temp_vec.end() ); 
     1156      for (; adj_it != adj_entities.end(); ++adj_it) 
     1157        if (std::binary_search(temp_vec.begin(), temp_vec.end(), *adj_it)) 
     1158          { *w_it = *adj_it; ++w_it; } 
     1159    } 
     1160    adj_entities.erase( w_it, adj_entities.end() ); 
     1161     
     1162      // we're intersecting, so if there are no more results, we're done 
     1163    if (adj_entities.empty()) 
     1164      break; 
     1165  } 
     1166 
     1167  return MB_SUCCESS; 
     1168} 
     1169 
     1170template <typename ITER> static  
     1171MBErrorCode get_adjacencies_intersection( MBCore* mb, 
     1172                             ITER begin, ITER end, 
     1173                             const int to_dimension, 
     1174                             const bool create_if_missing, 
     1175                             MBRange& adj_entities ) 
     1176{ 
     1177  std::vector<MBEntityHandle> results; 
     1178  MBErrorCode rval = get_adjacencies_intersection( mb, begin, end, to_dimension,  
     1179                                                   create_if_missing, results ); 
     1180  if (MB_SUCCESS != rval) 
     1181    return rval; 
     1182   
     1183  if (adj_entities.empty()) { 
     1184    std::copy( results.begin(), results.end(), mb_range_inserter(adj_entities) ); 
     1185    return MB_SUCCESS; 
     1186  } 
     1187   
     1188  MBRange::iterator it = adj_entities.begin(); 
     1189  while (it != adj_entities.end()) { 
     1190    if (std::find( results.begin(), results.end(), *it) == results.end()) 
     1191      it = adj_entities.erase( it ); 
     1192    else 
     1193      ++it; 
     1194  } 
     1195  return MB_SUCCESS; 
     1196} 
     1197 
    10491198MBErrorCode MBCore::get_adjacencies( const MBEntityHandle *from_entities, 
    10501199                                     const int num_entities, 
     
    10651214    return result; 
    10661215  } 
    1067    
    1068   if (operation_type == MBInterface::UNION) { 
    1069     std::vector<MBEntityHandle> tmp_storage; 
    1070     const MBEntityHandle* conn; 
    1071     int len; 
    1072     for (int i = 0; i < num_entities; ++i) { 
    1073       if(to_dimension == 0 && TYPE_FROM_HANDLE(from_entities[0]) != MBPOLYHEDRON) { 
    1074         result = get_connectivity(from_entities[i], conn, len, false, &tmp_storage); 
    1075         adj_entities.insert( adj_entities.end(), conn, conn+len ); 
    1076         if (MB_SUCCESS != result) 
    1077           return result; 
    1078       } 
    1079       else { 
    1080         result = aEntityFactory->get_adjacencies(from_entities[i], to_dimension,  
    1081                                                  create_if_missing, adj_entities); 
    1082         if (MB_SUCCESS != result) 
    1083           return result; 
    1084       } 
    1085     } 
    1086     std::sort( adj_entities.begin(), adj_entities.end() ); 
    1087     adj_entities.erase( std::unique( adj_entities.begin(), adj_entities.end() ), adj_entities.end() ); 
    1088     return MB_SUCCESS; 
    1089   } 
    1090    
    1091   std::vector<MBEntityHandle> tmp_adj; 
     1216  else if (operation_type == MBInterface::INTERSECT) 
     1217    return get_adjacencies_intersection( this, from_entities, from_entities+num_entities,  
     1218                                         to_dimension, create_if_missing, adj_entities ); 
     1219  else if (operation_type != MBInterface::UNION) 
     1220    return MB_FAILURE; 
     1221     
     1222    // do union 
     1223  std::vector<MBEntityHandle> tmp_storage; 
     1224  const MBEntityHandle* conn; 
     1225  int len; 
    10921226  for (int i = 0; i < num_entities; ++i) { 
    1093     tmp_adj.clear(); 
    1094     if(to_dimension == 0 && TYPE_FROM_HANDLE(from_entities[i]) != MBPOLYHEDRON) 
    1095       result = get_connectivity(&from_entities[i], 1, tmp_adj); 
    1096     else 
     1227    if(to_dimension == 0 && TYPE_FROM_HANDLE(from_entities[0]) != MBPOLYHEDRON) { 
     1228      result = get_connectivity(from_entities[i], conn, len, false, &tmp_storage); 
     1229      adj_entities.insert( adj_entities.end(), conn, conn+len ); 
     1230      if (MB_SUCCESS != result) 
     1231        return result; 
     1232    } 
     1233    else { 
    10971234      result = aEntityFactory->get_adjacencies(from_entities[i], to_dimension,  
    1098                                                create_if_missing, tmp_adj); 
    1099     if (MB_SUCCESS != result) 
    1100       return result; 
    1101      
    1102     if (tmp_adj.empty()) { 
    1103       adj_entities.clear(); 
    1104       return MB_SUCCESS; 
    1105     } 
    1106     else if (i == 0 && adj_entities.empty()) 
    1107       adj_entities.swap(tmp_adj); 
    1108     else { 
    1109       std::sort( tmp_adj.begin(), tmp_adj.end() ); 
    1110       std::vector<MBEntityHandle>::iterator it, w; 
    1111       for( it = w = adj_entities.begin(); it != adj_entities.end(); ++it ) { 
    1112         if (std::binary_search( tmp_adj.begin(), tmp_adj.end(), *it )) 
    1113           { *w = *it; ++w; } 
    1114       } 
    1115       adj_entities.erase( w, adj_entities.end() ); 
    1116     } 
    1117   } 
     1235                                               create_if_missing, adj_entities); 
     1236      if (MB_SUCCESS != result) 
     1237        return result; 
     1238    } 
     1239  } 
     1240  std::sort( adj_entities.begin(), adj_entities.end() ); 
     1241  adj_entities.erase( std::unique( adj_entities.begin(), adj_entities.end() ), adj_entities.end() ); 
    11181242  
    11191243  return MB_SUCCESS; 
    11201244} 
    11211245 
    1122 template <typename ITER> static inline 
    1123 MBErrorCode get_adjacencies_common( MBCore* mb, 
    1124                              ITER begin, ITER end, 
    1125                              const int to_dimension, 
    1126                              const bool create_if_missing, 
    1127                              MBRange &adj_entities, 
    1128                              const int operation_type ) 
    1129 { 
    1130   MBRange temp_range; 
    1131   std::vector<MBEntityHandle> temp_vec; 
    1132   std::vector<MBEntityHandle>::const_iterator adj_it; 
    1133   MBErrorCode result = MB_SUCCESS, tmp_result; 
    1134  
    1135   for (ITER from_it = begin; from_it != end; from_it++)  
    1136   { 
    1137       // running results kept in adj_entities; clear temp_vec and temp_range, which are working space 
    1138     temp_vec.clear(); 
    1139     temp_range.clear(); 
    1140  
    1141       // get the next set of adjacencies 
    1142     MBEntityType type = TYPE_FROM_HANDLE(*from_it); 
    1143     if (to_dimension == MBCN::Dimension(type))  
    1144       { temp_vec.push_back(*from_it); tmp_result = MB_SUCCESS; } 
    1145     else if(to_dimension == 0 && type != MBPOLYHEDRON) 
    1146       tmp_result = mb->get_connectivity(&(*from_it), 1, temp_vec); 
    1147     else 
    1148       tmp_result = mb->a_entity_factory()->get_adjacencies(*from_it, to_dimension,  
    1149                                                    create_if_missing, temp_vec); 
    1150      
    1151     if (MB_SUCCESS != tmp_result) result = tmp_result; 
    1152      
    1153     std::sort( temp_vec.begin(), temp_vec.end() ); 
    1154      
    1155       // if we're on the first iteration and we didn't come in with entities, 
    1156       // just get the first results and move on 
    1157     if (adj_entities.empty() && from_it == begin) { 
    1158       std::copy(temp_vec.rbegin(), temp_vec.rend(), mb_range_inserter(adj_entities)); 
    1159       continue; 
    1160     } 
    1161  
    1162       // operate on the vectors 
    1163     MBRange::iterator hint = adj_entities.begin(); 
    1164     if (operation_type == MBInterface::INTERSECT) { 
    1165       adj_it = temp_vec.begin(); 
    1166       while (hint != adj_entities.end()) { 
    1167         while (adj_it != temp_vec.end() && *adj_it < *hint) 
    1168           ++adj_it; 
    1169         if (adj_it == temp_vec.end()) { 
    1170           adj_entities.erase( hint, adj_entities.end() ); 
    1171           break; 
    1172         } 
    1173          
    1174         if (*adj_it == *hint) 
    1175           ++hint; 
    1176         else 
    1177           hint = adj_entities.erase(hint); 
    1178       } 
    1179        
    1180         // If doing INTERSECT and the current results are the empty set, 
    1181         // then the final result must also be the empty set.   
    1182       if (adj_entities.empty()) 
    1183         return MB_SUCCESS; 
    1184     } 
    1185     else if (operation_type == MBInterface::UNION) { 
    1186       for (adj_it = temp_vec.begin(); adj_it != temp_vec.end(); ++adj_it) 
    1187         hint = adj_entities.insert( hint, *adj_it ); 
    1188     } 
    1189   } 
    1190  
    1191   return result; 
    1192 } 
    11931246 
    11941247MBErrorCode MBCore::get_adjacencies( const MBEntityHandle *from_entities, 
     
    11991252                                     const int operation_type ) 
    12001253{ 
    1201   return get_adjacencies_common( this, from_entities, from_entities + num_entities, 
    1202                           to_dimension, create_if_missing, adj_entities, operation_type ); 
     1254  if (operation_type == MBInterface::INTERSECT) 
     1255    return get_adjacencies_intersection( this, from_entities, from_entities + num_entities, 
     1256                                         to_dimension, create_if_missing, adj_entities ); 
     1257  else if (operation_type == MBInterface::UNION) 
     1258    return get_adjacencies_union( this, from_entities, from_entities + num_entities, 
     1259                                  to_dimension, create_if_missing, adj_entities ); 
     1260  else 
     1261    return MB_FAILURE; 
    12031262} 
    12041263 
     
    12741333                                      const int operation_type) 
    12751334{ 
    1276   if (operation_type != MBInterface::INTERSECT && 
    1277       operation_type != MBInterface::UNION) return MB_FAILURE; 
    1278  
    1279   if(from_entities.size() == 0) 
    1280     return MB_SUCCESS; 
    1281  
    1282     // special case for getting all vertices 
    1283   if (to_dimension == 0 && operation_type == MBInterface::UNION) { 
     1335  if (operation_type == MBInterface::INTERSECT) 
     1336    return get_adjacencies_intersection( this, from_entities.begin(), from_entities.end(), 
     1337                                         to_dimension, create_if_missing, adj_entities ); 
     1338  else if (operation_type != MBInterface::UNION) 
     1339    return MB_FAILURE; 
     1340  else if (to_dimension == 0) 
    12841341    return get_vertices( from_entities, adj_entities ); 
    1285   } 
    1286  
    1287   return get_adjacencies_common( this, from_entities.begin(), from_entities.end(), 
    1288                            to_dimension, create_if_missing, adj_entities, operation_type ); 
     1342  else 
     1343    return get_adjacencies_union( this, from_entities.begin(), from_entities.end(), 
     1344                                  to_dimension, create_if_missing, adj_entities ); 
    12891345} 
    12901346