Save data for current step using streaming Arrow format
(self, id_cnt, token_id, prob, label)
| 178 | return id_cnt_list, token_id_list, prob_list |
| 179 | |
| 180 | def _save_step_data(self, id_cnt, token_id, prob, label): |
| 181 | """Save data for current step using streaming Arrow format""" |
| 182 | # Convert id_cnt to tensor for gathering |
| 183 | id_cnt_tensor = torch.tensor(id_cnt, device=self.device) |
| 184 | |
| 185 | # Step 1: Gather id_cnt and label first |
| 186 | id_cnt_gathered = self.accelerator.gather_for_metrics(id_cnt_tensor) |
| 187 | label_gathered = self.accelerator.gather_for_metrics(label) |
| 188 | |
| 189 | # Step 2: Get the largest value of id_cnt from gathered tensor |
| 190 | max_tokens_global = torch.max(id_cnt_gathered).item() |
| 191 | |
| 192 | # Step 3: Pad the original token_id and prob lists to the largest id_cnt |
| 193 | batch_size = id_cnt_tensor.shape[0] |
| 194 | token_id_padded = torch.full((batch_size, max_tokens_global), -1, dtype=torch.long, device=self.device) |
| 195 | prob_padded = torch.zeros((batch_size, max_tokens_global), dtype=torch.float16, device=self.device) |
| 196 | |
| 197 | for i in range(batch_size): |
| 198 | valid_count = id_cnt[i] |
| 199 | current_token_id = token_id[i] |
| 200 | current_prob = prob[i] |
| 201 | |
| 202 | # For the last batch, there may be list longer than max_tokens_global since there are some remainder. Truncate them ! |
| 203 | if current_token_id.shape[0] > max_tokens_global: |
| 204 | logger.debug(f"Truncating token_id and prob for batch {i} from {current_token_id.shape[0]} to {max_tokens_global}") |
| 205 | valid_count = max_tokens_global |
| 206 | current_token_id = current_token_id[:max_tokens_global] |
| 207 | current_prob = current_prob[:max_tokens_global] |
| 208 | |
| 209 | token_id_padded[i, :valid_count] = current_token_id |
| 210 | prob_padded[i, :valid_count] = current_prob |
| 211 | |
| 212 | # Step 4: Gather token_id_tensor and prob_tensor |
| 213 | token_id_gathered_padded = self.accelerator.gather_for_metrics(token_id_padded) |
| 214 | prob_gathered_padded = self.accelerator.gather_for_metrics(prob_padded) |
| 215 | |
| 216 | # Step 5: Unpad the result token_id_tensor and prob_tensor to original length list |
| 217 | total_batch_size = id_cnt_gathered.shape[0] |
| 218 | token_id_gathered = [] |
| 219 | prob_gathered = [] |
| 220 | |
| 221 | for i in range(total_batch_size): |
| 222 | valid_count = id_cnt_gathered[i].item() |
| 223 | token_id_gathered.append(token_id_gathered_padded[i, :valid_count].cpu().numpy()) |
| 224 | prob_gathered.append(prob_gathered_padded[i, :valid_count].cpu().numpy()) |
| 225 | |
| 226 | # Only main process writes to file |
| 227 | if self.process_index == 0: |
| 228 | id_cnt_np = id_cnt_gathered.cpu().numpy() |
| 229 | label_np = label_gathered.cpu().numpy() |
| 230 | |
| 231 | logger.info(f"id_cnt_np shape: {id_cnt_np.shape} ; token_id_gathered length: {len(token_id_gathered)}; prob_gathered length: {len(prob_gathered)}; label_np shape: {label_np.shape}") |
| 232 | |
| 233 | # Create Arrow arrays |
| 234 | id_cnt_array = pa.array(id_cnt_np, type=pa.int32()) |
| 235 | token_id_array = pa.array(token_id_gathered, type=pa.list_(pa.int32())) |
| 236 | prob_array = pa.array(prob_gathered, type=pa.list_(pa.float16())) |
| 237 | label_array = pa.array(label_np, type=pa.int32()) |