Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] View of /branches/cuda/src/lib/include/diderot/gpu-select.cuh
ViewVC logotype

View of /branches/cuda/src/lib/include/diderot/gpu-select.cuh

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5634 - (download) (annotate)
Wed Sep 15 21:02:20 2021 UTC (9 months, 1 week ago) by adrianlehmann
File size: 3398 byte(s)
Add GPU selection mechanism for multi-gpu machines
#ifndef _DIDEROT_GPU_SELECT_
#define _DIDEROT_GPU_SELECT_

#include "base.cuh"
#include "options.h"
#include <cmath>

namespace diderot {
class gpu_selector {
private:
    bool interactive = false;
    int32_t gpuIdx = -1;

    bool isValidGpu(cudaDeviceProp &deviceProperties) {
        return deviceProperties.major >= 6 && deviceProperties.totalGlobalMem >= 1000 * 1000 * 1000 /*1GB*/;
    }

public:
    void registerOptions(diderot::options *options) {
        options->addFlag("ig,interactive-gpu", "Interactively select CUDA GPU when launching", &interactive);
        options->add("gpu", "Specify id of CUDA GPU to select", &gpuIdx, true);
    }

    void selectGpu() {
        if (gpuIdx < -1) {
            std::cerr << "Warning: GPU id cannot be negative - ignoring" << std::endl;
        }
        bool validGpuId = gpuIdx >= 0;
        if (interactive && validGpuId) {
            std::cerr << "Warning: GPU specified, ignoring interactive GPU selection flag" << std::endl;
        }
        int devicesCount;
        cudaGetDeviceCount(&devicesCount);
        if (devicesCount == 0){
            std::cerr << "Error: No CUDA GPUs found." << std::endl;
            exit(1);
        }
        if (!validGpuId && interactive) {
            std::cout << "Available GPUs:" << std::endl;
            std::cout << "| id | name | memory | max grid | max threads per block |\n";
            for (int i = 0; i < devicesCount; i++) {
                cudaDeviceProp deviceProperties{};
                cudaGetDeviceProperties(&deviceProperties, i);
                if (!isValidGpu(deviceProperties)) {
                    continue;
                }
                int maxGridSize = std::min(deviceProperties.maxGridSize[0],
                                           std::min(deviceProperties.maxGridSize[1], deviceProperties.maxGridSize[2]));
                printf("| %d | %s | %zu | %d | %d |\n", i, deviceProperties.name, deviceProperties.totalGlobalMem,
                       maxGridSize, deviceProperties.maxThreadsPerBlock);
            }
            std::cout << std::endl;
            do {
                std::cout << "Enter GPU id:" << std::endl;
                std::string input;
                getline(std::cin, input);
                try {
                    gpuIdx = std::stoi(input);
                } catch (std::invalid_argument) {
                }
            } while (gpuIdx <= 0 || gpuIdx >= devicesCount);
        }
        validGpuId = gpuIdx >= 0 && gpuIdx <= devicesCount;
        if (validGpuId) {
            cudaDeviceProp deviceProperties{};
            cudaGetDeviceProperties(&deviceProperties, gpuIdx);
            if (!isValidGpu(deviceProperties)) {
                std::cerr
                        << "Warning: selected invalid GPU. Falling back to default GPU. Please use interactive GPU selection if unsure";
                return;
            }
            std::cout << "Set GPU to: " << deviceProperties.name << " (id:" << gpuIdx << ")" << std::endl;
            cudaSetDevice(gpuIdx);
        } else if (devicesCount > 1) { // No need to display selection when signle GPU 
            cudaDeviceProp deviceProperties{};
            cudaGetDeviceProperties(&deviceProperties, 0);
            std::cout << "Using default GPU: " << deviceProperties.name << std::endl;
            cudaSetDevice(0);
        }
    }
};
}
#endif //_DIDEROT_GPU_SELECT_

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0