Pytorch 중 torch.save 시 Unknown error:-1 오류 해결

5774 단어
최근에 Pytorch를 사용할 때 오류가 발생했습니다. error traceback은 다음과 같습니다.
Traceback (most recent call last):
File "main-train.py", line 250, in main()
File "main-train.py", line 232, in main
m.state_dict(), '../exp/{}/{}/model_{}.pth'.format(opt.dataset, opt.expID, opt.epoch))
File "/usr/local/lib/python3.5/dist-packages/torch/serialization.py", line 135, in save
return _with_file_like(f, "wb", lambda f: _save(obj, f, pickle_module, pickle_protocol))
File "/usr/local/lib/python3.5/dist-packages/torch/serialization.py", line 117, in _with_file_like
return body(f)
File "/usr/local/lib/python3.5/dist-packages/torch/serialization.py", line 135, in 
return _with_file_like(f, "wb", lambda f: _save(obj, f, pickle_module, pickle_protocol))
File "/usr/local/lib/python3.5/dist-packages/torch/serialization.py", line 204, in _save
serialized_storages[key]._write_file(f)
RuntimeError: Unknown error -1

이 오류 창고에서 보듯이 이것은 torch를 호출하는 것입니다.모델을 저장할 때 발생하는 구체적인 오류 발생 위치는torch/serialization입니다.py에서, 그리고 Pytorch 0.3.1과 Pytorch 0.4에서 나는 모두 이 문제에 부딪혔다. 아래에serialization을 붙인다.py 대응 함수 코드(Pytorch0.3.0 중국어 문서에서 붙여넣기 복사, 0.3.1과 0.4 버전의 경우 코드와 유사):
def save(obj, f, pickle_module=pickle, pickle_protocol=DEFAULT_PROTOCOL):
    """ .

     : :ref:`recommend-saving-models`

     :
        obj:  
        f:   (  fileno  )  
        pickle_module:   pickling  
        pickle_protocol:  
    """
    return _with_file_like(f, "wb", lambda f: _save(obj, f, pickle_module, pickle_protocol))

def _save(obj, f, pickle_module, pickle_protocol):
    import torch.nn as nn
    serialized_container_types = {}
    serialized_storages = {}

    def persistent_id(obj):
        # FIXME: the docs say that persistent_id should only return a string
        # but torch store returns tuples. This works only in the binary protocol
        # see
        # https://docs.python.org/2/library/pickle.html#pickling-and-unpickling-external-objects
        # https://github.com/python/cpython/blob/master/Lib/pickle.py#L527-L537
        if isinstance(obj, type) and issubclass(obj, nn.Module):
            if obj in serialized_container_types:
                return None
            serialized_container_types[obj] = True
            source_file = source = None
            try:
                source_file = inspect.getsourcefile(obj)
                source = inspect.getsource(obj)
            except Exception:  # saving the source is optional, so we can ignore any errors
                warnings.warn("Couldn't retrieve source code for container of "
                              "type " + obj.__name__ + ". It won't be checked "
                              "for correctness upon loading.")
            return ('module', obj, source_file, source)
        elif torch.is_storage(obj):
            storage_type = normalize_storage_type(type(obj))
            root, offset = obj._root_storage()
            root_key = str(root._cdata)
            location = location_tag(obj)
            serialized_storages[root_key] = root
            is_view = obj._cdata != root._cdata
            if is_view:
                view_metadata = (str(obj._cdata), offset, obj.size())
            else:
                view_metadata = None

            return ('storage',
                    storage_type,
                    root_key,
                    location,
                    root.size(),
                    view_metadata)

        return None

    sys_info = dict(
        protocol_version=PROTOCOL_VERSION,
        little_endian=sys.byteorder == 'little',
        type_sizes=dict(
            short=SHORT_SIZE,
            int=INT_SIZE,
            long=LONG_SIZE,
        ),
    )

    pickle_module.dump(MAGIC_NUMBER, f, protocol=pickle_protocol)
    pickle_module.dump(PROTOCOL_VERSION, f, protocol=pickle_protocol)
    pickle_module.dump(sys_info, f, protocol=pickle_protocol)
    pickler = pickle_module.Pickler(f, protocol=pickle_protocol)
    pickler.persistent_id = persistent_id
    pickler.dump(obj)

    serialized_storage_keys = sorted(serialized_storages.keys())
    pickle_module.dump(serialized_storage_keys, f, protocol=pickle_protocol)
    f.flush()
    for key in serialized_storage_keys:
        serialized_storages[key]._write_file(f)

이 오류에는 여러 가지 원인이 있을 수 있습니다. 두 가지 흔히 볼 수 있는 것은 다음과 같습니다.
  • 모델을 저장할 때 목표 디렉터리의 디스크 공간이 부족합니다. 유사한 issue는 이미 여러 사람에게 보고되었습니다(예를 들어 Pytorch Forum에서의 토론). 이런 상황에 대한 해결은 비교적 간단합니다. 모델을 다른 저장 공간의 경로에 저장하면 됩니다
  • Pytorch의 현재 버전에서 비교적 은밀한 버그가 있기 때문에 관련 설명은 Github의 issue #8477을 보십시오. 원인은 비교적 복잡하기 때문에 issue의 보고자는 관련 추론을 했습니다

  • I added some code in the source code to print the error and signal, then reproduced and got the bold lines.Seems like save operation happened right after validation finished, exit of worker subprocesses caused the SIGCHLD, then interrupted "write"system call.
    간단하게 말하자면 하나의 epoch 훈련이 끝난 후validation이 끝날 때 대응하는worker 하위 프로세스가 끝나고 SIGCHLD 신호를 던지기 때문이다. 그리고 이 신호는 때때로 부모 프로세스를 동원하여 현재'write'작업을 하는 동작을 중지한다. 즉, 모델을 저장할 때 하드디스크에 쓰는 동작을 중지한다.
    이런 상황에 대해 당연히 비교적 복잡한 수단을 통해 해결할 수 있지만 가장 간단한 방법은 torch이다.save 전에 일정한 대기 시간을 추가하여 SIGCHLD 작업에 영향을 미치지 않도록 합니다. 예를 들어 삽입:
    import time
    time.sleep(10)
    

    매우 불행하게도 상술한 두 가지 상황을 나는 모두 만났다. 첫 번째 상황은 매우 빨리 해결되었고, 두 번째 상황은 나를 매우 오랫동안 괴롭혔다.전체적으로 말하자면 이것은 Pytorch의 현재 버전의 버그이고 오류가 발생했을 때 우호적인 오류 정보를 주지 않았다. 앞에서 말한 두 가지 상황에 대응하는 발생 원인은 사실상 다르지만 사전에 설정된 우호적인 오류 처리 메커니즘 처리가 없어서'unkown error'라는 메시지가 생겼다.그래서 이 오보에 다른 오류가 있을 수도 있고 공유를 환영합니다.
    PS. Pytorch 팀은 이 문제를 알아차렸고 이 issue 처리를 TODO에 추가했습니다. 이후 버전에서 처리될 예정입니다.

    좋은 웹페이지 즐겨찾기