- Εισαγωγή
- Τι είναι το Qualcomm QNN;
- Εγκατάσταση
- Οδηγός Γρήγορης Εκκίνησης
- Παράδειγμα: Μετατροπή και Βελτιστοποίηση Μοντέλων με QNN
- Προχωρημένη Χρήση
- Βέλτιστες Πρακτικές
- Αντιμετώπιση Προβλημάτων
- Πρόσθετοι Πόροι
Το Qualcomm QNN (Qualcomm Neural Network) είναι ένα ολοκληρωμένο πλαίσιο AI inference σχεδιασμένο να αξιοποιεί πλήρως τις δυνατότητες των επιταχυντών AI υλικού της Qualcomm, όπως το Hexagon NPU, το Adreno GPU και το Kryo CPU. Είτε στοχεύετε σε κινητές συσκευές, πλατφόρμες edge computing ή συστήματα αυτοκινήτων, το QNN προσφέρει βελτιστοποιημένες δυνατότητες inference που αξιοποιούν τις εξειδικευμένες μονάδες επεξεργασίας AI της Qualcomm για μέγιστη απόδοση και ενεργειακή αποδοτικότητα.
Το Qualcomm QNN είναι ένα ενοποιημένο πλαίσιο AI inference που επιτρέπει στους προγραμματιστές να αναπτύσσουν μοντέλα AI αποτελεσματικά στην ετερογενή αρχιτεκτονική υπολογιστών της Qualcomm. Παρέχει μια ενοποιημένη διεπαφή προγραμματισμού για πρόσβαση στο Hexagon NPU (Neural Processing Unit), το Adreno GPU και το Kryo CPU, επιλέγοντας αυτόματα την βέλτιστη μονάδα επεξεργασίας για διαφορετικά επίπεδα και λειτουργίες του μοντέλου.
- Ετερογενής Υπολογισμός: Ενοποιημένη πρόσβαση σε NPU, GPU και CPU με αυτόματη κατανομή φόρτου εργασίας
- Βελτιστοποίηση με Γνώμονα το Υλικό: Εξειδικευμένες βελτιστοποιήσεις για πλατφόρμες Snapdragon της Qualcomm
- Υποστήριξη Ποσοτικοποίησης: Προηγμένες τεχνικές ποσοτικοποίησης INT8, INT16 και μικτής ακρίβειας
- Εργαλεία Μετατροπής Μοντέλων: Άμεση υποστήριξη για μοντέλα TensorFlow, PyTorch, ONNX και Caffe
- Βελτιστοποίηση για Edge AI: Σχεδιασμένο ειδικά για κινητές και edge εφαρμογές με έμφαση στην ενεργειακή αποδοτικότητα
- Μέγιστη Απόδοση: Αξιοποίηση εξειδικευμένου υλικού AI για έως και 15x βελτίωση απόδοσης
- Ενεργειακή Αποδοτικότητα: Βελτιστοποιημένο για κινητές και συσκευές με μπαταρία με έξυπνη διαχείριση ενέργειας
- Χαμηλή Καθυστέρηση: Επιτάχυνση inference με ελάχιστο overhead για εφαρμογές σε πραγματικό χρόνο
- Κλιμακούμενη Ανάπτυξη: Από smartphones έως πλατφόρμες αυτοκινήτων στο οικοσύστημα της Qualcomm
- Έτοιμο για Παραγωγή: Δοκιμασμένο πλαίσιο που χρησιμοποιείται σε εκατομμύρια συσκευές
- Qualcomm QNN SDK (απαιτεί εγγραφή στην Qualcomm)
- Python 3.7 ή νεότερη έκδοση
- Συμβατό υλικό Qualcomm ή προσομοιωτής
- Android NDK (για ανάπτυξη σε κινητά)
- Περιβάλλον ανάπτυξης Linux ή Windows
- Εγγραφή και Λήψη: Επισκεφθείτε το Qualcomm Developer Network για εγγραφή και λήψη του QNN SDK
- Αποσυμπίεση SDK: Αποσυμπιέστε το QNN SDK στον κατάλογο ανάπτυξής σας
- Ρύθμιση Μεταβλητών Περιβάλλοντος: Διαμορφώστε τις διαδρομές για τα εργαλεία και τις βιβλιοθήκες του QNN
# Set QNN environment variables
export QNN_SDK_ROOT=/path/to/qnn-sdk
export PATH=$QNN_SDK_ROOT/bin:$PATH
export LD_LIBRARY_PATH=$QNN_SDK_ROOT/lib:$LD_LIBRARY_PATHΔημιουργήστε και ενεργοποιήστε ένα εικονικό περιβάλλον:
# Create virtual environment
python -m venv qnn-env
# Activate virtual environment
# On Windows:
qnn-env\Scripts\activate
# On Linux:
source qnn-env/bin/activateΕγκαταστήστε τα απαραίτητα πακέτα Python:
pip install numpy tensorflow torch onnx# Check QNN tools availability
qnn-model-lib-generator --help
qnn-context-binary-generator --help
qnn-net-run --helpΕάν είναι επιτυχής, θα πρέπει να δείτε πληροφορίες βοήθειας για κάθε εργαλείο QNN.
Ας μετατρέψουμε ένα απλό μοντέλο PyTorch για εκτέλεση σε υλικό Qualcomm:
import torch
import torch.nn as nn
import numpy as np
# Define a simple model
class SimpleModel(nn.Module):
def __init__(self):
super(SimpleModel, self).__init__()
self.conv1 = nn.Conv2d(3, 32, 3, padding=1)
self.relu = nn.ReLU()
self.conv2 = nn.Conv2d(32, 64, 3, padding=1)
self.pool = nn.AdaptiveAvgPool2d((1, 1))
self.fc = nn.Linear(64, 10)
def forward(self, x):
x = self.relu(self.conv1(x))
x = self.relu(self.conv2(x))
x = self.pool(x)
x = x.view(x.size(0), -1)
x = self.fc(x)
return x
# Create and export model
model = SimpleModel()
model.eval()
# Create dummy input for tracing
dummy_input = torch.randn(1, 3, 224, 224)
# Export to ONNX
torch.onnx.export(
model,
dummy_input,
"simple_model.onnx",
export_params=True,
opset_version=11,
do_constant_folding=True,
input_names=['input'],
output_names=['output'],
dynamic_axes={'input': {0: 'batch_size'},
'output': {0: 'batch_size'}}
)# Convert ONNX model to QNN model library
qnn-onnx-converter \
--input_network simple_model.onnx \
--output_path simple_model.cpp \
--input_dim input 1,3,224,224 \
--quantization_overrides quantization_config.json# Compile model library
qnn-model-lib-generator \
-c simple_model.cpp \
-b simple_model.bin \
-t x86_64-linux-clang \
-l simple_model \
-o simple_model_qnn.soΗ ροή εργασίας βελτιστοποίησης περιλαμβάνει: μετατροπή του αρχικού μοντέλου σε μορφή ONNX, μετάφραση του ONNX σε ενδιάμεση αναπαράσταση QNN, εφαρμογή βελτιστοποιήσεων ειδικών για το υλικό και δημιουργία μιας βιβλιοθήκης μοντέλου για ανάπτυξη.
--input_network: Αρχείο μοντέλου ONNX--output_path: Δημιουργημένο αρχείο πηγαίου κώδικα C++--input_dim: Διαστάσεις tensor εισόδου για βελτιστοποίηση--quantization_overrides: Προσαρμοσμένη διαμόρφωση ποσοτικοποίησης-t x86_64-linux-clang: Αρχιτεκτονική στόχου και μεταγλωττιστής
Πώς να εφαρμόσετε προσαρμοσμένη ποσοτικοποίηση κατά τη μετατροπή:
// quantization_config.json
{
"activation_encodings": {
"conv1/Relu:0": {
"bitwidth": 8,
"max": 6.0,
"min": 0.0,
"scale": 0.023529,
"offset": 0
}
},
"param_encodings": {
"conv1.weight": {
"bitwidth": 8,
"max": 2.5,
"min": -2.5,
"scale": 0.019608,
"offset": 127
}
},
"activation_bitwidth": 8,
"param_bitwidth": 8,
"bias_bitwidth": 32
}Μετατροπή με προσαρμοσμένη ποσοτικοποίηση:
qnn-onnx-converter \
--input_network model.onnx \
--output_path model_quantized.cpp \
--input_dim input 1,3,224,224 \
--quantization_overrides quantization_config.json \
--target_device hexagon \
--optimization_level highΔιαμόρφωση για ετερογενή εκτέλεση σε NPU, GPU και CPU:
# Generate model library with multiple backend support
qnn-model-lib-generator \
-c model_quantized.cpp \
-b model_quantized.bin \
-t aarch64-android \
-l model_optimized \
-o model_optimized.so \
--target_backends htp,gpu,cpu# Generate optimized context binary
qnn-context-binary-generator \
--model model_optimized.so \
--backend libQnnHtp.so \
--output_dir ./context_binaries \
--input_list input_data.txt \
--optimization_level highimport ctypes
import numpy as np
# Load QNN library
qnn_lib = ctypes.CDLL('./libQnn.so')
class QNNInference:
def __init__(self, model_path, backend='htp'):
self.model_path = model_path
self.backend = backend
self.context = None
self._initialize()
def _initialize(self):
# Initialize QNN runtime
# Load model and create inference context
pass
def preprocess_input(self, data):
# Quantize input data if needed
if self.is_quantized:
# Apply quantization parameters
scale = self.input_scale
offset = self.input_offset
quantized = np.clip(
np.round(data / scale + offset),
0, 255
).astype(np.uint8)
return quantized
return data.astype(np.float32)
def inference(self, input_data):
# Preprocess input
processed_input = self.preprocess_input(input_data)
# Run inference on Qualcomm hardware
# This would call into QNN C++ API
output = self._run_inference(processed_input)
# Postprocess output
return self.postprocess_output(output)
def postprocess_output(self, output):
# Dequantize output if needed
if self.is_quantized:
scale = self.output_scale
offset = self.output_offset
dequantized = (output.astype(np.float32) - offset) * scale
return dequantized
return output
# Usage
inference_engine = QNNInference("model_optimized.so", backend="htp")
result = inference_engine.inference(input_tensor)
print(f"Inference result: {result}")Μετά τη βελτιστοποίηση, ο κατάλογος ανάπτυξης σας θα περιέχει:
qnn_model/
├── model_optimized.so # Compiled model library
├── context_binaries/ # Pre-compiled contexts
│ ├── htp_context.bin # NPU context
│ ├── gpu_context.bin # GPU context
│ └── cpu_context.bin # CPU context
├── quantization_config.json # Quantization parameters
└── input_specs.json # Input/output specifications
Διαμόρφωση συγκεκριμένων βελτιστοποιήσεων backend:
// backend_config.json
{
"htp_config": {
"device_id": 0,
"performance_mode": "high_performance",
"precision_mode": "int8",
"vtcm_mb": 8,
"enable_dma": true
},
"gpu_config": {
"device_id": 0,
"performance_mode": "sustained_high_performance",
"precision_mode": "fp16",
"enable_transform_optimization": true
},
"cpu_config": {
"num_threads": 4,
"performance_mode": "balanced",
"enable_fast_math": true
}
}Εφαρμογή ποσοτικοποίησης κατά την εκτέλεση για καλύτερη ακρίβεια:
class DynamicQuantization:
def __init__(self, model_path):
self.model_path = model_path
self.calibration_data = []
def collect_statistics(self, calibration_dataset):
"""Collect activation statistics for quantization"""
for data in calibration_dataset:
# Run inference and collect activation ranges
activations = self.forward_hooks(data)
self.calibration_data.append(activations)
def compute_quantization_params(self):
"""Compute optimal quantization parameters"""
params = {}
for layer_name, activations in self.calibration_data:
min_val = np.min(activations)
max_val = np.max(activations)
# Compute scale and offset for INT8 quantization
scale = (max_val - min_val) / 255.0
offset = -min_val / scale
params[layer_name] = {
"scale": scale,
"offset": int(offset),
"min": min_val,
"max": max_val
}
return params
def apply_quantization(self, quantization_params):
"""Apply computed quantization parameters"""
config = {
"activation_encodings": {},
"param_encodings": {}
}
for layer, params in quantization_params.items():
config["activation_encodings"][layer] = {
"bitwidth": 8,
"scale": params["scale"],
"offset": params["offset"],
"min": params["min"],
"max": params["max"]
}
return configΠαρακολούθηση απόδοσης σε διαφορετικά backends:
import time
import psutil
class QNNProfiler:
def __init__(self):
self.metrics = {}
def profile_inference(self, inference_func, input_data, num_runs=100):
"""Profile inference performance"""
latencies = []
cpu_usage = []
memory_usage = []
for i in range(num_runs):
# Monitor system resources
process = psutil.Process()
cpu_before = process.cpu_percent()
memory_before = process.memory_info().rss
# Measure inference time
start_time = time.perf_counter()
result = inference_func(input_data)
end_time = time.perf_counter()
latency = (end_time - start_time) * 1000 # Convert to ms
latencies.append(latency)
# Collect resource usage
cpu_after = process.cpu_percent()
memory_after = process.memory_info().rss
cpu_usage.append(cpu_after - cpu_before)
memory_usage.append(memory_after - memory_before)
return {
"avg_latency_ms": np.mean(latencies),
"p95_latency_ms": np.percentile(latencies, 95),
"p99_latency_ms": np.percentile(latencies, 99),
"throughput_fps": 1000 / np.mean(latencies),
"avg_cpu_usage": np.mean(cpu_usage),
"avg_memory_delta_mb": np.mean(memory_usage) / (1024 * 1024)
}
# Usage
profiler = QNNProfiler()
htp_metrics = profiler.profile_inference(htp_inference, test_data)
gpu_metrics = profiler.profile_inference(gpu_inference, test_data)
cpu_metrics = profiler.profile_inference(cpu_inference, test_data)
print("HTP Performance:", htp_metrics)
print("GPU Performance:", gpu_metrics)
print("CPU Performance:", cpu_metrics)Εφαρμογή έξυπνης επιλογής backend με βάση τα χαρακτηριστικά του μοντέλου:
class BackendSelector:
def __init__(self):
self.backend_capabilities = {
"htp": {
"supported_ops": ["Conv2d", "Dense", "BatchNorm", "ReLU"],
"max_tensor_size": 8 * 1024 * 1024, # 8MB
"preferred_precision": "int8",
"power_efficiency": 0.9
},
"gpu": {
"supported_ops": ["Conv2d", "Dense", "ReLU", "Softmax"],
"max_tensor_size": 64 * 1024 * 1024, # 64MB
"preferred_precision": "fp16",
"power_efficiency": 0.6
},
"cpu": {
"supported_ops": ["*"], # All operations
"max_tensor_size": 512 * 1024 * 1024, # 512MB
"preferred_precision": "fp32",
"power_efficiency": 0.4
}
}
def select_optimal_backend(self, model_info, constraints):
"""Select optimal backend based on model and constraints"""
scores = {}
for backend, caps in self.backend_capabilities.items():
score = 0
# Check operation support
if all(op in caps["supported_ops"] or "*" in caps["supported_ops"]
for op in model_info["operations"]):
score += 30
# Check tensor size compatibility
if model_info["max_tensor_size"] <= caps["max_tensor_size"]:
score += 25
# Power efficiency consideration
if constraints.get("power_critical", False):
score += caps["power_efficiency"] * 25
# Performance preference
if constraints.get("performance_critical", False):
if backend == "htp":
score += 20
scores[backend] = score
return max(scores, key=scores.get)
# Usage
selector = BackendSelector()
model_info = {
"operations": ["Conv2d", "ReLU", "Dense"],
"max_tensor_size": 4 * 1024 * 1024,
"precision": "int8"
}
constraints = {
"power_critical": True,
"performance_critical": True
}
optimal_backend = selector.select_optimal_backend(model_info, constraints)
print(f"Recommended backend: {optimal_backend}")- Συγχώνευση Επίπεδων: Συνδυάστε λειτουργίες όπως Conv+BatchNorm+ReLU για καλύτερη αξιοποίηση του NPU
- Συνελικώσεις Διαχωρισμού Βάθους: Προτιμήστε αυτές αντί για τυπικές συνελικώσεις για ανάπτυξη σε κινητά
- Σχεδιασμοί Φιλικοί προς την Ποσοτικοποίηση: Χρησιμοποιήστε ενεργοποιήσεις ReLU και αποφύγετε λειτουργίες που δεν ποσοτικοποιούνται καλά
- Ποσοτικοποίηση Μετά την Εκπαίδευση: Ξεκινήστε με αυτήν για γρήγορη ανάπτυξη
- Σετ Δεδομένων Βαθμονόμησης: Χρησιμοποιήστε αντιπροσωπευτικά δεδομένα που καλύπτουν όλες τις παραλλαγές εισόδου
- Μικτή Ακρίβεια: Χρησιμοποιήστε INT8 για τα περισσότερα επίπεδα, διατηρήστε κρίσιμα επίπεδα σε υψηλότερη ακρίβεια
- NPU (HTP): Ιδανικό για φόρτους CNN, ποσοτικοποιημένα μοντέλα και εφαρμογές ευαίσθητες στην ενέργεια
- GPU: Βέλτιστο για λειτουργίες υψηλής υπολογιστικής έντασης, μεγαλύτερα μοντέλα και ακρίβεια FP16
- CPU: Εναλλακτική για μη υποστηριζόμενες λειτουργίες και αποσφαλμάτωση
- Μέγεθος Παρτίδας: Χρησιμοποιήστε μέγεθος παρτίδας 1 για εφαρμογές σε πραγματικό χρόνο, μεγαλύτερες παρτίδες για απόδοση
- Προεπεξεργασία Εισόδου: Ελαχιστοποιήστε την αντιγραφή και τη μετατροπή δεδομένων
- Επαναχρησιμοποίηση Context: Προ-συγκεντρώστε contexts για αποφυγή overhead κατά την εκτέλεση
- Κατανομή Tensor: Χρησιμοποιήστε στατική κατανομή όπου είναι δυνατόν για αποφυγή overhead κατά την εκτέλεση
- Πισίνες Μνήμης: Εφαρμόστε προσαρμοσμένες πισίνες μνήμης για συχνά κατανεμημένα tensors
- Επαναχρησιμοποίηση Buffers: Επαναχρησιμοποιήστε buffers εισόδου/εξόδου σε κλήσεις inference
- Λειτουργίες Απόδοσης: Χρησιμοποιήστε κατάλληλες λειτουργίες απόδοσης με βάση τους θερμικούς περιορισμούς
- Δυναμική Κλιμάκωση Συχνότητας: Επιτρέψτε στο σύστημα να κλιμακώνει τη συχνότητα με βάση το φόρτο εργασίας
- Διαχείριση Κατάστασης Αδράνειας: Απελευθερώστε σωστά πόρους όταν δεν χρησιμοποιούνται
# Verify QNN SDK installation
echo $QNN_SDK_ROOT
ls $QNN_SDK_ROOT/bin/qnn-*
# Check library dependencies
ldd $QNN_SDK_ROOT/lib/libQnn.so# Enable verbose logging
qnn-onnx-converter \
--input_network model.onnx \
--output_path model.cpp \
--debug \
--log_level verbose# Validate quantization parameters
def validate_quantization_range(data, scale, offset, bitwidth=8):
quantized = np.clip(
np.round(data / scale + offset),
0, (2**bitwidth) - 1
)
dequantized = (quantized - offset) * scale
mse = np.mean((data - dequantized) ** 2)
print(f"Quantization MSE: {mse}")
return mse < threshold# Check hardware utilization
adb shell cat /sys/class/devfreq/soc:qcom,cpu*-cpu-ddr-latfloor/cur_freq
adb shell cat /sys/class/kgsl/kgsl-3d0/gpuclk
# Monitor NPU usage
adb shell cat /sys/kernel/debug/msm_vidc/load# Monitor memory usage
import tracemalloc
tracemalloc.start()
# Run inference
result = inference_engine.inference(input_data)
current, peak = tracemalloc.get_traced_memory()
print(f"Current memory usage: {current / 1024 / 1024:.1f} MB")
print(f"Peak memory usage: {peak / 1024 / 1024:.1f} MB")
tracemalloc.stop()# Check backend availability
def check_backend_support():
try:
# Load backend library
htp_lib = ctypes.CDLL('./libQnnHtp.so')
print("HTP backend available")
except OSError:
print("HTP backend not available")
try:
gpu_lib = ctypes.CDLL('./libQnnGpu.so')
print("GPU backend available")
except OSError:
print("GPU backend not available")# Create performance analysis tool
class QNNDebugger:
def __init__(self, model_path):
self.model_path = model_path
self.layer_timings = {}
def profile_layers(self, input_data):
"""Profile individual layer performance"""
# This would require integration with QNN profiling APIs
for layer_name in self.get_layer_names():
start = time.perf_counter()
# Execute layer
end = time.perf_counter()
self.layer_timings[layer_name] = (end - start) * 1000
def analyze_bottlenecks(self):
"""Identify performance bottlenecks"""
sorted_layers = sorted(
self.layer_timings.items(),
key=lambda x: x[1],
reverse=True
)
print("Top 5 slowest layers:")
for layer, time_ms in sorted_layers[:5]:
print(f" {layer}: {time_ms:.2f} ms")
def suggest_optimizations(self):
"""Suggest optimization strategies"""
suggestions = []
for layer, time_ms in self.layer_timings.items():
if time_ms > 10: # Layer takes more than 10ms
if "conv" in layer.lower():
suggestions.append(f"Consider depthwise separable conv for {layer}")
elif "dense" in layer.lower():
suggestions.append(f"Consider quantization for {layer}")
return suggestions- Qualcomm Developer Network: developer.qualcomm.com
- Τεκμηρίωση QNN: Διαθέσιμη στο πακέτο SDK
- Φόρουμ Κοινότητας: developer.qualcomm.com/forums
- Τεχνική Υποστήριξη: Μέσω της πύλης προγραμματιστών της Qualcomm
- Qualcomm AI Hub: aihub.qualcomm.com
- Πλατφόρμες Snapdragon: qualcomm.com/products/mobile/snapdragon
- Πύλη Προγραμματιστών: developer.qualcomm.com/software/qualcomm-neural-processing-sdk
- AI Engine: qualcomm.com/news/onq/2019/06/qualcomm-ai-engine-direct
- Οδηγός Ξεκινήματος: Διαθέσιμος στην τεκμηρίωση του QNN SDK
- Model Zoo: aihub.qualcomm.com/models
- Οδηγός Βελτιστοποίησης: Η τεκμηρίωση SDK περιλαμβάνει ολοκληρωμένες οδηγίες βελτιστοποίησης
- Βίντεο Εκμάθησης: Qualcomm Developer YouTube Channel
- SNPE (Legacy): developer.qualcomm.com/docs/snpe
- AI Hub: Προ-βελτιστοποιημένα μοντέλα για υλικό Qualcomm
- Android Neural Networks API: Ενσωμάτωση με Android NNAPI
- TensorFlow Lite Delegate: Αντιπρόσωπος Qualcomm για TFLite
- MLPerf Mobile: mlcommons.org/en/inference-mobile-21
- AI Benchmark: ai-benchmark.com/ranking
- Έρευνα AI Qualcomm: qualcomm.com/research/artificial-intelligence
- Δείγματα Εφαρμογών: Διαθέσιμα στον κατάλογο παραδειγμάτων του QNN SDK
- Αποθετήρια GitHub: Παραδείγματα και εργαλεία που συνεισφέρθηκαν από την κοινότητα
- Τεχνικά Blogs: Qualcomm Developer Blog
- Qualcomm AI Model Efficiency Toolkit (AIMET): github.com/quic/aimet - Προηγμένες τεχνικές ποσοτικοποίησης και συμπίεσης
- TensorFlow Lite: tensorflow.org/lite - Για σύγκριση και εναλλακτική ανάπτυξη
- ONNX Runtime: onnxruntime.ai - Μηχανή inference πολλαπλών πλατφορμών
- Hexagon NPU: developer.qualcomm.com/hardware/hexagon-dsp
- Adreno GPU: developer.qualcomm.com/hardware/adreno-gpu
- Πλατφόρμες Snapdragon: qualcomm.com/products/mobile/snapdragon
Συνεχίστε το ταξίδι σας στο Edge AI εξερευνώντας Ενότητα 5: SLMOps και Ανάπτυξη Παραγωγής για να μάθετε για τις λειτουργικές πτυχές της διαχείρισης κύκλου ζωής των Small Language Models.
Αποποίηση ευθύνης:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης Co-op Translator. Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.