|
1 | 1 | #include "ggml-vulkan.h" |
| 2 | +#include <limits> |
| 3 | +#include <map> |
| 4 | +#include <ostream> |
| 5 | +#include <string> |
| 6 | +#include <vulkan/vulkan_core.h> |
2 | 7 |
|
3 | 8 | #ifdef GGML_VULKAN_RUN_TESTS |
4 | 9 | #include <chrono> |
@@ -1691,7 +1696,64 @@ void ggml_vk_instance_init() { |
1691 | 1696 | vk::PhysicalDeviceProperties props = devices[i].getProperties(); |
1692 | 1697 |
|
1693 | 1698 | if (props.deviceType == vk::PhysicalDeviceType::eDiscreteGpu) { |
1694 | | - vk_instance.device_indices.push_back(i); |
| 1699 | + // Check if there are two physical devices corresponding to the same GPU |
| 1700 | + auto old_device = std::find_if( |
| 1701 | + vk_instance.device_indices.begin(), |
| 1702 | + vk_instance.device_indices.end(), |
| 1703 | + [&devices, &props](const size_t k){ return devices[k].getProperties().deviceID == props.deviceID; } |
| 1704 | + ); |
| 1705 | + if (old_device == vk_instance.device_indices.end()) { |
| 1706 | + vk_instance.device_indices.push_back(i); |
| 1707 | + } else { |
| 1708 | + // There can be two physical devices corresponding to the same GPU if there are 2 different drivers |
| 1709 | + // This can cause error when splitting layers aross the devices, need to keep only 1 |
| 1710 | + std::cout << "Device " << i << " and device " << *old_device << " have the same device id" << std::endl; |
| 1711 | + |
| 1712 | + vk::PhysicalDeviceProperties2 old_prop; |
| 1713 | + vk::PhysicalDeviceDriverProperties old_driver; |
| 1714 | + old_prop.pNext = &old_driver; |
| 1715 | + devices[*old_device].getProperties2(&old_prop); |
| 1716 | + std::string old_driver_name {old_driver.driverName.data()}; |
| 1717 | + |
| 1718 | + vk::PhysicalDeviceProperties2 new_prop; |
| 1719 | + vk::PhysicalDeviceDriverProperties new_driver; |
| 1720 | + new_prop.pNext = &new_driver; |
| 1721 | + devices[i].getProperties2(&new_prop); |
| 1722 | + std::string new_driver_name {new_driver.driverName.data()}; |
| 1723 | + |
| 1724 | + // Check https://vulkan.gpuinfo.org/displaycoreproperty.php?name=driverName&core=1.2 for a list of driver names |
| 1725 | + // Smaller number -> higher priority |
| 1726 | + std::map<std::string, int> driver_priorities {}; |
| 1727 | + driver_priorities["NVIDIA"] = 1; |
| 1728 | + driver_priorities["nvk"] = 2; |
| 1729 | + driver_priorities["radv"] = 3; |
| 1730 | + driver_priorities["AMD open-source driver"] = 4; |
| 1731 | + driver_priorities["AMD proprietary driver"] = 5; |
| 1732 | + driver_priorities["Intel open-source Mesa driver"] = 6; |
| 1733 | + driver_priorities["Intel Corporation"] = 7; |
| 1734 | + |
| 1735 | + // Select the driver based on the priority map |
| 1736 | + // Keep the old one if the names are not there |
| 1737 | + int old_priority = std::numeric_limits<int>::max(); |
| 1738 | + if (driver_priorities.count(old_driver_name)) { |
| 1739 | + old_priority = driver_priorities[old_driver_name]; |
| 1740 | + } |
| 1741 | + int new_priority = std::numeric_limits<int>::max(); |
| 1742 | + if (driver_priorities.count(new_driver_name)) { |
| 1743 | + new_priority = driver_priorities[new_driver_name]; |
| 1744 | + } |
| 1745 | + |
| 1746 | + if (new_priority < old_priority) { |
| 1747 | + auto r = std::remove(vk_instance.device_indices.begin(), vk_instance.device_indices.end(), *old_device); |
| 1748 | + vk_instance.device_indices.erase(r, vk_instance.device_indices.end()); |
| 1749 | + vk_instance.device_indices.push_back(i); |
| 1750 | + std::cout << "Prioritize device " << i << " driver " << new_driver_name << " over device " << *old_device << " driver " << old_driver_name << std::endl; |
| 1751 | + std::cout << "Remove device " << *old_device << std::endl; |
| 1752 | + } else { |
| 1753 | + std::cout << "Prioritize device " << *old_device << " driver " << old_driver_name << " over device " << i << " driver " << new_driver_name << std::endl; |
| 1754 | + std::cout << "Keep device " << *old_device << std::endl; |
| 1755 | + } |
| 1756 | + } |
1695 | 1757 | } |
1696 | 1758 | } |
1697 | 1759 |
|
|
0 commit comments