티스토리 뷰

음... onnxruntime 1.13 부터인가 정확히는 모르겠는데 onnxruntime을 1.13으로 올리니

 

GetInputName 과 GetOutputName 이 없다고 오류난다.

 

api가 변경됐다.

 

Name뒤에 Allocated가 붙었다.

 

찾아보니 기존의 GetInputName 과 GetOutputName 이 메모리 leak 나기 쉬워서 변경됐다는 거 같다.

 

그래서 기존의 코드에서 GetInputName 과 GetOutputNameGetInputNameAllocated 과 GetOutputNameAllocated 로 바꿨는데 빌드 안된다.

 

반환형도 살짝 바뀌었고 또 이에 맞춰 수정은 해서 빌드는 됐는데 실행해보니 input name이랑 output name을 출력해보니 엉뚱한 값들이 출력됐다.

 

이슈가 역시나 제기돼있었다.

 

https://github.com/microsoft/onnxruntime/issues/14157

 

Problems caused by GetInputNameAllocated after upgrading from 1.12 to 1.13 · Issue #14157 · microsoft/onnxruntime

Describe the issue When upgrading from 1.12.x to 1.13.x,GetInputName and GetOutputName need to be replaced with GetInputNameAllocated and GetOutputNameAllocated, I encountered a very strange bug he...

github.com

 

해결 방법

input name 담을때 std::vector<const char*> 에 저장한다. 주의할 점은 GetInputNameAllocatedGetOutputNameAllocated 를 사용할때 std::vector<const char*> 에 저장되는 const char* 가 엉뚱한 값을 가리키지 않도록 만들어줘야한다는 점이다.

 

이를 위해 std::vector<AllocatedStringPtr> 에 GetInputNameAllocated  혹은 GetOutputNameAllocated 로부터 반환되는 AllocatedStringPtr 값(의 소유권)을 별도로 생성한 std::vector<AllocatedStringPtr> 에  move 시키고  input name이 저장된 std::vector<const char*> 가 소멸되기 이전까지 std::vector<AllocatedStringPtr> 가 소멸되지 않도록 해주면 된다.  std::vector<AllocatedStringPtr> 가 먼저 소멸되면 std::vector<const char*> 의  const char* 가 가리키던 값이 메모리가 해제되는지 엉뚱한 값을 출력하게된다.

 

위 방법을 코드로 구현하면 아래와 같다.

 

아래 코드는 위에 이슈에서 나온 방법이다.

 

inputNodeNameAllocatedStrings 를 만들어주지 않고 직접해보면 문제가 발생함을 관측할 수 있을 것이다.

 

std::vector<const char*> inputNodeNames; //
std::vector<AllocatedStringPtr> inputNodeNameAllocatedStrings; // <-- newly added

...

auto inputNodesNum = session->GetInputCount();
for (int i = 0; i < inputNodesNum; i++) {
		auto input_name = session->GetInputNameAllocated(i, allocator);
		inputNodeNameAllocatedStrings.push_back(std::move(input_name));
		inputNodeNames.push_back(inputNodeNameAllocatedStrings.back().get());
}

 

onnxruntime 프로젝트에서는 아래처럼 쓰고있다.

 

https://github.com/microsoft/onnxruntime/blob/main/onnxruntime/python/tools/tensorrt/perf/mem_test/main.cpp#L70-L97

 

GitHub - microsoft/onnxruntime: ONNX Runtime: cross-platform, high performance ML inferencing and training accelerator

ONNX Runtime: cross-platform, high performance ML inferencing and training accelerator - GitHub - microsoft/onnxruntime: ONNX Runtime: cross-platform, high performance ML inferencing and training a...

github.com

std::vector<AllocatedStringPtr> 에 따로 std::move를 안해주고 input node name만 받게 끔 구현하는 것은 아래 처럼 코드를 작성하는 느낌이다.

 

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main()
{
    std::vector<const char *> v;
    
    {
        std::string s1 = "hdasdsadasdasdasdasdsai";
        std::string s2 = "hellasdsadasdasdasdsadasdasdasdsado";
        std::string s3 = "bysadsadsadasdsadasdsadsadsae";
        
        v.push_back(s1.c_str());
        v.push_back(s2.c_str());
        v.push_back(s3.c_str());
        for(auto e:v)
        {
            std::cout<< e << std::endl;
        }
    }
    
    for(auto e:v)
    {
        std::cout<< e << std::endl;
    }
    
    return 0;
}

출력 결과

main 문안에 존재하는 block 을 벗어나면 v에 저장된 값들의 출력값이 의도하지 않은 값으로 출력된다.

 

아래처럼 수정해보자.  string이 block내에서 소멸되면서 const char* 값이 맛탱이 가지 않도록 vector하나 더 만들고 그 vector에다가 string 을 move 시켜주자.

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main()
{
    std::vector<const char *> v;
    std::vector<string> v_s;
    
    {
        std::string s1 = "hdasdsadasdasdasdasdsai";
        std::string s2 = "hellasdsadasdasdasdsadasdasdasdsado";
        std::string s3 = "bysadsadsadasdsadasdsadsadsae";
        
        v.push_back(s1.c_str());
        v.push_back(s2.c_str());
        v.push_back(s3.c_str());
        
        v_s.push_back(std::move(s1)); //newly added
        v_s.push_back(std::move(s2)); //newly added
        v_s.push_back(std::move(s3)); //newly added
        
        for(auto e:v)
        {
            std::cout<< e << std::endl;
        }
    }
    
    for(auto e:v)
    {
        std::cout<< e << std::endl;
    }
    
    return 0;
}

출력 결과

main 문안에 존재하는 block 을 벗어나도 의도대로 잘 출력된다.

 

결론

모델 input, output node 이름 저장하려는건데 이렇게까지 해야하나 싶다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함