Returns a list of dictionaries, with the following keys:
    - index (integer, device index of the GPU)
    - name (str, GPU name)
    - memory_free (float, free memory in MiB)
    - memory_total (float, total memory in MiB)

def _get_cuda_gpus():
    """
    Returns a list of dictionaries, with the following keys:
    - index (integer, device index of the GPU)
    - name (str, GPU name)
    - memory_free (float, free memory in MiB)
    - memory_total (float, total memory in MiB)
    """
    import subprocess
    try:
        output = subprocess.check_output(['nvidia-smi',
                                          '--query-gpu=index,gpu_name,memory.free,memory.total',
                                          '--format=csv,noheader,nounits'],
                                         universal_newlines=True)
    except OSError:
        return []
    except subprocess.CalledProcessError:
        return []

    gpus = []
    for gpu_line in output.split('\n'):
        if gpu_line:
            index, gpu_name, memory_free, memory_total = gpu_line.split(', ')
            index = int(index)
            memory_free = float(memory_free)
            memory_total = float(memory_total)
            gpus.append({
                'index': index,
                'name': gpu_name,
                'memory_free': memory_free,
                'memory_total': memory_total,
            })
    return gpus