File size: 4,252 Bytes
563c80f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
/*
* Copyright 2015 NVIDIA Corporation. All rights reserved
*
* Sample CUPTI library for OpenACC data collection.
*/
#include <stdlib.h>
#include <stdio.h>
#include <cupti.h>
#include <cuda.h>
#include <openacc.h>
// helper macros
#define CUPTI_CALL(call) \
do { \
CUptiResult _status = call; \
if (_status != CUPTI_SUCCESS) { \
const char *errstr; \
cuptiGetResultString(_status, &errstr); \
fprintf(stderr, "%s:%d: error: function %s failed with error %s.\n", \
__FILE__, __LINE__, #call, errstr); \
exit(EXIT_FAILURE); \
} \
} while (0)
#define BUF_SIZE (32 * 1024)
#define ALIGN_SIZE (8)
#define ALIGN_BUFFER(buffer, align) \
(((uintptr_t) (buffer) & ((align)-1)) ? ((buffer) + (align) - ((uintptr_t) (buffer) & ((align)-1))) : (buffer))
static size_t openacc_records = 0;
static void
printActivity(CUpti_Activity *record)
{
switch (record->kind) {
case CUPTI_ACTIVITY_KIND_OPENACC_DATA:
case CUPTI_ACTIVITY_KIND_OPENACC_LAUNCH:
case CUPTI_ACTIVITY_KIND_OPENACC_OTHER:
{
CUpti_ActivityOpenAcc *oacc =
(CUpti_ActivityOpenAcc *)record;
if (oacc->deviceType != acc_device_nvidia) {
printf("Error: OpenACC device type is %u, not %u (acc_device_nvidia)\n",
oacc->deviceType, acc_device_nvidia);
exit(EXIT_FAILURE);
}
openacc_records++;
}
break;
default:
;
}
}
// CUPTI buffer handling
void CUPTIAPI bufferRequested(uint8_t **buffer, size_t *size, size_t *maxNumRecords)
{
uint8_t *bfr = (uint8_t *) malloc(BUF_SIZE + ALIGN_SIZE);
if (bfr == NULL) {
printf("Error: out of memory\n");
exit(EXIT_FAILURE);
}
*size = BUF_SIZE;
*buffer = ALIGN_BUFFER(bfr, ALIGN_SIZE);
*maxNumRecords = 0;
}
void CUPTIAPI bufferCompleted(CUcontext ctx, uint32_t streamId, uint8_t *buffer, size_t size, size_t validSize)
{
CUptiResult status;
CUpti_Activity *record = NULL;
if (validSize > 0) {
do {
status = cuptiActivityGetNextRecord(buffer, validSize, &record);
if (status == CUPTI_SUCCESS) {
printActivity(record);
}
else if (status == CUPTI_ERROR_MAX_LIMIT_REACHED)
break;
else {
CUPTI_CALL(status);
}
} while (1);
// report any records dropped from the queue
size_t dropped;
CUPTI_CALL(cuptiActivityGetNumDroppedRecords(ctx, streamId, &dropped));
if (dropped != 0) {
printf("Dropped %u activity records\n", (unsigned int) dropped);
}
}
free(buffer);
}
void finalize()
{
CUPTI_CALL(cuptiGetLastError());
CUPTI_CALL(cuptiActivityFlushAll(0));
printf("Found %llu OpenACC records\n", (long long unsigned) openacc_records);
}
// acc_register_library is defined by the OpenACC tools interface
// and allows to register this library with the OpenACC runtime.
extern "C" void
acc_register_library(void *profRegister, void *profUnregister, void *profLookup)
{
// once connected to the OpenACC runtime, initialize CUPTI's OpenACC interface
if (cuptiOpenACCInitialize(profRegister, profUnregister, profLookup) != CUPTI_SUCCESS) {
printf("Error: Failed to initialize CUPTI OpenACC support\n");
exit(EXIT_FAILURE);
}
printf("Initialized CUPTI OpenACC\n");
// only interested in OpenACC activity records
CUPTI_CALL(cuptiActivityEnable(CUPTI_ACTIVITY_KIND_OPENACC_DATA));
CUPTI_CALL(cuptiActivityEnable(CUPTI_ACTIVITY_KIND_OPENACC_LAUNCH));
CUPTI_CALL(cuptiActivityEnable(CUPTI_ACTIVITY_KIND_OPENACC_OTHER));
// setup CUPTI buffer handling
CUPTI_CALL(cuptiActivityRegisterCallbacks(bufferRequested, bufferCompleted));
// at program exit, flush CUPTI buffers and print results
atexit(finalize);
}
|