diff --git a/src/main/java/io/bioimage/modelrunner/tensor/shm/SharedMemoryArrayLinux.java b/src/main/java/io/bioimage/modelrunner/tensor/shm/SharedMemoryArrayLinux.java index 1c1ae2d5..a902618b 100644 --- a/src/main/java/io/bioimage/modelrunner/tensor/shm/SharedMemoryArrayLinux.java +++ b/src/main/java/io/bioimage/modelrunner/tensor/shm/SharedMemoryArrayLinux.java @@ -258,6 +258,14 @@ private SharedMemoryArrayLinux(String name, int size, String dtype, long[] shape INSTANCE_C.close(shmFd); throw new RuntimeException("mmap failed, errno: " + Native.getLastError()); } + + if (!alreadyExists && this.isNumpyFormat) { + byte[] header = getNpyHeader(dtype, shape, this.isFortran); + long offset = 0; + for (byte b : header) { + this.pSharedMemory.setByte(offset ++, b); + } + } } /** @@ -670,6 +678,35 @@ byte[] getNpyHeader(RandomAccessibleInterval tensor, boolean fortranOrder) { return total; } + @SuppressWarnings("unchecked") + private static & NativeType> + byte[] getNpyHeader(String dtype, long[] shape, boolean fortranOrder) { + String strHeader = "{'descr': '<"; + strHeader += DecodeNumpy.getDataType((T) CommonUtils.getImgLib2DataType(dtype)); + strHeader += "', 'fortran_order': " + (fortranOrder ? "True" : "False") + ", 'shape': ("; + for (long ll : shape) strHeader += ll + ", "; + strHeader = strHeader.substring(0, strHeader.length() - 2); + strHeader += "), }" + System.lineSeparator(); + byte[] bufInverse = strHeader.getBytes(StandardCharsets.UTF_8); + byte[] major = {1}; + byte[] minor = {0}; + byte[] len = new byte[2]; + len[0] = (byte) (short) strHeader.length(); + len[1] = (byte) (((short) strHeader.length()) >> 8); + int totalLen = DecodeNumpy.NUMPY_PREFIX.length + 2 + 2 + bufInverse.length; + byte[] total = new byte[totalLen]; + int c = 0; + for (int i = 0; i < DecodeNumpy.NUMPY_PREFIX.length; i ++) + total[c ++] = DecodeNumpy.NUMPY_PREFIX[i]; + total[c ++] = major[0]; + total[c ++] = minor[0]; + total[c ++] = len[0]; + total[c ++] = len[1]; + for (int i = 0; i < bufInverse.length; i ++) + total[c ++] = bufInverse[i]; + return total; + } + /** * {@inheritDoc} */ diff --git a/src/main/java/io/bioimage/modelrunner/tensor/shm/SharedMemoryArrayMacOS.java b/src/main/java/io/bioimage/modelrunner/tensor/shm/SharedMemoryArrayMacOS.java index 3a0cfac8..52739338 100644 --- a/src/main/java/io/bioimage/modelrunner/tensor/shm/SharedMemoryArrayMacOS.java +++ b/src/main/java/io/bioimage/modelrunner/tensor/shm/SharedMemoryArrayMacOS.java @@ -243,6 +243,16 @@ protected SharedMemoryArrayMacOS(String name, int size, String dtype, long[] sha INSTANCE.close(shmFd); throw new RuntimeException("mmap failed, errno: " + Native.getLastError()); } + + + + if (!alreadyExists && this.isNumpyFormat) { + byte[] header = getNpyHeader(dtype, shape, this.isFortran); + long offset = 0; + for (byte b : header) { + this.pSharedMemory.setByte(offset ++, b); + } + } } /** @@ -597,6 +607,35 @@ private void buildFloat64(RandomAccessibleInterval tensor, boolean i } } + @SuppressWarnings("unchecked") + private static & NativeType> + byte[] getNpyHeader(String dtype, long[] shape, boolean fortranOrder) { + String strHeader = "{'descr': '<"; + strHeader += DecodeNumpy.getDataType((T) CommonUtils.getImgLib2DataType(dtype)); + strHeader += "', 'fortran_order': " + (fortranOrder ? "True" : "False") + ", 'shape': ("; + for (long ll : shape) strHeader += ll + ", "; + strHeader = strHeader.substring(0, strHeader.length() - 2); + strHeader += "), }" + System.lineSeparator(); + byte[] bufInverse = strHeader.getBytes(StandardCharsets.UTF_8); + byte[] major = {1}; + byte[] minor = {0}; + byte[] len = new byte[2]; + len[0] = (byte) (short) strHeader.length(); + len[1] = (byte) (((short) strHeader.length()) >> 8); + int totalLen = DecodeNumpy.NUMPY_PREFIX.length + 2 + 2 + bufInverse.length; + byte[] total = new byte[totalLen]; + int c = 0; + for (int i = 0; i < DecodeNumpy.NUMPY_PREFIX.length; i ++) + total[c ++] = DecodeNumpy.NUMPY_PREFIX[i]; + total[c ++] = major[0]; + total[c ++] = minor[0]; + total[c ++] = len[0]; + total[c ++] = len[1]; + for (int i = 0; i < bufInverse.length; i ++) + total[c ++] = bufInverse[i]; + return total; + } + private static & NativeType> byte[] getNpyHeader(RandomAccessibleInterval tensor, boolean isFortran) { String strHeader = "{'descr': '<"; diff --git a/src/main/java/io/bioimage/modelrunner/tensor/shm/SharedMemoryArrayWin.java b/src/main/java/io/bioimage/modelrunner/tensor/shm/SharedMemoryArrayWin.java index d42ada1c..b8f0cae4 100644 --- a/src/main/java/io/bioimage/modelrunner/tensor/shm/SharedMemoryArrayWin.java +++ b/src/main/java/io/bioimage/modelrunner/tensor/shm/SharedMemoryArrayWin.java @@ -218,7 +218,8 @@ protected SharedMemoryArrayWin(String name, int size, String dtype, long[] shape this.isFortran = isFortran; int flag = WinNT.PAGE_READWRITE; boolean write = true; - if (checkSHMExists(memoryName)) { + boolean alreadyExists = checkSHMExists(memoryName); + if (alreadyExists) { long prevSize = getSHMSize(name); if (prevSize != 0 && prevSize != DEFAULT_RESERVED_MEMORY && prevSize < size) throw new FileAlreadyExistsException("Shared memory segment already exists with different dimensions, data type or format. " @@ -271,6 +272,16 @@ protected SharedMemoryArrayWin(String name, int size, String dtype, long[] shape + "" + Kernel32.INSTANCE.GetLastError()); } } + + + + if (!alreadyExists && this.isNumpyFormat) { + byte[] header = getNpyHeader(dtype, shape, this.isFortran); + long offset = 0; + for (byte b : header) { + this.mappedPointer.setByte(offset, b); + } + } } private boolean checkSHMExists(String memoryName) { @@ -486,6 +497,35 @@ private void addByteArray(byte[] arr) { } } + @SuppressWarnings("unchecked") + private static & NativeType> + byte[] getNpyHeader(String dtype, long[] shape, boolean fortranOrder) { + String strHeader = "{'descr': '<"; + strHeader += DecodeNumpy.getDataType((T) CommonUtils.getImgLib2DataType(dtype)); + strHeader += "', 'fortran_order': " + (fortranOrder ? "True" : "False") + ", 'shape': ("; + for (long ll : shape) strHeader += ll + ", "; + strHeader = strHeader.substring(0, strHeader.length() - 2); + strHeader += "), }" + System.lineSeparator(); + byte[] bufInverse = strHeader.getBytes(StandardCharsets.UTF_8); + byte[] major = {1}; + byte[] minor = {0}; + byte[] len = new byte[2]; + len[0] = (byte) (short) strHeader.length(); + len[1] = (byte) (((short) strHeader.length()) >> 8); + int totalLen = DecodeNumpy.NUMPY_PREFIX.length + 2 + 2 + bufInverse.length; + byte[] total = new byte[totalLen]; + int c = 0; + for (int i = 0; i < DecodeNumpy.NUMPY_PREFIX.length; i ++) + total[c ++] = DecodeNumpy.NUMPY_PREFIX[i]; + total[c ++] = major[0]; + total[c ++] = minor[0]; + total[c ++] = len[0]; + total[c ++] = len[1]; + for (int i = 0; i < bufInverse.length; i ++) + total[c ++] = bufInverse[i]; + return total; + } + private static & NativeType> byte[] getNpyHeader(RandomAccessibleInterval tensor, boolean isFortran) { String strHeader = "{'descr': '<";