TX2-GPU-100% v.s IPC-GPU-100%

2020-03-30  本文已影响0人  傻渡渡

'''

#define SIZE 2048ul // Matrices are SIZE*SIZE.. 2048^2 should be efficiently implemented in CUBLAS

#define USEMEM 0.9 // Try to allocate 90% of memory

// Used to report op/s, measured through Visual Profiler, CUBLAS from CUDA 7.5

// (Seems that they indeed take the naive dim^3 approach)

#define OPS_PER_MUL 17188257792ul

#include <cstdio>

#include <string>

#include <map>

#include <vector>

#include <sys/types.h>

#include <signal.h>

#include <sys/wait.h>

#include <sys/time.h>

#include <string.h>

#include <unistd.h>

#include <time.h>

#include <fstream>

#include <cuda.h>

#include "cublas_v2.h"

void checkError(int rCode, std::string desc = "") {

        static std::map<int, std::string> g_errorStrings;

        if (!g_errorStrings.size()) {

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_INVALID_VALUE, "CUDA_ERROR_INVALID_VALUE"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_OUT_OF_MEMORY, "CUDA_ERROR_OUT_OF_MEMORY"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_NOT_INITIALIZED, "CUDA_ERROR_NOT_INITIALIZED"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_DEINITIALIZED, "CUDA_ERROR_DEINITIALIZED"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_NO_DEVICE, "CUDA_ERROR_NO_DEVICE"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_INVALID_DEVICE, "CUDA_ERROR_INVALID_DEVICE"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_INVALID_IMAGE, "CUDA_ERROR_INVALID_IMAGE"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_INVALID_CONTEXT, "CUDA_ERROR_INVALID_CONTEXT"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_MAP_FAILED, "CUDA_ERROR_MAP_FAILED"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_UNMAP_FAILED, "CUDA_ERROR_UNMAP_FAILED"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_ARRAY_IS_MAPPED, "CUDA_ERROR_ARRAY_IS_MAPPED"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_ALREADY_MAPPED, "CUDA_ERROR_ALREADY_MAPPED"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_NO_BINARY_FOR_GPU, "CUDA_ERROR_NO_BINARY_FOR_GPU"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_ALREADY_ACQUIRED, "CUDA_ERROR_ALREADY_ACQUIRED"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_NOT_MAPPED, "CUDA_ERROR_NOT_MAPPED"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_NOT_MAPPED_AS_ARRAY, "CUDA_ERROR_NOT_MAPPED_AS_ARRAY"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_NOT_MAPPED_AS_POINTER, "CUDA_ERROR_NOT_MAPPED_AS_POINTER"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_UNSUPPORTED_LIMIT, "CUDA_ERROR_UNSUPPORTED_LIMIT"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_CONTEXT_ALREADY_IN_USE, "CUDA_ERROR_CONTEXT_ALREADY_IN_USE"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_INVALID_SOURCE, "CUDA_ERROR_INVALID_SOURCE"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_FILE_NOT_FOUND, "CUDA_ERROR_FILE_NOT_FOUND"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND, "CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_SHARED_OBJECT_INIT_FAILED, "CUDA_ERROR_SHARED_OBJECT_INIT_FAILED"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_OPERATING_SYSTEM, "CUDA_ERROR_OPERATING_SYSTEM"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_INVALID_HANDLE, "CUDA_ERROR_INVALID_HANDLE"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_NOT_FOUND, "CUDA_ERROR_NOT_FOUND"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_NOT_READY, "CUDA_ERROR_NOT_READY"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_LAUNCH_FAILED, "CUDA_ERROR_LAUNCH_FAILED"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES, "CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_LAUNCH_TIMEOUT, "CUDA_ERROR_LAUNCH_TIMEOUT"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING, "CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE, "CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_CONTEXT_IS_DESTROYED, "CUDA_ERROR_CONTEXT_IS_DESTROYED"));

                g_errorStrings.insert(std::pair<int, std::string>(CUDA_ERROR_UNKNOWN, "CUDA_ERROR_UNKNOWN"));

}

                if (rCode != CUDA_SUCCESS)

                        throw ((desc == "") ?

                                        std::string("Error: ") :

                                        (std::string("Error in \"") + desc + 

std::string("\": "))) +

                          g_errorStrings[rCode];

}

void checkError(cublasStatus_t rCode, std::string desc = "") {

static std::map<cublasStatus_t, std::string> g_errorStrings;

if (!g_errorStrings.size()) {

g_errorStrings.insert(std::pair<cublasStatus_t, std::string>(CUBLAS_STATUS_NOT_INITIALIZED, "CUBLAS_STATUS_NOT_INITIALIZED"));

g_errorStrings.insert(std::pair<cublasStatus_t, std::string>(CUBLAS_STATUS_ALLOC_FAILED, "CUBLAS_STATUS_ALLOC_FAILED"));

g_errorStrings.insert(std::pair<cublasStatus_t, std::string>(CUBLAS_STATUS_INVALID_VALUE, "CUBLAS_STATUS_INVALID_VALUE"));

g_errorStrings.insert(std::pair<cublasStatus_t, std::string>(CUBLAS_STATUS_ARCH_MISMATCH, "CUBLAS_STATUS_ARCH_MISMATCH"));

g_errorStrings.insert(std::pair<cublasStatus_t, std::string>(CUBLAS_STATUS_MAPPING_ERROR, "CUBLAS_STATUS_MAPPING_ERROR"));

g_errorStrings.insert(std::pair<cublasStatus_t, std::string>(CUBLAS_STATUS_EXECUTION_FAILED, "CUBLAS_STATUS_EXECUTION_FAILED"));

g_errorStrings.insert(std::pair<cublasStatus_t, std::string>(CUBLAS_STATUS_INTERNAL_ERROR, "CUBLAS_STATUS_INTERNAL_ERROR"));

}

if (rCode != CUBLAS_STATUS_SUCCESS)

throw ((desc == "") ?

std::string("Error: ") :

(std::string("Error in \"") + desc + std::string("\": "))) +

g_errorStrings[rCode];

}

double getTime()

{

struct timeval t;

gettimeofday(&t, NULL);

return (double)t.tv_sec + (double)t.tv_usec / 1e6;

}

bool g_running = false;

template <class T> class GPU_Test {

public:

GPU_Test(int dev, bool doubles, bool tensors) :

d_devNumber(dev), d_doubles(doubles), d_tensors(tensors) {

checkError(cuDeviceGet(&d_dev, d_devNumber));

checkError(cuCtxCreate(&d_ctx, 0, d_dev));

bind();

//checkError(cublasInit());

checkError(cublasCreate(&d_cublas), "init");

if(d_tensors)

checkError(cublasSetMathMode(d_cublas, CUBLAS_TENSOR_OP_MATH));

checkError(cuMemAllocHost((void**)&d_faultyElemsHost, sizeof(int)));

d_error = 0;

g_running = true;

struct sigaction action;

memset(&action, 0, sizeof(struct sigaction));

action.sa_handler = termHandler;

sigaction(SIGTERM, &action, NULL);

}

~GPU_Test() {

bind();

checkError(cuMemFree(d_Cdata), "Free A");

checkError(cuMemFree(d_Adata), "Free B");

checkError(cuMemFree(d_Bdata), "Free C");

cuMemFreeHost(d_faultyElemsHost);

printf("Freed memory for dev %d\n", d_devNumber);

cublasDestroy(d_cublas);

printf("Uninitted cublas\n");

}

static void termHandler(int signum)

{

g_running = false;

}

unsigned long long int getErrors() {

if (*d_faultyElemsHost) {

d_error += (long long int)*d_faultyElemsHost;

}

unsigned long long int tempErrs = d_error;

d_error = 0;

return tempErrs;

}

size_t getIters() {

return d_iters;

}

void bind() {

checkError(cuCtxSetCurrent(d_ctx), "Bind CTX");

}

size_t totalMemory() {

bind();

size_t freeMem, totalMem;

checkError(cuMemGetInfo(&freeMem, &totalMem));

return totalMem;

}

size_t availMemory() {

bind();

size_t freeMem, totalMem;

checkError(cuMemGetInfo(&freeMem, &totalMem));

return freeMem;

}

void initBuffers(T *A, T *B) {

bind();

size_t useBytes = (size_t)((double)availMemory()*USEMEM);

printf("Initialized device %d with %lu MB of memory (%lu MB available, using %lu MB of it), %s%s\n",

d_devNumber, totalMemory()/1024ul/1024ul, availMemory()/1024ul/1024ul, useBytes/1024ul/1024ul,

d_doubles ? "using DOUBLES" : "using FLOATS", d_tensors ? ", using Tensor Cores" : "");

size_t d_resultSize = sizeof(T)*SIZE*SIZE;

d_iters = (useBytes - 2*d_resultSize)/d_resultSize; // We remove A and B sizes

//printf("Results are %d bytes each, thus performing %d iterations\n", d_resultSize, d_iters);

checkError(cuMemAlloc(&d_Cdata, d_iters*d_resultSize), "C alloc");

checkError(cuMemAlloc(&d_Adata, d_resultSize), "A alloc");

checkError(cuMemAlloc(&d_Bdata, d_resultSize), "B alloc");

checkError(cuMemAlloc(&d_faultyElemData, sizeof(int)), "faulty data");

// Populating matrices A and B

checkError(cuMemcpyHtoD(d_Adata, A, d_resultSize), "A -> device");

checkError(cuMemcpyHtoD(d_Bdata, B, d_resultSize), "A -> device");

initCompareKernel();

}

void compute() {

bind();

static const float alpha = 1.0f;

static const float beta = 0.0f;

static const double alphaD = 1.0;

static const double betaD = 0.0;

for (size_t i = 0; i < d_iters; ++i) {

if (d_doubles)

checkError(cublasDgemm(d_cublas, CUBLAS_OP_N, CUBLAS_OP_N,

SIZE, SIZE, SIZE, &alphaD,

(const double*)d_Adata, SIZE,

(const double*)d_Bdata, SIZE,

&betaD,

(double*)d_Cdata + i*SIZE*SIZE, SIZE), "DGEMM");

else

checkError(cublasSgemm(d_cublas, CUBLAS_OP_N, CUBLAS_OP_N,

SIZE, SIZE, SIZE, &alpha,

(const float*)d_Adata, SIZE,

(const float*)d_Bdata, SIZE,

&beta,

(float*)d_Cdata + i*SIZE*SIZE, SIZE), "SGEMM");

}

}

void initCompareKernel() {

const char *kernelFile = "compare.ptx";

{

std::ifstream f(kernelFile);

checkError(f.good() ? CUDA_SUCCESS : CUDA_ERROR_NOT_FOUND, std::string("couldn't find file \"") + kernelFile + "\" from working directory");

}

checkError(cuModuleLoad(&d_module, kernelFile), "load module");

checkError(cuModuleGetFunction(&d_function, d_module,

d_doubles ? "compareD" : "compare"), "get func");

checkError(cuFuncSetCacheConfig(d_function, CU_FUNC_CACHE_PREFER_L1), "L1 config");

checkError(cuParamSetSize(d_function, __alignof(T*) + __alignof(int*) + __alignof(size_t)), "set param size");

checkError(cuParamSetv(d_function, 0, &d_Cdata, sizeof(T*)), "set param");

checkError(cuParamSetv(d_function, __alignof(T*), &d_faultyElemData, sizeof(T*)), "set param");

checkError(cuParamSetv(d_function, __alignof(T*) + __alignof(int*), &d_iters, sizeof(size_t)), "set param");

checkError(cuFuncSetBlockShape(d_function, g_blockSize, g_blockSize, 1), "set block size");

}

void compare() {

checkError(cuMemsetD32Async(d_faultyElemData, 0, 1, 0), "memset");

checkError(cuLaunchGridAsync(d_function, SIZE/g_blockSize, SIZE/g_blockSize, 0), "Launch grid");

checkError(cuMemcpyDtoHAsync(d_faultyElemsHost, d_faultyElemData, sizeof(int), 0), "Read faultyelemdata");

}

bool shouldRun()

{

return g_running;

}

private:

bool d_doubles;

bool d_tensors;

int d_devNumber;

size_t d_iters;

size_t d_resultSize;

long long int d_error;

static const int g_blockSize = 16;

CUdevice d_dev;

CUcontext d_ctx;

CUmodule d_module;

CUfunction d_function;

CUdeviceptr d_Cdata;

CUdeviceptr d_Adata;

CUdeviceptr d_Bdata;

CUdeviceptr d_faultyElemData;

int *d_faultyElemsHost;

cublasHandle_t d_cublas;

};

// Returns the number of devices

int initCuda() {

checkError(cuInit(0));

int deviceCount = 0;

checkError(cuDeviceGetCount(&deviceCount));

if (!deviceCount)

throw std::string("No CUDA devices");

#ifdef USEDEV

if (USEDEV >= deviceCount)

throw std::string("Not enough devices for USEDEV");

#endif

return deviceCount;

}

template<class T> void startBurn(int index, int writeFd, T *A, T *B, bool doubles, bool tensors) {

GPU_Test<T> *our;

try {

our = new GPU_Test<T>(index, doubles, tensors);

our->initBuffers(A, B);

} catch (std::string e) {

fprintf(stderr, "Couldn't init a GPU test: %s\n", e.c_str());

exit(124);

}

// The actual work

try {

int eventIndex = 0;

const int maxEvents = 2;

CUevent events[maxEvents];

for (int i = 0; i < maxEvents; ++i)

cuEventCreate(events + i, 0);

int nonWorkIters = maxEvents;

while (our->shouldRun()) {

our->compute();

our->compare();

checkError(cuEventRecord(events[eventIndex], 0), "Record event");

eventIndex = ++eventIndex % maxEvents;

while (cuEventQuery(events[eventIndex]) != CUDA_SUCCESS) usleep(1000);

if (--nonWorkIters > 0) continue;

int ops = our->getIters();

write(writeFd, &ops, sizeof(int));

ops = our->getErrors();

write(writeFd, &ops, sizeof(int));

}

for (int i = 0; i < maxEvents; ++i)

cuEventSynchronize(events[i]);

delete our;

} catch (std::string e) {

fprintf(stderr, "Failure during compute: %s\n", e.c_str());

int ops = -1;

// Signalling that we failed

write(writeFd, &ops, sizeof(int));

write(writeFd, &ops, sizeof(int));

exit(111);

}

}

int pollTemp(pid_t *p) {

int tempPipe[2];

pipe(tempPipe);

pid_t myPid = fork();

if (!myPid) {

close(tempPipe[0]);

dup2(tempPipe[1], STDOUT_FILENO); // Stdout

//execlp("nvidia-smi", "nvidia-smi", "-l", "5", "-q", "-d", "TEMPERATURE", NULL);//原代码这里没注释掉,但是TX2是不能使用nvidia-smi的,所以这里留着会报错;

//fprintf(stderr, "Could not invoke nvidia-smi, no temps available\n");//原代码这里没注释掉,但是TX2是不能使用nvidia-smi的,所以这里留着会报错;

exit(0);

}

*p = myPid;

close(tempPipe[1]);

return tempPipe[0];

}

void updateTemps(int handle, std::vector<int> *temps) {

const int readSize = 10240;

static int gpuIter = 0;

char data[readSize+1];

int curPos = 0;

do {

read(handle, data+curPos, sizeof(char));

} while (data[curPos++] != '\n');

data[curPos-1] = 0;

int tempValue;

// FIXME: The syntax of this print might change in the future..

if (sscanf(data, "        GPU Current Temp            : %d C", &tempValue) == 1) {

//printf("read temp val %d\n", tempValue);

temps->at(gpuIter) = tempValue;

gpuIter = (gpuIter+1)%(temps->size());

} else if (!strcmp(data, "        Gpu                    : N/A"))

gpuIter = (gpuIter+1)%(temps->size()); // We rotate the iterator for N/A values as well

}

void listenClients(std::vector<int> clientFd, std::vector<pid_t> clientPid, int runTime) {

fd_set waitHandles;

pid_t tempPid;

int tempHandle = pollTemp(&tempPid);

int maxHandle = tempHandle;

FD_ZERO(&waitHandles);

FD_SET(tempHandle, &waitHandles);

for (size_t i = 0; i < clientFd.size(); ++i) {

if (clientFd.at(i) > maxHandle)

maxHandle = clientFd.at(i);

FD_SET(clientFd.at(i), &waitHandles);

}

std::vector<int> clientTemp;

std::vector<int> clientErrors;

std::vector<int> clientCalcs;

std::vector<struct timespec> clientUpdateTime;

std::vector<float> clientGflops;

std::vector<bool> clientFaulty;

time_t startTime = time(0);

for (size_t i = 0; i < clientFd.size(); ++i) {

clientTemp.push_back(0);

clientErrors.push_back(0);

clientCalcs.push_back(0);

struct timespec thisTime;

clock_gettime(CLOCK_REALTIME, &thisTime);

clientUpdateTime.push_back(thisTime);

clientGflops.push_back(0.0f);

clientFaulty.push_back(false);

}

int changeCount;

float nextReport = 10.0f;

bool childReport = false;

while ((changeCount = select(maxHandle+1, &waitHandles, NULL, NULL, NULL))) {

size_t thisTime = time(0);

struct timespec thisTimeSpec;

clock_gettime(CLOCK_REALTIME, &thisTimeSpec);

//printf("got new data! %d\n", changeCount);

// Going through all descriptors

for (size_t i = 0; i < clientFd.size(); ++i)

if (FD_ISSET(clientFd.at(i), &waitHandles)) {

// First, reading processed

int processed, errors;

read(clientFd.at(i), &processed, sizeof(int));

// Then errors

read(clientFd.at(i), &errors, sizeof(int));

clientErrors.at(i) += errors;

if (processed == -1)

clientCalcs.at(i) = -1;

else

{

double flops = (double)processed * (double)OPS_PER_MUL;

struct timespec clientPrevTime = clientUpdateTime.at(i);

double clientTimeDelta = (double)thisTimeSpec.tv_sec + (double)thisTimeSpec.tv_nsec / 1000000000.0 - ((double)clientPrevTime.tv_sec + (double)clientPrevTime.tv_nsec / 1000000000.0);

clientUpdateTime.at(i) = thisTimeSpec;

clientGflops.at(i) = (double)((unsigned long long int)processed * OPS_PER_MUL) / clientTimeDelta / 1000.0 / 1000.0 / 1000.0;

clientCalcs.at(i) += processed;

}

childReport = true;

}

if (FD_ISSET(tempHandle, &waitHandles))

updateTemps(tempHandle, &clientTemp);

// Resetting the listeners

FD_ZERO(&waitHandles);

FD_SET(tempHandle, &waitHandles);

for (size_t i = 0; i < clientFd.size(); ++i)

FD_SET(clientFd.at(i), &waitHandles);

// Printing progress (if a child has initted already)

if (childReport) {

float elapsed = fminf((float)(thisTime-startTime)/(float)runTime*100.0f, 100.0f);

printf("\r%.1f%%  ", elapsed);

printf("proc'd: ");

for (size_t i = 0; i < clientCalcs.size(); ++i) {

printf("%d (%.0f Gflop/s) ", clientCalcs.at(i), clientGflops.at(i));

if (i != clientCalcs.size() - 1)

printf("- ");

}

printf("  errors: ");

for (size_t i = 0; i < clientErrors.size(); ++i) {

std::string note = "%d ";

if (clientCalcs.at(i) == -1)

note += " (DIED!)";

else if (clientErrors.at(i))

note += " (WARNING!)";

printf(note.c_str(), clientErrors.at(i));

if (i != clientCalcs.size() - 1)

printf("- ");

}

printf("  temps: ");

for (size_t i = 0; i < clientTemp.size(); ++i) {

printf(clientTemp.at(i) != 0 ? "%d C " : "-- ", clientTemp.at(i));

if (i != clientCalcs.size() - 1)

printf("- ");

}

fflush(stdout);

if (nextReport < elapsed) {

nextReport = elapsed + 10.0f;

printf("\n\tSummary at:  ");

fflush(stdout);

system("date"); // Printing a date

fflush(stdout);

printf("\n");

//printf("\t(checkpoint)\n");

for (size_t i = 0; i < clientErrors.size(); ++i) {

if (clientErrors.at(i))

clientFaulty.at(i) = true;

clientErrors.at(i) = 0;

}

}

}

// Checking whether all clients are dead

bool oneAlive = false;

for (size_t i = 0; i < clientCalcs.size(); ++i)

if (clientCalcs.at(i) != -1)

oneAlive = true;

if (!oneAlive) {

fprintf(stderr, "\n\nNo clients are alive!  Aborting\n");

exit(123);

}

if (startTime + runTime < thisTime)

break;

}

printf("\nKilling processes.. ");

fflush(stdout);

for (size_t i = 0; i < clientPid.size(); ++i)

kill(clientPid.at(i), 15);

kill(tempPid, 15);

close(tempHandle);

while (wait(NULL) != -1);

printf("done\n");

printf("\nTested %d GPUs:\n", (int)clientPid.size());

for (size_t i = 0; i < clientPid.size(); ++i)

printf("\tGPU %d: %s\n", (int)i, clientFaulty.at(i) ? "FAULTY" : "OK");

}

template<class T> void launch(int runLength, bool useDoubles, bool useTensorCores) {

//system("nvidia-smi -L");//原代码这里没注释掉,但是TX2是不能使用nvidia-smi的,所以这里留着会报错;

//system("tegrastats");//原代码这里根本没有,但是TX2是不能使用nvidia-smi,所以这里准备尝试曲线救国,使用tx2自带的tegrastats,但是尝试后不管用;

// Initting A and B with random data

T *A = (T*) malloc(sizeof(T)*SIZE*SIZE);

T *B = (T*) malloc(sizeof(T)*SIZE*SIZE);

srand(10);

for (size_t i = 0; i < SIZE*SIZE; ++i) {

A[i] = (T)((double)(rand()%1000000)/100000.0);

B[i] = (T)((double)(rand()%1000000)/100000.0);

}

// Forking a process..  This one checks the number of devices to use,

// returns the value, and continues to use the first one.

int mainPipe[2];

pipe(mainPipe);

int readMain = mainPipe[0];

std::vector<int> clientPipes;

std::vector<pid_t> clientPids;

clientPipes.push_back(readMain);

pid_t myPid = fork();

if (!myPid) {

// Child

close(mainPipe[0]);

int writeFd = mainPipe[1];

int devCount = initCuda();

write(writeFd, &devCount, sizeof(int));

startBurn<T>(0, writeFd, A, B, useDoubles, useTensorCores);

close(writeFd);

return;

} else {

clientPids.push_back(myPid);

close(mainPipe[1]);

int devCount;

    read(readMain, &devCount, sizeof(int));

if (!devCount) {

fprintf(stderr, "No CUDA devices\n");

exit(EXIT_FAILURE);

} else {

for (int i = 1; i < devCount; ++i) {

int slavePipe[2];

pipe(slavePipe);

clientPipes.push_back(slavePipe[0]);

pid_t slavePid = fork();

if (!slavePid) {

// Child

close(slavePipe[0]);

initCuda();

startBurn<T>(i, slavePipe[1], A, B, useDoubles, useTensorCores);

close(slavePipe[1]);

return;

} else {

clientPids.push_back(slavePid);

close(slavePipe[1]);

}

}

listenClients(clientPipes, clientPids, runLength);

}

}

for (size_t i = 0; i < clientPipes.size(); ++i)

close(clientPipes.at(i));

free(A);

free(B);

}

int main(int argc, char **argv) {

int runLength = 10;

bool useDoubles = false;

bool useTensorCores = false;

int thisParam = 0;

std::vector<std::string> args(argv, argv + argc);

for (size_t i = 1; i < args.size(); ++i)

{

if (argc >= 2 && std::string(argv[i]).find("-d") != std::string::npos)

{

useDoubles = true;

thisParam++;

}

if (argc >= 2 && std::string(argv[i]).find("-tc") != std::string::npos)

{

useTensorCores = true;

thisParam++;

}

}

if (argc-thisParam < 2)

printf("Run length not specified in the command line.  Burning for 10 secs\n");

else

runLength = atoi(argv[1+thisParam]);

useDoubles = true;//原代码这里根本没有,但是这里需要修改形式参数,增加gpu-burn的运行时间,之前只能10秒,增加这条之后可以达到95秒;

runLength = 60;//原代码这里根本没有,但是这里需要修改形式参数,增加gpu-burn的运行时间,之前只能10秒,增加这条之后可以达到95秒;

if (useDoubles)

launch<double>(runLength, useDoubles, useTensorCores);

else

launch<float>(runLength, useDoubles, useTensorCores);

return 0;

}

'''

上一篇下一篇

猜你喜欢

热点阅读