Changed the semantics of -R to compare the data with the expected data buffer.
Previously -R did run another read phase and compared if the output of both reads is identical. -R now checks if the data matches the expected signature (as set using -G <NUMBER>), so reads data once and then directly compares the read data with the expected buffer. This allows to first run IOR with a write only phase, then later with a read phase that checks if the data still is correct. Since the read can be repeated multiple times, there is no need for the old -R semantics.master
parent
9eac84d50a
commit
2ce37ae90a
203
src/ior.c
203
src/ior.c
|
@ -391,12 +391,9 @@ CompareBuffers(void *expectedBuffer,
|
|||
unsigned long long *goodbuf = (unsigned long long *)expectedBuffer;
|
||||
unsigned long long *testbuf = (unsigned long long *)unknownBuffer;
|
||||
|
||||
if (access == WRITECHECK) {
|
||||
if (access == WRITECHECK || access == READCHECK) {
|
||||
strcpy(bufferLabel1, "Expected: ");
|
||||
strcpy(bufferLabel2, "Actual: ");
|
||||
} else if (access == READCHECK) {
|
||||
strcpy(bufferLabel1, "1st Read: ");
|
||||
strcpy(bufferLabel2, "2nd Read: ");
|
||||
} else {
|
||||
ERR("incorrect argument for CompareBuffers()");
|
||||
}
|
||||
|
@ -754,7 +751,7 @@ static void DisplayUsage(char **argv)
|
|||
" -f S scriptFile -- test script name",
|
||||
" -F filePerProc -- file-per-process",
|
||||
" -g intraTestBarriers -- use barriers between open, write/read, and close",
|
||||
" -G N setTimeStampSignature -- set value for time stamp signature",
|
||||
" -G N setTimeStampSignature -- set value for time stamp signature/random seed",
|
||||
" -h showHelp -- displays options and help",
|
||||
" -H showHints -- show hints",
|
||||
" -i N repetitions -- number of repetitions of test",
|
||||
|
@ -775,7 +772,7 @@ static void DisplayUsage(char **argv)
|
|||
" -q quitOnError -- during file error-checking, abort on error",
|
||||
" -Q N taskPerNodeOffset for read tests use with -C & -Z options (-C constant N, -Z at least N)",
|
||||
" -r readFile -- read existing file",
|
||||
" -R checkRead -- check read after read",
|
||||
" -R checkRead -- verify that the output of read matches the expected signature (used with -G)",
|
||||
" -s N segmentCount -- number of segments",
|
||||
" -S useStridedDatatype -- put strided access into datatype [not working]",
|
||||
" -t N transferSize -- size of transfer in bytes (e.g.: 8, 4k, 2m, 1g)",
|
||||
|
@ -861,13 +858,13 @@ FillIncompressibleBuffer(void* buffer, IOR_param_t * test)
|
|||
size_t i;
|
||||
unsigned long long hi, lo;
|
||||
unsigned long long *buf = (unsigned long long *)buffer;
|
||||
|
||||
|
||||
for (i = 0; i < test->transferSize / sizeof(unsigned long long); i++) {
|
||||
hi = ((unsigned long long) rand_r(&test->incompressibleSeed) << 32);
|
||||
lo = (unsigned long long) rand_r(&test->incompressibleSeed);
|
||||
buf[i] = hi | lo;
|
||||
buf[i] = hi | lo;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
unsigned int reseed_incompressible_prng = TRUE;
|
||||
|
@ -879,17 +876,17 @@ FillBuffer(void *buffer,
|
|||
size_t i;
|
||||
unsigned long long hi, lo;
|
||||
unsigned long long *buf = (unsigned long long *)buffer;
|
||||
|
||||
|
||||
if(test->dataPacketType == incompressible ) { /* Make for some non compressable buffers with randomish data */
|
||||
|
||||
/* In order for write checks to work, we have to restart the psuedo random sequence */
|
||||
if(reseed_incompressible_prng == TRUE) {
|
||||
test->incompressibleSeed = test->setTimeStampSignature ; /* We copied seed into timestampSignature at initialization */
|
||||
test->incompressibleSeed = test->setTimeStampSignature + rank; /* We copied seed into timestampSignature at initialization, also add the rank to add randomness between processes */
|
||||
reseed_incompressible_prng = FALSE;
|
||||
}
|
||||
FillIncompressibleBuffer(buffer, test);
|
||||
}
|
||||
|
||||
|
||||
else {
|
||||
hi = ((unsigned long long)fillrank) << 32;
|
||||
lo = (unsigned long long)test->timeStampSignatureValue;
|
||||
|
@ -1192,79 +1189,6 @@ static char *PrependDir(IOR_param_t * test, char *rootDir)
|
|||
return dir;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read and then reread buffer to confirm data read twice matches.
|
||||
*/
|
||||
static void
|
||||
ReadCheck(void *fd,
|
||||
void *buffer,
|
||||
void *checkBuffer,
|
||||
void *readCheckBuffer,
|
||||
IOR_param_t *params,
|
||||
IOR_offset_t transfer,
|
||||
IOR_offset_t blockSize,
|
||||
IOR_offset_t *amtXferred,
|
||||
IOR_offset_t *transferCount, int access, int *errors)
|
||||
{
|
||||
int readCheckToRank;
|
||||
int readCheckFromRank;
|
||||
MPI_Status status;
|
||||
IOR_offset_t tmpOffset;
|
||||
IOR_offset_t segmentSize;
|
||||
IOR_offset_t segmentNum;
|
||||
|
||||
memset(buffer, 'a', transfer);
|
||||
*amtXferred = backend->xfer(access, fd, buffer, transfer, params);
|
||||
tmpOffset = params->offset;
|
||||
if (params->filePerProc == FALSE) {
|
||||
/* offset changes for shared file, not for file-per-proc */
|
||||
segmentSize = params->numTasks * blockSize;
|
||||
segmentNum = params->offset / segmentSize;
|
||||
|
||||
/* work in current segment */
|
||||
params->offset = (((params->offset % segmentSize)
|
||||
/* offset to neighbor's data */
|
||||
+ ((params->reorderTasks ?
|
||||
params->tasksPerNode : 0) * blockSize))
|
||||
/* stay within current segment */
|
||||
% segmentSize)
|
||||
/* return segment to actual file offset */
|
||||
+ (segmentNum * segmentSize);
|
||||
}
|
||||
if (*amtXferred != transfer)
|
||||
ERR("cannot read from file on read check");
|
||||
memset(checkBuffer, 'a', transfer); /* empty buffer */
|
||||
MPI_CHECK(MPI_Barrier(testComm), "barrier error");
|
||||
if (params->filePerProc) {
|
||||
*amtXferred = backend->xfer(access, params->fd_fppReadCheck,
|
||||
checkBuffer, transfer, params);
|
||||
} else {
|
||||
*amtXferred =
|
||||
backend->xfer(access, fd, checkBuffer, transfer, params);
|
||||
}
|
||||
params->offset = tmpOffset;
|
||||
if (*amtXferred != transfer)
|
||||
ERR("cannot reread from file read check");
|
||||
(*transferCount)++;
|
||||
/* exchange buffers */
|
||||
memset(readCheckBuffer, 'a', transfer);
|
||||
readCheckToRank = (rank + (params->reorderTasks ? params->tasksPerNode : 0))
|
||||
% params->numTasks;
|
||||
readCheckFromRank = (rank + (params->numTasks
|
||||
-
|
||||
(params->
|
||||
reorderTasks ? params->tasksPerNode : 0)))
|
||||
% params->numTasks;
|
||||
MPI_CHECK(MPI_Barrier(testComm), "barrier error");
|
||||
MPI_Sendrecv(checkBuffer, transfer, MPI_CHAR, readCheckToRank, 1,
|
||||
readCheckBuffer, transfer, MPI_CHAR, readCheckFromRank, 1,
|
||||
testComm, &status);
|
||||
MPI_CHECK(MPI_Barrier(testComm), "barrier error");
|
||||
*errors += CompareBuffers(buffer, readCheckBuffer, transfer,
|
||||
*transferCount, params, READCHECK);
|
||||
return;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Reduce test results, and show if verbose set.
|
||||
|
@ -1366,7 +1290,7 @@ static void RemoveFile(char *testFileName, int filePerProc, IOR_param_t * test)
|
|||
// errors), or extend the aiori struct to include
|
||||
// something to safely check for existence of the
|
||||
// "file".
|
||||
//
|
||||
//
|
||||
if ((rank == 0) && (access(testFileName, F_OK) == 0)) {
|
||||
backend->delete(testFileName, test);
|
||||
}
|
||||
|
@ -1438,7 +1362,7 @@ static IOR_test_t *SetupTests(int argc, char **argv)
|
|||
/*
|
||||
* Setup transfer buffers, creating and filling as needed.
|
||||
*/
|
||||
static void XferBuffersSetup(IOR_io_buffers* ioBuffers, IOR_param_t* test,
|
||||
static void XferBuffersSetup(IOR_io_buffers* ioBuffers, IOR_param_t* test,
|
||||
int pretendRank)
|
||||
{
|
||||
ioBuffers->buffer = aligned_buffer_alloc(test->transferSize);
|
||||
|
@ -1644,7 +1568,7 @@ static void ShowSetup(IOR_param_t *params)
|
|||
static void ShowTest(IOR_param_t * test)
|
||||
{
|
||||
const char* data_packets[] = {"g", "t","o","i"};
|
||||
|
||||
|
||||
fprintf(stdout, "TEST:\t%s=%d\n", "id", test->id);
|
||||
fprintf(stdout, "\t%s=%d\n", "refnum", test->referenceNumber);
|
||||
fprintf(stdout, "\t%s=%s\n", "api", test->api);
|
||||
|
@ -1783,7 +1707,7 @@ static void PrintLongSummaryOneOperation(IOR_test_t *test, double *times, char *
|
|||
IOR_results_t *results = test->results;
|
||||
struct results *bw;
|
||||
int reps;
|
||||
|
||||
|
||||
if (rank != 0 || verbose < VERBOSE_0)
|
||||
return;
|
||||
|
||||
|
@ -1868,7 +1792,7 @@ static void PrintShortSummary(IOR_test_t * test)
|
|||
double bw;
|
||||
int reps;
|
||||
int i;
|
||||
|
||||
|
||||
if (rank != 0 || verbose < VERBOSE_0)
|
||||
return;
|
||||
|
||||
|
@ -2083,7 +2007,11 @@ static void TestIoSys(IOR_test_t *test)
|
|||
|
||||
/* IO Buffer Setup */
|
||||
|
||||
if (params->setTimeStampSignature) { // initialize the buffer properly
|
||||
params->timeStampSignatureValue = (unsigned int)params->setTimeStampSignature;
|
||||
}
|
||||
XferBuffersSetup(&ioBuffers, params, pretendRank);
|
||||
reseed_incompressible_prng = TRUE; // reset pseudo random generator, necessary to guarantee the next call to FillBuffer produces the same value as it is right now
|
||||
|
||||
/* Initial time stamp */
|
||||
startTime = GetTimeStamp();
|
||||
|
@ -2094,22 +2022,19 @@ static void TestIoSys(IOR_test_t *test)
|
|||
/* Get iteration start time in seconds in task 0 and broadcast to
|
||||
all tasks */
|
||||
if (rank == 0) {
|
||||
if (params->dataPacketType == timestamp && params->setTimeStampSignature) {
|
||||
params->timeStampSignatureValue =
|
||||
(unsigned int)params->setTimeStampSignature;
|
||||
} else {
|
||||
if (! params->setTimeStampSignature) {
|
||||
time_t currentTime;
|
||||
if ((currentTime = time(NULL)) == -1) {
|
||||
ERR("cannot get current time");
|
||||
}
|
||||
params->timeStampSignatureValue =
|
||||
(unsigned int)currentTime;
|
||||
}
|
||||
if (verbose >= VERBOSE_2) {
|
||||
fprintf(stdout,
|
||||
"Using Time Stamp %u (0x%x) for Data Signature\n",
|
||||
params->timeStampSignatureValue,
|
||||
params->timeStampSignatureValue);
|
||||
if (verbose >= VERBOSE_2) {
|
||||
fprintf(stdout,
|
||||
"Using Time Stamp %u (0x%x) for Data Signature\n",
|
||||
params->timeStampSignatureValue,
|
||||
params->timeStampSignatureValue);
|
||||
}
|
||||
}
|
||||
if (rep == 0 && verbose >= VERBOSE_0) {
|
||||
fprintf(stdout, "\n");
|
||||
|
@ -2213,7 +2138,12 @@ static void TestIoSys(IOR_test_t *test)
|
|||
/*
|
||||
* read the file(s), getting timing between I/O calls
|
||||
*/
|
||||
if (params->readFile && !test_time_elapsed(params, startTime)) {
|
||||
if ((params->readFile || params->checkRead ) && !test_time_elapsed(params, startTime)) {
|
||||
int operation_flag = READ;
|
||||
if ( params->checkRead ){
|
||||
// actually read and then compare the buffer
|
||||
operation_flag = READCHECK;
|
||||
}
|
||||
/* Get rankOffset [file offset] for this process to read, based on -C,-Z,-Q,-X options */
|
||||
/* Constant process offset reading */
|
||||
if (params->reorderTasks) {
|
||||
|
@ -2247,6 +2177,10 @@ static void TestIoSys(IOR_test_t *test)
|
|||
file_hits_histogram(params);
|
||||
}
|
||||
}
|
||||
if(operation_flag == READCHECK){
|
||||
FillBuffer(ioBuffers.readCheckBuffer, params, 0, rank + rankOffset);
|
||||
}
|
||||
|
||||
/* Using globally passed rankOffset, following function generates testFileName to read */
|
||||
GetTestFileName(testFileName, params);
|
||||
|
||||
|
@ -2269,7 +2203,7 @@ static void TestIoSys(IOR_test_t *test)
|
|||
CurrentTimeString());
|
||||
}
|
||||
timer[8][rep] = GetTimeStamp();
|
||||
dataMoved = WriteOrRead(params, fd, READ, &ioBuffers);
|
||||
dataMoved = WriteOrRead(params, fd, operation_flag, &ioBuffers);
|
||||
timer[9][rep] = GetTimeStamp();
|
||||
if (params->intraTestBarriers)
|
||||
MPI_CHECK(MPI_Barrier(testComm),
|
||||
|
@ -2295,45 +2229,6 @@ static void TestIoSys(IOR_test_t *test)
|
|||
}
|
||||
}
|
||||
|
||||
/* end readFile test */
|
||||
/*
|
||||
* perform a check of data, reading back data twice and
|
||||
* comparing against what was expected to be read
|
||||
*/
|
||||
if (params->checkRead && !test_time_elapsed(params, startTime)) {
|
||||
MPI_CHECK(MPI_Barrier(testComm), "barrier error");
|
||||
if (rank == 0 && verbose >= VERBOSE_1) {
|
||||
fprintf(stdout, "Re-reading the file(s) twice to ");
|
||||
fprintf(stdout, "verify that reads are consistent.\n");
|
||||
fprintf(stdout, "%s\n", CurrentTimeString());
|
||||
}
|
||||
if (params->reorderTasks) {
|
||||
/* move three nodes away from reading node */
|
||||
rankOffset = (3 * params->tasksPerNode) % params->numTasks;
|
||||
}
|
||||
GetTestFileName(testFileName, params);
|
||||
MPI_CHECK(MPI_Barrier(testComm), "barrier error");
|
||||
params->open = READCHECK;
|
||||
fd = backend->open(testFileName, params);
|
||||
if (params->filePerProc) {
|
||||
int tmpRankOffset;
|
||||
tmpRankOffset = rankOffset;
|
||||
/* increment rankOffset to open comparison file on other node */
|
||||
if (params->reorderTasks) {
|
||||
/* move four nodes away from reading node */
|
||||
rankOffset = (4 * params->tasksPerNode) % params->numTasks;
|
||||
}
|
||||
GetTestFileName(params->testFileName_fppReadCheck, params);
|
||||
rankOffset = tmpRankOffset;
|
||||
params->fd_fppReadCheck = backend->open(params->testFileName_fppReadCheck, params);
|
||||
}
|
||||
dataMoved = WriteOrRead(params, fd, READCHECK, &ioBuffers);
|
||||
if (params->filePerProc) {
|
||||
backend->close(params->fd_fppReadCheck, params);
|
||||
params->fd_fppReadCheck = NULL;
|
||||
}
|
||||
backend->close(fd, params);
|
||||
}
|
||||
if (!params->keepFile
|
||||
&& !(params->errorFound && params->keepFileWithError)) {
|
||||
double start, finish;
|
||||
|
@ -2684,15 +2579,16 @@ static IOR_offset_t WriteOrRead(IOR_param_t * test, void *fd, int access, IOR_io
|
|||
/* loop over offsets to access */
|
||||
while ((offsetArray[pairCnt] != -1) && !hitStonewall) {
|
||||
test->offset = offsetArray[pairCnt];
|
||||
/*
|
||||
* fills each transfer with a unique pattern
|
||||
* containing the offset into the file
|
||||
*/
|
||||
if (test->storeFileOffset == TRUE) {
|
||||
FillBuffer(buffer, test, test->offset, pretendRank);
|
||||
}
|
||||
|
||||
transfer = test->transferSize;
|
||||
if (access == WRITE) {
|
||||
/*
|
||||
* fills each transfer with a unique pattern
|
||||
* containing the offset into the file
|
||||
*/
|
||||
if (test->storeFileOffset == TRUE) {
|
||||
FillBuffer(buffer, test, test->offset, pretendRank);
|
||||
}
|
||||
amtXferred =
|
||||
backend->xfer(access, fd, buffer, transfer, test);
|
||||
if (amtXferred != transfer)
|
||||
|
@ -2714,9 +2610,14 @@ static IOR_offset_t WriteOrRead(IOR_param_t * test, void *fd, int access, IOR_io
|
|||
transferCount, test,
|
||||
WRITECHECK);
|
||||
} else if (access == READCHECK) {
|
||||
ReadCheck(fd, buffer, checkBuffer, readCheckBuffer,
|
||||
test, transfer, test->blockSize, &amtXferred,
|
||||
&transferCount, access, &errors);
|
||||
amtXferred = backend->xfer(access, fd, buffer, transfer, test);
|
||||
if (amtXferred != transfer){
|
||||
ERR("cannot read from file");
|
||||
}
|
||||
if (test->storeFileOffset == TRUE) {
|
||||
FillBuffer(readCheckBuffer, test, test->offset, pretendRank);
|
||||
}
|
||||
errors += CompareBuffers(readCheckBuffer, buffer, transfer, transferCount, test, READCHECK);
|
||||
}
|
||||
dataMoved += amtXferred;
|
||||
pairCnt++;
|
||||
|
|
Loading…
Reference in New Issue