deepspeedai / deepspeedai/DeepSpeed

[BUG] ZeRO Stage 3 is consuming more memory than Stage 2 when using DeepSpeed-Chat

Open
#4,305 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug compression
Dominant language
Python
Stars
43.1k
Forks
5k
Avg merge
4d 15h
Merged PRs (30d)
112

Description

Describe the bug

When using DeepSpeed-Chat, ZeRO Stage 3 appears to consume more memory than Stage 2. While fine-tuning the Pythia-6.9b model with a context length of approximately 1200 and a LoRA_rank of 128, I observed the following memory behavior:

After deepspeed.initialize:
Stage 2: 16.6 GB
Stage 3: 6.6 GB

Immediately after the first forward pass:
Stage 2: 32.4 GB
Stage 3: 36.6 GB

This indicates a noticeable increase in memory consumption for Stage 3 compared to Stage 2 during the forward pass.

To Reproduce
Steps to reproduce the behavior:
Excuting DeepSpeed-Chat (supervised finetuning) with Pythia-6.9b, LoRA_rank=128

Expected behavior
Stage 3 is supposed to consume less memory than Stage 2

System info (please complete the following information):

  • OS: NAME=20.04.5 LTS (Focal Fossa)
  • GPU count and types = 4*RTX6000
  • Python version = 3.10
  • DeepSpeed = 0.10.2

Launcher context
deepspeed.launcher.launch

Full log

2 Time to load fused_adam op: 0.5769875049591064 seconds
3 [2023-09-12 00:26:08,683] [INFO] [logging.py:96:log_dist] [Rank 0] DeepSpeed info: version=0.10.2, git-hash=unknown, git-branch=unknown
4 [2023-09-12 00:26:08,683] [INFO] [comm.py:662:init_distributed] Distributed backend already initialized
5 [2023-09-12 00:26:08,874] [INFO] [logging.py:96:log_dist] [Rank 0] DeepSpeed Flops Profiler Enabled: False
6 [2023-09-12 00:26:08,908] [INFO] [logging.py:96:log_dist] [Rank 0] Removing param_group that has no 'params' in the client Optimizer
7 [2023-09-12 00:26:08,909] [INFO] [logging.py:96:log_dist] [Rank 0] Using client Optimizer as basic optimizer
8 [2023-09-12 00:26:08,983] [INFO] [logging.py:96:log_dist] [Rank 0] DeepSpeed Basic Optimizer = FusedAdam
9 [2023-09-12 00:26:08,983] [INFO] [utils.py:54:is_zero_supported_optimizer] Checking ZeRO support for optimizer=FusedAdam type=<class 'deepspeed.ops.adam.fused_adam.FusedAdam'>
10 [2023-09-12 00:26:08,983] [INFO] [logging.py:96:log_dist] [Rank 0] Creating fp16 ZeRO stage 3 optimizer, MiCS is enabled False, Hierarchical params gather False
11 [2023-09-12 00:26:08,984] [INFO] [logging.py:96:log_dist] [Rank 0] Creating torch.float16 ZeRO stage 3 optimizer
12 [2023-09-12 00:26:09,304] [INFO] [utils.py:803:see_memory_usage] Stage 3 initialize beginning
13 [2023-09-12 00:26:09,307] [INFO] [utils.py:804:see_memory_usage] MA 4.03 GB Max_MA 4.39 GB CA 6.77 GB Max_CA 7 GB
14 [2023-09-12 00:26:09,308] [INFO] [utils.py:811:see_memory_usage] CPU Virtual Memory: used = 45.66 GB, percent = 11.6%
15 [2023-09-12 00:26:09,316] [INFO] [stage3.py:126:init] Reduce bucket size 500,000,000
16 [2023-09-12 00:26:09,316] [INFO] [stage3.py:127:init] Prefetch bucket size 30000000
17 Using /home/ubuntu/.cache/torch_extensions/py310_cu118 as PyTorch extensions root...
18 Detected CUDA files, patching ldflags
19 Emitting ninja build file /home/ubuntu/.cache/torch_extensions/py310_cu118/fused_adam/build.ninja...
20 Building extension module fused_adam...
21 Allowing ninja to set a default number of workers... (overridable by setting the environment variable MAX_JOBS=N)
22 Loading extension module fused_adam...
23 [2023-09-12 00:26:09,668] [INFO] [utils.py:803:see_memory_usage] DeepSpeedZeRoOffload initialize [begin]
24 [2023-09-12 00:26:09,670] [INFO] [utils.py:804:see_memory_usage] MA 4.03 GB Max_MA 4.03 GB CA 6.77 GB Max_CA 7 GB
25 [2023-09-12 00:26:09,671] [INFO] [utils.py:811:see_memory_usage] CPU Virtual Memory: used = 45.66 GB, percent = 11.6%
26 Parameter Offload: Total persistent parameters: 794624 in 194 params
27 [2023-09-12 00:26:10,345] [INFO] [utils.py:803:see_memory_usage] DeepSpeedZeRoOffload initialize [end]
28 [2023-09-12 00:26:10,348] [INFO] [utils.py:804:see_memory_usage] MA 3.65 GB Max_MA 4.03 GB CA 6.77 GB Max_CA 7 GB
29 [2023-09-12 00:26:10,348] [INFO] [utils.py:811:see_memory_usage] CPU Virtual Memory: used = 45.67 GB, percent = 11.6%
30 [2023-09-12 00:26:10,667] [INFO] [utils.py:803:see_memory_usage] Before creating fp16 partitions
31 [2023-09-12 00:26:10,669] [INFO] [utils.py:804:see_memory_usage] MA 3.65 GB Max_MA 3.65 GB CA 6.77 GB Max_CA 7 GB
32 [2023-09-12 00:26:10,670] [INFO] [utils.py:811:see_memory_usage] CPU Virtual Memory: used = 45.67 GB, percent = 11.6%
33 [2023-09-12 00:26:11,405] [INFO] [utils.py:803:see_memory_usage] After creating fp16 partitions: 1
34 [2023-09-12 00:26:11,408] [INFO] [utils.py:804:see_memory_usage] MA 3.65 GB Max_MA 3.65 GB CA 3.92 GB Max_CA 7 GB
35 [2023-09-12 00:26:11,408] [INFO] [utils.py:811:see_memory_usage] CPU Virtual Memory: used = 45.68 GB, percent = 11.6%
36 [2023-09-12 00:26:11,700] [INFO] [utils.py:803:see_memory_usage] Before creating fp32 partitions
37 [2023-09-12 00:26:11,702] [INFO] [utils.py:804:see_memory_usage] MA 3.65 GB Max_MA 3.65 GB CA 3.92 GB Max_CA 4 GB
38 [2023-09-12 00:26:11,702] [INFO] [utils.py:811:see_memory_usage] CPU Virtual Memory: used = 45.68 GB, percent = 11.6%
39 [2023-09-12 00:26:11,996] [INFO] [utils.py:803:see_memory_usage] After creating fp32 partitions
40 [2023-09-12 00:26:11,999] [INFO] [utils.py:804:see_memory_usage] MA 3.9 GB Max_MA 4.03 GB CA 4.3 GB Max_CA 4 GB
41 [2023-09-12 00:26:11,999] [INFO] [utils.py:811:see_memory_usage] CPU Virtual Memory: used = 45.68 GB, percent = 11.6%
42 [2023-09-12 00:26:12,291] [INFO] [utils.py:803:see_memory_usage] Before initializing optimizer states
43 [2023-09-12 00:26:12,294] [INFO] [utils.py:804:see_memory_usage] MA 3.9 GB Max_MA 3.9 GB CA 4.3 GB Max_CA 4 GB
44 [2023-09-12 00:26:12,295] [INFO] [utils.py:811:see_memory_usage] CPU Virtual Memory: used = 45.68 GB, percent = 11.6%
45 [2023-09-12 00:26:12,590] [INFO] [utils.py:803:see_memory_usage] After initializing optimizer states
46 [2023-09-12 00:26:12,592] [INFO] [utils.py:804:see_memory_usage] MA 4.4 GB Max_MA 4.65 GB CA 5.05 GB Max_CA 5 GB
47 [2023-09-12 00:26:12,593] [INFO] [utils.py:811:see_memory_usage] CPU Virtual Memory: used = 45.68 GB, percent = 11.6%
48 [2023-09-12 00:26:12,594] [INFO] [stage3.py:445:_setup_for_real_optimizer] optimizer state initialized
49 [2023-09-12 00:26:13,108] [INFO] [utils.py:803:see_memory_usage] After initializing ZeRO optimizer
50 [2023-09-12 00:26:13,111] [INFO] [utils.py:804:see_memory_usage] MA 5.46 GB Max_MA 5.47 GB CA 5.98 GB Max_CA 6 GB
51 [2023-09-12 00:26:13,111] [INFO] [utils.py:811:see_memory_usage] CPU Virtual Memory: used = 45.68 GB, percent = 11.6%
52 [2023-09-12 00:26:13,112] [INFO] [logging.py:96:log_dist] [Rank 0] DeepSpeed Final Optimizer = FusedAdam
53 [2023-09-12 00:26:13,112] [INFO] [logging.py:96:log_dist] [Rank 0] DeepSpeed using client LR scheduler
54 [2023-09-12 00:26:13,113] [INFO] [logging.py:96:log_dist] [Rank 0] DeepSpeed LR Scheduler = <torch.optim.lr_scheduler.LambdaLR object at 0x7f487c2cddb0>
55 [2023-09-12 00:26:13,113] [INFO] [logging.py:96:log_dist] [Rank 0] step=0, skipped=0, lr=[0.0005], mom=[(0.9, 0.95)]
56 [2023-09-12 00:26:13,135] [INFO] [config.py:963:print] DeepSpeedEngine configuration:
57 [2023-09-12 00:26:13,135] [INFO] [config.py:967:print] activation_checkpointing_config {
58 "partition_activations": true,
59 "contiguous_memory_optimization": true,
60 "cpu_checkpointing": true,
61 "number_checkpoints": 5,
62 "synchronize_checkpoint_boundary": false,
63 "profile": false
64 }
65 [2023-09-12 00:26:13,136] [INFO] [config.py:967:print] aio_config ................... {'block_size': 1048576, 'queue_depth': 8, 'thread_count': 1, 'single_submit': False, 'overlap_events': True}
66 [2023-09-12 00:26:13,136] [INFO] [config.py:967:print] amp_enabled .................. False
67 [2023-09-12 00:26:13,136] [INFO] [config.py:967:print] amp_params ................... False
68 [2023-09-12 00:26:13,139] [INFO] [config.py:967:print] autotuning_config ............ {
69 "enabled": false,
70 "start_step": null,
71 "end_step": null,
72 "metric_path": null,
73 "arg_mappings": null,
74 "metric": "throughput",
75 "model_info": null,
76 "results_dir": "autotuning_results",
77 "exps_dir": "autotuning_exps",
78 "overwrite": true,
79 "fast": true,
80 "start_profile_step": 3,
81 "end_profile_step": 5,
82 "tuner_type": "gridsearch",
83 "tuner_early_stopping": 5,
84 "tuner_num_trials": 50,
85 "model_info_path": null,
86 "mp_size": 1,
87 "max_train_batch_size": null,
88 "min_train_batch_size": 1,
89 "max_train_micro_batch_size_per_gpu": 1.024000e+03,
90 "min_train_micro_batch_size_per_gpu": 1,
91 "num_tuning_micro_batch_sizes": 3
92 }
93 [2023-09-12 00:26:13,139] [INFO] [config.py:967:print] bfloat16_enabled ............. False
94 [2023-09-12 00:26:13,139] [INFO] [config.py:967:print] checkpoint_parallel_write_pipeline False
95 [2023-09-12 00:26:13,140] [INFO] [config.py:967:print] checkpoint_tag_validation_enabled True
96 [2023-09-12 00:26:13,140] [INFO] [config.py:967:print] checkpoint_tag_validation_fail False
97 [2023-09-12 00:26:13,140] [INFO] [config.py:967:print] comms_config ................. <deepspeed.comm.config.DeepSpeedCommsConfig object at 0x7f44d015c9a0>
98 [2023-09-12 00:26:13,140] [INFO] [config.py:967:print] communication_data_type ...... None
99 [2023-09-12 00:26:13,140] [INFO] [config.py:967:print] compression_config ........... {'weight_quantization': {'shared_parameters': {'enabled': False, 'quantizer_kernel': False, 'schedule_offset': 0, 'quantize_groups': 1, 'quantize_verbose': False, 'quantization_type': 'symmetric', 'quantize_weight_in_forward': False, 'rounding': 'nearest', 'fp16_mixed_quantize': False, 'quantize_change_ratio': 0.001}, 'different_groups': {}}, 'activation_quantization': {'shared_parameters': {'enabled': False, 'quantization_type': 'symmetric', 'range_calibration': 'dynamic', 'schedule_offset': 1000}, 'different_groups': {}}, 'sparse_pruning': {'shared_parameters': {'enabled': False, 'method': 'l1', 'schedule_offset': 1000}, 'different_groups': {}}, 'row_pruning': {'shared_parameters': {'enabled': False, 'method': 'l1', 'schedule_offset': 1000}, 'different_groups': {}}, 'head_pruning': {'shared_parameters': {'enabled': False, 'method': 'topk', 'schedule_offset': 1000}, 'different_groups': {}}, 'channel_pruning': {'shared_parameters': {'enabled': False, 'method': 'l1', 'schedule_offset': 1000}, 'different_groups': {}}, 'layer_reduction': {'enabled': False}}
100 [2023-09-12 00:26:13,141] [INFO] [config.py:967:print] curriculum_enabled_legacy .... False
101 [2023-09-12 00:26:13,141] [INFO] [config.py:967:print] curriculum_params_legacy ..... False
102 [2023-09-12 00:26:13,141] [INFO] [config.py:967:print] data_efficiency_config ....... {'enabled': False, 'seed': 1234, 'data_sampling': {'enabled': False, 'num_epochs': 1000, 'num_workers': 0, 'curriculum_learning': {'enabled': False}}, 'data_routing': {'enabled': False, 'random_ltd': {'enabled': False, 'layer_token_lr_schedule': {'enabled': False}}}}
103 [2023-09-12 00:26:13,141] [INFO] [config.py:967:print] data_efficiency_enabled ...... False
104 [2023-09-12 00:26:13,142] [INFO] [config.py:967:print] dataloader_drop_last ......... False
105 [2023-09-12 00:26:13,142] [INFO] [config.py:967:print] disable_allgather ............ False
106 [2023-09-12 00:26:13,142] [INFO] [config.py:967:print] dump_state ................... False
107 [2023-09-12 00:26:13,142] [INFO] [config.py:967:print] dynamic_loss_scale_args ...... {'init_scale': 65536, 'scale_window': 100, 'delayed_shift': 2, 'consecutive_hysteresis': False, 'min_scale': 1}
108 [2023-09-12 00:26:13,143] [INFO] [config.py:967:print] eigenvalue_enabled ........... False
109 [2023-09-12 00:26:13,143] [INFO] [config.py:967:print] eigenvalue_gas_boundary_resolution 1
110 [2023-09-12 00:26:13,143] [INFO] [config.py:967:print] eigenvalue_layer_name ........ bert.encoder.layer
111 [2023-09-12 00:26:13,144] [INFO] [config.py:967:print] eigenvalue_layer_num ......... 0
112 [2023-09-12 00:26:13,144] [INFO] [config.py:967:print] eigenvalue_max_iter .......... 100
113 [2023-09-12 00:26:13,144] [INFO] [config.py:967:print] eigenvalue_stability ......... 1e-06
114 [2023-09-12 00:26:13,144] [INFO] [config.py:967:print] eigenvalue_tol ............... 0.01
115 [2023-09-12 00:26:13,145] [INFO] [config.py:967:print] eigenvalue_verbose ........... False
116 [2023-09-12 00:26:13,145] [INFO] [config.py:967:print] elasticity_enabled ........... False
117 [2023-09-12 00:26:13,145] [INFO] [config.py:967:print] flops_profiler_config ........ {
118 "enabled": false,
119 "recompute_fwd_factor": 0.0,
120 "profile_step": 1,
121 "module_depth": -1,
122 "top_modules": 1,
123 "detailed": true,
124 "output_file": null
125 }
126 [2023-09-12 00:26:13,145] [INFO] [config.py:967:print] fp16_auto_cast ............... False
127 [2023-09-12 00:26:13,146] [INFO] [config.py:967:print] fp16_enabled ................. True
128 [2023-09-12 00:26:13,146] [INFO] [config.py:967:print] fp16_master_weights_and_gradients False
129 [2023-09-12 00:26:13,146] [INFO] [config.py:967:print] global_rank .................. 0
130 [2023-09-12 00:26:13,146] [INFO] [config.py:967:print] grad_accum_dtype ............. None
131 [2023-09-12 00:26:13,147] [INFO] [config.py:967:print] gradient_accumulation_steps .. 16
132 [2023-09-12 00:26:13,147] [INFO] [config.py:967:print] gradient_clipping ............ 1.0
133 [2023-09-12 00:26:13,147] [INFO] [config.py:967:print] gradient_predivide_factor .... 1.0
134 [2023-09-12 00:26:13,148] [INFO] [config.py:967:print] hybrid_engine ................ enabled=False max_out_tokens=1250 inference_tp_size=1 release_inference_cache=False pin_parameters=True tp_gather_partition_size=8
135 [2023-09-12 00:26:13,148] [INFO] [config.py:967:print] initial_dynamic_scale ........ 65536
136 [2023-09-12 00:26:13,148] [INFO] [config.py:967:print] load_universal_checkpoint .... False
137 [2023-09-12 00:26:13,149] [INFO] [config.py:967:print] loss_scale ................... 0
138 [2023-09-12 00:26:13,149] [INFO] [config.py:967:print] memory_breakdown ............. False
139 [2023-09-12 00:26:13,149] [INFO] [config.py:967:print] mics_hierarchial_params_gather False
140 [2023-09-12 00:26:13,149] [INFO] [config.py:967:print] mics_shard_size .............. -1
141 [2023-09-12 00:26:13,150] [INFO] [config.py:967:print] monitor_config ............... tensorboard=TensorBoardConfig(enabled=False, output_path='', job_name='DeepSpeedJobName') wandb=WandbConfig(enabled=False, group=None, team=None, project='deepspeed') csv_monitor=CSVConfig(enabled=False, output_path='', job_name='DeepSpeedJobName') enabled=False
142 [2023-09-12 00:26:13,150] [INFO] [config.py:967:print] nebula_config ................ {
143 "enabled": false,
144 "persistent_storage_path": null,
145 "persistent_time_interval": 100,
146 "num_of_version_in_retention": 2,
147 "enable_nebula_load": true,
148 "load_path": null
149 }
150 [2023-09-12 00:26:13,150] [INFO] [config.py:967:print] optimizer_legacy_fusion ...... False
151 [2023-09-12 00:26:13,151] [INFO] [config.py:967:print] optimizer_name ............... None
152 [2023-09-12 00:26:13,151] [INFO] [config.py:967:print] optimizer_params ............. None
153 [2023-09-12 00:26:13,151] [INFO] [config.py:967:print] pipeline ..................... {'stages': 'auto', 'partition': 'best', 'seed_layers': False, 'activation_checkpoint_interval': 0}
154 [2023-09-12 00:26:13,151] [INFO] [config.py:967:print] pld_enabled .................. False
155 [2023-09-12 00:26:13,151] [INFO] [config.py:967:print] pld_params ................... False
156 [2023-09-12 00:26:13,152] [INFO] [config.py:967:print] prescale_gradients ........... False
157 [2023-09-12 00:26:13,152] [INFO] [config.py:967:print] scheduler_name ............... None
158 [2023-09-12 00:26:13,152] [INFO] [config.py:967:print] scheduler_params ............. None
159 [2023-09-12 00:26:13,152] [INFO] [config.py:967:print] sparse_attention ............. None
160 [2023-09-12 00:26:13,153] [INFO] [config.py:967:print] sparse_gradients_enabled ..... False
161 [2023-09-12 00:26:13,153] [INFO] [config.py:967:print] steps_per_print .............. 10
162 [2023-09-12 00:26:13,153] [INFO] [config.py:967:print] train_batch_size ............. 64
163 [2023-09-12 00:26:13,154] [INFO] [config.py:967:print] train_micro_batch_size_per_gpu 1
164 [2023-09-12 00:26:13,154] [INFO] [config.py:967:print] use_node_local_storage ....... False
165 [2023-09-12 00:26:13,154] [INFO] [config.py:967:print] wall_clock_breakdown ......... False
166 [2023-09-12 00:26:13,155] [INFO] [config.py:967:print] world_size ................... 4
167 [2023-09-12 00:26:13,155] [INFO] [config.py:967:print] zero_allow_untested_optimizer False
168 [2023-09-12 00:26:13,155] [INFO] [config.py:967:print] zero_config .................. stage=3 contiguous_gradients=True reduce_scatter=True reduce_bucket_size=500,000,000 allgather_partitions=True allgather_bucket_size=500,000,000 overlap_comm=True load_from_fp32_weights=True elastic_checkpoint=False offload_param=DeepSpeedZeroOffloadParamConfig(device='none', nvme_path=None, buffer_count=5, buffer_size=100,000,000, max_in_cpu=1,000,000,000, pin_memory=False) offload_optimizer=DeepSpeedZeroOffloadOptimizerConfig(device='none', nvme_path=None, buffer_count=4, pin_memory=False, pipeline=False, pipeline_read=False, pipeline_write=False, fast_init=False) sub_group_size=1,000,000,000 cpu_offload_param=None cpu_offload_use_pin_memory=None cpu_offload=None prefetch_bucket_size=30000000 param_persistence_threshold=10000 model_persistence_threshold=sys.maxsize max_live_parameters=30000000 max_reuse_distance=1,000,000,000 gather_16bit_weights_on_model_save=False stage3_gather_fp16_weights_on_model_save=False ignore_unused_parameters=True legacy_stage1=False round_robin_gradients=False zero_hpz_partition_size=1 zero_quantized_weights=False zero_quantized_nontrainable_weights=False zero_quantized_gradients=False mics_shard_size=-1 mics_hierarchical_params_gather=False memory_efficient_linear=False pipeline_loading_checkpoint=False override_module_apply=True
169 [2023-09-12 00:26:13,155] [INFO] [config.py:967:print] zero_enabled ................. True
170 [2023-09-12 00:26:13,155] [INFO] [config.py:967:print] zero_force_ds_cpu_optimizer .. True
171 [2023-09-12 00:26:13,156] [INFO] [config.py:967:print] zero_optimization_stage ...... 3
172 [2023-09-12 00:26:13,156] [INFO] [config.py:953:print_user_config] json = {
173 "train_batch_size": 64,
174 "train_micro_batch_size_per_gpu": 1,
175 "steps_per_print": 10,
176 "zero_optimization": {
177 "stage": 3,
178 "offload_param": {
179 "device": "none"
180 },
181 "offload_optimizer": {
182 "device": "none"
183 },
184 "stage3_param_persistence_threshold": 1.000000e+04,
185 "stage3_max_live_parameters": 3.000000e+07,
186 "stage3_prefetch_bucket_size": 3.000000e+07,
187 "memory_efficient_linear": false
188 },
189 "fp16": {
190 "enabled": true,
191 "loss_scale_window": 100
192 },
193 "gradient_clipping": 1.0,
194 "prescale_gradients": false,
195 "wall_clock_breakdown": false,
196 "hybrid_engine": {
197 "enabled": false,
198 "max_out_tokens": 1.250000e+03,
199 "inference_tp_size": 1,
200 "release_inference_cache": false,
201 "pin_parameters": true,
202 "tp_gather_partition_size": 8
203 },
204 "activation_checkpointing": {
205 "partition_activations": true,
206 "cpu_checkpointing": true,
207 "contiguous_memory_optimization": true,
208 "number_checkpoints": 5
209 }
210 }

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing DeepSpeed-Chat supervised fine-tuning with Pythia-6.9b, LoRA rank 128, and the stated four RTX6000 setup, comparing memory after initialization and the first forward pass. Inspect the ZeRO Stage 3 path in deepspeed/runtime/zero/stage3.py and the logged configuration in config.py. Done means the cause of the Stage 3 increase is confirmed and the expected memory behavior is verified.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, pytorch
Domain
distributed-systems, machine-learning, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.