예제 #1
0
def get_perf_profiles(project_id: str):
    """
    Route for getting a list of project perf profiles filtered by the flask request args
    Raises an HTTPNotFoundError if the project is not found in the database.

    :param project_id: the id of the project to get the perf profiles for
    :return: a tuple containing (json response, http status code)
    """
    _LOGGER.info("getting perf profiles for project {} ".format(project_id))

    get_project_by_id(project_id)  # validate id

    args = SearchProjectProfilesSchema().load(
        {key: val
         for key, val in request.args.items()})
    perf_profiles_query = (ProjectPerfProfile.select().where(
        ProjectPerfProfile.project_id == project_id).order_by(
            ProjectPerfProfile.created).paginate(args["page"],
                                                 args["page_length"]))
    perf_profiles = [res for res in perf_profiles_query]

    resp_profiles = data_dump_and_validation(
        ResponseProjectPerfProfilesSchema(), {"profiles": perf_profiles})
    _LOGGER.info("retrieved {} profiles".format(len(perf_profiles)))

    return jsonify(resp_profiles), HTTPStatus.OK.value
예제 #2
0
def upload_perf_profile(project_id: str):
    """
    Route for creating a new perf profile for a given project from uploaded data.
    Raises an HTTPNotFoundError if the project is not found in the database.

    :param project_id: the id of the project to create a perf profile for
    :return: a tuple containing (json response, http status code)
    """
    _LOGGER.info("uploading perf profile for project {}".format(project_id))

    project = get_project_by_id(project_id)  # validate id

    if "perf_file" not in request.files:
        _LOGGER.error("missing uploaded file 'perf_file'")
        raise ValidationError("missing uploaded file 'perf_file'")

    # read perf analysis file
    try:
        perf_analysis = json.load(request.files["perf_file"])
    except Exception as err:
        _LOGGER.error(
            "error while reading uploaded perf analysis file: {}".format(err))
        raise ValidationError(
            "error while reading uploaded perf analysis file: {}".format(err))

    # override or default potential previous data fields
    perf_analysis_args = CreateProjectPerfProfileSchema().load(perf_analysis)
    perf_analysis.update(perf_analysis_args)
    perf_analysis["profile_id"] = "<none>"
    perf_analysis["project_id"] = "<none>"
    perf_analysis["created"] = datetime.datetime.now()
    perf_analysis["source"] = "uploaded"
    perf_analysis["job"] = None

    perf_analysis = data_dump_and_validation(ProjectPerfProfileSchema(),
                                             perf_analysis)
    del perf_analysis["profile_id"]  # delete to create a new one on DB insert
    del perf_analysis[
        "project_id"]  # delete because project is passed in on DB insert

    model = project.model
    if model is None:
        raise ValidationError(
            ("A model has not been set for the project with id {}, "
             "project must set a model before running a perf profile."
             ).format(project_id))

    perf_profile = ProjectPerfProfile.create(project=project, **perf_analysis)

    resp_profile = data_dump_and_validation(ResponseProjectPerfProfileSchema(),
                                            {"profile": perf_profile})
    _LOGGER.info("created perf profile: id: {}, name: {}".format(
        resp_profile["profile"]["profile_id"],
        resp_profile["profile"]["name"]))

    return jsonify(resp_profile), HTTPStatus.OK.value
예제 #3
0
    def _get_project_perf_profile(self) -> ProjectPerfProfile:
        perf_profile = ProjectPerfProfile.get_or_none(
            ProjectPerfProfile.profile_id == self._profile_id)

        if perf_profile is None:
            raise ValueError(
                "ProjectPerfProfile with profile_id {} was not found".format(
                    self._profile_id))

        return perf_profile
예제 #4
0
def delete_perf_profile(project_id: str, profile_id: str):
    """
    Route for deleting a specific perf profile for a given project.
    Raises an HTTPNotFoundError if the project or perf profile are
    not found in the database.

    :param project_id: the id of the project to delete the perf profile for
    :param profile_id: the id of the perf profile to delete
    :return: a tuple containing (json response, http status code)
    """
    _LOGGER.info("deleting perf profile for project {} with id {}".format(
        project_id, profile_id))

    get_project_by_id(project_id)  # validate id

    # search for perf profile and verify that project_id matches
    perf_profile = ProjectPerfProfile.get_or_none(
        ProjectPerfProfile.profile_id == profile_id,
        ProjectPerfProfile.project_id == project_id,
    )

    if perf_profile is None:
        _LOGGER.error(
            "could not find perf profile with profile_id {} and project_id {}".
            format(profile_id, project_id))
        raise HTTPNotFoundError(
            "could not find perf profile with profile_id {} and project_id {}".
            format(profile_id, project_id))

    perf_profile.delete_instance()

    resp_del = data_dump_and_validation(
        ResponseProjectProfileDeletedSchema(),
        {
            "success": True,
            "project_id": project_id,
            "profile_id": profile_id
        },
    )
    _LOGGER.info(
        "deleted perf profile with profile_id {} and project_id: {}".format(
            profile_id, project_id))

    return jsonify(resp_del), HTTPStatus.OK.value
def get_profiles_by_id(
    profile_perf_id: Union[None, str], profile_loss_id: Union[None, str]
) -> Tuple[ProjectPerfProfile, ProjectLossProfile]:
    """
    Get a performance and loss profile by their ids.
    If not found will return None instead of raising not found.

    :param profile_perf_id: id of the performance profile to get
    :param profile_loss_id: id of the loss profile to get
    :return: tuple containing (performance profile, loss profile)
    """
    profile_perf = (ProjectPerfProfile.get_or_none(
        ProjectPerfProfile.profile_id == profile_perf_id)
                    if profile_perf_id else None)
    profile_loss = (ProjectLossProfile.get_or_none(
        ProjectLossProfile.profile_id == profile_loss_id)
                    if profile_loss_id else None)

    return profile_perf, profile_loss
예제 #6
0
def create_perf_profile(project_id: str):
    """
    Route for creating a new perf profile for a given project.
    Raises an HTTPNotFoundError if the project is not found in the database.

    :param project_id: the id of the project to create a perf profile for
    :return: a tuple containing (json response, http status code)
    """
    _LOGGER.info(
        "creating perf profile for project {} for request json {}".format(
            project_id, request.json))
    project = get_project_by_id(project_id)

    perf_profile_params = CreateProjectPerfProfileSchema().load(
        request.get_json(force=True))
    sys_info = get_ml_sys_info()

    if not perf_profile_params[
            "core_count"] or perf_profile_params["core_count"] < 1:
        perf_profile_params["core_count"] = sys_info["cores_per_socket"]

    if not perf_profile_params["core_count"]:
        # extra check in case the system couldn't get cores_per_socket
        perf_profile_params["core_count"] = -1

    perf_profile_params["instruction_sets"] = sys_info[
        "available_instructions"]

    model = project.model
    if model is None:
        raise ValidationError(
            ("A model is has not been set for the project with id {}, "
             "project must set a model before running a perf profile."
             ).format(project_id))
    perf_profile = None
    job = None

    try:
        perf_profile = ProjectPerfProfile.create(project=project,
                                                 source="generated",
                                                 **perf_profile_params)
        job = Job.create(
            project_id=project_id,
            type_=CreatePerfProfileJobWorker.get_type(),
            worker_args=CreatePerfProfileJobWorker.format_args(
                model_id=model.model_id,
                profile_id=perf_profile.profile_id,
                batch_size=perf_profile_params["batch_size"],
                core_count=perf_profile_params["core_count"],
                pruning_estimations=perf_profile_params["pruning_estimations"],
                quantized_estimations=perf_profile_params[
                    "quantized_estimations"],
                iterations_per_check=perf_profile_params[
                    "iterations_per_check"],
                warmup_iterations_per_check=perf_profile_params[
                    "warmup_iterations_per_check"],
            ),
        )
        perf_profile.job = job
        perf_profile.save()
    except Exception as err:
        _LOGGER.error(
            "error while creating new perf profile, rolling back: {}".format(
                err))
        if perf_profile:
            try:
                perf_profile.delete_instance()
            except Exception as rollback_err:
                _LOGGER.error(
                    "error while rolling back new perf profile: {}".format(
                        rollback_err))
        if job:
            try:
                job.delete_instance()
            except Exception as rollback_err:
                _LOGGER.error(
                    "error while rolling back new perf profile: {}".format(
                        rollback_err))
        raise err

    # call into JobWorkerManager to kick off job if it's not already running
    JobWorkerManager().refresh()

    resp_profile = data_dump_and_validation(ResponseProjectPerfProfileSchema(),
                                            {"profile": perf_profile})
    _LOGGER.info("created perf profile and job: {}".format(resp_profile))

    return jsonify(resp_profile), HTTPStatus.OK.value