已合并
【bugfix】修复目前比对DataFrame赋值导致内存占用过高程序崩溃问题 #260
louyujing创建于 1月8日
【bugfix】修复目前比对DataFrame赋值导致内存占用过高程序崩溃问题 #260
已合并
共 1 个文件变更+27-10
| @@ -115,13 +115,14 @@ class ApiIndicatorCalculator: | |||
| 115 | self.add_algorithm(checker()) | 115 | self.add_algorithm(checker()) |
| 116 | 116 | ||
| 117 | 117 | ||
| 118 | -def calculate_excel_result_df(result_df, mode): | 118 | +def calculate_excel_result_df(result_df, mode, chunk_size=1000): |
| 119 | """ | 119 | """ |
| 120 | 仅适用于excel比对场景,得到表格每行数据的精度比对指标(pass/warning/error) | 120 | 仅适用于excel比对场景,得到表格每行数据的精度比对指标(pass/warning/error) |
| 121 | 121 | ||
| 122 | Args: | 122 | Args: |
| 123 | result_df: DataFrame数据结构,即转换成excel前的表单结构 | 123 | result_df: DataFrame数据结构,即转换成excel前的表单结构 |
| 124 | mode: 比对模式,分为 tensor 模式、统计量模式和 md5 模式 | 124 | mode: 比对模式,分为 tensor 模式、统计量模式和 md5 模式 |
| 125 | + chunk_size: 分块赋值参数,默认1000,把 result 分成小块,逐块赋值给 result_df,这样每次只占用小块内存,避免内存峰值过高 | ||
| 125 | """ | 126 | """ |
| 126 | result_dict = divide_result_df(result_df) | 127 | result_dict = divide_result_df(result_df) |
| 127 | calculator = ApiIndicatorCalculator(mode) | 128 | calculator = ApiIndicatorCalculator(mode) |
| @@ -130,15 +131,31 @@ def calculate_excel_result_df(result_df, mode): | |||
| 130 | calculator.calculate(data_lists) | 131 | calculator.calculate(data_lists) |
| 131 | calculated_result_lists.extend(data_lists) | 132 | calculated_result_lists.extend(data_lists) |
| 132 | 133 | ||
| 133 | - # 将列表中的列表元素转换为str,避免list转换为ndarray报错 | 134 | + head = CompareConst.HEAD_OF_COMPARE_MODE.get(mode) |
| 134 | - # 可以使用一行列表推导式实现,但会被codecheck拦截(推导式和生成器表达式仅用于简单的逻辑表达) | 135 | + if not head: |
| 135 | - result = [] | 136 | + logger.error(f'Unable to obtain header based on compare mode: {mode}') |
| 136 | - for sublist in calculated_result_lists: | 137 | + raise RuntimeError() |
| 137 | - processed_sublist = [] | 138 | + # 配置列映射关系:[(result_df的目标列名, result子列表的列索引)] |
| 138 | - for item in sublist: | 139 | + try: |
| 139 | - processed_sublist.append(json.dumps(item)) if isinstance(item, list) else processed_sublist.append(item) | 140 | + cols_mapping = [ |
| 140 | - result.append(processed_sublist) | 141 | + (CompareConst.RESULT, head.index(CompareConst.RESULT)), |
| 141 | - result_df[:] = result | 142 | + (CompareConst.ERROR_MESSAGE, head.index(CompareConst.ERROR_MESSAGE)) |
| 143 | + ] | ||
| 144 | + except ValueError as e: | ||
| 145 | + logger.error(f'The {CompareConst.RESULT} or {CompareConst.ERROR_MESSAGE} does not exist in the header: {e}') | ||
| 146 | + raise e | ||
| 147 | + | ||
| 148 | + total_rows = len(calculated_result_lists) | ||
| 149 | + | ||
| 150 | + # 分块逐批赋值,降低内存瞬时峰值 | ||
| 151 | + for i in range(0, total_rows, chunk_size): | ||
| 152 | + end_idx = min(i + chunk_size, total_rows) | ||
| 153 | + current_result_chunk = calculated_result_lists[i:end_idx] | ||
| 154 | + | ||
| 155 | + for df_col_name, result_col_idx in cols_mapping: | ||
| 156 | + col_data = [sublist[result_col_idx] for sublist in current_result_chunk] | ||
| 157 | + df_col_idx = result_df.columns.get_loc(df_col_name) | ||
| 158 | + result_df.iloc[i:end_idx, df_col_idx] = col_data | ||
| 142 | 159 | ||
| 143 | 160 | ||
| 144 | def calculate_result(result, mode): | 161 | def calculate_result(result, mode): |