/* * Copyright (c) 2015, PHILIPPE TILLET. All rights reserved. * * This file is part of ISAAC. * * ISAAC is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ #include #include #include #include #include "isaac/driver/device.h" #include "helpers/ocl/infos.hpp" namespace isaac { namespace driver { template int Device::cuGetInfo() const { int res; cuda::check(dispatch::cuDeviceGetAttribute(&res, attr, h_.cu())); return res; } Device::Device(CUdevice const & device, bool take_ownership): backend_(CUDA), h_(backend_, take_ownership) { h_.cu() = device; } Device::Device(cl_device_id const & device, bool take_ownership) : backend_(OPENCL), h_(backend_, take_ownership) { h_.cl() = device; } bool Device::operator==(Device const & other) const { return h_==other.h_; } bool Device::operator<(Device const & other) const { return h_ sm = nv_compute_capability(); switch(sm.first) { case 5: return Architecture::MAXWELL; case 3: return Architecture::KEPLER; case 2: return Architecture::FERMI; case 1: return Architecture::TESLA; } } case Vendor::AMD: { //No simple way to query TeraScale/GCN version. Enumerate... std::string device_name = name(); #define MAP_DEVICE(device,arch)if (device_name.find(device,0)!=std::string::npos) return Architecture::arch; //TERASCALE 2 MAP_DEVICE("Barts",TERASCALE_2); MAP_DEVICE("Cedar",TERASCALE_2); MAP_DEVICE("Redwood",TERASCALE_2); MAP_DEVICE("Juniper",TERASCALE_2); MAP_DEVICE("Cypress",TERASCALE_2); MAP_DEVICE("Hemlock",TERASCALE_2); MAP_DEVICE("Caicos",TERASCALE_2); MAP_DEVICE("Turks",TERASCALE_2); MAP_DEVICE("WinterPark",TERASCALE_2); MAP_DEVICE("BeaverCreek",TERASCALE_2); //TERASCALE 3 MAP_DEVICE("Cayman",TERASCALE_3); MAP_DEVICE("Antilles",TERASCALE_3); MAP_DEVICE("Scrapper",TERASCALE_3); MAP_DEVICE("Devastator",TERASCALE_3); //GCN 1.0 MAP_DEVICE("Cape",GCN_1_0); MAP_DEVICE("Pitcairn",GCN_1_0); MAP_DEVICE("Tahiti",GCN_1_0); MAP_DEVICE("New Zealand",GCN_1_0); MAP_DEVICE("Curacao",GCN_1_0); MAP_DEVICE("Malta",GCN_1_0); //GCN 1.1 MAP_DEVICE("Bonaire",GCN_1_1); MAP_DEVICE("Hawaii",GCN_1_1); MAP_DEVICE("Vesuvius",GCN_1_1); //GCN 1.2 MAP_DEVICE("Tonga",GCN_1_2); MAP_DEVICE("Fiji",GCN_1_2); #undef MAP_DEVICE } default: { return Architecture::UNKNOWN; } } } backend_type Device::backend() const { return backend_; } unsigned int Device::address_bits() const { switch(backend_) { case CUDA: return sizeof(size_t)*8; case OPENCL: return ocl::info(h_.cl()); default: throw; } return backend_; } driver::Platform Device::platform() const { switch(backend_) { case CUDA: return Platform(CUDA); case OPENCL: return Platform(ocl::info(h_.cl())); default: throw; } } std::string Device::name() const { switch(backend_) { case CUDA: char tmp[128]; cuda::check(dispatch::cuDeviceGetName(tmp, 128, h_.cu())); return std::string(tmp); case OPENCL: return ocl::info(h_.cl()); default: throw; } } std::string Device::vendor_str() const { switch(backend_) { case CUDA: return "NVidia"; case OPENCL: return ocl::info(h_.cl()); default: throw; } } std::vector Device::max_work_item_sizes() const { switch(backend_) { case CUDA: { std::vector result(3); result[0] = cuGetInfo(); result[1] = cuGetInfo(); result[2] = cuGetInfo(); return result; } case OPENCL: return ocl::info(h_.cl()); default: throw; } } Device::Type Device::type() const { switch(backend_) { case CUDA: return Type::GPU; case OPENCL: return static_cast(ocl::info(h_.cl())); default: throw; } } std::string Device::extensions() const { switch(backend_) { case CUDA: return ""; case OPENCL: return ocl::info(h_.cl()); default: throw; } } std::pair Device::nv_compute_capability() const { switch(backend_) { case OPENCL: return std::pair(ocl::info(h_.cl()), ocl::info(h_.cl())); case CUDA: return std::pair(cuGetInfo(), cuGetInfo()); default: throw; } } bool Device::fp64_support() const { switch(backend_) { case OPENCL: return extensions().find("cl_khr_fp64")!=std::string::npos; case CUDA: return true; default: throw; } } std::string Device::infos() const { std::ostringstream oss; std::vector max_wi_sizes = max_work_item_sizes(); oss << "Platform: " << platform().name() << std::endl; oss << "Vendor: " << vendor_str() << std::endl; oss << "Name: " << name() << std::endl; oss << "Maximum total work-group size: " << max_work_group_size() << std::endl; oss << "Maximum individual work-group sizes: " << max_wi_sizes[0] << ", " << max_wi_sizes[1] << ", " << max_wi_sizes[2] << std::endl; oss << "Local memory size: " << local_mem_size() << std::endl; return oss.str(); } // Properties #define WRAP_ATTRIBUTE(ret, fname, CUNAME, CLNAME) \ ret Device::fname() const\ {\ switch(backend_)\ {\ case CUDA: return cuGetInfo();\ case OPENCL: return static_cast(ocl::info(h_.cl()));\ default: throw;\ }\ }\ WRAP_ATTRIBUTE(size_t, max_work_group_size, CU_DEVICE_ATTRIBUTE_MAX_THREADS_PER_BLOCK, CL_DEVICE_MAX_WORK_GROUP_SIZE) WRAP_ATTRIBUTE(size_t, local_mem_size, CU_DEVICE_ATTRIBUTE_MAX_SHARED_MEMORY_PER_BLOCK, CL_DEVICE_LOCAL_MEM_SIZE) WRAP_ATTRIBUTE(size_t, warp_wavefront_size, CU_DEVICE_ATTRIBUTE_WARP_SIZE, CL_DEVICE_WAVEFRONT_WIDTH_AMD) WRAP_ATTRIBUTE(size_t, clock_rate, CU_DEVICE_ATTRIBUTE_CLOCK_RATE, CL_DEVICE_MAX_CLOCK_FREQUENCY) } }