Integrated comparison checks into CompareData() which prevents additi… (#254)

* Integrated comparison checks into CompareData() which prevents additional buffer comparisons at the expense of some computation #249.

* IOR: Added code documentation to warn people for changing the creation pattern but not the verification pattern.
master
Julian Kunkel 2020-09-28 20:09:48 +01:00 committed by GitHub
parent 8f14166a79
commit bd76b45ef9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 58 additions and 110 deletions

168
src/ior.c
View File

@ -374,36 +374,56 @@ static void CheckFileSize(IOR_test_t *test, char * testFilename, IOR_offset_t da
* difference in buffers and returns total errors counted.
*/
static size_t
CompareBuffers(void *expectedBuffer,
void *unknownBuffer,
size_t size,
IOR_offset_t transferCount, IOR_param_t *test, int access)
CompareData(void *expectedBuffer, size_t size, IOR_offset_t transferCount, IOR_param_t *test, IOR_offset_t offset, int fillrank, int access)
{
char testFileName[MAX_PATHLEN];
char bufferLabel1[MAX_STR];
char bufferLabel2[MAX_STR];
size_t i, j, length, first, last;
size_t i, j, length;
size_t errorCount = 0;
int inError = 0;
unsigned long long *goodbuf = (unsigned long long *)expectedBuffer;
unsigned long long *testbuf = (unsigned long long *)unknownBuffer;
IOR_offset_t offsetSignature = 0;
unsigned long long hi, lo, val; // for data verification
hi = ((unsigned long long)fillrank) << 32;
lo = (unsigned long long)test->timeStampSignatureValue;
if (test->storeFileOffset){
offsetSignature = offset;
}
unsigned long long *testbuf = (unsigned long long *)expectedBuffer;
if (access == WRITECHECK || access == READCHECK) {
strcpy(bufferLabel1, "Expected: ");
strcpy(bufferLabel2, "Actual: ");
} else {
ERR("incorrect argument for CompareBuffers()");
ERR("incorrect argument for CompareData()");
}
length = size / sizeof(IOR_size_t);
first = -1;
if (verbose >= VERBOSE_3) {
fprintf(out_logfile,
"[%d] At file byte offset %lld, comparing %llu-byte transfer\n",
rank, (long long) offset, (long long)size);
}
int incompressibleSeed = test->setTimeStampSignature + fillrank;
for (i = 0; i < length; i++) {
if (testbuf[i] != goodbuf[i]) {
if(test->dataPacketType == incompressible ) {
/* same logic as in FillIncompressibleBuffer() */
/* WARNING: make sure that both functions are changed at the same time */
hi = ((unsigned long long) rand_r(& incompressibleSeed) << 32);
lo = (unsigned long long) rand_r(& incompressibleSeed);
val = hi | lo;
}else{
if ((i % 2) == 0) {
/* evens contain MPI rank and time in seconds */
val = hi | lo;
} else {
/* odds contain offset */
val = offsetSignature + (i * sizeof(unsigned long long));
}
}
if (testbuf[i] != val) {
errorCount++;
if (verbose >= VERBOSE_2) {
fprintf(out_logfile,
@ -412,58 +432,28 @@ CompareBuffers(void *expectedBuffer,
(long long) offset +
(IOR_size_t) (i * sizeof(IOR_size_t)));
fprintf(out_logfile, "[%d] %s0x", rank, bufferLabel1);
fprintf(out_logfile, "%016llx\n", goodbuf[i]);
fprintf(out_logfile, "%016llx\n", val);
fprintf(out_logfile, "[%d] %s0x", rank, bufferLabel2);
fprintf(out_logfile, "%016llx\n", testbuf[i]);
}
if (!inError) {
inError = 1;
first = i;
last = i;
} else {
last = i;
}
} else if (verbose >= VERBOSE_5 && i % 4 == 0) {
} else if (verbose >= VERBOSE_5) {
fprintf(out_logfile,
"[%d] PASSED offset = %lu bytes, transfer %lld\n",
rank,
((i * sizeof(unsigned long long)) +
offset), transferCount);
"[%d] PASSED offset = %llu bytes, transfer %lld\n",
rank, ((i * sizeof(unsigned long long)) + offset), transferCount);
fprintf(out_logfile, "[%d] GOOD %s0x", rank, bufferLabel1);
for (j = 0; j < 4; j++)
fprintf(out_logfile, "%016llx ", goodbuf[i + j]);
fprintf(out_logfile, "%016llx ", val);
fprintf(out_logfile, "\n[%d] GOOD %s0x", rank, bufferLabel2);
for (j = 0; j < 4; j++)
fprintf(out_logfile, "%016llx ", testbuf[i + j]);
fprintf(out_logfile, "%016llx ", testbuf[i]);
fprintf(out_logfile, "\n");
}
}
if (inError) {
inError = 0;
if (errorCount > 0) {
GetTestFileName(testFileName, test);
EWARNF("[%d] FAILED comparison of buffer containing %d-byte ints:\n",
rank, (int)sizeof(unsigned long long int));
fprintf(out_logfile, "[%d] File name = %s\n", rank, testFileName);
fprintf(out_logfile, "[%d] In transfer %lld, ", rank,
transferCount);
fprintf(out_logfile,
"%lld errors between buffer indices %lld and %lld.\n",
(long long)errorCount, (long long)first,
(long long)last);
fprintf(out_logfile, "[%d] File byte offset = %lu:\n", rank,
((first * sizeof(unsigned long long)) + offset));
fprintf(out_logfile, "[%d] %s0x", rank, bufferLabel1);
for (j = first; j < length && j < first + 4; j++)
fprintf(out_logfile, "%016llx ", goodbuf[j]);
if (j == length)
fprintf(out_logfile, "[end of buffer]");
fprintf(out_logfile, "\n[%d] %s0x", rank, bufferLabel2);
for (j = first; j < length && j < first + 4; j++)
fprintf(out_logfile, "%016llx ", testbuf[j]);
if (j == length)
fprintf(out_logfile, "[end of buffer]");
fprintf(out_logfile, "\n");
EWARNF("[%d] FAILED comparison of buffer in file %s during transfer %lld offset %lld containing %d-byte ints (%zd errors)",
rank, testFileName, transferCount, offset, (int)sizeof(unsigned long long int),errorCount);
}else if(verbose >= VERBOSE_2){
fprintf(out_logfile, "[%d] comparison successful during transfer %lld offset %lld\n", rank, transferCount, offset);
}
return (errorCount);
}
@ -639,15 +629,22 @@ void DistributeHints(void)
* ints, store transfer offset. If storeFileOffset option is used, the file
* (not transfer) offset is stored instead.
*/
static unsigned int reseed_incompressible_prng = TRUE;
static void
FillIncompressibleBuffer(void* buffer, IOR_param_t * test)
{
size_t i;
unsigned long long hi, lo;
unsigned long long *buf = (unsigned long long *)buffer;
/* In order for write checks to work, we have to restart the pseudo random sequence */
/* This function has the same logic as CompareData() */
/* WARNING: make sure that both functions are changed at the same time */
if(reseed_incompressible_prng == TRUE) {
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;
}
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);
@ -655,8 +652,6 @@ FillIncompressibleBuffer(void* buffer, IOR_param_t * test)
}
}
unsigned int reseed_incompressible_prng = TRUE;
static void
FillBuffer(void *buffer,
IOR_param_t * test, unsigned long long offset, int fillrank)
@ -666,16 +661,8 @@ FillBuffer(void *buffer,
unsigned long long *buf = (unsigned long long *)buffer;
if(test->dataPacketType == incompressible ) { /* Make for some non compressible buffers with randomish data */
/* In order for write checks to work, we have to restart the pseudo random sequence */
if(reseed_incompressible_prng == TRUE) {
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 {
} else {
hi = ((unsigned long long)fillrank) << 32;
lo = (unsigned long long)test->timeStampSignatureValue;
for (i = 0; i < test->transferSize / sizeof(unsigned long long); i++) {
@ -1051,15 +1038,6 @@ static void XferBuffersSetup(IOR_io_buffers* ioBuffers, IOR_param_t* test,
int pretendRank)
{
ioBuffers->buffer = aligned_buffer_alloc(test->transferSize);
if (test->checkWrite || test->checkRead) {
ioBuffers->checkBuffer = aligned_buffer_alloc(test->transferSize);
}
if (test->checkRead || test->checkWrite) {
ioBuffers->readCheckBuffer = aligned_buffer_alloc(test->transferSize);
}
return;
}
/*
@ -1069,15 +1047,6 @@ static void XferBuffersFree(IOR_io_buffers* ioBuffers, IOR_param_t* test)
{
aligned_buffer_free(ioBuffers->buffer);
if (test->checkWrite || test->checkRead) {
aligned_buffer_free(ioBuffers->checkBuffer);
}
if (test->checkRead) {
aligned_buffer_free(ioBuffers->readCheckBuffer);
}
return;
}
@ -1439,10 +1408,6 @@ static void TestIoSys(IOR_test_t *test)
}
rankOffset = (2 * shift) % params->numTasks;
}
// update the check buffer
FillBuffer(ioBuffers.readCheckBuffer, params, 0, (rank + rankOffset) % params->numTasks);
reseed_incompressible_prng = TRUE; /* Re-Seed the PRNG to get same sequence back, if random */
GetTestFileName(testFileName, params);
@ -1505,10 +1470,6 @@ static void TestIoSys(IOR_test_t *test)
file_hits_histogram(params);
}
}
if(operation_flag == READCHECK){
FillBuffer(ioBuffers.readCheckBuffer, params, 0, (rank + rankOffset) % params->numTasks);
}
/* Using globally passed rankOffset, following function generates testFileName to read */
GetTestFileName(testFileName, params);
@ -1816,8 +1777,6 @@ static IOR_offset_t WriteOrReadSingle(IOR_offset_t pairCnt, IOR_offset_t *offset
IOR_offset_t transfer;
void *buffer = ioBuffers->buffer;
void *checkBuffer = ioBuffers->checkBuffer;
void *readCheckBuffer = ioBuffers->readCheckBuffer;
IOR_offset_t offset = offsetArray[pairCnt]; // this looks inappropriate
@ -1846,30 +1805,19 @@ static IOR_offset_t WriteOrReadSingle(IOR_offset_t pairCnt, IOR_offset_t *offset
nanosleep( & wait, NULL);
}
} else if (access == WRITECHECK) {
memset(checkBuffer, 'a', transfer);
if (test->storeFileOffset == TRUE) {
FillBuffer(readCheckBuffer, test, offset, pretendRank);
}
amtXferred = backend->xfer(access, fd, checkBuffer, transfer, offset, test->backend_options);
((long long int*) buffer)[0] = ~((long long int*) buffer)[0]; // changes the buffer, no memset to reduce the memory pressure
amtXferred = backend->xfer(access, fd, buffer, transfer, offset, test->backend_options);
if (amtXferred != transfer)
ERR("cannot read from file write check");
(*transferCount)++;
*errors += CompareBuffers(readCheckBuffer, checkBuffer, transfer,
*transferCount, test,
WRITECHECK);
*errors += CompareData(buffer, transfer, *transferCount, test, offset, pretendRank, WRITECHECK);
} else if (access == READCHECK) {
memset(checkBuffer, 'a', transfer);
amtXferred = backend->xfer(access, fd, checkBuffer, transfer, offset, test->backend_options);
((long long int*) buffer)[0] = ~((long long int*) buffer)[0]; // changes the buffer, no memset to reduce the memory pressure
amtXferred = backend->xfer(access, fd, buffer, transfer, offset, test->backend_options);
if (amtXferred != transfer){
ERR("cannot read from file");
}
if (test->storeFileOffset == TRUE) {
FillBuffer(readCheckBuffer, test, offset, pretendRank);
}
*errors += CompareBuffers(readCheckBuffer, checkBuffer, transfer, *transferCount, test, READCHECK);
*errors += CompareData(buffer, transfer, *transferCount, test, offset, pretendRank, READCHECK);
}
return amtXferred;
}