| 1032 | } |
| 1033 | |
| 1034 | Status ColocationGraph::GetDevicesForNode( |
| 1035 | Node* node, const std::vector<Device*>** possible_devices) { |
| 1036 | *possible_devices = nullptr; |
| 1037 | const int node_root = FindAndUpdateRoot(node->id()); |
| 1038 | if (!members_[node_root].possible_devices().empty()) { |
| 1039 | *possible_devices = &members_[node_root].possible_devices(); |
| 1040 | return Status::OK(); |
| 1041 | } |
| 1042 | |
| 1043 | Member& root_member = members_[node_root]; |
| 1044 | |
| 1045 | // We have not yet computed the possible devices for the |
| 1046 | // colocated node set containing 'node', so we do so now using the |
| 1047 | // constraints on the root node. |
| 1048 | |
| 1049 | // "devices" will contain the set of feasible placements for the |
| 1050 | // colocated node set containing 'node'. |
| 1051 | // NOTE: Basing possible device computation on requested device name |
| 1052 | // is guaranteed to respect the assigned and resource device names because |
| 1053 | // requested device is always a specialization of both. |
| 1054 | std::vector<Device*> devices; |
| 1055 | if (DeviceNameUtils::HasSomeDetails(root_member.requested_device_name())) { |
| 1056 | // The root node has a (possibly partial) device |
| 1057 | // specification, so enumerate the physical devices that |
| 1058 | // conform to it. |
| 1059 | device_set_.FindMatchingDevices(root_member.requested_device_name(), |
| 1060 | &devices); |
| 1061 | |
| 1062 | if (!devices.empty()) { |
| 1063 | // Filter devices into those that are compatible with the root |
| 1064 | // node (and its children). |
| 1065 | devices = FilterSupportedDevices( |
| 1066 | devices, root_member.supported_device_types(), default_local_device_); |
| 1067 | } |
| 1068 | |
| 1069 | // Perform soft placement if allow_soft_placement_ is set. |
| 1070 | if (devices.empty() && allow_soft_placement_) { |
| 1071 | GetSoftDeviceCandidates(*node, root_member, node_root, &devices); |
| 1072 | } |
| 1073 | |
| 1074 | if (devices.empty()) { |
| 1075 | // Return an error when a physical device that matches an explicit |
| 1076 | // device specification is not found. This ensures that we don't |
| 1077 | // assign a node to GPU when the user wanted to force it on CPU. |
| 1078 | string debug_info = DebugInfo(node_root); |
| 1079 | |
| 1080 | DeviceNameUtils::ParsedName specified_device_name; |
| 1081 | if (DeviceNameUtils::ParseFullName(node->requested_device(), |
| 1082 | &specified_device_name) && |
| 1083 | specified_device_name == root_member.requested_device_name()) { |
| 1084 | // The specified device and merged set device match, and |
| 1085 | // will appear in the GraphDef (for debugging), so just |
| 1086 | // print the specified device. |
| 1087 | std::vector<Device*> devices_matching_nodedef; |
| 1088 | device_set_.FindMatchingDevices(specified_device_name, |
| 1089 | &devices_matching_nodedef); |
| 1090 | if (devices_matching_nodedef.empty()) { |
| 1091 | // Sometimes it is almost impossible to understand the problem |
no test coverage detected