

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# 모델 관리
<a name="edge-manage-model"></a>

Edge Manager 에이전트는 한 번에 다중 모델을 로드하고 엣지 디바이스에 로드된 모델로 추론할 수 있습니다. 에이전트가 로드할 수 있는 모델 수는 디바이스의 사용 가능한 메모리에 따라 결정됩니다. 에이전트는 모델 서명을 검증하고 엣지 패키징 작업에서 생성된 모든 아티팩트를 메모리에 로드합니다. 이 단계를 수행하려면 이전 단계에서 설명한 모든 필수 인증서를 나머지 바이너리 설치와 함께 설치해야 합니다. 모델 서명을 검증할 수 없는 경우, 적절한 반환 코드 및 사유와 함께 모델 로드가 실패합니다

SageMaker Edge Manager 에이전트는 엣지 디바이스에서 제어 플레인 및 데이터 플레인 API를 구현하는 모델 관리 API 목록을 제공합니다. 이 설명서와 함께 아래에 설명된 API의 정식 사용량이 표시된 샘플 클라이언트 구현을 살펴볼 것을 권장합니다.

`proto` 파일은 릴리스 아티팩트의 일부로 이용 가능합니다(릴리스 tarball 내부). 이 문서에서는 `proto` 파일에 나열된 API 사용량을 나열하고 설명합니다.

**참고**  
Windows 릴리스에서는 이러한 API에 대한 일대일 매핑이 적용되며 C\$1에 있는 애플리케이션 구현 샘플 코드는 Windows용 릴리스 아티팩트와 공유됩니다. 다음은 Linux용 릴리스 아티팩트에 적용할 수 있는 독립 실행형 프로세스로 에이전트를 실행하는 방법입니다.

OS에 따라 아카이브를 추출합니다. 여기서 `VERSION`은(는) 세 가지 구성 요소 `<MAJOR_VERSION>.<YYYY-MM-DD>-<SHA-7>`(으)로 구분됩니다. [Edge Manager 에이전트 설치](edge-device-fleet-manual.md#edge-device-fleet-installation)에서 릴리스 버전(`<MAJOR_VERSION>`), 릴리스 아티팩트 타임스탬프(`<YYYY-MM-DD>`), 리포지토리 커밋 ID(`SHA-7`) 획득 방법을 확인하세요

------
#### [ Linux ]

zip 아카이브는 명령어로 추출할 수 있습니다.

```
tar -xvzf <VERSION>.tgz
```

------
#### [ Windows ]

zip 아카이브는 UI 또는 명령어로 추출할 수 있습니다.

```
unzip <VERSION>.tgz
```

------

릴리스 아티팩트 계층 구조(`tar/zip` 아카이브 추출 후)는 다음과 같습니다. 에이전트 `proto` 파일은 `api/` 아래에 있습니다.

```
0.20201205.7ee4b0b
├── bin
│         ├── sagemaker_edge_agent_binary
│         └── sagemaker_edge_agent_client_example
└── docs
├── api
│         └── agent.proto
├── attributions
│         ├── agent.txt
│         └── core.txt
└── examples
└── ipc_example
├── CMakeLists.txt
├── sagemaker_edge_client.cc
├── sagemaker_edge_client_example.cc
├── sagemaker_edge_client.hh
├── sagemaker_edge.proto
├── README.md
├── shm.cc
├── shm.hh
└── street_small.bmp
```

**Topics**
+ [모델 로드](#edge-manage-model-loadmodel)
+ [모델 언로드](#edge-manage-model-unloadmodel)
+ [모델 나열](#edge-manage-model-listmodels)
+ [모델 설명](#edge-manage-model-describemodel)
+ [데이터 캡처](#edge-manage-model-capturedata)
+ [캡처 상태 가져오기](#edge-manage-model-getcapturedata)
+ [예측](#edge-manage-model-predict)

## 모델 로드
<a name="edge-manage-model-loadmodel"></a>

Edge Manager 에이전트는 다중 모델 로드를 지원합니다. 이 API는 모델 서명을 검증하고 `EdgePackagingJob` 작업에서 생성된 모든 아티팩트를 메모리에 로드합니다. 이 단계를 수행하려면 모든 필수 인증서를 나머지 에이전트 바이너리 설치와 함께 설치해야 합니다. 모델 서명을 검증할 수 없는 경우, 적절한 반환 코드 및 로그 내 오류 메시지와 함께 이 단계가 실패합니다

```
// perform load for a model
// Note:
// 1. currently only local filesystem paths are supported for loading models.
// 2. multiple models can be loaded at the same time, as limited by available device memory
// 3. users are required to unload any loaded model to load another model.
// Status Codes:
// 1. OK - load is successful
// 2. UNKNOWN - unknown error has occurred
// 3. INTERNAL - an internal error has occurred
// 4. NOT_FOUND - model doesn't exist at the url
// 5. ALREADY_EXISTS - model with the same name is already loaded
// 6. RESOURCE_EXHAUSTED - memory is not available to load the model
// 7. FAILED_PRECONDITION - model is not compiled for the machine.
//
rpc LoadModel(LoadModelRequest) returns (LoadModelResponse);
```

------
#### [ Input ]

```
//
// request for LoadModel rpc call
//
message LoadModelRequest {
  string url = 1;
  string name = 2;  // Model name needs to match regex "^[a-zA-Z0-9](-*[a-zA-Z0-9])*$"
}
```

------
#### [ Output ]

```
//
//
// response for LoadModel rpc call
//
message LoadModelResponse {
  Model model = 1;
}

//
// Model represents the metadata of a model
//  url - url representing the path of the model
//  name - name of model
//  input_tensor_metadatas - TensorMetadata array for the input tensors
//  output_tensor_metadatas - TensorMetadata array for the output tensors
//
// Note:
//  1. input and output tensor metadata could empty for dynamic models.
//
message Model {
  string url = 1;
  string name = 2;
  repeated TensorMetadata input_tensor_metadatas = 3;
  repeated TensorMetadata output_tensor_metadatas = 4;
}
```

------

## 모델 언로드
<a name="edge-manage-model-unloadmodel"></a>

이전에 로드한 모델을 언로드합니다. `loadModel` 중에 입력된 모델 별칭으로 식별됩니다. 별칭을 찾을 수 없거나 모델이 로드되지 않은 경우 오류가 반환됩니다.

```
//
// perform unload for a model
// Status Codes:
// 1. OK - unload is successful
// 2. UNKNOWN - unknown error has occurred
// 3. INTERNAL - an internal error has occurred
// 4. NOT_FOUND - model doesn't exist
//
rpc UnLoadModel(UnLoadModelRequest) returns (UnLoadModelResponse);
```

------
#### [ Input ]

```
//
// request for UnLoadModel rpc call
//
message UnLoadModelRequest {
 string name = 1; // Model name needs to match regex "^[a-zA-Z0-9](-*[a-zA-Z0-9])*$"
}
```

------
#### [ Output ]

```
//
// response for UnLoadModel rpc call
//
message UnLoadModelResponse {}
```

------

## 모델 나열
<a name="edge-manage-model-listmodels"></a>

로드된 모든 모델과 별칭을 나열합니다.

```
//
// lists the loaded models
// Status Codes:
// 1. OK - unload is successful
// 2. UNKNOWN - unknown error has occurred
// 3. INTERNAL - an internal error has occurred
//
rpc ListModels(ListModelsRequest) returns (ListModelsResponse);
```

------
#### [ Input ]

```
//
// request for ListModels rpc call
//
message ListModelsRequest {}
```

------
#### [ Output ]

```
//
// response for ListModels rpc call
//
message ListModelsResponse {
 repeated Model models = 1;
}
```

------

## 모델 설명
<a name="edge-manage-model-describemodel"></a>

에이전트에 로드되는 모델을 설명합니다.

```
//
// Status Codes:
// 1. OK - load is successful
// 2. UNKNOWN - unknown error has occurred
// 3. INTERNAL - an internal error has occurred
// 4. NOT_FOUND - model doesn't exist at the url
//
rpc DescribeModel(DescribeModelRequest) returns (DescribeModelResponse);
```

------
#### [ Input ]

```
//
// request for DescribeModel rpc call
//
message DescribeModelRequest {
  string name = 1;
}
```

------
#### [ Output ]

```
//
// response for DescribeModel rpc call
//
message DescribeModelResponse {
  Model model = 1;
}
```

------

## 데이터 캡처
<a name="edge-manage-model-capturedata"></a>

클라이언트 애플리케이션이 Amazon S3 버킷 및 선택적으로 보조 버킷의 입력 및 출력 텐서를 캡처할 수 있도록 허용합니다. 클라이언트 애플리케이션은 이 API를 개별 호출하여 고유한 캡처 ID를 전달해야 합니다. 이 ID는 나중에 캡처 상태 쿼리 시 사용 가능합니다.

```
//
// allows users to capture input and output tensors along with auxiliary data.
// Status Codes:
// 1. OK - data capture successfully initiated
// 2. UNKNOWN - unknown error has occurred
// 3. INTERNAL - an internal error has occurred
// 5. ALREADY_EXISTS - capture initiated for the given capture_id
// 6. RESOURCE_EXHAUSTED - buffer is full cannot accept any more requests.
// 7. OUT_OF_RANGE - timestamp is in the future.
// 8. INVALID_ARGUMENT - capture_id is not of expected format.
//
rpc CaptureData(CaptureDataRequest) returns (CaptureDataResponse);
```

------
#### [ Input ]

```
enum Encoding {
 CSV = 0;
 JSON = 1;
 NONE = 2;
 BASE64 = 3;
}

//
// AuxilaryData represents a payload of extra data to be capture along with inputs and outputs of inference
// encoding - supports the encoding of the data
// data - represents the data of shared memory, this could be passed in two ways:
// a. send across the raw bytes of the multi-dimensional tensor array
// b. send a SharedMemoryHandle which contains the posix shared memory segment id and
// offset in bytes to location of multi-dimensional tensor array.
//
message AuxilaryData {
 string name = 1;
 Encoding encoding = 2;
 oneof data {
 bytes byte_data = 3;
 SharedMemoryHandle shared_memory_handle = 4;
 }
}

//
// Tensor represents a tensor, encoded as contiguous multi-dimensional array.
// tensor_metadata - represents metadata of the shared memory segment
// data_or_handle - represents the data of shared memory, this could be passed in two ways:
// a. send across the raw bytes of the multi-dimensional tensor array
// b. send a SharedMemoryHandle which contains the posix shared memory segment
// id and offset in bytes to location of multi-dimensional tensor array.
//
message Tensor {
 TensorMetadata tensor_metadata = 1; //optional in the predict request
 oneof data {
 bytes byte_data = 4;
 // will only be used for input tensors
 SharedMemoryHandle shared_memory_handle = 5;
 }
}

//
// request for CaptureData rpc call
//
message CaptureDataRequest {
 string model_name = 1;
 string capture_id = 2; //uuid string
 Timestamp inference_timestamp = 3;
 repeated Tensor input_tensors = 4;
 repeated Tensor output_tensors = 5;
 repeated AuxilaryData inputs = 6;
 repeated AuxilaryData outputs = 7;
}
```

------
#### [ Output ]

```
//
// response for CaptureData rpc call
//
message CaptureDataResponse {}
```

------

## 캡처 상태 가져오기
<a name="edge-manage-model-getcapturedata"></a>

로드된 모델에 따라 입력 및 출력 텐서가 커질 수 있습니다(많은 엣지 디바이스의 경우). 클라우드 캡처는 시간이 많이 걸릴 수 있습니다. 따라서 `CaptureData()`은(는) 비동기식 작업으로 구현됩니다. 캡처 ID는 클라이언트가 캡쳐 데이터 호출 중에 입력하는 고유 식별자이며, 이 ID는 비동기식 호출 상태 쿼리 시 사용 가능합니다.

```
//
// allows users to query status of capture data operation
// Status Codes:
// 1. OK - data capture successfully initiated
// 2. UNKNOWN - unknown error has occurred
// 3. INTERNAL - an internal error has occurred
// 4. NOT_FOUND - given capture id doesn't exist.
//
rpc GetCaptureDataStatus(GetCaptureDataStatusRequest) returns (GetCaptureDataStatusResponse);
```

------
#### [ Input ]

```
//
// request for GetCaptureDataStatus rpc call
//
message GetCaptureDataStatusRequest {
  string capture_id = 1;
}
```

------
#### [ Output ]

```
enum CaptureDataStatus {
  FAILURE = 0;
  SUCCESS = 1;
  IN_PROGRESS = 2;
  NOT_FOUND = 3;
}

//
// response for GetCaptureDataStatus rpc call
//
message GetCaptureDataStatusResponse {
  CaptureDataStatus status = 1;
}
```

------

## 예측
<a name="edge-manage-model-predict"></a>

`predict` API는 이전에 로드된 모델에서 추론을 수행합니다. 신경망에 직접 공급되는 텐서 형태의 요청을 수락합니다. 출력은 모델의 출력 텐서(또는 스칼라)입니다. 이는 차단 호출입니다.

```
//
// perform inference on a model.
//
// Note:
// 1. users can chose to send the tensor data in the protobuf message or
// through a shared memory segment on a per tensor basis, the Predict
// method with handle the decode transparently.
// 2. serializing large tensors into the protobuf message can be quite expensive,
// based on our measurements it is recommended to use shared memory of
// tenors larger than 256KB.
// 3. SMEdge IPC server will not use shared memory for returning output tensors,
// i.e., the output tensor data will always send in byte form encoded
// in the tensors of PredictResponse.
// 4. currently SMEdge IPC server cannot handle concurrent predict calls, all
// these call will be serialized under the hood. this shall be addressed
// in a later release.
// Status Codes:
// 1. OK - prediction is successful
// 2. UNKNOWN - unknown error has occurred
// 3. INTERNAL - an internal error has occurred
// 4. NOT_FOUND - when model not found
// 5. INVALID_ARGUMENT - when tenors types mismatch
//
rpc Predict(PredictRequest) returns (PredictResponse);
```

------
#### [ Input ]

```
// request for Predict rpc call
//
message PredictRequest {
string name = 1;
repeated Tensor tensors = 2;
}

//
// Tensor represents a tensor, encoded as contiguous multi-dimensional array.
//    tensor_metadata - represents metadata of the shared memory segment
//    data_or_handle - represents the data of shared memory, this could be passed in two ways:
//                        a. send across the raw bytes of the multi-dimensional tensor array
//                        b. send a SharedMemoryHandle which contains the posix shared memory segment
//                            id and offset in bytes to location of multi-dimensional tensor array.
//
message Tensor {
  TensorMetadata tensor_metadata = 1; //optional in the predict request
  oneof data {
    bytes byte_data = 4;
    // will only be used for input tensors
    SharedMemoryHandle shared_memory_handle = 5;
  }
}

//
// Tensor represents a tensor, encoded as contiguous multi-dimensional array.
//    tensor_metadata - represents metadata of the shared memory segment
//    data_or_handle - represents the data of shared memory, this could be passed in two ways:
//                        a. send across the raw bytes of the multi-dimensional tensor array
//                        b. send a SharedMemoryHandle which contains the posix shared memory segment
//                            id and offset in bytes to location of multi-dimensional tensor array.
//
message Tensor {
  TensorMetadata tensor_metadata = 1; //optional in the predict request
  oneof data {
    bytes byte_data = 4;
    // will only be used for input tensors
    SharedMemoryHandle shared_memory_handle = 5;
  }
}

//
// TensorMetadata represents the metadata for a tensor
//    name - name of the tensor
//    data_type  - data type of the tensor
//    shape - array of dimensions of the tensor
//
message TensorMetadata {
  string name = 1;
  DataType data_type = 2;
  repeated int32 shape = 3;
}

//
// SharedMemoryHandle represents a posix shared memory segment
//    offset - offset in bytes from the start of the shared memory segment.
//    segment_id - shared memory segment id corresponding to the posix shared memory segment.
//    size - size in bytes of shared memory segment to use from the offset position.
//
message SharedMemoryHandle {
  uint64 size = 1;
  uint64 offset = 2;
  uint64 segment_id = 3;
}
```

------
#### [ Output ]

**참고**  
`PredictResponse`은(는) `Tensors`만 반환하며 `SharedMemoryHandle`은(는) 반환하지 않습니다.

```
// response for Predict rpc call
//
message PredictResponse {
   repeated Tensor tensors = 1;
}
```

------