Git Product home page Git Product logo

furiosa-models's People

Contributors

furiosamg avatar hyeokjunejeon avatar hyeonu-furiosa avatar hyunsik avatar ileixe avatar libc-furiosa avatar sukyoungjeong-furiosa avatar yungbumjung avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

furiosa-models's Issues

Expose API reference documents to mkdocs site

API reference도 생성되어 mkdocs에 링크로 노출될 필요가 있겠습니다. 다음 이유 때문입니다.

  • Model 클래스에 대해서는 코드 외에는 정보가 없습니다.
  • Pre/post process 의 입출력이 각기 조금씩 다릅니다. 레퍼런스 없이는 코드를 들여다 봐야 이해할 수 있을 것 같습니다.

Artifacts file locations

enf, dfg, dvc 파일들이 어디에 위치하고(특히 패키징 되어있을 때) 어떻게 캐시되고 어떻게 fetch될 지 정리와 리팩토링이 필요할 것 같습니다.

제가 파악한 현 상태는 다음과 같습니다.

  • 로컬에서 개발하는 상황만 고려되어 있음 (패키징 되지않는 경로인 /models에서 찾음)
  • enf의 경우 /models에 .dvc 파일을 찾아서 fetch함
  • dfg는 /models/generated에 실제 파일이 있기를 기대함

요구사항은 다음과 같을 것 같습니다.

  • 파일을 로컬에서 가져올 지 DVC에서 가져올 지 일관성이 있어야 하고 우선순위가 명확히 드러나야 함, 테스트 및 개발 시나리오도 고려되어야함
  • 선행이슈로 #36 , #34 가 있는데 요구사항이 좀 더 있는 것 같아서 여기서 논의하면 좋을 것 같습니다.

괜찮으시면 제가 다음과 같이 변경 및 개발해보려 합니다.

  • #36 에서 제안해주신 USE_LOCAL_ARTIFACTS 같이 로컬에서 파일을 찾는 환경 변수를 두는 대신 로컬에서 파일을 찾는 걸 우선시함 (개발시에만 로컬에서 파일을 찾을 수 있을 것 같아서요)
  • 우선순위를 다음과 같이 바꿔보려 합니다.
  • 로컬 경로(/models) 에서 실제 파일을 찾으려 함 (개발할 때 편의를 위해, 엔드 사용자는 이 단계에서 파일을 찾지 않을 것으로 기대함)
  • 로컬 캐시($HOME/.cache/furiosa/*)에서 실제 파일 찾으려 함 (#34 구현 전까지는 건너뜀)
  • 패키지된 DVC 파일을 찾아서 가져오고 캐시함
  • 모든 과정이 Python logger debug level로 나타났으면 좋겠음

cc. @sukyoungjeong-furiosa

PS. @hyunsik 괜찮으시다면 이 이슈를 가장 먼저 작업할까 합니다.

Make API more consistent

API를 더 일관되게 통일 하려고 합니다 (WIP)

  • Rename batch_preproc_params of ssd mobilenet, resnet34 to context
  • NativePostProcessor is designed to take only one context, but python version of postprocessor can take a list of contexts. (except YOLOv5)

Add furiosa-models to nightly build

pip에 nightly에 추가하여 패키지로 설치했을 때 잘 동작하는지 (특히 DVC 관련 이슈) 그리고 CI 에서 통합하여 sdk 와 함께 테스트 해볼 필요가 있을 것 같습니다.

C버전 cbox_decod library 설치 과정 개선

현황

furiosa/models/vision/yolov5/box_decode/cbox_decode 패키지 수동/별도 설치
pip install 형태로 별도로 설치하는 형태입니다.
공개된 코드는 아닌 것 같고, 자체 개발한 코드로 보입니다.

개선 포인트

furisoa.models가 설치될때 함께 포함되어 설치가 되었으면 합니다.
통합 설치로 models의 버전과 cbox_decode의 버전이 항상 일치하여 side-effect가 없었으면 좋겠습니다.

[Umbrella Issue] Make furiosa-models deliverable without compiler

Model Zoo 목적에 맞게 필요한 경우 배포 시 컴파일러를 완전 제거 하고 컴파일러가 빠진 Nux 만으로 배포할 수 있도록 다음과 같은 다양한 일을 진행합니다.

  • 컴파일된 ENF를 furiosa-models에 추가 및 ENF 파일 및 디렉토리 구조 설계
    • Scope을 최소로 하기 위해 Model zoo에 포함되는 모델은 warboy-2pe 로 컴파일된 ENF로 한정
    • 컴파일러 버전에 따른 ENF 파일을 저장하고 엑세스 할 수 있어야 함
  • 단기적으로 현재 시스템에 설치된 모델들을 일괄적으로 컴파일 하여 위에서 설계된 파일 및 디렉토리 구조에 맞게 ENF를 저장하는 Makefile 구현
  • libnux 등 런타임 라이브러리가 컴파일러 없이 패키징
  • furiosa-models가 컴파일러 버전에 맞게 DVC에서 파일을 엑세스 오도록 개선

CI에서 manylinux로 빌드 및 pip에 배포

작업했었던 github workflow 일부를 남겨놓습니다.

env:
  PACKAGE_NAME: furiosa_models
###
    - name: Install Rust toolchain
      uses: actions-rs/toolchain@v1
      with:
        toolchain: nightly
        profile: minimal
        default: true
    - name: Build Wheels
      uses: messense/maturin-action@v1
      with:
        manylinux: auto
        args: -i ${{ matrix.python-version }} --release --out dist
###
        pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall

Models for blocking API

현재 non-blocking 으로 구현이 되어 있고 blocking api는 동적으로 생성해내고 있는데요.
개발은 편하지만 사용에 불편한 점이 있습니다. 우선 IDE등이 인식을 못하고 문서화도 불편한 점이 있는데요.

그래서 대안을 고민 중입니다. 우선 두 가지 옵션을 생각하고 있습니다.

모델을 생성하는 현재의 주요 부분은 다음과 같습니다.

async def ResNet50(*args: Any, **kwargs: Any) -> resnet50.MLCommonsResNet50Model:
    return resnet50.MLCommonsResNet50Model(
        name="ResNet50",
        model=await load_dvc("models/mlcommons_resnet50_v1.5_int8.onnx"),
        format=Format.ONNX,
        family="ResNet",
        version="v1.5",
        metadata=Metadata(
            description="ResNet50 v1.5 int8 ImageNet-1K Accuracy 75.982% @ Top1",
            publication=Publication(url="https://arxiv.org/abs/1512.03385.pdf"),
        ),
        *args,
        **kwargs,
    )

1. Class의 class method로 모델 인스턴스를 생성

장점:

  • 함수에 기술되고 있는 주요한 메타데이터가 class에 포함되어 코드 응집력 좋아짐
  • ResNet50Model라는 클래스와 생성하는 함수 ResNet50가 분리되어 있어 혼란을 야기하는데 이 문제도 해결 가능
  • 문서화 용이, IDE에서 접근 용이
class ResNet50(Model):
  def __load(model, *args, **kwargs):
     ResNet50(
          name="ResNet50",
          model=model,
          format=Format.ONNX,
          family="ResNet",
          version="v1.5",
          metadata=Metadata(
              description="ResNet50 v1.5 int8 ImageNet-1K Accuracy 75.982% @ Top1",
              publication=Publication(url="https://arxiv.org/abs/1512.03385.pdf"),
          ),
          *args,
          **kwargs,
      )
  
  @classmethod
  async def load_async(*args, **kwargs) -> Model:
    return ResNet50.__load(await load_dvc("models/mlcommons_resnet50_v1.5_int8.onnx")
  
  @classmethod
  def load(*args, *kwargs) -> Model:
    return synchronous(load_async(args, kwargs)

2. 직접 blocking API 코드 wrapper를 추가

장점: 현재 API와 호환성 유지

지금 사용되고 있는 동적인 추가 방법

__all__ = []

# Iterate over non-blocking versions of Model classes (that of .nonblocking.vision)
for model in [
    getattr(nonblocking, m)
    for m in dir(nonblocking)
    if iscoroutinefunction(getattr(nonblocking, m))
]:
    # Export synchronous version of Model class in this module scope
    name = model.__name__
    if name[0].isupper():
        globals()[name] = synchronous(model)
        __all__.append(name)

# Clean up unnecessary variables in this module
del iscoroutinefunction, Model, model, name, synchronous

직접 wrapper 구현을 추가할 경우

def ResNet50(*args, **kwargs) -> Model:
  return synchronous(nonblocking.ResNet50(*args, **kwargs)

@furiosamg 의견 주시면 감사하겠습니다.

mlcommons compiler와, 최신 npu-tools compiler 결과의 output tensor shape 차이 문제

#16

관련 노션 페이지
see https://www.notion.so/furiosa/2022-08-25-9ec4bed79419457c80e37cced1f18017

For ssd-small,

  • Original Model’s Shapes
0 - (1, 273, 19, 19)
1 - (1, 546, 10, 10)
2 - (1, 546, 5, 5)
3 - (1, 546, 3, 3)
4 - (1, 546, 2, 2)
5 - (1, 546, 1, 1)
6 - (1, 12, 19, 19)
7 - (1, 24, 10, 10)
8 - (1, 24, 5, 5)
9 - (1, 24, 3, 3)
10 - (1, 24, 2, 2)
11 - (1, 24, 1, 1)
0 - (1, 2, 64, 10, 19, 5)
1 - (1, 1, 128, 10, 10, 5)
2 - (1, 1, 128, 5, 5, 5)
3 - (1, 1, 128, 3, 5, 3)
4 - (1, 1, 128, 2, 5, 2)
5 - (1, 1, 128, 1, 5, 1)
6 - (1, 4, 32, 5, 1, 19)
7 - (1, 8, 16, 2, 2, 10)
8 - (1, 1, 128, 5, 1, 5)
9 - (1, 1, 128, 3, 1, 3)
10 - (1, 1, 128, 2, 1, 2)
11 - (1, 1, 128, 1, 1, 1)
  • with mlcommons compiler
[0] - 1,1,128,19,3,32
[1] - 1,1,128,10,5,32
[2] - 1,1,128,5,5,32
[3] - 1,1,128,3,5,32
[4] - 1,1,128,2,5,32
[5] - 1,1,128,1,5,32
[6] - 1,8,16,3,1,32
[7] - 1,8,16,2,2,32
[8] - 1,8,16,1,2,32
[9] - 1,4,32,1,1,32
[10] - 1,1,128,2,1,32
[11] - 1,1,128,1,1,32

performance benchmarks and optimization chances on ssd-mobilenet

MLPerf performance

mlperf 제출분의 ssd-mobilenet singlestream 시나리오 성능은 다음과 같습니다.

Mean latency (ns)               : 362108
QPS w/ loadgen overhead         : 2753.81

container 환경에서 같은 시나리오의 성능은 대략 다음 수준입니다.

Mean latency (ns)               : 505417
QPS w/ loadgen overhead         : 1973.84

AS-IS

현재 furiosa-models에서 사용하는 f32 모델의 python 구현의 벤치마크는 다음과 같습니다. 16CPU의 container 환경을 사용하였는데 필요하면 다른 환경에서의 값으로 업데이트 하겠습니다. (native 구현은 각각 단계의 수행시간 합보다 e2e 성능이 더 느린것이 이해가지 않아서 살펴보고 있습니다)

------------------------------------------------------------------------------------------------ benchmark: 4 tests ------------------------------------------------------------------------------------------------
Name (time in ms)                                         Min                Max              Mean            StdDev            Median               IQR            Outliers       OPS            Rounds  Iterations
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_ssd_mobilenet_benchmark_python_pre_O_post_O       7.1728 (3.67)     14.5963 (1.96)     7.7863 (3.31)     0.3721 (2.40)     7.7200 (3.39)     0.2563 (2.37)        98;60  128.4310 (0.30)       1000           1
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

=> e2e Latency 7.7ms / QPS 128 (excluding I/O time)

  • 주된 차이는 다음과 같다고 생각합니다.

    • (1) f32모델이라 quantization 오퍼레이터(external)가 추가됩니다.
    • (2) preprocess를 포함합니다.
    • (3) CPU가 적고 container 환경입니다.
  • 각각 단계의 수행시간도 측정했습니다. variance가 높아서 대략적인 수치만 봐주시면 됩니다.

    • (1) preprocess 0.7ms
    • (2) model inference (session run) 4.2ms
      • NPU execution = 320us
      • Quantization
      • Lower
      • 그외 Dram I/O, Unlower, ...
    • (3) numpy copy 0.5ms
    • (4) postprocess 2.3ms

Optimization chances

  • preprocess(0.7ms)

    • 추가로 최적화 하거나 pp처럼 rust / cpp 구현을 쓸수 있습니다.
  • model inference (4.2ms)

  • numpy copy (0.5ms)

  • postprocess (2.3ms)

    • 같은 환경에서 native cpp 구현의 성능은 0.7~8ms 안팎으로 더 빠릅니다. 병렬화 라이브러리를 쓰기 때문에 환경에 따라 더 개선됩니다.

flakey behavior in regression test

=================================== FAILURES ===================================
____________________ test_mlcommons_ssd_mobilenet_accuracy _____________________

    def test_mlcommons_ssd_mobilenet_accuracy():
        model: Model = SSDMobileNet()
    
        image_directory, coco = load_coco_from_env_variable()
        detections = []
    
        with session.create(model.source) as sess:
            for image_src in tqdm.tqdm(coco.dataset["images"]):
                image_path = str(image_directory / image_src["file_name"])
                image, contexts = preprocess([image_path])
                outputs = [sess.run](http://sess.run/)(image).numpy()
                batch_result = postprocess(outputs, contexts, confidence_threshold=0.3)
                result = np.squeeze(batch_result, axis=0)  # squeeze the batch axis
    
                for res in result:
                    detection = {
                        "image_id": image_src["id"],
                        "category_id": res.index,
                        "bbox": [
                            res.boundingbox.left,
                            [res.boundingbox.top](http://res.boundingbox.top/),
                            (res.boundingbox.right - res.boundingbox.left),
                            (res.boundingbox.bottom - [res.boundingbox.top](http://res.boundingbox.top/)),
                        ],
                        "score": res.score,
                    }
                    detections.append(detection)
        coco_detections = coco.loadRes(detections)
        coco_eval = COCOeval(coco, coco_detections, iouType="bbox")
        coco_eval.evaluate()
        coco_eval.accumulate()
        coco_eval.summarize()
        print("mAP:", coco_eval.stats[0])
>       assert coco_eval.stats[0] == EXPECTED_ACCURACY, "Accuracy check failed"
E       AssertionError: Accuracy check failed
E       assert 0.22761947009250402 == 0.22762065944402837

tests/accuracy/test_ssd_mobilenet_acc.py:66: AssertionError
__________ test_mlcommons_ssd_mobilenet_with_native_rust_pp_accuracy ___________

    def test_mlcommons_ssd_mobilenet_with_native_rust_pp_accuracy():
        model = SSDMobileNet(use_native_post=True)
        processor = NativePostProcessor(model, version="rust")
    
        image_directory, coco = load_coco_from_env_variable()
        detections = []
    
        with session.create(model.enf) as sess:
            for image_src in tqdm.tqdm(coco.dataset["images"]):
                image_path = str(image_directory / image_src["file_name"])
                image, contexts = preprocess([image_path])
                outputs = [sess.run](http://sess.run/)(image).numpy()
                result = processor.eval(outputs, context=contexts[0])
    
                for res in result:
                    detection = {
                        "image_id": image_src["id"],
                        "category_id": res.index,
                        "bbox": [
                            res.boundingbox.left,
                            [res.boundingbox.top](http://res.boundingbox.top/),
                            (res.boundingbox.right - res.boundingbox.left),
                            (res.boundingbox.bottom - [res.boundingbox.top](http://res.boundingbox.top/)),
                        ],
                        "score": res.score,
                    }
                    detections.append(detection)
        coco_detections = coco.loadRes(detections)
        coco_eval = COCOeval(coco, coco_detections, iouType="bbox")
        coco_eval.evaluate()
        coco_eval.accumulate()
        coco_eval.summarize()
        print("mAP:", coco_eval.stats[0])
>       assert coco_eval.stats[0] == EXPECTED_ACCURACY_NATIVE_RUST_PP, "Accuracy check failed"
E       AssertionError: Accuracy check failed
E       assert 0.22808151613353822 == 0.22808056885213657

tests/accuracy/test_ssd_mobilenet_acc.py:102: AssertionError
___________ test_mlcommons_ssd_mobilenet_with_native_cpp_pp_accuracy ___________

    def test_mlcommons_ssd_mobilenet_with_native_cpp_pp_accuracy():
        model = SSDMobileNet(use_native_post=True)
        processor = NativePostProcessor(model, version="cpp")
    
        image_directory, coco = load_coco_from_env_variable()
        detections = []
    
        with session.create(model.enf) as sess:
            for image_src in tqdm.tqdm(coco.dataset["images"]):
                image_path = str(image_directory / image_src["file_name"])
                image, contexts = preprocess([image_path])
                outputs = [sess.run](http://sess.run/)(image).numpy()
                result = processor.eval(outputs, context=contexts[0])
    
                for res in result:
                    detection = {
                        "image_id": image_src["id"],
                        "category_id": res.index,
                        "bbox": [
                            res.boundingbox.left,
                            [res.boundingbox.top](http://res.boundingbox.top/),
                            (res.boundingbox.right - res.boundingbox.left),
                            (res.boundingbox.bottom - [res.boundingbox.top](http://res.boundingbox.top/)),
                        ],
                        "score": res.score,
                    }
                    detections.append(detection)
        coco_detections = coco.loadRes(detections)
        coco_eval = COCOeval(coco, coco_detections, iouType="bbox")
        coco_eval.evaluate()
        coco_eval.accumulate()
        coco_eval.summarize()
        print("mAP:", coco_eval.stats[0])
>       assert coco_eval.stats[0] == EXPECTED_ACCURACY_NATIVE_CPP_PP, "Accuracy check failed"
E       AssertionError: Accuracy check failed
E       assert 0.228139746436464 == 0.22814002771459183

tests/accuracy/test_ssd_mobilenet_acc.py:138: AssertionError

CI에서 정확도 측정이 불안정합니다. 제 생각에는 npu 장치에 따라 정확도가 좀 다른것 같은데요.
어느쪽 숫자가 맞는지도 확신이 없네요.
9/21에 npu 수거 점검이 예정되어 있으니 그 이후에 다시 판단해보겠습니다.
그 전에는 임의로 숫자를 바꾸거나, 여러번 다시 돌려서 통과시켜 보겠습니다.

Module 구조 및 export 구조 논의

@furiosamg @ileixe @hyeokjunejeon @sukyoungjeong-furiosa

기존 것을 최대한 참고하여 제안 드려봅니다. 어떤 면에서는 큰 차이는 없습니다만, 지난 주에 논의되었던 pre/post process 함수 재활용을 위해 노출을 고려하였습니다. 의견 편하게 주시면 감사하겠습니다.

또한 지난 주에 모두 동의하였던 내용을 간단히 정리 해봤습니다. 차이가 있으면 의견 부탁드립니다.

  • furiosa-models에는 코드가 위치
  • furiosa-artifacts에는 model 이미지와 메타데이터 저장
  • furiosa-models 각 모델 클래스에서는 furiosa-artifats의 model key를 이용해 모델 이미지와 metadata를 lazy 하게 fetch

(참고로 모델 개발 중에는 furiosa-models에서 furiosa-artifacts metadata의 local file path를 입력해서 개발할 수 있도록 고려 필요)

최상단 모델 reexport 형태의 예

from furiosa.models.vision import Resnet50v2
from furiosa.models.vision import EfficientNetv2
from furiosa.models.vision import EfficientDet
from furiosa.models.vision import YOLOv5M

실제 구현 위치의 예

  • 각 모델의 고유의 서브 모듈에 속함
  • 필요한 경우 모델 구현 모듈에 hierarchy 를 둘 수 있음
  • preprocess 대부분의 코드는 image 변환 및 tensor 변환이므로 preprocess 과정 일부는 여러 모델에서 재활용 될 가능성이 높으며 모델에 특화되지 않은 일반적인 image 관련 코드는 furiosa.models.vision.utils에 위치
 furiosa
     |- models
             |- vision
                   |- resnet50v2
                          |- Resnet50v2 (class)
                          |- preprocess (function)
                          |- postprocess (function)
                   |- yolov5
                          |- YOLOv5M (class)
                          |- YOLOv5L (function)
                          |- preprocess (function)
                          |- postprocess (function)
                    |- utils
                          |- resize (function)
                          |- crop (function)
                          |-  ...

the resolver occasionally finds artifact files from site-packages

@furiosamg 새 환경에 설치하면 저는 종종 아래 문제를 겪는데요. 혹시 짐작가는 바가 있으실까요? clone 하자 마자 editable 로 설치 하지 않고 pip install --pre . 와 같이 설치했을 때 주로 발생했습니다.

Traceback (most recent call last):
  File "/home/hyunsik/Code/furiosa-models-2/docs/examples/ssd_resnet34.py", line 5, in <module>
    ssd_resnet34 = SSDResNet34.load()
  File "/home/hyunsik/.local/anaconda3/envs/furiosa-models/lib/python3.9/site-packages/furiosa/models/vision/ssd_resnet34/__init__.py", line 279, in load
    return cls.__load(synchronous(load_artifacts)(artifact_name), *args, **kwargs)
  File "/home/hyunsik/.local/anaconda3/envs/furiosa-models/lib/python3.9/site-packages/furiosa/common/thread.py", line 29, in wrapper
    raise e from None
  File "/home/hyunsik/.local/anaconda3/envs/furiosa-models/lib/python3.9/site-packages/furiosa/common/thread.py", line 26, in wrapper
    return asyncio.run(f(*args, **kwargs))
  File "/home/hyunsik/.local/anaconda3/envs/furiosa-models/lib/python3.9/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/home/hyunsik/.local/anaconda3/envs/furiosa-models/lib/python3.9/asyncio/base_events.py", line 647, in run_until_complete
    return future.result()
  File "/home/hyunsik/.local/anaconda3/envs/furiosa-models/lib/python3.9/site-packages/furiosa/models/utils.py", line 141, in load_artifacts
    artifacts[ext] = await resolve_file(name, ext).read()
  File "/home/hyunsik/.local/anaconda3/envs/furiosa-models/lib/python3.9/site-packages/furiosa/models/utils.py", line 99, in read
    raise e
  File "/home/hyunsik/.local/anaconda3/envs/furiosa-models/lib/python3.9/site-packages/furiosa/models/utils.py", line 92, in read
    str(self.uri.relative_to(Path.cwd())),
  File "/home/hyunsik/.local/anaconda3/envs/furiosa-models/lib/python3.9/pathlib.py", line 939, in relative_to
    raise ValueError("{!r} is not in the subpath of {!r}"
ValueError: '/home/hyunsik/.local/anaconda3/envs/furiosa-models/lib/python3.9/site-packages/furiosa/models/data/mlcommons_ssd_resnet34_int8.onnx' is not in the subpath of '/home/hyunsik/Code/furiosa-models-2' OR one path is relative and the other is absolute.

CLI Scale-UP 구조 개선

소개

CLI Main에 모든 모델을 커버하는 옵션 설계를, 모델별 Visitor Pattern(?)으로 설계하여 scale-up을 만드는 것이 목적입니다.

사용 예시

furiosa-models resnet help
furiosa-models ssd-mobilenet help
furiosa-models yolov5 inference snap --model-type=enf --input test.jpg
furiosa-models yolov5 inference stream --model-type=enf --input test.avi
furiosa-models opengpt-3 run model-speicified options
furiosa-models opengpt-3 test --input textfile model-speicified options

역할 정의:

  1. CLI Main에서는 기본적인 분기 처리만 담당. 개개의 모델의 cli 모듈은 기초적인 metadata 제공.
  2. 모델의 의존적인 세세한 옵션 검증, 파싱 및 처리는 모델 모듈에서 처리(역할 위임).

관련 PR

#28

compiler config should be loaded from dvc instead of using python dict

  • 기존에는 소스 코드에 dict로 compiler config를 포함하고 있음
  • dfg, enf 생성을 위해 yaml 파일 기반의 compiler config를 어차피 repository에 포함해야 함
  • compiler config가 중복이 되므로 dvc에 compiler config를 넣어 dfg, enf 생성에도 사용하고 동적으로 source로 부터 컴파일 해야 하는 상황에서도 활용 하도록 개선 필요

Add benchmark

해당 프로젝트의 주 목적 중 하나가 성능을 보여주는 것이므로 사용자도 쉽게 벤치마크를 돌려 성능을 확인할 수 있으면 좋겠습니다. 개발 과정에 있어서도 python에서 처리하는 전/후처리와 rust의 전/후처리를 비교하는 과정이 있으면 좋을 것 같습니다.

http://pytest-benchmark.readthedocs.org/en/stable/

pytest-benchmark를 이용하면 기존의 pytest를 활용해서 쉽게 벤치마크를 만들 수 있을 것 같습니다.

CI task `test examples` fails but marked as success

From log
https://tekton.office.furiosa.in/#/namespaces/ci-furiosa-models/pipelineruns/pr-102-cc6907581a-7dwnh-r-6m774?pipelineTask=test-examples&step=run

[TEST] docs/examples/ssd_mobilenet_native.py ...
INFO:furiosa.common.native:loaded native library [libnux.so](http://libnux.so/) (0.8.0 d9f0d7728)
INFO:furiosa.common.native:loaded native library [libnux.so](http://libnux.so/) (0.8.0 d9f0d7728)
INFO:furiosa.common.native:loaded native library [libnux.so](http://libnux.so/) (0.8.0 d9f0d7728)
Traceback (most recent call last):
  File "/workspace/source/docs/examples/ssd_mobilenet_native.py", line 6, in <module>
    mobilenet = SSDMobileNet.load(use_native=True)
  File "/usr/local/lib/python3.9/dist-packages/furiosa/models/types.py", line 81, in load
    return cls.load_aux(synchronous(load_artifacts)(artifact_name), use_native, *args, **kwargs)
  File "/usr/local/lib/python3.9/dist-packages/furiosa/models/vision/ssd_mobilenet/__init__.py", line 331, in load_aux
    postprocessor = get_field_default(cls, "postprocessor_map")[postproc_type](dfg)
  File "/usr/local/lib/python3.9/dist-packages/furiosa/models/vision/ssd_mobilenet/__init__.py", line 276, in __init__
    self._native = native.ssd_mobilenet.CppPostProcessor(dfg)
AttributeError: module 'ssd_mobilenet' has no attribute 'CppPostProcessor'

One or more tasks has failed but the CI overall has succeeded.

Make base class for YOLOv5

YOLOv5 medium과 large에 duplicated된 코드들이 많은데 Base class를 만들어서 줄이면 좋을 것 같습니다.

Common utility functions to be implemented

Model Zoo에서 러스트로 구현할 유틸리티 함수들

Image

  • Image opening?
  • Center crop
  • Zero-pad extension
  • Color <-> grayscale conversion
  • Image patch slicer/weaver (w/ padding?)
    ...

Postprocessing

  • nms
    ...

Passing compiler config `remove_unlower` to enf for truncated models harms accuracy

ENF 생성 시 remove_unlower 옵션을 주었을 때 올바르게 동작하지 않는 현상이 있었습니다. (#16)

ssd-small model의 경우 (truncated model)

 Average Precision  (AP) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.000
 Average Precision  (AP) @[ IoU=0.50      | area=   all | maxDets=100 ] = 0.000
 Average Precision  (AP) @[ IoU=0.75      | area=   all | maxDets=100 ] = 0.000
 Average Precision  (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.000
 Average Precision  (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.000
 Average Precision  (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.000
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=  1 ] = 0.000
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets= 10 ] = 0.002
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.037
 Average Recall     (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.000
 Average Recall     (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.011
 Average Recall     (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.083
mAP: 1.8134108678906026e-05
F

target accuracy는 0.22808056885213657 이어야 합니다.

PyO3과련 기존 레이아웃 변경 Rollback 논의: python/furiosa/models --> furiosa/models

@furiosamg 님, @hyunsik 님,

제가 테스트 해본 결과
기존 레이아웃 방식이 잘 진행되고 테스트도 잘 되었습니다.
예를들면, furiosa.init.py 를 생성하지 않아도 됩니다.

PyO3 문서에 따르면(https://maturin.rs/project_layout.html#alternate-python-source-directory-src-layout)가 python 폴더를 만들라는 것도 아닌 듯합니다.

[package]
name = "furiosa-models"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "furiosa_models_native"
crate-type = ["cdylib"]

# https://maturin.rs/project_layout.html#alternate-python-source-directory-src-layout
[package.metadata.maturin]
python-source = "furiosa/models"
name = "furiosa.models.furiosa_models_native"

[dependencies]
pyo3 = { version = "0.16.5", features = ["extension-module"] }

Test code

pip install -e .

from furiosa.models import sum_as_string
sum_as_string(1,2)

Originally posted by @hyeokjunejeon in #10 (comment)

Editable installation has problems

After installing the current package in editable mode, other furiosa packages (e.g, furiosa-common, furiosa-registry) are not able to be imported.

Scale-Up을 위한 Model URI와 코드가 분산된 문제되어 혼선이 발생하는 해결 방안 필요

소개

모델 읽는 파트와 코드가 연결 고리를 짓기가 어려운 개선이 필요해 보입니다. 예를들면 model 경로는 어디에서 갱신해야지? 이 모델의 관련 코드는 어디에 있지? 혼선이 계속 발생합니다.
이 혼선을 막기위해서 추가 적인 별도 wiki 관리 문서를 유지해야 되는 유지보수 어려움이 발생합니다. 이 방식은 scale-up을 할 수 없을 듯 합니다.

예상되는 수정 스텝을 보면 다음과 같습니다:

  • resnet50.py 수정
  • init.py 수정
  • wiki 테이블 수정
    • md5 해시
    • 모델 위치 테이블 작성

내용

ResNet50 작동 코드

# f.m.v.resnet50.py
class MLCommonsResNet50Model(Model):
    """MLCommons ResNet50 model"""
    pass

ResNet50 모델 읽는 파트

# f.m.v.nonblocking.__init__.py
async def ResNet50(*args: Any, **kwargs: Any) -> resnet50.MLCommonsResNet50Model:
    return resnet50.MLCommonsResNet50Model(
        name="ResNet50",
        model=await load_dvc("models/mlcommons_resnet50_v1.5_int8.onnx"),
        format=Format.ONNX,
        family="ResNet",
        version="v1.5",
        metadata=Metadata(
            description="ResNet50 v1.5 int8 ImageNet-1K Accuracy 75.982% @ Top1",
            publication=Publication(url="https://arxiv.org/abs/1512.03385.pdf"),
        ),
        *args,
        **kwargs,
    )

CI 시간 단축

현재 lint 및 build만에도 20분정도 소요되는데요. 로그를 살펴보면 clippy가 9분 내외, pip install 하는데 10분 내외 걸립니다. 두가지 스텝을 분리하고 병렬로 돌려도 되기 때문에 우선 절반으로 줄일 수 있을듯 합니다. pip 쪽 dependency는 정리하면 좋을것 같고요, clippy는 mlperf-postprocess에서 protobuf build하는게 오래걸리는것 같은데요. 조금더 살펴보려고 합니다.

Originally posted by @sukyoungjeong-furiosa in #41 (comment)

Add an environment variable to force models to use a local file

Motivation

DVC에 업로드 전에 로컬에 생성된 enf, dfg가 잘 동작하는지 테스트가 필요하다. 그러나 현재 구현은 반드시 DVC를 통해서만 파일을 접근할 수 있음

Solution

  • 특정 환경 변수 (예: USE_LOCAL_ARTIFACTS) 가 주어지면 dvc 대신에 대응되는 로컬파일을 읽어서 동작하도록 기능 추가
  • 파일이 없을 경우에는 에러 발생

should expected color order of preprocess be rgb?

이번 릴리즈는 아니고 다음 릴리즈에서 진행하면 좋을 것 같은데요.

color order 도 사소하지만 신경 쓰이는 부분이네요. model zoo의 모델들 자체는 RGB를 예상 order 로 하고 있군요. 그리고 preprocess 에서는 BGR을 받아서 RGB로 변환하는 로직들이 포함되어 있네요. yolov5의 preprocess는 옵션으로 color order가 제공되지만 궁극적으로는 RGB로 변환하는 내용이군요.

preprocess의 입력 color order를 아예 RGB로 하면 변환 부분을 뺄 수 있을 것 같은데요. 혹시 어떻게 생각하시는지요? 각 preprocess 마다 변환 로직을 가지고 있기 보다는 preprocess에서는 모델의 color order와 동일하게 가져가고 API doc에서 expected color order와 사용할 image util 함수 이름을 써주는게 더 좋을 것 같습니다.

artifacts cache 기능 구현

요구 사항

  • 사용자가 한번 download 받은 aritfacts는 local cache를 이용하도록 개선 필요
  • ~/.cache/furiosa/models 디렉토리에 cache 저장

ModuleNotFoundError in other locations

$ maturin develop
# blah blah
🛠  Installed furiosa-models-0.0.1
(models) root@mg-shin-npu-0:~/furiosa-models-experimental# python -c "import furiosa.models"
(models) root@mg-shin-npu-0:~/furiosa-models-experimental# cd ..
(models) root@mg-shin-npu-0:~# python -c "import furiosa.models"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'furiosa.models'

git root directory가 아닌 곳에서 module을 import할 수 없는 것 같습니다. (maturin develop, pip install . 모두 안됩니다 ㅜㅜ)
CLI 지원을 위해서도 우선순위가 좀 있는 것 같습니다.

Add how to download the datasets to the document

  • Dataset에 대한 문서 추가 필요
  • Dataset 종류별 다운 로드 방법 및 설명 추가
  • 각 모델 마다 Dataset 문서 링크
  • 장기적으로는 Dataset downloader까지 개발하여 우리가 제시하는 일관된 커맨드로 Dataset 다운로드와 model zoo client 를 통한 실행까지 instruction 으로 제공

Model Zoo CLI/Client 설계 및 개발

@furiosamg 님이 진행 중이신 Model Zoo CLI/Client 의 진행을 추적하고 요구사항 등을 정리하기 위해 이슈를 만듭니다. 업데이트가 있을 때 이곳에 코멘트로 남겨주시면 감사하겠습니다.

이미지 로딩 단계를 별도 유틸이나 클래스로 분리

Motivation

  • 현재는 preprocess 단계에서 IO를 통해 파일로 된 이미지를 읽고 있음
  • end-to-end 실행 시 IO가 포함되어 성능 evaluation 결과가 왜곡 될 수 있음

Solution

  • 이미지와 관련 메타데이터를 미리 로딩하여 메모리에 유지하는 기능 제공
  • Optional 하게 preprocess 단계까지 완료된 결과를 메모리에 유지하는 기능도 제공
    • 카메라 등 HW로 raw 이미지를 바로 얻을 수 있는 사용자가 성능을 평가할 때 적절히 사용될 수 있음

Prune unused packages in pyproject.toml

현재 무거우면서 사용하지 않는 package를 의존성으로 가지고 있습니다. 관련 패키지들의 의존성을 정리할 필요가 있는 듯 합니다.

dependencies = [
"furiosa-common == 0.8.*",
"furiosa-registry == 0.8.*",
"furiosa-runtime == 0.8.*",
"onnx",
"onnxruntime",
"opencv-python-headless",
"pycocotools",
"timm",
"torch",
"torchvision",
"dvc[s3]",
"pydantic",
# Protobuf major version change issue: https://github.com/furiosa-ai/furiosa-artifacts/issues/23
"protobuf < 4.0dev",
"segmentation_models_pytorch",
"pretrainedmodels",
"effdet",
"cbox_decode @ git+https://github.com/furiosa-ai/furiosa-artifacts.git#subdirectory=furiosa/models/vision/yolov5/box_decode/cbox_decode"
]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.