Skip to content

Updated implementation of Compress ops#3166

Open
johnplatts wants to merge 4 commits into
google:masterfrom
johnplatts:hwy_compress_062926
Open

Updated implementation of Compress ops#3166
johnplatts wants to merge 4 commits into
google:masterfrom
johnplatts:hwy_compress_062926

Conversation

@johnplatts

Copy link
Copy Markdown
Contributor

Resolves one of the issues raised in issue #3142.

Moved the default implementation of the Compress ops for vectors with 16-bit, 32-bit, or 64-bit lane types into generic_ops-inl.h.

Added new Compress(d, v, m) and CompressNot(d, v, m) overloads that take an additional d parameter as the additional d parameter allows the SVE implementation of I8/U8/I16/U16/F16/BF16 Compress(d, v, m) to avoid having to split v into halves if Lanes(d) <= Lanes(RepartitionToWide<RebindToUnsigned<DFromV<decltype(v)>>>()) is known to be true at compile time.

Added new CompressBits(d, v, bits) overload that takes an additional d parameter, which allows the CompressBits(d, v, bits) overload to avoid having to load more than HWY_MAX(Lanes(d), 8) mask bits if Lanes(d) < Lanes(DFromV<decltype(v)>()) is true, which is possible on RVV and SVE targets.

In addition, it is also possible for Lanes(DFromV<decltype(v)>()) to be greater than 64 on RVV and SVE targets (other than SVE_256 or SVE2_128), and LoadMaskBits only requires that 8 bytes of bits be readable if Lanes(d) <= 64 is true.

Also reimplemented I8/U8/I16/U16/F16/BF16 Compress(d, v, m) for SVE targets to avoid unnecessary splitting of v if Lanes(d) <= Lanes(RepartitionToWide<RebindToUnsigned<DFromV<decltype(v)>>>()) is known to be true at compile time.

The new I8/U8 Compress implementation in arm_sve-inl.h also avoids using temporary arrays to store v and the bits of m as SVE can efficiently combine the results of compressing the two halves of v using detail::Splice.

Also updated emu128-inl.h to use the implementation of Compress in emu128-inl.h for I8/U8 vectors as the implementation in emu128-inl.h is more efficient than the default implementation in generic_ops-inl.h for I8/U8 vectors.

Also updated CompressIsPartition<T> to make CompressIsPartition::value equal to 1 for all lane types on the EMU128 target as the EMU128 implementation of Compress is known to be a partitioning compress.

@jan-wassenberg jan-wassenberg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent, thanks for tackling this duplication.
Some suggestions, happy to discuss:

Comment thread hwy/ops/arm_sve-inl.h Outdated
template <class D>
static constexpr bool NeedToSplitForCompress8Or16() {
return (HWY_MAX_LANES_D(D) * sizeof(TFromD<D>)) >=
((HWY_TARGET == HWY_SVE_256) ? 32 : 16) &&

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be HWY_MIN_BYTES? It is possible we later add a 512-bit SVE target.

Comment thread hwy/ops/arm_sve-inl.h Outdated
using TW =
If<(sizeof(T) == 1 &&
((HWY_POW2_D(D) <= -2) ||
(HWY_MAX_LANES_D(D) <= ((HWY_TARGET == HWY_SVE_256) ? 8 : 4)))),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HWY_MIN_BYTES/4?

Comment thread hwy/ops/arm_sve-inl.h Outdated
template <class V, HWY_IF_T_SIZE_V(V, 8)>
HWY_API V CompressNot(V v, svbool_t mask) {
#if HWY_TARGET == HWY_SVE2_128 || HWY_IDE
#if HWY_TARGET == HWY_SVE2_128

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI the HWY_IDE is to prevent our IDE from greying out the code. Not a big deal for short code sections, but still nice to keep. The endif/if instead of elif is also for this purpose, so that multiple blocks are not greyed out.

Comment thread hwy/ops/generic_ops-inl.h Outdated
return kCompressNot64x2Table;
}

#if HWY_CAP_GE256

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is deprecated, how about HWY_MIN_BYTES >= 32?

Comment thread hwy/ops/generic_ops-inl.h
// is likely more costly than the higher cache footprint from storing bytes.
const uint8_t (&table)[2048] = detail::GetCompress16x8Table();

#if HWY_IS_BIG_ENDIAN

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you like to add/use a constexpr NativeFromLittleEndian (or similar name) function to reduce #if?

Comment thread hwy/ops/generic_ops-inl.h Outdated
}
}

#if HWY_CAP_GE256

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also HWY_MIN_BYTES?

Comment thread hwy/ops/generic_ops-inl.h
Comment thread hwy/ops/generic_ops-inl.h Outdated
const size_t count = PopCount(mask_bits);

const auto compressed = Compress(v, m);
#if (HWY_ARCH_S390X && HWY_TARGET <= HWY_Z14) || \

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also add a HWY_NATIVE_STOREN (like HWY_NATIVE_MASK) for this?

Comment thread hwy/ops/set_macros-inl.h Outdated
#define HWY_NATIVE_FMA 1
#define HWY_NATIVE_DOT_BF16 0
#define HWY_NATIVE_MASK 1
#define HWY_HAVE_NATIVE_STORE_N 1

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more thing: how about we rename HWY_HAVE_NATIVE_STORE_N to HWY_NATIVE_STORE_N ? Currently, HWY_HAVE_ is for "are these available at all, e.g. float64", whereas HWY_NATIVE_MASK etc mean "it's available everywhere, but is it efficient"? This new flag belongs to the latter category, so good to keep it consistent with naming.

@jan-wassenberg

Copy link
Copy Markdown
Member

We had an internal user calling the detail:: functions, causing internal CI to fail. I will fix that soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants