Skip to content

Commit

Permalink
Add warning if the memory is insufficient to load everything.
Browse files Browse the repository at this point in the history
Refs #11056
  • Loading branch information
martyngigg committed Dec 11, 2015
1 parent 694f376 commit 7c9c35e
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 3 deletions.
1 change: 1 addition & 0 deletions Framework/MDAlgorithms/inc/MantidMDAlgorithms/LoadSQW2.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class DLLExport LoadSQW2 : public API::IFileLoader<Kernel::FileDescriptor> {
void setupBoxController();
void setupFileBackend(std::string filebackPath);
void readPixelData();
void warnIfMemoryInsufficient(int64_t npixtot);
void addEventFromBuffer(const float *pixel);
void toHKL(float &u1, float &u2, float &u3, const uint16_t runIndex);
void finalize();
Expand Down
31 changes: 28 additions & 3 deletions Framework/MDAlgorithms/src/LoadSQW2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "MantidGeometry/MDGeometry/MDHistoDimensionBuilder.h"
#include "MantidKernel/make_unique.h"
#include "MantidKernel/Matrix.h"
#include "MantidKernel/Memory.h"
#include "MantidKernel/ThreadScheduler.h"
#include "MantidKernel/Timer.h"
#include "MantidKernel/V3D.h"
Expand All @@ -34,6 +35,8 @@ using Kernel::V3D;
/// number of pixels to read in a single call. A single pixel is 9 float
/// fields. 150000 is ~5MB buffer
constexpr int64_t NPIX_CHUNK = 150000;
/// Defines the number of fields that define a single pixel
constexpr int32_t FIELDS_PER_PIXEL = 9;

// Register the algorithm into the AlgorithmFactory
DECLARE_FILELOADER_ALGORITHM(LoadSQW2)
Expand Down Expand Up @@ -462,20 +465,20 @@ void LoadSQW2::readPixelData() {
int64_t npixtot(0);
*m_reader >> npixtot;
g_log.debug() << " npixtot: " << npixtot << "\n";
warnIfMemoryInsufficient(npixtot);
m_progress->setNumSteps(npixtot);

// Each pixel has 9 float fields. Do a chunked read to avoid
// using too much memory for the buffer
constexpr int32_t numFields(9);
constexpr int64_t bufferSize(numFields * NPIX_CHUNK);
constexpr int64_t bufferSize(FIELDS_PER_PIXEL * NPIX_CHUNK);
std::vector<float> pixBuffer(bufferSize);
int64_t pixelsToRead(npixtot);
while (pixelsToRead > 0) {
int64_t readNPix(pixelsToRead);
if (readNPix > NPIX_CHUNK) {
readNPix = NPIX_CHUNK;
}
m_reader->read(pixBuffer, numFields * readNPix);
m_reader->read(pixBuffer, FIELDS_PER_PIXEL * readNPix);
for (int64_t i = 0; i < readNPix; ++i) {
addEventFromBuffer(pixBuffer.data() + i * 9);
m_progress->report();
Expand All @@ -485,6 +488,28 @@ void LoadSQW2::readPixelData() {
g_log.debug() << "Time to read all pixels: " << timer.elapsed() << "s\n";
}

/**
* If the output is not file backed and the machine appears to have insufficient
* memory to read the data in total then warn the user. We don't stop
* the algorithm just in case our memory calculation is wrong.
* @param npixtot The total number of pixels to be read
*/
void LoadSQW2::warnIfMemoryInsufficient(int64_t npixtot) {
using DataObjects::MDEvent;
using Kernel::MemoryStats;
if (m_outputWS->isFileBacked())
return;
MemoryStats stat;
size_t reqdMemory =
(npixtot * sizeof(MDEvent<4>) + NPIX_CHUNK * FIELDS_PER_PIXEL) / 1024;
if (reqdMemory < stat.availMem()) {
g_log.warning()
<< "It looks as if there is insufficient memory to load the "
<< "entire file. It is recommended to cancel the algorith and specify "
"the OutputFilename option to create a file-backed workspace.\n";
}
}

/**
* Assume the given pointer points to the start of a full pixel and create
* an MDEvent based on it
Expand Down

0 comments on commit 7c9c35e

Please sign in to comment.