00001
00007 #include <stdio.h>
00008 #include <time.h>
00009 #include <sys/types.h>
00010
00011 #include "binarysave.h"
00012 #include "ipc.h"
00013 #include "cmdparam.h"
00014 #include "globals.h"
00015 #include "kernel.h"
00016 #define NO_ANALYZE
00017
00018
00019
00020
00021
00022
00023
00024 Tristate LISSOMBinaryStateSaver::save_afferent_weights_only=False;
00025 Tristate LISSOMBinaryStateSaver::save_all_lateral_weights=False;
00026 Tristate LISSOMBinaryStateSaver::load_afferent_weights_only=False;
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00043 #define LF_BUFFER_VERIFY
00044
00045
00046
00048 typedef f32 LFFloatType;
00049 #define LF_FLOAT_SIZE sizeof(LFFloatType)
00050
00051
00052
00053 #define SMALLEST_LFTOK 1
00054 #define LFTOK_NO_TOKEN 0
00055 #define LFTOK_SNAPSHOT_HEADER 1
00056 #define LFTOK_ROW_HEADER 2
00057 #define LFTOK_NEURON_HEADER_ORIG 3
00058 #define LFTOK_AFF_WEIGHTS 4
00059 #define LFTOK_LEXC_WEIGHTS_OLD 5
00060 #define LFTOK_LINH_WEIGHT_CHUNK 6
00061 #define LFTOK_NEURON_TRAILER 7
00062 #define LFTOK_SNAPSHOT_TRAILER 8
00063 #define LFTOK_LEXC_WEIGHTS 9
00064 #define LFTOK_NEURON_HEADER_BUG 10
00065 #define LARGEST_LFTOK 10
00066
00068 #define LF_UNUSED 0x00
00069
00070 #define LF_ALL_EYES 99
00071
00072
00073
00074 #define LF_FLOAT_TOLERANCE 0.0000001
00075
00076
00077 #define LF_NO_ERROR 0
00078 #define LF_ERROR -1
00079
00080 #define LF_MAXWARNINGS 5
00081
00082
00083
00084
00085
00086
00087
00088 void LISSOMBinaryStateSaver::binarysave_init_hook( void )
00089 {
00090 PARAM_I(PARAM_3BOOL, load_afferent_weights_only,False,True,
00091 "If true, when loading weights, load only the afferent ones. This allows\n"
00092 "a machine with little memory to read in a file created on a much larger one,\n"
00093 "though all it can do is compute initial activations and map values which\n"
00094 "depend on them.");
00095
00096 PARAM_I(PARAM_3BOOL, save_afferent_weights_only,False,True,
00097 "If true, when saving weights, save only the afferent ones. This results\n"
00098 "in a much smaller file, but the resulting network is of only limited use.");
00099
00100 PARAM_I(PARAM_3BOOL, save_all_lateral_weights,False,True,
00101 "If true, when saving weights, save all lateral weights whether\n"
00102 "they are negative or not.");
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00113 int LISSOMBinaryStateSaver::binaryWeightsFileWrite( FILE *file )
00114 {
00115 int current_local_row;
00116 int part_of_row;
00117 time_t start_time, end_time;
00118
00119
00120 tokensWritten = 0;
00121 status = 0;
00122 errorsEncountered = 0;
00123
00124
00125 if (AMYOUNGESTPE) {
00126 start_time = time(NULL);
00127 ipc_notify(IPC_ALL,IPC_STD,"Weight file saving started %.24s", ctime(&start_time));
00128
00129
00130 writeToken( file, makeToken( LFTOK_SNAPSHOT_HEADER, 2+1, lm.N, lm.perows));
00131 writeInteger( file, iteration);
00132 }
00133
00134
00135 for (current_local_row=0; current_local_row <lm.perows; current_local_row++) {
00136 for (part_of_row=0; part_of_row <parts_per_row; part_of_row++) {
00137
00138 const int current_map_row = MAPROW(current_local_row);
00139 LFBufferClear( &binaryBuffer );
00140 binaryWeightsBufferFill( &binaryBuffer, current_map_row, current_local_row, part_of_row );
00141 if (status != 0) return status;
00142
00143
00144 #ifdef LF_BUFFER_VERIFY
00145 tokensRead = 0;
00146 binaryWeightsBufferProcess( &binaryBuffer, True);
00147 if(status != 0) return status;
00148 #endif
00149
00150
00151 ipc_barrier();
00152
00153
00154 if (AMYOUNGESTPE) {
00155 int pe;
00156
00157 for(pe=(NPEs-1); pe>=0; pe--){
00158
00159 if (!PEISME(pe))
00160 LFBufferGet(&binaryBuffer, pe);
00161
00162
00163 writeToken( file, makeToken( LFTOK_ROW_HEADER, 2 + 1,
00164 ARBITRARY_MAPROW(current_local_row,pe), LF_UNUSED));
00165 writeInteger(file, LFBufferLength(&binaryBuffer));
00166
00167
00168 LFBufferWrite(&binaryBuffer,file);
00169 }
00170 }
00171
00172
00173 ipc_barrier();
00174 }
00175 }
00176
00177 if (AMYOUNGESTPE) {
00178
00179
00180 writeToken( file, makeToken( LFTOK_SNAPSHOT_TRAILER, 2 + 1, LF_UNUSED, LF_UNUSED));
00181 writeInteger(file, iteration);
00182
00183 end_time = time(NULL);
00184
00185
00186 ipc_notify(IPC_ALL,IPC_STD,"Weight saving took %g seconds, completing %.24s",
00187 (double)difftime(end_time, start_time),
00188 ctime(&end_time));
00189 }
00190
00191 if (errorsEncountered != 0) {
00192 ipc_notify(IPC_ALL,IPC_ERROR,"There were %d non-fatal errors during saving",errorsEncountered);
00193 ipc_notify(IPC_ALL,IPC_ERROR,"Consult the log file for more information");
00194 }
00195
00196 return LF_NO_ERROR;
00197 }
00198
00199
00200
00202 int LISSOMBinaryStateSaver::binaryWeightsBufferFill( LFBuffer *buffer, int current_map_row,
00203 int current_local_row, int part_of_row )
00204 {
00205 int current_j;
00206 int which_eye;
00207
00208 int start_j = part_of_row * (lm.N/parts_per_row);
00209 int end_j = (part_of_row + 1) * (lm.N/parts_per_row);
00210
00211
00212 if (lm.N%parts_per_row != 0){
00213 ipc_notify(IPC_ALL,IPC_ERROR,"N must be divisible by parts_per_row: %d%%%d != 0",
00214 (int)lm.N, (int)parts_per_row);
00215 return LF_ERROR;
00216
00217 }
00218
00219
00220 for (current_j =start_j; current_j <end_j; current_j++){
00221
00222 if(status != 0) return status;
00223
00224
00225 LFBufferWriteToken(buffer,
00226 makeToken( LFTOK_NEURON_HEADER_ORIG, 2 + 2, current_map_row, current_j));
00227
00228 LFBufferWriteInteger(buffer, lm.cortex_map[current_map_row][current_j].centerx);
00229 LFBufferWriteInteger(buffer, lm.cortex_map[current_map_row][current_j].centery);
00230
00231
00232 {
00233 const int rf_width = 1 + 2*lm.rf_radius;
00234
00235
00236 const double wt_scale = lm.num_aff_inputs()/2.0;
00237
00238 int x,y;
00239
00240
00241
00242
00243
00244
00245
00246 for (which_eye = 0; which_eye < lm.num_aff_inputs(); which_eye++) {
00247 LFBufferWriteToken(buffer, makeToken( LFTOK_AFF_WEIGHTS,
00248 2 + rf_width*rf_width,
00249 rf_width, which_eye));
00250
00251 for (x=0; x<rf_width; x++)
00252 for (y=0; y<rf_width; y++)
00253 LFBufferWriteFloat(buffer, wt_scale *
00254 lm.wts[current_local_row][current_j].weights[which_eye][x][y]);
00255
00256 }
00257 }
00258
00259
00260
00261 if (!save_afferent_weights_only) {
00262
00263
00264 binaryWeightsBufferWriteLatWeights( buffer, LFTOK_LEXC_WEIGHTS,
00265 current_map_row, current_j,
00266 lm.exc_rad, lm.exc_array_width,
00267 &(lm.wts[current_local_row][current_j].lat_exc_wts[0]));
00268
00269
00270 {
00271 int start_index=0, end_index=-1, i;
00272 int dynamic_lat_inh_dimension = (2*lm.inh_rad + 1)*(2*lm.inh_rad + 1);
00273 f64 live_threshold = 1.5 * DEATH_FLAG;
00274
00275 if (save_all_lateral_weights)
00276 live_threshold = -1.0E30;
00277
00278 if (dynamic_lat_inh_dimension != lm.lat_inh_dimension)
00279 ipc_notify(IPC_ONE,IPC_ERROR,"Lateral inhibitory radius changed; not supported by binarysave.c");
00280
00281
00282
00283 for (;;) {
00284
00285
00286
00287
00288
00289
00290
00291 for (start_index = end_index+1;
00292 ((start_index <= dynamic_lat_inh_dimension-1) &&
00293 (lm.wts[current_local_row][current_j].lat_inh_wts[start_index] < live_threshold));
00294 start_index++);
00295
00296
00297 if (start_index >= dynamic_lat_inh_dimension)
00298 break;
00299
00300
00301
00302 for (end_index=start_index;
00303 ((end_index < dynamic_lat_inh_dimension - 2) &&
00304 !((lm.wts[current_local_row][current_j].lat_inh_wts[end_index+1] < live_threshold) &&
00305 (lm.wts[current_local_row][current_j].lat_inh_wts[end_index+2] < live_threshold)));
00306 end_index +=2);
00307
00308
00309 if (end_index >= (dynamic_lat_inh_dimension-2))
00310 end_index = dynamic_lat_inh_dimension - 1;
00311
00312
00313
00314
00315 if (lm.wts[current_local_row][current_j].lat_inh_wts[end_index] < live_threshold)
00316 end_index--;
00317
00318
00319 LFBufferWriteToken(buffer, makeToken( LFTOK_LINH_WEIGHT_CHUNK,
00320 2 + (end_index - start_index + 1),
00321 start_index, end_index));
00322
00323
00324 for (i=start_index; i<=end_index; i++)
00325 LFBufferWriteFloat(buffer, lm.wts[current_local_row][current_j].lat_inh_wts[i]);
00326
00327 };
00328 }
00329 }
00330
00331
00332 LFBufferWriteToken(buffer, makeToken( LFTOK_NEURON_TRAILER, 2, current_map_row, current_j));
00333
00334 }
00335
00336 return LF_NO_ERROR;
00337 }
00338
00339
00340
00342 int LISSOMBinaryStateSaver::binaryWeightsFileRead( FILE *file )
00343 {
00344 LFTokenType thisToken;
00345
00346 time_t start_time, end_time;
00347
00348
00349 tokensRead = 0;
00350 status = 0;
00351 errorsEncountered = 0;
00352 LFBufferClear( &binaryBuffer );
00353
00354
00355 if (AMPARENTPE){
00356
00357 start_time = time(NULL);
00358 ipc_notify(IPC_ALL,IPC_STD,"Weight file loading started %.24s", ctime(&start_time));
00359
00360
00361 thisToken = readTokenExpecting(LFTOK_SNAPSHOT_HEADER, file);
00362 compareParameter(tokenInfoa(thisToken), lm.N, "N" );
00363 #ifdef ASSUME_FIXED_PE_CONFIGURATION
00364 compareParameter(tokenInfob(thisToken), lm.perows, "perows");
00365 #endif
00366
00367
00368 iteration = readInteger(file);
00369 }
00370
00371 #ifdef ASSUME_FIXED_PE_CONFIGURATION
00372 ipc_notify(IPC_ONE,IPC_VERBOSE,"Assuming fixed order of rows in binary weights file");
00373 binaryWeightsFileReadInFixedOrder(file, &binaryBuffer);
00374 #else
00375 binaryWeightsFileReadInArbitraryOrder(file, &binaryBuffer);
00376 #endif
00377
00378
00379 if (AMPARENTPE){
00380 thisToken = readTokenExpecting(LFTOK_SNAPSHOT_TRAILER, file);
00381 if (readInteger(file) != iteration)
00382 ipc_notify(IPC_ALL,IPC_ERROR,"File truncated: End of SNAPSHOT_TRAILER missing");
00383
00384 end_time = time(NULL);
00385
00386
00387 ipc_notify(IPC_ALL,IPC_STD,"Weight loading took %g seconds, completing %.24s",
00388 (double)(difftime(end_time, start_time)),
00389 ctime(&end_time));
00390
00391 }
00392
00393 if (errorsEncountered != 0) {
00394 ipc_notify(IPC_ALL,IPC_ERROR,"There were %d non-fatal errors during loading",errorsEncountered);
00395 ipc_notify(IPC_ALL,IPC_ERROR,"Consult the runfile for more information");
00396 }
00397
00398 return LF_NO_ERROR;
00399 }
00400
00401
00402
00403 int LISSOMBinaryStateSaver::binaryWeightsBufferWriteLatWeights( LFBuffer *buffer, int token_name,
00404 int i, int j, int radius, int array_width,
00405 l_weight *weights)
00406 {
00407 const int lowk = MAX(i-radius,0 );
00408 const int highk = MIN(i+radius,lm.N-1);
00409 const int lowl = MAX(j-radius,0 );
00410 const int highl = MIN(j+radius,lm.N-1);
00411 const int num = (highk-lowk+1)*(highl-lowl+1);
00412
00413 int k,l;
00414
00415 LFBufferWriteToken(buffer, makeToken( token_name, 2+num, num, 0));
00416
00417 for(k=lowk; k<= highk; k++) {
00418 const int partial_idx = PARTIAL_LAT_INDEX(i,j,k,radius,array_width);
00419 for (l=lowl; l<=highl; l++) {
00420 const int idx = FULL_LAT_INDEX(partial_idx,l);
00421
00422 LFBufferWriteFloat(buffer, weights[idx]);
00423 }
00424 }
00425
00426 return LF_NO_ERROR;
00427 }
00428
00429
00430
00431 int LISSOMBinaryStateSaver::binaryWeightsBufferReadLatWeights( LFBuffer *buffer, LFTokenType token,
00432 int i, int j, int radius, int array_width,
00433 l_weight *weights, int verify, const char *description)
00434 {
00435 const int lowk = MAX(i-radius,0 );
00436 const int highk = MIN(i+radius,lm.N-1);
00437 const int lowl = MAX(j-radius,0 );
00438 const int highl = MIN(j+radius,lm.N-1);
00439 const int num = (highk-lowk+1)*(highl-lowl+1);
00440
00441 int k,l;
00442
00443 if (load_afferent_weights_only) {
00444
00445 int idx;
00446 for(idx=0; idx<tokenInfoa(token); idx++)
00447 LFBufferReadFloat(buffer);
00448 return LF_NO_ERROR;
00449 }
00450
00451
00452 if (num != tokenInfoa(token)) {
00453 const int maxwarnings=10;
00454 static int warnings = 0;
00455
00456 warnings++;
00457 if (warnings < maxwarnings) {
00458 ipc_notify(IPC_ALL,IPC_ERROR,
00459 "Problem with lateral weight encoding (at neuron (%d,%d): file %d != computed %d); current parameters may not match file",
00460 i,j,tokenInfoa(token),num);
00461 }
00462 else if (warnings == maxwarnings)
00463 ipc_notify(IPC_ALL,IPC_ERROR,
00464 "Maximum number of lateral weight warnings reached (%d); the rest will be discarded",
00465 maxwarnings);
00466
00467 for (k=tokenInfoa(token); k>0; k--)
00468 LFBufferReadFloat(buffer);
00469 } else
00470
00471 for(k=lowk; k<= highk; k++) {
00472 const int partial_idx = PARTIAL_LAT_INDEX(i,j,k,radius,array_width);
00473 for (l=lowl; l<=highl; l++) {
00474 const int idx = FULL_LAT_INDEX(partial_idx,l);
00475 const l_weight aFloat = LFBufferReadFloat(buffer);
00476
00477 compareOrSet_l_weight(&weights[idx], aFloat, verify, description);
00478 }
00479 }
00480
00481 return LF_NO_ERROR;
00482 }
00483
00484
00485
00492 int LISSOMBinaryStateSaver::binaryWeightsFileReadInFixedOrder(FILE *file, LFBuffer *buffer)
00493 {
00494 int current_map_row;
00495 int current_local_row;
00496 int part_of_row;
00497 int row_length;
00498 LFTokenType thisToken;
00499
00500
00501 for (current_local_row =0; current_local_row <lm.perows; current_local_row++) {
00502 for (part_of_row=0; part_of_row <parts_per_row; part_of_row++) {
00503
00504 if (AMPARENTPE){
00505 int pe;
00506 int rowsRead = 0;
00507
00508
00509 do
00510 {
00511 thisToken = readTokenExpecting(LFTOK_ROW_HEADER, file);
00512
00513 current_map_row = tokenInfoa(thisToken);
00514 row_length = readInteger(file);
00515 LFBufferClear( buffer );
00516 LFBufferRead( buffer, file, row_length);
00517
00518 if ( current_local_row != LOCALROW(current_map_row)) {
00519 status = LF_ERROR;
00520 ipc_notify(IPC_ALL,IPC_ERROR,"Rows are not in the correct major order in file");
00521 }
00522 pe = PEFORROW(current_map_row);
00523 if (!PEISME(pe))
00524 LFBufferPut( buffer, pe);
00525
00526 rowsRead++;
00527
00528 } while (!PEISME(pe));
00529
00530 if ( rowsRead != NPEs) {
00531 status = LF_ERROR;
00532 ipc_notify(IPC_ALL,IPC_ERROR,"Rows are not in the correct minor order in file");
00533 }
00534 }
00535
00536
00537
00538 ipc_barrier();
00539
00540 #ifdef CRAY
00541 #pragma _CRI suppress (buffer)
00542 #endif
00543
00544
00545 binaryWeightsBufferProcess( buffer, False);
00546
00547
00548 ipc_barrier();
00549
00550 if(status != 0) return status;
00551 }
00552 }
00553
00554 return LF_NO_ERROR;
00555 }
00556
00557
00558
00559 int LISSOMBinaryStateSaver::binaryWeightsFileReadInArbitraryOrder(FILE *file, LFBuffer *buffer)
00560 {
00561 static int done;
00562 done=0;
00563
00564 while (!done) {
00565
00566
00567 ipc_barrier();
00568
00569
00570
00571 if (AMPARENTPE) {
00572 LFTokenType nextToken;
00573 int i, ownerpe, pe_has_data[NPES];
00574
00575
00576 for (i=0; i<NPEs; i++)
00577 pe_has_data[i]=False;
00578
00579
00580 nextToken = peekToken(file);
00581 ownerpe = PEFORROW(tokenInfoa(nextToken));
00582 done = (tokenName(nextToken) != LFTOK_ROW_HEADER);
00583
00584
00585 while (!done && !pe_has_data[ownerpe]) {
00586 int row_length;
00587
00588 readTokenExpecting(LFTOK_ROW_HEADER,file);
00589 row_length = readInteger(file);
00590
00591 LFBufferRead( buffer, file, row_length);
00592 pe_has_data[ownerpe]=True;
00593
00594 if (!PEISME(ownerpe)) {
00595 LFBufferPut( buffer, ownerpe);
00596 LFBufferClear( buffer );
00597 }
00598
00599 nextToken = peekToken(file);
00600 ownerpe = PEFORROW(tokenInfoa(nextToken));
00601 done = (tokenName(nextToken) != LFTOK_ROW_HEADER);
00602 }
00603 }
00604
00605
00606 ipc_barrier();
00607 ipc_get( &done, IPC_INT, 1, PARENTPE);
00608
00609
00610 #ifdef CRAY
00611 #pragma _CRI suppress (buffer)
00612 #endif
00613 if (LFBufferLength(buffer)!=0)
00614 binaryWeightsBufferProcess(buffer, False);
00615 }
00616
00617 if(status != 0) return status;
00618 return LF_NO_ERROR;
00619 }
00620
00621
00622
00623 #define MAKE_SURE_NEURON_HEADER_INFO_AVAILABLE \
00624 if (current_map_row == Uninitialized || current_j == Uninitialized) { \
00625 ipc_notify(IPC_ALL,IPC_ERROR,"Missing neuron header"); \
00626 return LF_ERROR; \
00627 }
00628
00629
00630
00632 int LISSOMBinaryStateSaver::binaryWeightsBufferProcess( LFBuffer *buffer, int verify)
00633 {
00634 LFTokenType thisToken;
00635 int max_eye_data_found=-1;
00636
00637 #ifdef LF_DEBUG_FILE
00638 int offset;
00639 #endif
00640
00641 int current_local_row = Uninitialized;
00642 int current_map_row = Uninitialized;
00643 int current_j = Uninitialized;
00644
00645
00646
00647 int bufferStart = buffer->start;
00648 int bufferEnd = buffer->end;
00649
00650
00651 do
00652 {
00653 if(status != LF_NO_ERROR) return status;
00654
00655 #ifdef LF_DEBUG_FILE
00656 offset = buffer->start;
00657 #endif
00658 thisToken = LFBufferReadToken(buffer);
00659 #ifdef LF_DEBUG_FILE
00660 printToken( thisToken, offset );
00661 #endif
00662
00663 switch(tokenName(thisToken)){
00664
00665 case LFTOK_NEURON_HEADER_ORIG:
00666 case LFTOK_NEURON_HEADER_BUG:
00667
00668 if (current_map_row != Uninitialized || current_j != Uninitialized) {
00669 ipc_notify(IPC_ALL,IPC_ERROR,"Missing neuron trailer");
00670 return LF_ERROR;
00671 }
00672
00673 current_map_row = tokenInfoa(thisToken);
00674 current_j = tokenInfob(thisToken);
00675 current_local_row = LOCALROW(current_map_row);
00676
00677 compareOrSetInt(&lm.cortex_map[current_map_row][current_j].centerx,
00678 LFBufferReadInteger(buffer),
00679 verify, "centerx");
00680 compareOrSetInt(&lm.cortex_map[current_map_row][current_j].centery,
00681 LFBufferReadInteger(buffer),
00682 verify, "centery");
00683
00684 max_eye_data_found=-1;
00685
00686 if (tokenName(thisToken)==LFTOK_NEURON_HEADER_BUG) {
00687 int which_eye;
00688 for (which_eye = 0; which_eye < lm.num_aff_inputs(); which_eye++) {
00689 #ifdef NO_ANALYZE
00690 LFBufferReadInteger(buffer);
00691 #else
00692 compareOrSetInt(&or_pref[which_eye][current_map_row][current_j],
00693 LFBufferReadInteger(buffer),
00694 verify, "orientation preference");
00695 #endif
00696 }
00697 }
00698
00699 break;
00700
00701 case LFTOK_AFF_WEIGHTS:
00702 {
00703 int x,y,eye;
00704 const int rf_width = tokenInfoa(thisToken);
00705 const int which_eye = tokenInfob(thisToken);
00706 const int eye_start = (which_eye==LF_ALL_EYES ? 0 : which_eye);
00707 const int eye_bound = (which_eye==LF_ALL_EYES ? lm.num_aff_inputs() : which_eye+1);
00708 const double wt_scale = 2.0/lm.num_aff_inputs();
00709
00710 if (which_eye!=LF_ALL_EYES)
00711 max_eye_data_found = MAX(max_eye_data_found,which_eye);
00712
00713 compareParameter((rf_width-1)/2, lm.rf_radius, "rf_radius" );
00714
00715 MAKE_SURE_NEURON_HEADER_INFO_AVAILABLE;
00716
00717 for (x=0; x<rf_width; x++)
00718 for (y=0; y<rf_width; y++) {
00719 a_weight aFloat = wt_scale * LFBufferReadFloat(buffer);
00720
00721 for (eye=eye_start; eye<eye_bound; eye++)
00722 compareOrSet_a_weight(&lm.wts[current_local_row][current_j].weights[eye][x][y],
00723 aFloat, verify, "afferent weight");
00724 }
00725 }
00726 break;
00727
00728
00729 case LFTOK_LEXC_WEIGHTS:
00730 MAKE_SURE_NEURON_HEADER_INFO_AVAILABLE;
00731 binaryWeightsBufferReadLatWeights( buffer, thisToken,
00732 current_map_row, current_j,
00733 lm.exc_rad, lm.exc_array_width,
00734 &(lm.wts[current_local_row][current_j].lat_exc_wts[0]),
00735 verify,"lateral excitatory weight");
00736 break;
00737
00738 case LFTOK_LEXC_WEIGHTS_OLD:
00739 {
00740 int start_index, end_index, i;
00741 static int ignoring_weights = False;
00742
00743 start_index = tokenInfoa(thisToken);
00744 end_index = tokenInfob(thisToken);
00745
00746 MAKE_SURE_NEURON_HEADER_INFO_AVAILABLE;
00747
00748 for (i=start_index; i<=end_index; i++) {
00749 l_weight aFloat = LFBufferReadFloat(buffer);
00750
00751 if (!ignoring_weights && (end_index > lm.lat_exc_dimension)) {
00752 if (!load_afferent_weights_only)
00753 ipc_notify(IPC_ALL,IPC_WARNING,"Not enough space for the lateral excitatory weights; ignoring them");
00754 ignoring_weights = True;
00755 }
00756
00757 if (!ignoring_weights && !load_afferent_weights_only)
00758 compareOrSet_l_weight(&lm.wts[current_local_row][current_j].lat_exc_wts[i],
00759 aFloat, verify, "lateral excitatory weight");
00760 }
00761 }
00762 break;
00763
00764
00765 case LFTOK_LINH_WEIGHT_CHUNK:
00766 {
00767 int i;
00768 int start_index, end_index;
00769 static int ignoring_weights = False;
00770
00771 start_index = tokenInfoa(thisToken);
00772 end_index = tokenInfob(thisToken);
00773
00774 MAKE_SURE_NEURON_HEADER_INFO_AVAILABLE;
00775
00776 for (i=start_index; i<=end_index; i++) {
00777 l_weight aFloat = LFBufferReadFloat(buffer);
00778
00779 if (!ignoring_weights && (end_index > lm.lat_inh_dimension)) {
00780 if (!load_afferent_weights_only)
00781 ipc_notify(IPC_ALL,IPC_WARNING,"Not enough space for the lateral inhibitory weights; ignoring them");
00782 ignoring_weights = True;
00783 }
00784
00785 if (!ignoring_weights && !load_afferent_weights_only)
00786 compareOrSet_l_weight(&lm.wts[current_local_row][current_j].lat_inh_wts[i],
00787 aFloat, verify, "lateral inhibitory weight");
00788 }
00789 }
00790 break;
00791
00792
00793 case LFTOK_NEURON_TRAILER:
00794 if ((tokenInfoa(thisToken) != current_map_row) ||
00795 (tokenInfob(thisToken) != current_j)) {
00796 status = LF_ERROR;
00797 ipc_notify(IPC_ALL,IPC_ERROR,"File format error -- neuron trailer");
00798 }
00799
00800
00801
00802 if (max_eye_data_found >= 0 && lm.num_aff_inputs() < max_eye_data_found+1) {
00803 static int warned=False;
00804 if (!warned) {
00805 ipc_notify(IPC_ONE,IPC_CAUTION,"Data in file was for %d eyes; ignoring eyes larger than %d",
00806 max_eye_data_found+1,lm.num_aff_inputs()-1);
00807 warned=True;
00808 }
00809 }
00810
00811 if (max_eye_data_found >= 0 && lm.num_aff_inputs() > max_eye_data_found+1) {
00812 int x,y,eye;
00813 static int warned=False;
00814
00815 if (!warned) {
00816 ipc_notify(IPC_ONE,IPC_CAUTION,"Data in file was for %d eyes; extending to %d eyes",
00817 max_eye_data_found+1,lm.num_aff_inputs());
00818 warned=True;
00819 }
00820
00821 for (x=0; x<1+lm.rf_radius*2; x++)
00822 for (y=0; y<1+lm.rf_radius*2; y++)
00823 for (eye=max_eye_data_found+1; eye<lm.num_aff_inputs(); eye++)
00824 lm.wts[current_local_row][current_j].weights[eye][x][y] =
00825 lm.wts[current_local_row][current_j].weights[max_eye_data_found][x][y];
00826 }
00827
00828 current_map_row = Uninitialized;
00829 current_local_row = Uninitialized;
00830 current_j = Uninitialized;
00831 break;
00832
00833
00834 default:
00835 status = LF_ERROR;
00836 ipc_notify(IPC_ALL,IPC_ERROR,"Error in input file -- unknown token: %ld",
00837 (long)tokenName(thisToken));
00838 }
00839 } while (LFBufferLength(buffer) > 0);
00840
00841
00842 LFBufferClear( buffer );
00843
00844
00845 if (verify){
00846 buffer->start = bufferStart;
00847 buffer->end = bufferEnd;
00848 }
00849
00850 return LF_NO_ERROR;
00851 }
00852
00853
00854
00856 void LISSOMBinaryStateSaver::printTokens( FILE *file )
00857 {
00858 int offset;
00859 LFTokenType token;
00860 f32 float32;
00861 i32 int32;
00862 int i;
00863
00864
00865 if (AMPARENTPE)
00866 do {
00867 offset = ftell(file);
00868
00869 token = readToken(file);
00870
00871 printToken( token, offset );
00872
00873 if ( (tokenName(token) >= SMALLEST_LFTOK) && (tokenName(token) <= LARGEST_LFTOK) )
00874 for(i=2; i<tokenLength(token); i++) {
00875 offset = ftell(file);
00876 int32 = (i32)readInteger(file);
00877 fseek(file, offset, SEEK_SET);
00878 float32 = (f32)readFloat(file);
00879
00880 ipc_notify(IPC_ALL,IPC_STD,"Offset: %#6x Hex: %10x Int: %11d Float: %e",
00881 (int)offset,(int)int32,(int)int32,(double)float32);
00882 }
00883 }
00884 while (tokenName(token) != LFTOK_SNAPSHOT_TRAILER);
00885 }
00886
00887
00888
00889 void LISSOMBinaryStateSaver::printTokensInBuffer( LFBuffer *buffer )
00890 {
00891 int offset;
00892 LFTokenType token;
00893 f32 float32;
00894 i32 int32;
00895 int i;
00896 int bufferStart = buffer->start;
00897 int bufferEnd = buffer->end;
00898
00899
00900 if (AMPARENTPE)
00901 do {
00902 offset = buffer->start;
00903
00904 token = LFBufferReadToken(buffer);
00905
00906 printToken( token, offset );
00907
00908 if ( (tokenName(token) >= SMALLEST_LFTOK) && (tokenName(token) <= LARGEST_LFTOK) )
00909 for(i=2; i<tokenLength(token); i++) {
00910 offset = buffer->start;
00911 int32 = (i32)LFBufferReadInteger(buffer);
00912 buffer->start = offset;
00913 float32 = (f32)LFBufferReadFloat(buffer);
00914
00915 ipc_notify(IPC_ALL,IPC_STD,"Offset: %#6x Hex: %10x Int: %11d Float: %e",
00916 (int)offset,(int)int32,(int)int32,(double)float32);
00917 }
00918 }
00919 while (LFBufferLength(buffer)>0);
00920
00921 buffer->start = bufferStart;
00922 buffer->end = bufferEnd;
00923 }
00924
00925
00926
00927
00928
00929
00930
00935 LISSOMBinaryStateSaver::LFTokenType LISSOMBinaryStateSaver::makeToken(int name, int length, int infoa, int infob )
00936 {
00937 LFTokenType temp;
00938 temp.right=
00939 ( ((i32)infob & 0xFFFF) ) |
00940 ( ((i32)infoa & 0xFFFF) << 16);
00941
00942 temp.left=
00943 ( ((i32)length & 0xFFFF) ) |
00944 ( ((i32)name & 0xFFFF) << 16);
00945
00946 return temp;
00947 }
00948
00949
00950
00951
00952 int LISSOMBinaryStateSaver::tokenName( LFTokenType token ) { return (int)((token.left >> 16) ); }
00953 int LISSOMBinaryStateSaver::tokenLength( LFTokenType token ) { return (int)((token.left ) & 0xFFFF); }
00954 int LISSOMBinaryStateSaver::tokenInfoa( LFTokenType token ) { return (int)((token.right >> 16) & 0xFFFF); }
00955 int LISSOMBinaryStateSaver::tokenInfob( LFTokenType token ) { return (int)((token.right ) & 0xFFFF); }
00956
00957
00958
00959 const char* LISSOMBinaryStateSaver::tokenNameString(LFTokenType token)
00960 {
00961 static char buf[20];
00962
00963 switch (tokenName(token)) {
00964 case LFTOK_SNAPSHOT_HEADER: return("SNAPSHOT_HEADER");
00965 case LFTOK_ROW_HEADER: return("ROW_HEADER");
00966 case LFTOK_NEURON_HEADER_ORIG:return("NEURON_HEADER_ORIG");
00967 case LFTOK_NEURON_HEADER_BUG: return("NEURON_HEADER_BUG");
00968 case LFTOK_AFF_WEIGHTS: return("AFF_WEIGHTS");
00969 case LFTOK_LEXC_WEIGHTS_OLD: return("LEXC_WEIGHTS_OLD");
00970 case LFTOK_LEXC_WEIGHTS: return("LEXC_WEIGHTS");
00971 case LFTOK_LINH_WEIGHT_CHUNK: return("LINH_WEIGHT_CHUNK");
00972 case LFTOK_NEURON_TRAILER: return("NEURON_TRAILER");
00973 case LFTOK_SNAPSHOT_TRAILER: return("SNAPSHOT_TRAILER");
00974 default:
00975 sprintf(buf,"Token: %4d", (int)tokenName(token));
00976 return buf;
00977 }
00978 }
00979
00980
00981
00982 void LISSOMBinaryStateSaver::printToken( LFTokenType token, int offset )
00983 {
00984 ipc_notify(IPC_ALL,IPC_STD,"Offset: %#6x %-18s Length: %3d Infoa: %3d Infob: %3d",
00985 offset,tokenNameString(token),(int)tokenLength(token),
00986 (int)tokenInfoa(token),(int)tokenInfob(token));
00987 }
00988
00989
00990
00991
00992
00993
00994
00996 void LISSOMBinaryStateSaver::LFBufferGet( LFBuffer *buffer, int pe )
00997 {
00998 ipc_get64(&(buffer->start), 1, pe);
00999 ipc_get64(&(buffer->end), 1, pe);
01000 ipc_get32(&(buffer->data[0]), buffer->end + 1, pe);
01001 }
01002
01003
01004
01006 void LISSOMBinaryStateSaver::LFBufferPut( LFBuffer *buffer, int pe )
01007 {
01008
01009
01010
01011
01012 #if (NPES>1)
01013 ipc_notify(IPC_ONE,IPC_ERROR,
01014 "Binary file saving is currently not supported on multi-PE architectures"),
01015 #else
01016 ipc_put64(&(buffer->start), 1, pe);
01017 ipc_put64(&(buffer->end), 1, pe);
01018 ipc_put32(&(buffer->data[0]), buffer->end + 1, pe);
01019 #endif
01020 }
01021
01022
01023
01025 void LISSOMBinaryStateSaver::LFBufferClear( LFBuffer *buffer )
01026 {
01027 buffer->start = 0;
01028 buffer->end = -1;
01029 }
01030
01031
01032
01034 int LISSOMBinaryStateSaver::LFBufferLength( LFBuffer *buffer )
01035 { return buffer->length(); }
01036
01037
01038
01040 int LISSOMBinaryStateSaver::LFBufferWrite( LFBuffer *buffer, FILE *file )
01041 {
01042 buffer->start += fwrite(&(buffer->data[buffer->start]), sizeof(buffer->data[0]),
01043 LFBufferLength(buffer), file);
01044
01045 if ((buffer->end - buffer->start + 1) !=0){
01046 ipc_notify(IPC_ALL,IPC_ERROR,"Cannot write buffer to file -- Disk or quota full?");
01047 return LF_ERROR;
01048 }
01049
01050 return LF_NO_ERROR;
01051 }
01052
01053
01054
01058 int LISSOMBinaryStateSaver::LFBufferRead( LFBuffer *buffer, FILE *file, int length)
01059 {
01060 buffer->ensure_space_available(length);
01061 buffer->end += fread( &buffer->data[buffer->end + 1],
01062 sizeof(buffer->data[0]), length, file);
01063
01064 return LF_NO_ERROR;
01065 }
01066
01067
01068
01070 int LISSOMBinaryStateSaver::LFBufferWriteToken(LFBuffer *buffer, LFTokenType token )
01071 {
01072 i32 words[2];
01073 words[0] = token.left;
01074 words[1] = token.right;
01075
01076 if (!bigendian) {
01077 words[0] = i32_swap_endian(words[0]);
01078 words[1] = i32_swap_endian(words[1]);
01079 }
01080
01081 buffer->ensure_space_available(3);
01082 buffer->data[++buffer->end] = words[0];
01083 buffer->data[++buffer->end] = words[1];
01084
01085 tokensWritten++;
01086
01087 return LF_NO_ERROR;
01088 }
01089
01090
01091
01093 LISSOMBinaryStateSaver::LFTokenType LISSOMBinaryStateSaver::LFBufferReadToken(LFBuffer *buffer )
01094 {
01095 LFTokenType token;
01096 i32 words[2];
01097
01098
01099
01100
01101 if ((buffer->end - buffer-> start) < 1)
01102 ipc_notify(IPC_ALL,IPC_ERROR,"Buffer is empty -- cannot read token");
01103
01104 words[0] = buffer->data[buffer->start++];
01105 words[1] = buffer->data[buffer->start++];
01106 if (!bigendian) {
01107 words[0] = i32_swap_endian(words[0]);
01108 words[1] = i32_swap_endian(words[1]);
01109 }
01110
01111 token.left = words[0];
01112 token.right = words[1];
01113
01114 tokensRead++;
01115
01116 if ( (tokenName(token) < SMALLEST_LFTOK) || (tokenName(token) > LARGEST_LFTOK) )
01117 ipc_notify(IPC_ALL,IPC_WARNING,"Unknown token: %08x %08x", (int)token.left, (int)token.right);
01118
01119 return token;
01120 }
01121
01122
01124 int LISSOMBinaryStateSaver::LFBufferWriteItem(LFBuffer *buffer, void *itemptr)
01125 {
01126
01127 LFBufferDataType item = *(LFBufferDataType *)itemptr;
01128 if (!bigendian)
01129 item = LFBufferDataType_swap_endian(item);
01130
01131
01132 buffer->ensure_space_available(1);
01133 buffer->data[++buffer->end] = item;
01134 return LF_NO_ERROR;
01135 }
01136
01137
01138
01140 LISSOMBinaryStateSaver::LFBufferDataType LISSOMBinaryStateSaver::LFBufferReadItem(LFBuffer *buffer)
01141 {
01142 LFBufferDataType item;
01143
01144
01145 if ((buffer->end - buffer->start) < 0){
01146 ipc_notify(IPC_ALL,IPC_ERROR,"Buffer is empty -- cannot read integer");
01147 return 0;
01148 }
01149
01150
01151 item = buffer->data[buffer->start++];
01152 if (!bigendian)
01153 item = LFBufferDataType_swap_endian(item);
01154
01155
01156 return item;
01157 }
01158
01159
01160
01163 int LISSOMBinaryStateSaver::LFBufferWriteFloat(LFBuffer *buffer, f32 aFloat )
01164 {
01165 assert(sizeof(f32)==sizeof(LFBufferDataType));
01166 return LFBufferWriteItem(buffer,&aFloat);
01167 }
01168
01169
01170
01172 f32 LISSOMBinaryStateSaver::LFBufferReadFloat(LFBuffer *buffer)
01173 {
01174 LFBufferDataType item = LFBufferReadItem(buffer);
01175 assert(sizeof(f32)==sizeof(LFBufferDataType));
01176 return *(f32 * )(void *)(&item);
01177 }
01178
01179
01180
01183 int LISSOMBinaryStateSaver::LFBufferWriteInteger(LFBuffer *buffer, int anInteger )
01184 {
01185 i32 output=(i32)anInteger;
01186 assert(sizeof(i32)==sizeof(LFBufferDataType));
01187 return LFBufferWriteItem(buffer,&output);
01188 }
01189
01190
01191
01193 int LISSOMBinaryStateSaver::LFBufferReadInteger(LFBuffer *buffer)
01194 { return (int) LFBufferReadItem(buffer); }
01195
01196
01197
01198
01199
01200
01201
01203 int LISSOMBinaryStateSaver::writeToken(FILE *file, LFTokenType token )
01204 {
01205 i32 words[2];
01206 words[0] = token.left;
01207 words[1] = token.right;
01208
01209 if (!bigendian) {
01210 words[0] = i32_swap_endian(words[0]);
01211 words[1] = i32_swap_endian(words[1]);
01212 }
01213
01214 if (2 != fwrite( &words, sizeof(words[0]), 2, file)){
01215 ipc_notify(IPC_ALL,IPC_ERROR,"Cannot write to file");
01216 return LF_ERROR;
01217 }
01218 tokensWritten++;
01219
01220 return LF_NO_ERROR;
01221 }
01222
01223
01224
01226 LISSOMBinaryStateSaver::LFTokenType LISSOMBinaryStateSaver::readToken(FILE *file )
01227 {
01228 LFTokenType token;
01229 i32 words[2];
01230
01231 if (2 != fread( &words, sizeof(words[0]), 2, file))
01232 ipc_notify(IPC_ALL,IPC_ERROR,"Cannot read token from file");
01233
01234 tokensRead++;
01235
01236 if (!bigendian) {
01237 words[0] = i32_swap_endian(words[0]);
01238 words[1] = i32_swap_endian(words[1]);
01239 }
01240
01241 token.left = words[0];
01242 token.right = words[1];
01243
01244 if ( (tokenName(token) < SMALLEST_LFTOK) || (tokenName(token) > LARGEST_LFTOK) )
01245 ipc_notify(IPC_ALL,IPC_WARNING,"Unknown token: %08x %08x", (int)token.left, (int)token.right);
01246
01247 return token;
01248 }
01249
01250
01251
01253 LISSOMBinaryStateSaver::LFTokenType LISSOMBinaryStateSaver::peekToken(FILE *file )
01254 {
01255 LFTokenType token;
01256 i32 words[2];
01257 long position = ftell(file);
01258
01259 if (2 != fread( &words, sizeof(words[0]), 2, file))
01260 ipc_notify(IPC_ALL,IPC_ERROR,"Cannot read token from file");
01261
01262 fseek(file, position, SEEK_SET);
01263
01264 if (!bigendian) {
01265 words[0] = i32_swap_endian(words[0]);
01266 words[1] = i32_swap_endian(words[1]);
01267 }
01268
01269 token.left = words[0];
01270 token.right = words[1];
01271
01272 if ( (tokenName(token) < SMALLEST_LFTOK) || (tokenName(token) > LARGEST_LFTOK) )
01273 ipc_notify(IPC_ALL,IPC_WARNING,"Unknown token: %08x %08x", (int)token.left, (int)token.right);
01274
01275 return token;
01276 }
01277
01278
01279
01281 LISSOMBinaryStateSaver::LFTokenType
01282 LISSOMBinaryStateSaver::readTokenExpecting(int tokenNameExpected, FILE *file)
01283 {
01284 int offset = ftell(file);
01285 LFTokenType token;
01286 token=readToken(file);
01287
01288 #ifdef LF_DEBUG_FILE
01289 printToken( token, offset );
01290 #endif
01291
01292 if (tokenName(token) != tokenNameExpected)
01293 ipc_notify(IPC_ALL,IPC_ERROR,"Expected token %s at offset %d but found %d. (Full token: 0x%08x %08x)",
01294 tokenNameString(makeToken(tokenNameExpected,0,0,0)), offset, (int)tokenName(token),
01295 (int)token.left, (int)token.right);
01296
01297 return token;
01298 }
01299
01300
01301
01303 int LISSOMBinaryStateSaver::writeItem(FILE *file, void *itemptr)
01304 {
01305 static int warningprinted = False;
01306 LFBufferDataType item = *(LFBufferDataType *)itemptr;
01307
01308 if (!bigendian)
01309 item = LFBufferDataType_swap_endian(item);
01310
01311 if (1 != fwrite( &item, sizeof(item), 1, file))
01312 if (!warningprinted) {
01313 ipc_notify(IPC_ALL,IPC_ERROR,"Cannot write to file");
01314 warningprinted=True;
01315 }
01316
01317 return LF_NO_ERROR;
01318 }
01319
01320
01321
01323 LISSOMBinaryStateSaver::LFBufferDataType
01324 LISSOMBinaryStateSaver::readItem(FILE* file)
01325 {
01326 LFBufferDataType item;
01327 static int warningprinted = False;
01328
01329 if (1 != fread( &item, sizeof(item), 1, file))
01330 if (!warningprinted) {
01331 ipc_notify(IPC_ALL,IPC_ERROR,"Cannot read from file");
01332 warningprinted=True;
01333 }
01334
01335 if (!bigendian)
01336 item = LFBufferDataType_swap_endian(item);
01337
01338 return item;
01339 }
01340
01341
01342
01345 int LISSOMBinaryStateSaver::writeFloat(FILE *file, f32 aFloat )
01346 {
01347 assert(sizeof(f32)==sizeof(LFBufferDataType));
01348 return writeItem(file,&aFloat);
01349 }
01350
01351
01352
01354 f32 LISSOMBinaryStateSaver::readFloat(FILE *file)
01355 {
01356 LFBufferDataType item = readItem(file);
01357 assert(sizeof(f32)==sizeof(LFBufferDataType));
01358 return *(f32 * )(void *)(&item);
01359 }
01360
01361
01362
01365 int LISSOMBinaryStateSaver::writeInteger(FILE *file, int anInteger )
01366 {
01367 i32 output=(i32)anInteger;
01368 assert(sizeof(i32)==sizeof(LFBufferDataType));
01369 return writeItem(file,&output);
01370 }
01371
01372
01373
01375 int LISSOMBinaryStateSaver::readInteger(FILE *file)
01376 { return (int)readItem(file); }
01377
01378
01379
01380
01381
01382
01383
01384
01386 int LISSOMBinaryStateSaver::compareParameter(int weight_file_parameter, int param_file_parameter, const char *description)
01387 {
01388 if (weight_file_parameter != param_file_parameter) {
01389 ipc_notify(IPC_ALL,IPC_ERROR,"Value for %s in weight file (%d) differs from value in param file (%d)",
01390 description, (int)weight_file_parameter, (int)param_file_parameter);
01391 return LF_ERROR;
01392 }
01393
01394 return LF_NO_ERROR;
01395 }
01396
01397
01398
01400 int LISSOMBinaryStateSaver::compareOrSetInt(int *destination, int value, int verify, const char *description)
01401 {
01402 if (!verify)
01403 *destination = value;
01404 else if (*destination != value) {
01405 static int warnings=0;
01406 warnings++;
01407 if (warnings < LF_MAXWARNINGS)
01408 ipc_notify(IPC_ALL,IPC_ERROR,"compareOrSetInt: Value for %s stored in buffer (%d) differs from value in memory (%d)",
01409 description, (int)value, (int)*destination);
01410 else if (warnings == LF_MAXWARNINGS)
01411 ipc_notify(IPC_ALL,IPC_ERROR,"compareOrSetInt: Maximum number of warnings reached (%d)",warnings);
01412 }
01413
01414 return *destination;
01415 }
01416
01417
01418
01422 #define compareOrSet_proc(type) \
01423 LISSOMBinaryStateSaver::type LISSOMBinaryStateSaver::compareOrSet_ ## type (type *destination, type value, int verify, const char *description) \
01424 { \
01425 if (!verify) \
01426 *destination = value; \
01427 else \
01428 \
01429 if ((*destination == 0 && ((*destination - value) > LF_FLOAT_TOLERANCE ))|| \
01430 (*destination != 0 && ((*destination - value)/(*destination)) > LF_FLOAT_TOLERANCE ) ) {\
01431 static int warnings=0; \
01432 warnings++; \
01433 if (warnings < LF_MAXWARNINGS) \
01434 ipc_notify(IPC_ALL,IPC_ERROR,"compareOrSet_" #type ": Value for %s stored in buffer (%e) differs from value in memory (%e)", \
01435 description, (double)value, (double)(*destination)); \
01436 else if (warnings == LF_MAXWARNINGS) \
01437 ipc_notify(IPC_ALL,IPC_ERROR,"compareOrSet_" #type ": Maximum number of warnings reached (%d)",warnings); \
01438 } \
01439 \
01440 return *destination; \
01441 }
01442
01443
01444
01445 compareOrSet_proc(a_weight)
01446 compareOrSet_proc(l_weight)
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489