Changeset a4fee13 for GenericIO.cxx
- Timestamp:
- 10/09/15 19:14:02 (9 years ago)
- Branches:
- master, pympi
- Children:
- 8f0a211
- Parents:
- 406b50a
- git-author:
- Hal Finkel <hfinkel@…> (10/09/15 19:14:02)
- git-committer:
- Hal Finkel <hfinkel@…> (10/09/15 19:14:02)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
GenericIO.cxx
rda65757 ra4fee13 238 238 } 239 239 240 static void bswap(void *v, size_t s) { 241 char *p = (char *) v; 242 for (size_t i = 0; i < s/2; ++i) 243 std::swap(p[i], p[s - (i+1)]); 244 } 245 246 // Using #pragma pack here, instead of __attribute__((packed)) because xlc, at 247 // least as of v12.1, won't take __attribute__((packed)) on non-POD and/or 248 // templated types. 249 #pragma pack(1) 250 251 template <typename T, bool IsBigEndian> 252 struct endian_specific_value { 253 operator T() const { 254 T rvalue = value; 255 if (IsBigEndian != isBigEndian()) 256 bswap(&rvalue, sizeof(T)); 257 258 return rvalue; 259 }; 260 261 endian_specific_value &operator = (T nvalue) { 262 if (IsBigEndian != isBigEndian()) 263 bswap(&nvalue, sizeof(T)); 264 265 value = nvalue; 266 return *this; 267 } 268 269 endian_specific_value &operator += (T nvalue) { 270 *this = *this + nvalue; 271 return *this; 272 } 273 274 endian_specific_value &operator -= (T nvalue) { 275 *this = *this - nvalue; 276 return *this; 277 } 278 279 private: 280 T value; 281 }; 282 240 283 static const size_t CRCSize = 8; 241 284 … … 244 287 static const char *MagicLE = "HACC01L"; 245 288 289 template <bool IsBigEndian> 246 290 struct GlobalHeader { 247 291 char Magic[MagicSize]; 248 uint64_tHeaderSize;249 uint64_tNElems; // The global total250 uint64_tDims[3];251 uint64_tNVars;252 uint64_tVarsSize;253 uint64_tVarsStart;254 uint64_tNRanks;255 uint64_tRanksSize;256 uint64_tRanksStart;257 uint64_tGlobalHeaderSize;258 doublePhysOrigin[3];259 doublePhysScale[3];260 uint64_tBlocksSize;261 uint64_tBlocksStart;262 } __attribute__((packed));292 endian_specific_value<uint64_t, IsBigEndian> HeaderSize; 293 endian_specific_value<uint64_t, IsBigEndian> NElems; // The global total 294 endian_specific_value<uint64_t, IsBigEndian> Dims[3]; 295 endian_specific_value<uint64_t, IsBigEndian> NVars; 296 endian_specific_value<uint64_t, IsBigEndian> VarsSize; 297 endian_specific_value<uint64_t, IsBigEndian> VarsStart; 298 endian_specific_value<uint64_t, IsBigEndian> NRanks; 299 endian_specific_value<uint64_t, IsBigEndian> RanksSize; 300 endian_specific_value<uint64_t, IsBigEndian> RanksStart; 301 endian_specific_value<uint64_t, IsBigEndian> GlobalHeaderSize; 302 endian_specific_value<double, IsBigEndian> PhysOrigin[3]; 303 endian_specific_value<double, IsBigEndian> PhysScale[3]; 304 endian_specific_value<uint64_t, IsBigEndian> BlocksSize; 305 endian_specific_value<uint64_t, IsBigEndian> BlocksStart; 306 }; 263 307 264 308 enum { … … 272 316 273 317 static const size_t NameSize = 256; 318 template <bool IsBigEndian> 274 319 struct VariableHeader { 275 320 char Name[NameSize]; 276 uint64_t Flags; 277 uint64_t Size; 278 } __attribute__((packed)); 279 321 endian_specific_value<uint64_t, IsBigEndian> Flags; 322 endian_specific_value<uint64_t, IsBigEndian> Size; 323 }; 324 325 template <bool IsBigEndian> 280 326 struct RankHeader { 281 uint64_tCoords[3];282 uint64_tNElems;283 uint64_tStart;284 uint64_tGlobalRank;285 } __attribute__((packed));327 endian_specific_value<uint64_t, IsBigEndian> Coords[3]; 328 endian_specific_value<uint64_t, IsBigEndian> NElems; 329 endian_specific_value<uint64_t, IsBigEndian> Start; 330 endian_specific_value<uint64_t, IsBigEndian> GlobalRank; 331 }; 286 332 287 333 static const size_t FilterNameSize = 8; 288 334 static const size_t MaxFilters = 4; 335 template <bool IsBigEndian> 289 336 struct BlockHeader { 290 337 char Filters[MaxFilters][FilterNameSize]; 291 uint64_t Start; 292 uint64_t Size; 293 } __attribute__((packed)); 294 338 endian_specific_value<uint64_t, IsBigEndian> Start; 339 endian_specific_value<uint64_t, IsBigEndian> Size; 340 }; 341 342 template <bool IsBigEndian> 295 343 struct CompressHeader { 296 uint64_tOrigCRC;297 } __attribute__((packed));344 endian_specific_value<uint64_t, IsBigEndian> OrigCRC; 345 }; 298 346 const char *CompressName = "BLOSC"; 347 348 #pragma pack() 299 349 300 350 unsigned GenericIO::DefaultFileIOType = FileIOPOSIX; … … 309 359 310 360 #ifndef GENERICIO_NO_MPI 361 void GenericIO::write() { 362 if (isBigEndian()) 363 write<true>(); 364 else 365 write<false>(); 366 } 367 311 368 // Note: writing errors are not currently recoverable (one rank may fail 312 369 // while the others don't). 370 template <bool IsBigEndian> 313 371 void GenericIO::write() { 314 const char *Magic = isBigEndian()? MagicBE : MagicLE;372 const char *Magic = IsBigEndian ? MagicBE : MagicLE; 315 373 316 374 uint64_t FileSize = 0; … … 383 441 } 384 442 385 RankHeader RHLocal;443 RankHeader<IsBigEndian> RHLocal; 386 444 int Dims[3], Periods[3], Coords[3]; 387 445 … … 417 475 } 418 476 419 vector<BlockHeader > LocalBlockHeaders;477 vector<BlockHeader<IsBigEndian> > LocalBlockHeaders; 420 478 vector<void *> LocalData; 421 479 vector<bool> LocalHasExtraSpace; … … 431 489 // Filters null by default, leave null starting address (needs to be 432 490 // calculated by the header-writing rank). 433 memset(&LocalBlockHeaders[i], 0, sizeof(BlockHeader ));491 memset(&LocalBlockHeaders[i], 0, sizeof(BlockHeader<IsBigEndian>)); 434 492 if (ShouldCompress) { 435 LocalCData[i].resize(sizeof(CompressHeader ));436 437 CompressHeader *CH = (CompressHeader*) &LocalCData[i][0];493 LocalCData[i].resize(sizeof(CompressHeader<IsBigEndian>)); 494 495 CompressHeader<IsBigEndian> *CH = (CompressHeader<IsBigEndian>*) &LocalCData[i][0]; 438 496 CH->OrigCRC = crc64_omp(Vars[i].Data, Vars[i].Size*NElems); 439 497 … … 455 513 LocalCData[i].resize(LocalCData[i].size() + NElems*Vars[i].Size); 456 514 if (blosc_compress(9, 1, Vars[i].Size, NElems*Vars[i].Size, Vars[i].Data, 457 &LocalCData[i][0] + sizeof(CompressHeader ),515 &LocalCData[i][0] + sizeof(CompressHeader<IsBigEndian>), 458 516 NElems*Vars[i].Size) <= 0) 459 517 goto nocomp; … … 461 519 strncpy(LocalBlockHeaders[i].Filters[0], CompressName, FilterNameSize); 462 520 size_t CNBytes, CCBytes, CBlockSize; 463 blosc_cbuffer_sizes(&LocalCData[i][0] + sizeof(CompressHeader ),521 blosc_cbuffer_sizes(&LocalCData[i][0] + sizeof(CompressHeader<IsBigEndian>), 464 522 &CNBytes, &CCBytes, &CBlockSize); 465 LocalCData[i].resize(CCBytes + sizeof(CompressHeader ));523 LocalCData[i].resize(CCBytes + sizeof(CompressHeader<IsBigEndian>)); 466 524 467 525 LocalBlockHeaders[i].Size = LocalCData[i].size(); … … 481 539 482 540 if (SplitRank == 0) { 483 uint64_t HeaderSize = sizeof(GlobalHeader ) + Vars.size()*sizeof(VariableHeader) +484 SplitNRanks*sizeof(RankHeader ) + CRCSize;541 uint64_t HeaderSize = sizeof(GlobalHeader<IsBigEndian>) + Vars.size()*sizeof(VariableHeader<IsBigEndian>) + 542 SplitNRanks*sizeof(RankHeader<IsBigEndian>) + CRCSize; 485 543 if (NeedsBlockHeaders) 486 HeaderSize += SplitNRanks*Vars.size()*sizeof(BlockHeader );544 HeaderSize += SplitNRanks*Vars.size()*sizeof(BlockHeader<IsBigEndian>); 487 545 488 546 vector<char> Header(HeaderSize, 0); 489 GlobalHeader *GH = (GlobalHeader*) &Header[0];547 GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &Header[0]; 490 548 std::copy(Magic, Magic + MagicSize, GH->Magic); 491 549 GH->HeaderSize = HeaderSize - CRCSize; … … 493 551 std::copy(Dims, Dims + 3, GH->Dims); 494 552 GH->NVars = Vars.size(); 495 GH->VarsSize = sizeof(VariableHeader );496 GH->VarsStart = sizeof(GlobalHeader );553 GH->VarsSize = sizeof(VariableHeader<IsBigEndian>); 554 GH->VarsStart = sizeof(GlobalHeader<IsBigEndian>); 497 555 GH->NRanks = SplitNRanks; 498 GH->RanksSize = sizeof(RankHeader );499 GH->RanksStart = GH->VarsStart + Vars.size()*sizeof(VariableHeader );500 GH->GlobalHeaderSize = sizeof(GlobalHeader );556 GH->RanksSize = sizeof(RankHeader<IsBigEndian>); 557 GH->RanksStart = GH->VarsStart + Vars.size()*sizeof(VariableHeader<IsBigEndian>); 558 GH->GlobalHeaderSize = sizeof(GlobalHeader<IsBigEndian>); 501 559 std::copy(PhysOrigin, PhysOrigin + 3, GH->PhysOrigin); 502 560 std::copy(PhysScale, PhysScale + 3, GH->PhysScale); … … 504 562 GH->BlocksSize = GH->BlocksStart = 0; 505 563 } else { 506 GH->BlocksSize = sizeof(BlockHeader );507 GH->BlocksStart = GH->RanksStart + SplitNRanks*sizeof(RankHeader );564 GH->BlocksSize = sizeof(BlockHeader<IsBigEndian>); 565 GH->BlocksStart = GH->RanksStart + SplitNRanks*sizeof(RankHeader<IsBigEndian>); 508 566 } 509 567 510 568 uint64_t RecordSize = 0; 511 VariableHeader *VH = (VariableHeader*) &Header[GH->VarsStart];569 VariableHeader<IsBigEndian> *VH = (VariableHeader<IsBigEndian> *) &Header[GH->VarsStart]; 512 570 for (size_t i = 0; i < Vars.size(); ++i, ++VH) { 513 571 string VName(Vars[i].Name); … … 515 573 516 574 std::copy(VName.begin(), VName.end(), VH->Name); 517 if (Vars[i].IsFloat) VH->Flags |= FloatValue; 518 if (Vars[i].IsSigned) VH->Flags |= SignedValue; 519 if (Vars[i].IsPhysCoordX) VH->Flags |= ValueIsPhysCoordX; 520 if (Vars[i].IsPhysCoordY) VH->Flags |= ValueIsPhysCoordY; 521 if (Vars[i].IsPhysCoordZ) VH->Flags |= ValueIsPhysCoordZ; 522 if (Vars[i].MaybePhysGhost) VH->Flags |= ValueMaybePhysGhost; 575 uint64_t VFlags = 0; 576 if (Vars[i].IsFloat) VFlags |= FloatValue; 577 if (Vars[i].IsSigned) VFlags |= SignedValue; 578 if (Vars[i].IsPhysCoordX) VFlags |= ValueIsPhysCoordX; 579 if (Vars[i].IsPhysCoordY) VFlags |= ValueIsPhysCoordY; 580 if (Vars[i].IsPhysCoordZ) VFlags |= ValueIsPhysCoordZ; 581 if (Vars[i].MaybePhysGhost) VFlags |= ValueMaybePhysGhost; 582 VH->Flags = VFlags; 523 583 RecordSize += VH->Size = Vars[i].Size; 524 584 } … … 530 590 if (NeedsBlockHeaders) { 531 591 MPI_Gather(&LocalBlockHeaders[0], 532 Vars.size()*sizeof(BlockHeader ), MPI_BYTE,592 Vars.size()*sizeof(BlockHeader<IsBigEndian>), MPI_BYTE, 533 593 &Header[GH->BlocksStart], 534 Vars.size()*sizeof(BlockHeader ), MPI_BYTE,594 Vars.size()*sizeof(BlockHeader<IsBigEndian>), MPI_BYTE, 535 595 0, SplitComm); 536 596 537 BlockHeader *BH = (BlockHeader*) &Header[GH->BlocksStart];597 BlockHeader<IsBigEndian> *BH = (BlockHeader<IsBigEndian> *) &Header[GH->BlocksStart]; 538 598 for (int i = 0; i < SplitNRanks; ++i) 539 599 for (size_t j = 0; j < Vars.size(); ++j, ++BH) { … … 544 604 } 545 605 546 RankHeader *RH = (RankHeader*) &Header[GH->RanksStart];606 RankHeader<IsBigEndian> *RH = (RankHeader<IsBigEndian> *) &Header[GH->RanksStart]; 547 607 RH->Start = HeaderSize; ++RH; 548 608 for (int i = 1; i < SplitNRanks; ++i, ++RH) { 549 609 RH->Start = 550 ((BlockHeader *) &Header[GH->BlocksStart])[i*Vars.size()].Start;610 ((BlockHeader<IsBigEndian> *) &Header[GH->BlocksStart])[i*Vars.size()].Start; 551 611 GH->NElems += RH->NElems; 552 612 } … … 556 616 FileSize = BH[-1].Start + LastData; 557 617 } else { 558 RankHeader *RH = (RankHeader*) &Header[GH->RanksStart];618 RankHeader<IsBigEndian> *RH = (RankHeader<IsBigEndian> *) &Header[GH->RanksStart]; 559 619 RH->Start = HeaderSize; ++RH; 560 620 for (int i = 1; i < SplitNRanks; ++i, ++RH) { … … 578 638 if (NeedsBlockHeaders) 579 639 MPI_Scatter(&Header[GH->BlocksStart], 580 sizeof(BlockHeader )*Vars.size(), MPI_BYTE,640 sizeof(BlockHeader<IsBigEndian>)*Vars.size(), MPI_BYTE, 581 641 &LocalBlockHeaders[0], 582 sizeof(BlockHeader )*Vars.size(), MPI_BYTE,642 sizeof(BlockHeader<IsBigEndian>)*Vars.size(), MPI_BYTE, 583 643 0, SplitComm); 584 644 … … 601 661 MPI_Gather(&RHLocal, sizeof(RHLocal), MPI_BYTE, 0, 0, MPI_BYTE, 0, SplitComm); 602 662 if (NeedsBlockHeaders) 603 MPI_Gather(&LocalBlockHeaders[0], Vars.size()*sizeof(BlockHeader ),663 MPI_Gather(&LocalBlockHeaders[0], Vars.size()*sizeof(BlockHeader<IsBigEndian>), 604 664 MPI_BYTE, 0, 0, MPI_BYTE, 0, SplitComm); 605 665 MPI_Scatter(0, 0, MPI_BYTE, &RHLocal, sizeof(RHLocal), MPI_BYTE, 0, SplitComm); 606 666 if (NeedsBlockHeaders) 607 MPI_Scatter(0, 0, MPI_BYTE, &LocalBlockHeaders[0], sizeof(BlockHeader )*Vars.size(),667 MPI_Scatter(0, 0, MPI_BYTE, &LocalBlockHeaders[0], sizeof(BlockHeader<IsBigEndian>)*Vars.size(), 608 668 MPI_BYTE, 0, SplitComm); 609 669 } … … 678 738 #endif // GENERICIO_NO_MPI 679 739 740 template <bool IsBigEndian> 741 void GenericIO::readHeaderLeader(void *GHPtr, bool MustMatch, int SplitNRanks, 742 string &LocalFileName, uint64_t &HeaderSize, vector<char> &Header) { 743 GlobalHeader<IsBigEndian> &GH = *(GlobalHeader<IsBigEndian> *) GHPtr; 744 745 if (MustMatch) { 746 if (SplitNRanks != (int) GH.NRanks) { 747 stringstream ss; 748 ss << "Won't read " << LocalFileName << ": communicator-size mismatch: " << 749 "current: " << SplitNRanks << ", file: " << GH.NRanks; 750 throw runtime_error(ss.str()); 751 } 752 753 #ifndef GENERICIO_NO_MPI 754 int TopoStatus; 755 MPI_Topo_test(Comm, &TopoStatus); 756 if (TopoStatus == MPI_CART) { 757 int Dims[3], Periods[3], Coords[3]; 758 MPI_Cart_get(Comm, 3, Dims, Periods, Coords); 759 760 bool DimsMatch = true; 761 for (int i = 0; i < 3; ++i) { 762 if ((uint64_t) Dims[i] != GH.Dims[i]) { 763 DimsMatch = false; 764 break; 765 } 766 } 767 768 if (!DimsMatch) { 769 stringstream ss; 770 ss << "Won't read " << LocalFileName << 771 ": communicator-decomposition mismatch: " << 772 "current: " << Dims[0] << "x" << Dims[1] << "x" << Dims[2] << 773 ", file: " << GH.Dims[0] << "x" << GH.Dims[1] << "x" << 774 GH.Dims[2]; 775 throw runtime_error(ss.str()); 776 } 777 } 778 #endif 779 } 780 781 HeaderSize = GH.HeaderSize; 782 Header.resize(HeaderSize + CRCSize, 0xFE /* poison */); 783 FH.get()->read(&Header[0], HeaderSize + CRCSize, 0, "header"); 784 785 uint64_t CRC = crc64_omp(&Header[0], HeaderSize + CRCSize); 786 if (CRC != (uint64_t) -1) { 787 throw runtime_error("Header CRC check failed: " + LocalFileName); 788 } 789 } 790 680 791 // Note: Errors from this function should be recoverable. This means that if 681 792 // one rank throws an exception, then all ranks should. 682 793 void GenericIO::openAndReadHeader(bool MustMatch, int EffRank, bool CheckPartMap) { 683 const char *Magic = isBigEndian() ? MagicBE : MagicLE;684 const char *MagicInv = isBigEndian() ? MagicLE : MagicBE;685 686 794 int NRanks, Rank; 687 795 #ifndef GENERICIO_NO_MPI … … 785 893 FH.get()->open(LocalFileName, true); 786 894 787 GlobalHeader GH; 788 FH.get()->read(&GH, sizeof(GlobalHeader), 0, "global header"); 789 790 if (string(GH.Magic, GH.Magic + MagicSize - 1) != Magic) { 791 string Error; 792 if (string(GH.Magic, GH.Magic + MagicSize - 1) == MagicInv) { 793 Error = "wrong endianness"; 794 } else { 795 Error = "invalid file-type identifier"; 796 } 895 GlobalHeader<false> GH; // endianness does not matter yet... 896 FH.get()->read(&GH, sizeof(GlobalHeader<false>), 0, "global header"); 897 898 if (string(GH.Magic, GH.Magic + MagicSize - 1) == MagicLE) { 899 readHeaderLeader<false>(&GH, MustMatch, SplitNRanks, LocalFileName, 900 HeaderSize, Header); 901 } else if (string(GH.Magic, GH.Magic + MagicSize - 1) == MagicBE) { 902 readHeaderLeader<true>(&GH, MustMatch, SplitNRanks, LocalFileName, 903 HeaderSize, Header); 904 } else { 905 string Error = "invalid file-type identifier"; 797 906 throw runtime_error("Won't read " + LocalFileName + ": " + Error); 798 }799 800 if (MustMatch) {801 if (SplitNRanks != (int) GH.NRanks) {802 stringstream ss;803 ss << "Won't read " << LocalFileName << ": communicator-size mismatch: " <<804 "current: " << SplitNRanks << ", file: " << GH.NRanks;805 throw runtime_error(ss.str());806 }807 808 #ifndef GENERICIO_NO_MPI809 int TopoStatus;810 MPI_Topo_test(Comm, &TopoStatus);811 if (TopoStatus == MPI_CART) {812 int Dims[3], Periods[3], Coords[3];813 MPI_Cart_get(Comm, 3, Dims, Periods, Coords);814 815 bool DimsMatch = true;816 for (int i = 0; i < 3; ++i) {817 if ((uint64_t) Dims[i] != GH.Dims[i]) {818 DimsMatch = false;819 break;820 }821 }822 823 if (!DimsMatch) {824 stringstream ss;825 ss << "Won't read " << LocalFileName <<826 ": communicator-decomposition mismatch: " <<827 "current: " << Dims[0] << "x" << Dims[1] << "x" << Dims[2] <<828 ", file: " << GH.Dims[0] << "x" << GH.Dims[1] << "x" <<829 GH.Dims[2];830 throw runtime_error(ss.str());831 }832 }833 #endif834 }835 836 HeaderSize = GH.HeaderSize;837 Header.resize(HeaderSize + CRCSize, 0xFE /* poison */);838 FH.get()->read(&Header[0], HeaderSize + CRCSize, 0, "header");839 840 uint64_t CRC = crc64_omp(&Header[0], HeaderSize + CRCSize);841 if (CRC != (uint64_t) -1) {842 throw runtime_error("Header CRC check failed: " + LocalFileName);843 907 } 844 908 … … 872 936 #endif 873 937 938 874 939 FH.getHeaderCache().clear(); 940 941 GlobalHeader<false> *GH = (GlobalHeader<false> *) &Header[0]; 942 FH.setIsBigEndian(string(GH->Magic, GH->Magic + MagicSize - 1) == MagicBE); 943 875 944 FH.getHeaderCache().swap(Header); 876 945 OpenFileName = LocalFileName; … … 905 974 906 975 int GenericIO::readNRanks() { 976 if (FH.isBigEndian()) 977 return readNRanks<true>(); 978 return readNRanks<false>(); 979 } 980 981 template <bool IsBigEndian> 982 int GenericIO::readNRanks() { 907 983 if (RankMap.size()) 908 984 return RankMap.size(); 909 985 910 986 assert(FH.getHeaderCache().size() && "HeaderCache must not be empty"); 911 GlobalHeader *GH = (GlobalHeader*) &FH.getHeaderCache()[0];987 GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 912 988 return (int) GH->NRanks; 913 989 } 914 990 991 void GenericIO::readDims(int Dims[3]) { 992 if (FH.isBigEndian()) 993 readDims<true>(Dims); 994 else 995 readDims<false>(Dims); 996 } 997 998 template <bool IsBigEndian> 915 999 void GenericIO::readDims(int Dims[3]) { 916 1000 assert(FH.getHeaderCache().size() && "HeaderCache must not be empty"); 917 GlobalHeader *GH = (GlobalHeader*) &FH.getHeaderCache()[0];1001 GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 918 1002 std::copy(GH->Dims, GH->Dims + 3, Dims); 919 1003 } 920 1004 1005 uint64_t GenericIO::readTotalNumElems() { 1006 if (FH.isBigEndian()) 1007 return readTotalNumElems<true>(); 1008 return readTotalNumElems<false>(); 1009 } 1010 1011 template <bool IsBigEndian> 921 1012 uint64_t GenericIO::readTotalNumElems() { 922 1013 if (RankMap.size()) … … 924 1015 925 1016 assert(FH.getHeaderCache().size() && "HeaderCache must not be empty"); 926 GlobalHeader *GH = (GlobalHeader*) &FH.getHeaderCache()[0];1017 GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 927 1018 return GH->NElems; 928 1019 } 929 1020 1021 void GenericIO::readPhysOrigin(double Origin[3]) { 1022 if (FH.isBigEndian()) 1023 readPhysOrigin<true>(Origin); 1024 else 1025 readPhysOrigin<false>(Origin); 1026 } 1027 1028 // Define a "safe" version of offsetof (offsetof itself might not work for 1029 // non-POD types, and at least xlC v12.1 will complain about this if you try). 1030 #define offsetof_safe(S, F) (size_t(&(S)->F) - size_t(S)) 1031 1032 template <bool IsBigEndian> 930 1033 void GenericIO::readPhysOrigin(double Origin[3]) { 931 1034 assert(FH.getHeaderCache().size() && "HeaderCache must not be empty"); 932 GlobalHeader *GH = (GlobalHeader*) &FH.getHeaderCache()[0];933 if (offsetof (GlobalHeader, PhysOrigin) >= GH->GlobalHeaderSize) {1035 GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 1036 if (offsetof_safe(GH, PhysOrigin) >= GH->GlobalHeaderSize) { 934 1037 std::fill(Origin, Origin + 3, 0.0); 935 1038 return; … … 940 1043 941 1044 void GenericIO::readPhysScale(double Scale[3]) { 1045 if (FH.isBigEndian()) 1046 readPhysScale<true>(Scale); 1047 else 1048 readPhysScale<false>(Scale); 1049 } 1050 1051 template <bool IsBigEndian> 1052 void GenericIO::readPhysScale(double Scale[3]) { 942 1053 assert(FH.getHeaderCache().size() && "HeaderCache must not be empty"); 943 GlobalHeader *GH = (GlobalHeader*) &FH.getHeaderCache()[0];944 if (offsetof (GlobalHeader, PhysScale) >= GH->GlobalHeaderSize) {1054 GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 1055 if (offsetof_safe(GH, PhysScale) >= GH->GlobalHeaderSize) { 945 1056 std::fill(Scale, Scale + 3, 0.0); 946 1057 return; … … 950 1061 } 951 1062 952 static size_t getRankIndex(int EffRank, GlobalHeader *GH, 1063 template <bool IsBigEndian> 1064 static size_t getRankIndex(int EffRank, GlobalHeader<IsBigEndian> *GH, 953 1065 vector<int> &RankMap, vector<char> &HeaderCache) { 954 if ( offsetof(RankHeader, GlobalRank) >= GH->RanksSize ||RankMap.empty())1066 if (RankMap.empty()) 955 1067 return EffRank; 956 1068 957 1069 for (size_t i = 0; i < GH->NRanks; ++i) { 958 RankHeader *RH = (RankHeader*) &HeaderCache[GH->RanksStart +1070 RankHeader<IsBigEndian> *RH = (RankHeader<IsBigEndian> *) &HeaderCache[GH->RanksStart + 959 1071 i*GH->RanksSize]; 1072 if (offsetof_safe(RH, GlobalRank) >= GH->RanksSize) 1073 return EffRank; 1074 960 1075 if ((int) RH->GlobalRank == EffRank) 961 1076 return i; … … 966 1081 } 967 1082 1083 int GenericIO::readGlobalRankNumber(int EffRank) { 1084 if (FH.isBigEndian()) 1085 return readGlobalRankNumber<true>(EffRank); 1086 return readGlobalRankNumber<false>(EffRank); 1087 } 1088 1089 template <bool IsBigEndian> 968 1090 int GenericIO::readGlobalRankNumber(int EffRank) { 969 1091 if (EffRank == -1) { … … 979 1101 assert(FH.getHeaderCache().size() && "HeaderCache must not be empty"); 980 1102 981 GlobalHeader *GH = (GlobalHeader*) &FH.getHeaderCache()[0];982 size_t RankIndex = getRankIndex (EffRank, GH, RankMap, FH.getHeaderCache());1103 GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 1104 size_t RankIndex = getRankIndex<IsBigEndian>(EffRank, GH, RankMap, FH.getHeaderCache()); 983 1105 984 1106 assert(RankIndex < GH->NRanks && "Invalid rank specified"); 985 1107 986 if (offsetof(RankHeader, GlobalRank) >= GH->RanksSize) 1108 RankHeader<IsBigEndian> *RH = (RankHeader<IsBigEndian> *) &FH.getHeaderCache()[GH->RanksStart + 1109 RankIndex*GH->RanksSize]; 1110 1111 if (offsetof_safe(RH, GlobalRank) >= GH->RanksSize) 987 1112 return EffRank; 988 1113 989 RankHeader *RH = (RankHeader *) &FH.getHeaderCache()[GH->RanksStart +990 RankIndex*GH->RanksSize];991 992 1114 return (int) RH->GlobalRank; 993 1115 } 994 1116 1117 size_t GenericIO::readNumElems(int EffRank) { 1118 if (FH.isBigEndian()) 1119 return readNumElems<true>(EffRank); 1120 return readNumElems<false>(EffRank); 1121 } 1122 1123 template <bool IsBigEndian> 995 1124 size_t GenericIO::readNumElems(int EffRank) { 996 1125 if (EffRank == -1) { … … 1006 1135 assert(FH.getHeaderCache().size() && "HeaderCache must not be empty"); 1007 1136 1008 GlobalHeader *GH = (GlobalHeader*) &FH.getHeaderCache()[0];1009 size_t RankIndex = getRankIndex (EffRank, GH, RankMap, FH.getHeaderCache());1137 GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 1138 size_t RankIndex = getRankIndex<IsBigEndian>(EffRank, GH, RankMap, FH.getHeaderCache()); 1010 1139 1011 1140 assert(RankIndex < GH->NRanks && "Invalid rank specified"); 1012 1141 1013 RankHeader *RH = (RankHeader*) &FH.getHeaderCache()[GH->RanksStart +1142 RankHeader<IsBigEndian> *RH = (RankHeader<IsBigEndian> *) &FH.getHeaderCache()[GH->RanksStart + 1014 1143 RankIndex*GH->RanksSize]; 1015 1144 return (size_t) RH->NElems; 1016 1145 } 1017 1146 1147 void GenericIO::readCoords(int Coords[3], int EffRank) { 1148 if (FH.isBigEndian()) 1149 readCoords<true>(Coords, EffRank); 1150 else 1151 readCoords<false>(Coords, EffRank); 1152 } 1153 1154 template <bool IsBigEndian> 1018 1155 void GenericIO::readCoords(int Coords[3], int EffRank) { 1019 1156 if (EffRank == -1) { … … 1029 1166 assert(FH.getHeaderCache().size() && "HeaderCache must not be empty"); 1030 1167 1031 GlobalHeader *GH = (GlobalHeader*) &FH.getHeaderCache()[0];1032 size_t RankIndex = getRankIndex (EffRank, GH, RankMap, FH.getHeaderCache());1168 GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 1169 size_t RankIndex = getRankIndex<IsBigEndian>(EffRank, GH, RankMap, FH.getHeaderCache()); 1033 1170 1034 1171 assert(RankIndex < GH->NRanks && "Invalid rank specified"); 1035 1172 1036 RankHeader *RH = (RankHeader*) &FH.getHeaderCache()[GH->RanksStart +1173 RankHeader<IsBigEndian> *RH = (RankHeader<IsBigEndian> *) &FH.getHeaderCache()[GH->RanksStart + 1037 1174 RankIndex*GH->RanksSize]; 1038 1175 1039 1176 std::copy(RH->Coords, RH->Coords + 3, Coords); 1177 } 1178 1179 void GenericIO::readData(int EffRank, bool PrintStats, bool CollStats) { 1180 if (FH.isBigEndian()) 1181 readData<true>(EffRank, PrintStats, CollStats); 1182 else 1183 readData<false>(EffRank, PrintStats, CollStats); 1040 1184 } 1041 1185 1042 1186 // Note: Errors from this function should be recoverable. This means that if 1043 1187 // one rank throws an exception, then all ranks should. 1188 template <bool IsBigEndian> 1044 1189 void GenericIO::readData(int EffRank, bool PrintStats, bool CollStats) { 1045 1190 int Rank; … … 1057 1202 EffRank = Rank; 1058 1203 1059 GlobalHeader *GH = (GlobalHeader*) &FH.getHeaderCache()[0];1060 size_t RankIndex = getRankIndex (EffRank, GH, RankMap, FH.getHeaderCache());1204 GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 1205 size_t RankIndex = getRankIndex<IsBigEndian>(EffRank, GH, RankMap, FH.getHeaderCache()); 1061 1206 1062 1207 assert(RankIndex < GH->NRanks && "Invalid rank specified"); 1063 1208 1064 RankHeader *RH = (RankHeader*) &FH.getHeaderCache()[GH->RanksStart +1209 RankHeader<IsBigEndian> *RH = (RankHeader<IsBigEndian> *) &FH.getHeaderCache()[GH->RanksStart + 1065 1210 RankIndex*GH->RanksSize]; 1066 1211 … … 1077 1222 bool VarFound = false; 1078 1223 for (uint64_t j = 0; j < GH->NVars; ++j) { 1079 VariableHeader *VH = (VariableHeader*) &FH.getHeaderCache()[GH->VarsStart +1224 VariableHeader<IsBigEndian> *VH = (VariableHeader<IsBigEndian> *) &FH.getHeaderCache()[GH->VarsStart + 1080 1225 j*GH->VarsSize]; 1081 1226 … … 1121 1266 void *Data = Vars[i].Data; 1122 1267 bool HasExtraSpace = Vars[i].HasExtraSpace; 1123 if (offsetof (GlobalHeader, BlocksStart) < GH->GlobalHeaderSize &&1268 if (offsetof_safe(GH, BlocksStart) < GH->GlobalHeaderSize && 1124 1269 GH->BlocksSize > 0) { 1125 BlockHeader *BH = (BlockHeader*)1270 BlockHeader<IsBigEndian> *BH = (BlockHeader<IsBigEndian> *) 1126 1271 &FH.getHeaderCache()[GH->BlocksStart + 1127 1272 (RankIndex*GH->NVars + j)*GH->BlocksSize]; … … 1240 1385 1241 1386 if (LData.size()) { 1242 CompressHeader *CH = (CompressHeader*) &LData[0];1387 CompressHeader<IsBigEndian> *CH = (CompressHeader<IsBigEndian>*) &LData[0]; 1243 1388 1244 1389 #ifdef _OPENMP … … 1257 1402 #endif 1258 1403 1259 blosc_decompress(&LData[0] + sizeof(CompressHeader ),1404 blosc_decompress(&LData[0] + sizeof(CompressHeader<IsBigEndian>), 1260 1405 Vars[i].Data, Vars[i].Size*RH->NElems); 1261 1406 … … 1265 1410 } 1266 1411 } 1412 1413 // Byte swap the data if necessary. 1414 if (IsBigEndian != isBigEndian()) 1415 for (size_t j = 0; j < RH->NElems; ++j) { 1416 char *Offset = ((char *) Vars[i].Data) + j*Vars[i].Size; 1417 bswap(Offset, Vars[i].Size); 1418 } 1267 1419 1268 1420 break; … … 1352 1504 1353 1505 void GenericIO::getVariableInfo(vector<VariableInfo> &VI) { 1506 if (FH.isBigEndian()) 1507 getVariableInfo<true>(VI); 1508 else 1509 getVariableInfo<false>(VI); 1510 } 1511 1512 template <bool IsBigEndian> 1513 void GenericIO::getVariableInfo(vector<VariableInfo> &VI) { 1354 1514 assert(FH.getHeaderCache().size() && "HeaderCache must not be empty"); 1355 1515 1356 GlobalHeader *GH = (GlobalHeader*) &FH.getHeaderCache()[0];1516 GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 1357 1517 for (uint64_t j = 0; j < GH->NVars; ++j) { 1358 VariableHeader *VH = (VariableHeader*) &FH.getHeaderCache()[GH->VarsStart +1518 VariableHeader<IsBigEndian> *VH = (VariableHeader<IsBigEndian> *) &FH.getHeaderCache()[GH->VarsStart + 1359 1519 j*GH->VarsSize]; 1360 1520
Note: See TracChangeset
for help on using the changeset viewer.