/*- * #%L * Fiji distribution of ImageJ for the life sciences. * %% * Copyright (C) 2007 - 2017 Fiji developers. * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-2.0.html>. * #L% */ package spim.process.cuda; import ij.gui.GenericDialog; import java.util.ArrayList; import java.util.Collections; import mpicbg.spim.io.IOFunctions; import spim.fiji.plugin.util.GenericDialogAppender; public class CUDATools { /** * 0 ... n == index for i'th CUDA device */ public static ArrayList< Boolean > deviceChoice = null; public static int standardDevice = -1; /** * @param cuda * @param askForMultipleDevices * @return - a list of CUDA device Id's to be used */ public static ArrayList< CUDADevice > queryCUDADetails( final CUDAStandardFunctions cuda, final boolean askForMultipleDevices ) { return queryCUDADetails( cuda, askForMultipleDevices, null ); } /** * @param cuda * @param askForMultipleDevices * @param additionalQueries * @return - a list of CUDA device Id's to be used */ public static ArrayList< CUDADevice > queryCUDADetails( final CUDAStandardFunctions cuda, final boolean askForMultipleDevices, final GenericDialogAppender additionalQueries ) { final int numDevices = cuda.getNumDevicesCUDA(); if ( numDevices == -1 ) { IOFunctions.println( "Querying CUDA devices crashed, no devices available." ); return null; } else if ( numDevices == 0 ) { IOFunctions.println( "No CUDA devices detected." ); return null; } // // get the ID's and functionality of the CUDA GPU's // final CUDADevice[] deviceList = new CUDADevice[ numDevices ]; final byte[] name = new byte[ 256 ]; int highestComputeCapability = 0; long highestMemory = 0; int highestComputeCapabilityDevice = -1; for ( int i = 0; i < numDevices; ++i ) { cuda.getNameDeviceCUDA( i, name ); String deviceName = ""; for ( final byte b : name ) if ( b != 0 ) deviceName += (char)b; deviceName.trim(); final long mem = cuda.getMemDeviceCUDA( i ); long freeMem; try { freeMem = cuda.getFreeMemDeviceCUDA( i ); } catch (UnsatisfiedLinkError e ) { IOFunctions.println( "Using an outdated version of the CUDA libs, cannot query free memory. Assuming total memory." ); freeMem = mem; } final int majorVersion = cuda.getCUDAcomputeCapabilityMajorVersion( i ); final int minorVersion = cuda.getCUDAcomputeCapabilityMinorVersion( i ); final int compCap = 10 * majorVersion + minorVersion; if ( compCap > highestComputeCapability ) { highestComputeCapability = compCap; highestComputeCapabilityDevice = i; } if ( mem > highestMemory ) highestMemory = mem; deviceList[ i ] = new CUDADevice( i, deviceName, mem, freeMem, majorVersion, minorVersion ); } // get the CPU specs // final String cpuSpecs = "CPU (" + Threads.numThreads() + " cores, " + Runtime.getRuntime().maxMemory()/(1024*1024) + " MB RAM available)"; final ArrayList< CUDADevice > selectedDevices = new ArrayList< CUDADevice >(); // if we use blocks, it makes sense to run more than one device if ( askForMultipleDevices ) { // make a list where all are checked if there is no previous selection if ( deviceChoice == null || deviceChoice.size() != deviceList.length ) //+ 1 ) { deviceChoice = new ArrayList<Boolean>( deviceList.length + 1 ); for ( int i = 0; i < deviceList.length; ++i ) deviceChoice.add( true ); // CPU is by default not checked deviceChoice.add( false ); } final GenericDialog gdCUDA = new GenericDialog( "Choose CUDA/CPUs devices to use" ); for ( int i = 0; i < deviceList.length; ++i ) gdCUDA.addCheckbox( "GPU_" + (i+1) + " of " + deviceList.length + ": " + deviceList[ i ], deviceChoice.get( i ) ); if ( additionalQueries != null ) additionalQueries.addQuery( gdCUDA ); gdCUDA.showDialog(); if ( gdCUDA.wasCanceled() ) return null; // check all CUDA devices for ( int i = 0; i < deviceList.length; ++i ) { if( gdCUDA.getNextBoolean() ) { selectedDevices.add( deviceList[ i ] ); deviceChoice.set( i , true ); } else { deviceChoice.set( i , false ); } } if ( additionalQueries != null ) if ( !additionalQueries.parseDialog( gdCUDA ) ) return null; if ( selectedDevices.size() == 0 ) { IOFunctions.println( "You selected no device, quitting." ); return null; } } else { // only choose one device to run everything at once final GenericDialog gdCUDA = new GenericDialog( "Choose CUDA device" ); if ( standardDevice < 0 || standardDevice >= deviceList.length ) standardDevice = highestComputeCapabilityDevice; final String desc[] = new String[ deviceList.length ]; for ( int i = 0; i < deviceList.length; ++i ) desc[ i ] = "GPU " + (i+1) + " of " + deviceList.length + ": " + deviceList[ i ]; gdCUDA.addChoice( "Device", desc, desc[ standardDevice ] ); if ( additionalQueries != null ) additionalQueries.addQuery( gdCUDA ); gdCUDA.showDialog(); if ( gdCUDA.wasCanceled() ) return null; selectedDevices.add( deviceList[ standardDevice = gdCUDA.getNextChoiceIndex() ] ); if ( additionalQueries != null ) if ( !additionalQueries.parseDialog( gdCUDA ) ) return null; } Collections.sort( selectedDevices ); for ( final CUDADevice dev : selectedDevices ) IOFunctions.println( "Using device " + dev ); return selectedDevices; } }