Entw.: Tensorflow mit Delphi (1)
Möchte man TensorFlow von Delphi aus nutzen, so kann dies über die Verwendung der DLL
tensorflow.dll geschehen. Siehe dazu den vorhergehenden
Artikel.
Die in der TensorFlow-DLL vorhandene C-API ist von Delphi aufrufbar. Dazu wurde eine
Delphi-Unit erstellt, die diese C-API verwendet.
Lizenz
Die Bestimmungen zur Nutzung von TensorFlow und dadurch auch der API erfolgt nach den Apache-Lizenzbedingungen.
{ Copyright 2015 The TensorFlow Authors. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Source: https://github.com/tensorflow/tensorflow Docu: https://www.tensorflow.org Versions: 1.0: 2017/06/16 - Orginal Delphi 10.2 port by hadv.de ==============================================================================}
C-API
Die C-API wird definiert durch die Header-Datei c_api.h im Verzeichnis tensorflow/c
der GIT-Repository.
Die folgende C-Source zeigt ein kleinen Ausschnitt dieser Header-Datei.
// -------------------------------------------------------------------------- // TF_Version returns a string describing version information of the // TensorFlow library. TensorFlow using semantic versioning. TF_CAPI_EXPORT extern const char* TF_Version(); // -------------------------------------------------------------------------- // TF_DataType holds the type for a scalar value. E.g., one slot in a tensor. // The enum values here are identical to corresponding values in types.proto. typedef enum TF_DataType { TF_FLOAT = 1, TF_DOUBLE = 2, TF_INT32 = 3, // Int32 tensors are always in 'host' memory. TF_UINT8 = 4, TF_INT16 = 5, TF_INT8 = 6, TF_STRING = 7, TF_COMPLEX64 = 8, // Single-precision complex TF_COMPLEX = 8, // Old identifier kept for API backwards compatibility TF_INT64 = 9, TF_BOOL = 10, TF_QINT8 = 11, // Quantized int8 TF_QUINT8 = 12, // Quantized uint8 TF_QINT32 = 13, // Quantized int32 TF_BFLOAT16 = 14, // Float32 truncated to 16 bits. Only for cast ops. TF_QINT16 = 15, // Quantized int16 TF_QUINT16 = 16, // Quantized uint16 TF_UINT16 = 17, TF_COMPLEX128 = 18, // Double-precision complex TF_HALF = 19, TF_RESOURCE = 20, } TF_DataType; // TF_DataTypeSize returns the sizeof() for the underlying type corresponding // to the given TF_DataType enum value. Returns 0 for variable length types // (eg. TF_STRING) or on failure. TF_CAPI_EXPORT extern size_t TF_DataTypeSize(TF_DataType dt);
Verwendung der C-API mit Delphi
Die Umsetzung des obigen C-Source-Codes nach Delphi zeigt folgender Abschnitt:
unit uTensorFlowAPI; interface uses System.Types, Winapi.Windows; type TF_DataType = ( TF_DATATYPE_UNKNOWN = 0, TF_FLOAT = 1, TF_DOUBLE = 2, TF_INT32 = 3, // Int32 tensors are always in 'host' memory. TF_UINT8 = 4, TF_INT16 = 5, TF_INT8 = 6, TF_STRING = 7, TF_COMPLEX64 = 8, // Single-precision complex TF_COMPLEX = 8, // Old identifier kept for API backwards compatibility TF_INT64 = 9, TF_BOOL = 10, TF_QINT8 = 11, // Quantized int8 TF_QUINT8 = 12, // Quantized uint8 TF_QINT32 = 13, // Quantized int32 TF_BFLOAT16 = 14, // Float32 truncated to 16 bits. Only for cast ops. TF_QINT16 = 15, // Quantized int16 TF_QUINT16 = 16, // Quantized uint16 TF_UINT16 = 17, TF_COMPLEX128 = 18, // Double-precision complex TF_HALF = 19, TF_RESOURCE = 20, TF_FLOAT_REF = 101, TF_DOUBLE_REF = 102, TF_INT32_REF = 103, TF_UINT8_REF = 104, TF_INT16_REF = 105, TF_INT8_REF = 106, TF_STRING_REF = 107, TF_COMPLEX64_REF = 108, TF_INT64_REF = 109, TF_BOOL_REF = 110, TF_QINT8_REF = 111, TF_QUINT8_REF = 112, TF_QINT32_REF = 113, TF_BFLOAT16_REF = 114, TF_QINT16_REF = 115, TF_QUINT16_REF = 116, TF_UINT16_REF = 117, TF_COMPLEX128_REF = 118, TF_HALF_REF = 119, TF_RESOURCE_REF = 120 ); PTF_DataType = ^TF_DataType; const c_sNameOfTensorflowLib = 'tensorflow.dll'; // TF_Version returns a string describing version information of the // TensorFlow library. TensorFlow using semantic versioning. function TF_Version(): PAnsiChar; {$EXTERNALSYM TF_Version} // TF_DataTypeSize returns the sizeof() for the underlying type corresponding // to the given TF_DataType enum value. Returns 0 for variable length types // (eg. TF_STRING) or on failure. function TF_DataTypeSize(dt: Int32): TF_size_t; {$EXTERNALSYM TF_DataTypeSize} // ... implementation function TF_Version; external c_sNameOfTensorflowLib name 'TF_Version'; function TF_DataTypeSize; external c_sNameOfTensorflowLib name 'TF_DataTypeSize'; // ... end.
Die Delphi-API liefert zum grossen Teil nur Pointer auf Tensorflow-Datenstrukturen.
Die Interpretation dieser Daten sollte immer nur über API-Aufrufe erfolgen.
Nur so bleiben die Abhängigkeiten zwischen Delphi- und C-API übersichtlich transparent.
Auch bleibt der Plegeaufwand dieser Delphi-API gering und fehlerunanfällig.
Die vollständige Delphi-Tensorflow-API für die Version 1.2.1 kann
hier als Zip-Datei herunter geladen werden.
Copyright © 17.06.2017 hadv.de. All Rights Reserved.