perf(hex8): packetize ordered gradient and geometric contractions

This commit is contained in:
KOKO\Mimi
2026-10-14 22:37:39 +09:00
parent 01590bbb0d
commit 96772651d8
5 changed files with 323 additions and 3 deletions
+31 -3
View File
@@ -246,11 +246,38 @@ Result<Hex8HighLowResponse> Hex8Element::EvaluateHighLow(
gradient_stress[a][j][l] = gradients[a][j] * s[l][j];
for (std::size_t a = 0; a < 8; ++a) {
std::array<HighLow, 8> dots{};
std::array<HighLow, 8> weighted_geo{};
if (use_packets)
for (std::size_t first_b = 0; first_b < 8; first_b += 4) {
hex8_internal::GeometryPacketInput input{};
const auto raw_pair = [](HighLow pair) {
return hex8_internal::PacketPair{pair.high, pair.low};
};
input.weight = raw_pair(HighLow{point.weight});
for (std::size_t j = 0; j < 3; ++j) {
input.gradient_a[j] = raw_pair(gradients[a][j]);
for (std::size_t l = 0; l < 3; ++l)
input.gradient_stress[j][l] = raw_pair(gradient_stress[a][j][l]);
for (std::size_t lane = 0; lane < 4; ++lane)
input.gradient_b[j].values[lane] =
raw_pair(gradients[first_b + lane][j]);
}
hex8_internal::GeometryPacketOutput output;
// Same selector contract as material; unsupported/linear stays below.
hex8_internal::EvaluateGeometryPacketAvx2(input, &output);
for (std::size_t lane = 0; lane < 4; ++lane) {
dots[first_b + lane] = {output.gradient_dot.values[lane].high,
output.gradient_dot.values[lane].low};
weighted_geo[first_b + lane] =
{output.weighted_geometric.values[lane].high,
output.weighted_geometric.values[lane].low};
}
}
for (std::size_t b = 0; b < 8; ++b) {
const auto dot = Dot(gradients[a], gradients[b]);
const auto dot = use_packets ? dots[b] : Dot(gradients[a], gradients[b]);
dots[b] = dot;
HighLow geo;
if (nonlinear)
if (nonlinear && !use_packets)
for (std::size_t j = 0; j < 3; ++j)
for (std::size_t l = 0; l < 3; ++l)
geo += gradient_stress[a][j][l] * gradients[b][l];
@@ -265,7 +292,8 @@ Result<Hex8HighLowResponse> Hex8Element::EvaluateHighLow(
material[row][column] += mat * HighLow{point.weight};
}
if (i == k)
geometric[row][column] += geo * HighLow{point.weight};
geometric[row][column] +=
use_packets ? weighted_geo[b] : geo * HighLow{point.weight};
}
}
if (use_packets)