Repository: deepjavalibrary/djl
Pull request #1490 (2022-02-01 22:29:20)

Device Name parsing
This adds support for device names to the Device class and the ability to parse
those names.

codecov-commenter: # [Codecov](https://codecov.io/gh/deepjavalibrary/djl/pull/1490?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary) Report
> Merging [#1490](https://codecov.io/gh/deepjavalibrary/djl/pull/1490?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary) (467fd36) into [master](https://codecov.io/gh/deepjavalibrary/djl/commit/bb5073f7ffc33f1883621fc1783dbb01e70b418f?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary) (bb5073f) will **decrease** coverage by `1.35%`.
> The diff coverage is `50.07%`.

[![Impacted file tree graph](https://codecov.io/gh/deepjavalibrary/djl/pull/1490/graphs/tree.svg?width=650&height=150&src=pr&token=mDKVNwFXRV&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary)](https://codecov.io/gh/deepjavalibrary/djl/pull/1490?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary)

```diff
@@             Coverage Diff              @@
##             master    #1490      +/-   ##
============================================
- Coverage     72.08%   70.73%   -1.36%     
- Complexity     5126     5318     +192     
============================================
  Files           473      493      +20     
  Lines         21970    23285    +1315     
  Branches       2351     2548     +197     
============================================
+ Hits          15838    16471     +633     
- Misses         4925     5534     +609     
- Partials       1207     1280      +73     
```


| [Impacted Files](https://codecov.io/gh/deepjavalibrary/djl/pull/1490?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary) | Coverage Δ | |
|---|---|---|
| [api/src/main/java/ai/djl/modality/cv/Image.java](https://codecov.io/gh/deepjavalibrary/djl/pull/1490/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL21vZGFsaXR5L2N2L0ltYWdlLmphdmE=) | `69.23% <ø> (-4.11%)` | :arrow_down: |
| [...i/djl/modality/cv/translator/BigGANTranslator.java](https://codecov.io/gh/deepjavalibrary/djl/pull/1490/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL21vZGFsaXR5L2N2L3RyYW5zbGF0b3IvQmlnR0FOVHJhbnNsYXRvci5qYXZh) | `21.42% <ø> (-5.24%)` | :arrow_down: |
| [...odality/cv/translator/BigGANTranslatorFactory.java](https://codecov.io/gh/deepjavalibrary/djl/pull/1490/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL21vZGFsaXR5L2N2L3RyYW5zbGF0b3IvQmlnR0FOVHJhbnNsYXRvckZhY3RvcnkuamF2YQ==) | `33.33% <0.00%> (+8.33%)` | :arrow_up: |
| [...nslator/InstanceSegmentationTranslatorFactory.java](https://codecov.io/gh/deepjavalibrary/djl/pull/1490/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL21vZGFsaXR5L2N2L3RyYW5zbGF0b3IvSW5zdGFuY2VTZWdtZW50YXRpb25UcmFuc2xhdG9yRmFjdG9yeS5qYXZh) | `14.28% <0.00%> (-3.90%)` | :arrow_down: |
| [.../modality/cv/translator/YoloTranslatorFactory.java](https://codecov.io/gh/deepjavalibrary/djl/pull/1490/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL21vZGFsaXR5L2N2L3RyYW5zbGF0b3IvWW9sb1RyYW5zbGF0b3JGYWN0b3J5LmphdmE=) | `8.33% <0.00%> (-1.67%)` | :arrow_down: |
| [...i/djl/modality/cv/translator/YoloV5Translator.java](https://codecov.io/gh/deepjavalibrary/djl/pull/1490/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL21vZGFsaXR5L2N2L3RyYW5zbGF0b3IvWW9sb1Y1VHJhbnNsYXRvci5qYXZh) | `5.69% <0.00%> (ø)` | |
| [...odality/cv/translator/YoloV5TranslatorFactory.java](https://codecov.io/gh/deepjavalibrary/djl/pull/1490/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL21vZGFsaXR5L2N2L3RyYW5zbGF0b3IvWW9sb1Y1VHJhbnNsYXRvckZhY3RvcnkuamF2YQ==) | `8.33% <0.00%> (-1.67%)` | :arrow_down: |
| [...pi/src/main/java/ai/djl/ndarray/BytesSupplier.java](https://codecov.io/gh/deepjavalibrary/djl/pull/1490/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL25kYXJyYXkvQnl0ZXNTdXBwbGllci5qYXZh) | `54.54% <0.00%> (-12.13%)` | :arrow_down: |
| [...i/src/main/java/ai/djl/ndarray/NDArrayAdapter.java](https://codecov.io/gh/deepjavalibrary/djl/pull/1490/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL25kYXJyYXkvTkRBcnJheUFkYXB0ZXIuamF2YQ==) | `15.23% <0.00%> (-0.83%)` | :arrow_down: |
| [...l/training/loss/SigmoidBinaryCrossEntropyLoss.java](https://codecov.io/gh/deepjavalibrary/djl/pull/1490/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary#diff-YXBpL3NyYy9tYWluL2phdmEvYWkvZGpsL3RyYWluaW5nL2xvc3MvU2lnbW9pZEJpbmFyeUNyb3NzRW50cm9weUxvc3MuamF2YQ==) | `64.00% <0.00%> (ø)` | |
| ... and [176 more](https://codecov.io/gh/deepjavalibrary/djl/pull/1490/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/deepjavalibrary/djl/pull/1490?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/deepjavalibrary/djl/pull/1490?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary). Last update [c3bd94d...467fd36](https://codecov.io/gh/deepjavalibrary/djl/pull/1490?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deepjavalibrary).


Patch:
diff --git a/api/src/main/java/ai/djl/Device.java b/api/src/main/java/ai/djl/Device.java
index f2adaf880..ed90c4ef2 100644
--- a/api/src/main/java/ai/djl/Device.java
+++ b/api/src/main/java/ai/djl/Device.java
@@ -15,6 +15,8 @@ package ai.djl;
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * The {@code Device} class provides the specified assignment for CPU/GPU processing on the {@code
@@ -33,6 +35,8 @@ public final class Device {
     private static final Device CPU = new Device(Type.CPU, -1);
     private static final Device GPU = Device.of(Type.GPU, 0);
 
+    private static final Pattern DEVICE_NAME = Pattern.compile("([a-z]+)([0-9]*)");
+
     private String deviceType;
     private int deviceId;
 
@@ -63,6 +67,46 @@ public final class Device {
         return CACHE.computeIfAbsent(key, k -> new Device(deviceType, deviceId));
     }
 
+    /**
+     * Parses a deviceName string into a device.
+     *
+     * <p>The main format of a device name string is "cpu", "gpu0", or "nc1". This is simply
+     * deviceType concatenated with the deviceId. If no deviceId is used, -1 will be assumed.
+     *
+     * <p>There are also several simplified formats. "-1", "", and null deviceNames correspond to
+     * cpu. Non-negative integer deviceNames such as "0", "1", or "2" correspond to gpus with those
+     * deviceIds.
+     *
+     * @param deviceName deviceName string
+     * @return the device
+     */
+    public static Device fromName(String deviceName) {
+        if (deviceName == null || deviceName.isEmpty()) {
+            return Device.cpu();
+        }
+
+        Matcher matcher = DEVICE_NAME.matcher(deviceName);
+        if (matcher.matches()) {
+            String deviceType = matcher.group(1);
+            int deviceId = -1;
+            if (!matcher.group(2).isEmpty()) {
+                deviceId = Integer.parseInt(matcher.group(2));
+            }
+            return Device.of(deviceType, deviceId);
+        }
+
+        try {
+            int deviceId = Integer.parseInt(deviceName);
+
+            if (deviceId < 0) {
+                return Device.cpu();
+            }
+            return Device.gpu(deviceId);
+        } catch (NumberFormatException ignored) {
+        }
+        throw new IllegalArgumentException("Failed to parse device name: " + deviceName);
+    }
+
     /**
      * Returns the device type of the Device.
      *


Test patch:
diff --git a/api/src/test/java/ai/djl/DeviceTest.java b/api/src/test/java/ai/djl/DeviceTest.java
index 8cd4ed3c7..da9b736ff 100644
--- a/api/src/test/java/ai/djl/DeviceTest.java
+++ b/api/src/test/java/ai/djl/DeviceTest.java
@@ -36,4 +36,19 @@ public class DeviceTest {
 
         Engine.debugEnvironment();
     }
+
+    @Test
+    public void testDeviceName() {
+        Assert.assertEquals(Device.fromName("cpu"), Device.cpu());
+        Assert.assertEquals(Device.fromName(""), Device.cpu());
+        Assert.assertEquals(Device.fromName("-1"), Device.cpu());
+        Assert.assertEquals(Device.fromName(null), Device.cpu());
+
+        Assert.assertEquals(Device.fromName("gpu0"), Device.gpu());
+        Assert.assertEquals(Device.fromName("0"), Device.gpu());
+        Assert.assertEquals(Device.fromName("1"), Device.gpu(1));
+
+        Assert.assertEquals(Device.fromName("nc1"), Device.of("nc", 1));
+        Assert.assertEquals(Device.fromName("a999"), Device.of("a", 999));
+    }
 }