-
Notifications
You must be signed in to change notification settings - Fork 195
fix(qlinear): size pack_original qweight/qzeros by bits/32 for 3-bit GPTQ #2984
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -1395,7 +1395,7 @@ def pack_original(self, linear: nn.Module, scales: t.Tensor, zeros: t.Tensor, g_ | |||||
| int_weight = int_weight.to(t.int32).T.contiguous() | ||||||
| int_weight = int_weight.numpy().astype(self.pack_np_math_dtype) | ||||||
|
|
||||||
| qweight = np.zeros((math.ceil(int_weight.shape[0] / self.pack_factor), int_weight.shape[1]), | ||||||
| qweight = np.zeros((math.ceil(int_weight.shape[0] * self.bits / 32), int_weight.shape[1]), | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Packed weight buffers become half-sized and drop data for 16-bit and 8-bit storage formats The packed weight and zero-point buffers are sized using a hardcoded 32 ( Why hardcoding 32 diverges from pack_dtype_bits for the 2/4/8-bit pathThe old code sized these buffers as
This also mismatches the pre-registered buffer shape ( Using
Suggested change
Was this helpful? React with 👍 or 👎 to provide feedback. |
||||||
| dtype=self.pack_np_math_dtype) | ||||||
| if self.bits in [2, 4, 8]: | ||||||
| for row in range(qweight.shape[0]): | ||||||
|
|
@@ -1428,7 +1428,7 @@ def pack_original(self, linear: nn.Module, scales: t.Tensor, zeros: t.Tensor, g_ | |||||
| self.register_buffer("qweight", t.from_numpy(qweight.astype(self.pack_np_dtype))) | ||||||
|
|
||||||
| zeros = zeros.numpy().astype(self.pack_np_math_dtype) | ||||||
| qzeros = np.zeros((zeros.shape[0], math.ceil(zeros.shape[1] / self.pack_factor)), dtype=self.pack_np_math_dtype) | ||||||
| qzeros = np.zeros((zeros.shape[0], math.ceil(zeros.shape[1] * self.bits / 32)), dtype=self.pack_np_math_dtype) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Packed zero-point buffer becomes half-sized and drops data for 16-bit and 8-bit storage formats The packed zero-point buffer is sized using a hardcoded 32 ( Same hardcoded-32 divergence on the qzeros pathSee BUG-0001:
Suggested change
Was this helpful? React with 👍 or 👎 to provide feedback. |
||||||
| if self.bits in [2, 4, 8]: | ||||||
| for col in range(qzeros.shape[1]): | ||||||
| for j in range(self.pack_factor): | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔍 3-bit while loop relies on in_features being a multiple of 32
The 3-bit branch (
gptqmodel/nn_modules/qlinear/__init__.py:1404-1425) advancesrowby 3 per iteration and consumes 32 input rows per iteration. This only terminates cleanly whenqweight.shape[0]is a multiple of 3, i.e. whenint_weight.shape[0]is a multiple of 32. With the newceil(dim*3/32)sizing, a non-multiple-of-32dimwould produce ashape[0]that is not a multiple of 3, and the while loop could read pastint_weightor write pastqweight. This precondition (32-alignment of in_features) is enforced elsewhere for the block/gpu packers (:991), and 3-bit only supports int32, so this is likely safe in practice, but worth confirming that callers ofpack_originalalways pad in_features to a multiple of 32 for 3-bit.(Refers to lines 1404-1425)
Was this helpful? React with 👍 or 👎 to provide feedback.