Skip to content
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

Fix several integer-signedness warnings #1380

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

iskunk
Copy link

@iskunk iskunk commented Mar 6, 2024

I am building cutlass 3.4.1 using the Intel LLVM (oneAPI) compiler. There are a lot of warnings being produced related to implicit integer sign conversions.

This PR does not fix all of them, but it addresses all the instances that individually result in over a thousand warnings. Test suite results are left no worse off, but please review these changes carefully.

Here is the bulk of the warnings removed from the build output, sorted in order of decreasing count:

   2158 .../cutlass-3.4.1/include/cutlass/fast_math.h:249:8: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
   2158 .../cutlass-3.4.1/include/cutlass/fast_math.h:368:17: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
   2132 .../cutlass-3.4.1/include/cute/numeric/math.hpp:154:49: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
   1813 .../cutlass-3.4.1/include/cutlass/arch/mma_sm60.h:134:27: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1813 .../cutlass-3.4.1/include/cutlass/arch/mma_sm60.h:134:38: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1813 .../cutlass-3.4.1/include/cutlass/arch/mma_sm60.h:134:5: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1813 .../cutlass-3.4.1/include/cutlass/arch/mma_sm60.h:88:18: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1813 .../cutlass-3.4.1/include/cutlass/arch/mma_sm60.h:88:38: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1813 .../cutlass-3.4.1/include/cutlass/arch/mma_sm60.h:88:5: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1809 .../cutlass-3.4.1/include/cutlass/arch/mma_sm60.h:188:28: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1809 .../cutlass-3.4.1/include/cutlass/arch/mma_sm60.h:188:37: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1809 .../cutlass-3.4.1/include/cutlass/arch/mma_sm60.h:188:50: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1809 .../cutlass-3.4.1/include/cutlass/arch/mma_sm60.h:188:7: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1809 .../cutlass-3.4.1/include/cutlass/arch/mma_sm60.h:242:13: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1809 .../cutlass-3.4.1/include/cutlass/arch/mma_sm60.h:242:28: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1809 .../cutlass-3.4.1/include/cutlass/arch/mma_sm60.h:242:37: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1809 .../cutlass-3.4.1/include/cutlass/arch/mma_sm60.h:242:56: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1809 .../cutlass-3.4.1/include/cutlass/arch/mma_sm61.h:133:13: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1809 .../cutlass-3.4.1/include/cutlass/arch/mma_sm61.h:133:22: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1809 .../cutlass-3.4.1/include/cutlass/arch/mma_sm61.h:86:13: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1809 .../cutlass-3.4.1/include/cutlass/arch/mma_sm61.h:86:22: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1788 .../cutlass-3.4.1/test/unit/gemm/device/testbed.h:158:60: warning: implicit conversion changes signedness: '::size_t' (aka 'unsigned long') to '::int64_t' (aka 'long') [-Wsign-conversion]
   1763 .../cutlass-3.4.1/include/cutlass/predicate_vector.h:162:9: warning: implicit conversion changes signedness: 'int' to 'unsigned long' [-Wsign-conversion]
   1763 .../cutlass-3.4.1/include/cutlass/predicate_vector.h:163:19: warning: implicit conversion changes signedness: 'int' to 'unsigned long' [-Wsign-conversion]
   1761 .../cutlass-3.4.1/include/cutlass/gemm/warp/mma_tensor_op.h:103:45: warning: implicit conversion changes signedness: 'unsigned int' to 'int' [-Wsign-conversion]
   1761 .../cutlass-3.4.1/include/cutlass/gemm/warp/mma_tensor_op.h:103:48: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
   1761 .../cutlass-3.4.1/include/cutlass/gemm/warp/mma_tensor_op.h:124:45: warning: implicit conversion changes signedness: 'unsigned int' to 'int' [-Wsign-conversion]
   1761 .../cutlass-3.4.1/include/cutlass/gemm/warp/mma_tensor_op.h:124:48: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
   1761 .../cutlass-3.4.1/include/cutlass/layout/permute.h:321:58: warning: implicit conversion changes signedness: 'const unsigned int' to 'Index' (aka 'int') [-Wsign-conversion]
   1761 .../cutlass-3.4.1/include/cutlass/layout/permute.h:384:58: warning: implicit conversion changes signedness: 'const unsigned int' to 'Index' (aka 'int') [-Wsign-conversion]
   1761 .../cutlass-3.4.1/include/cutlass/layout/permute.h:456:58: warning: implicit conversion changes signedness: 'const unsigned int' to 'Index' (aka 'int') [-Wsign-conversion]
   1761 .../cutlass-3.4.1/include/cutlass/layout/permute.h:517:58: warning: implicit conversion changes signedness: 'const unsigned int' to 'Index' (aka 'int') [-Wsign-conversion]
   1737 .../cutlass-3.4.1/include/cutlass/epilogue/warp/tile_iterator_tensor_op_mixed.h:405:21: warning: implicit conversion changes signedness: 'Index' (aka 'long') to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
   1737 .../cutlass-3.4.1/include/cutlass/epilogue/warp/tile_iterator_tensor_op_mixed.h:606:21: warning: implicit conversion changes signedness: 'Index' (aka 'long') to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
   1735 .../cutlass-3.4.1/include/cutlass/gemm/threadblock/threadblock_swizzle_streamk.h:450:131: warning: implicit conversion changes signedness: 'Index' (aka 'int') to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
   1735 .../cutlass-3.4.1/include/cutlass/gemm/threadblock/threadblock_swizzle_streamk.h:450:155: warning: implicit conversion changes signedness: 'Index' (aka 'int') to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
   1735 .../cutlass-3.4.1/include/cutlass/gemm/threadblock/threadblock_swizzle_streamk.h:450:201: warning: implicit conversion changes signedness: 'Index' (aka 'int') to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
   1735 .../cutlass-3.4.1/include/cutlass/gemm/threadblock/threadblock_swizzle_streamk.h:450:225: warning: implicit conversion changes signedness: 'Index' (aka 'int') to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
   1735 .../cutlass-3.4.1/include/cutlass/gemm/threadblock/threadblock_swizzle_streamk.h:450:62: warning: implicit conversion changes signedness: 'Index' (aka 'int') to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
   1735 .../cutlass-3.4.1/include/cutlass/gemm/threadblock/threadblock_swizzle_streamk.h:450:86: warning: implicit conversion changes signedness: 'Index' (aka 'int') to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
   1705 .../cutlass-3.4.1/include/cutlass/gemm/threadblock/threadblock_swizzle.h:112:31: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
   1705 .../cutlass-3.4.1/include/cutlass/gemm/threadblock/threadblock_swizzle.h:112:70: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
   1705 .../cutlass-3.4.1/include/cutlass/gemm/threadblock/threadblock_swizzle.h:112:90: warning: implicit conversion changes signedness: 'Index' (aka 'int') to 'unsigned int' [-Wsign-conversion]
   1631 .../cutlass-3.4.1/include/cutlass/gemm/threadblock/threadblock_swizzle.h:112:29: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
   1631 .../cutlass-3.4.1/include/cutlass/gemm/threadblock/threadblock_swizzle.h:112:68: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
   1631 .../cutlass-3.4.1/include/cutlass/gemm/threadblock/threadblock_swizzle.h:112:88: warning: implicit conversion changes signedness: 'Index' (aka 'int') to 'unsigned int' [-Wsign-conversion]
   1553 .../cutlass-3.4.1/test/unit/gemm/device/testbed_universal.h:135:60: warning: implicit conversion changes signedness: '::size_t' (aka 'unsigned long') to '::int64_t' (aka 'long') [-Wsign-conversion]
   1235 .../cutlass-3.4.1/include/cutlass/half.h:227:15: warning: implicit conversion changes signedness: 'uint16_t' (aka 'unsigned short') to 'int16_t' (aka 'short') [-Wsign-conversion]
   1235 .../cutlass-3.4.1/include/cutlass/half.h:251:8: warning: implicit conversion changes signedness: 'uint16_t' (aka 'unsigned short') to 'int16_t' (aka 'short') [-Wsign-conversion]
    929 .../cutlass-3.4.1/include/cute/atom/mma_traits_sm90_gmma.hpp:211:51: warning: implicit conversion loses integer precision: 'uint32_t' (aka 'unsigned int') to 'uint16_t' (aka 'unsigned short') [-Wimplicit-int-conversion]
    927 .../cutlass-3.4.1/include/cutlass/half.h:227:17: warning: implicit conversion changes signedness: '::uint16_t' (aka 'unsigned short') to '::int16_t' (aka 'short') [-Wsign-conversion]
    927 .../cutlass-3.4.1/include/cutlass/half.h:251:8: warning: implicit conversion changes signedness: '::uint16_t' (aka 'unsigned short') to '::int16_t' (aka 'short') [-Wsign-conversion]
    917 .../cutlass-3.4.1/include/cutlass/numeric_conversion.h:3708:46: warning: implicit conversion loses integer precision: 'unsigned int' to '::uint8_t' (aka 'unsigned char') [-Wimplicit-int-conversion]

@thakkarV
Copy link
Collaborator

thakkarV commented Mar 6, 2024

Hi! Thanks a lot for this MR! We are about to release CUTLASS 3.5 in the next 10 days or so. This update includes tons of fixes for warnings as we move towards a warnings as errors build system. Would you mind waiting for this MR until we release 3.5 and then rebasing to see if there is anything we have missed?

@iskunk
Copy link
Author

iskunk commented Mar 6, 2024

Hi @thakkarV, is there a repo where I can try out the new version?

I have some additional (non-warning) fixes for the current tree, so I'll push those out ASAP.

@thakkarV
Copy link
Collaborator

thakkarV commented Mar 6, 2024

No other repo unfortunately. We expect 3.5 to be available in this repo by March 15th.

@@ -84,7 +84,7 @@ struct Mma<

#else
CUTLASS_PRAGMA_UNROLL
for (int i = 0; i < 2; ++i) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Given that size_t is normally unsigned and the integer literal 2 is normally signed, it seems like this change would actually introduce a build warning, rather than fix one. Is size_t signed on your platform?

Copy link
Author

Choose a reason for hiding this comment

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

No, size_t is effectively unsigned long. But the compiler doesn't appear to like int used as an array index. It doesn't complain about mixing size_t with integer literals.

Copy link
Contributor

Choose a reason for hiding this comment

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

But the compiler doesn't appear to like int used as an array index.

We don't have that experience with Clang as a host compiler. We would generally prefer to retain use of int where it makes sense to do so. P0907 ("Signed Integers are Two’s Complement"), which was adopted into C++20, was revised in R1 "to maintain undefined behavior when signed integer overflow occurs, instead of defining wrapping behavior," as unsigned integers do. Compilers historically have relied on that undefined behavior to optimize loops with signed integer indices. This explains the cross-compiler experience (including with Intel's compilers, at least the pre-LLVM one) that signed integers give better vectorization.

In this case, it may not matter, because the loop has an integer literal bound, cannot overflow, and can be trivially unrolled. Nevertheless, introducing size_t makes the index have a different signedness than the bound.

Copy link
Contributor

Choose a reason for hiding this comment

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

But the compiler doesn't appear to like int used as an array index.

What warning does it issue?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think I know what's going on -- the compiler must be warning about cutlass::Array::operator[], which takes size_type (which is size_t).

It's utterly conventional to use int to index, say, std::vector. I'm a bit surprised that the compiler warns about this. We could consider adding int overloads of cutlass::Array::operator[] as a work-around. If you have a chance, could you try doing that? They would go in include/cutlass/array.h. Thanks! : - )

Copy link
Author

Choose a reason for hiding this comment

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

Unfortunately, that doesn't seem to help. Either the overload is too similar for the compiler's taste...

/tmp/cutlass-git/include/cutlass/gemm/warp/mma_complex_tensor_op_fast_f32.h(161): error: more than one operator "[]" matches these operands:
            function "cutlass::Array<T, N, true>::operator[](int) const [with T=cutlass::complex<float>, N=8]"
/tmp/cutlass-git/include/cutlass/array.h(396): here
            function "cutlass::Array<T, N, true>::operator[](cutlass::Array<T, N, true>::size_type) const [with T=cutlass::complex<float>, N=8]"
/tmp/cutlass-git/include/cutlass/array.h(401): here
            operand types are: const cutlass::Array<cutlass::complex<float>, 8, true> [ cutlass::layout::ColumnMajor::LongIndex ]
          detected during:
            [instantiation contexts mercifully elided]

or the conversion warnings still occur. I tried having the operators take int only, deleting the size_t ones. But the [] operators in include/cutlass/array_subbyte.h also appear to be involved, and they're implemented using at() which also takes a size_t... this quickly turns into a rabbit hole.

Copy link
Contributor

Choose a reason for hiding this comment

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

@iskunk Thanks for trying this out! I appreciate you taking the time.

We'll try out some possible fixes with the most recent Clang as host compiler, and NVCC as device compiler. That is currently the only supported LLVM configuration. If we can't get it to work, then unfortunately we won't be able to accept these particular index type changes.

Copy link
Contributor

Choose a reason for hiding this comment

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

@iskunk FYI, I added a unit test specifically to exercise cutlass::Array in host code, but couldn't replicate these build errors with Clang 17.0.6 (as the host compiler).

We have two reasons not to add operator[] overloads to cutlass::Array.

  1. It's not consistent with C++ Standard Library array types such as std::array and std::vector.
  2. It introduces the possibility of ambiguity in operator[] overload resolution.

Do you normally get build warnings when using int indices with std::array or std::vector?

@@ -404,7 +404,7 @@ class TileIteratorTensorOpMixed<WarpShape_, OperatorShape_, int32_t, 32, OutputS
TensorRef const &ref,
unsigned lane_id
):
stride_(ref.stride()[0] / AccessType::kElements) {
stride_(size_t(ref.stride()[0]) / AccessType::kElements) {
Copy link
Contributor

@mhoemmen mhoemmen Apr 1, 2024

Choose a reason for hiding this comment

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

stride_ is an int. It's not clear to me how casting to size_t would fix an integer conversion warning. Is size_t signed on your platform?

Copy link
Author

Choose a reason for hiding this comment

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

No; the compiler was complaining about an implicit conversion from Index (i.e. long) to size_t in the divide operation, I believe due to AccessType::kElements being a size_t.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for explaining!

@@ -133,7 +133,7 @@ struct TestbedUniversal {
else if (dist_kind == cutlass::Distribution::Sequential) {

cutlass::reference::host::BlockFillSequential(
view.data(), view.capacity());
view.data(), int64_t(view.capacity()));
Copy link
Contributor

Choose a reason for hiding this comment

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

Note to self: BlockFillSequential's int64_t capacity parameter gets cast internally anyway, so it might make sense instead to change BlockFillSequential instead.

@@ -3705,7 +3705,7 @@ struct PackPredicates {
int word_idx = (i / kWordSize);
int bit_idx = (i % kWordSize);

uint8_t mask = ((predicates[i] ? 1u : 0u) << bit_idx);
uint8_t mask = uint8_t((predicates[i] ? 1u : 0u) << bit_idx);
Copy link
Contributor

Choose a reason for hiding this comment

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

The "Don't Repeat Yourself" principle suggests using auto here.

Suggested change
uint8_t mask = uint8_t((predicates[i] ? 1u : 0u) << bit_idx);
auto mask = uint8_t((predicates[i] ? 1u : 0u) << bit_idx);

@@ -514,7 +514,7 @@ class Tensor4DPermuteBMM0321ColumnMajorInverse : public PermuteBase {
CUTLASS_HOST_DEVICE
LongIndex operator()(MatrixCoord coord) const {

Index BMM_batch_idx = blockIdx.z;
Index BMM_batch_idx = Index(blockIdx.z);
Copy link
Contributor

Choose a reason for hiding this comment

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

The "Don't Repeat Yourself" principle suggests using auto here.

Suggested change
Index BMM_batch_idx = Index(blockIdx.z);
auto BMM_batch_idx = Index(blockIdx.z);

@@ -453,7 +453,7 @@ class Tensor4DPermuteBMM0321ColumnMajor : public PermuteBase {
CUTLASS_HOST_DEVICE
LongIndex operator()(MatrixCoord coord) const {

Index BMM_batch_idx = blockIdx.z;
Index BMM_batch_idx = Index(blockIdx.z);
Copy link
Contributor

Choose a reason for hiding this comment

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

The "Don't Repeat Yourself" principle suggests using auto here.

Suggested change
Index BMM_batch_idx = Index(blockIdx.z);
auto BMM_batch_idx = Index(blockIdx.z);

@@ -381,7 +381,7 @@ class Tensor4DPermuteBMM0213RowMajorInverse : public PermuteBase {
LongIndex operator()(MatrixCoord coord) const {

// The batch index for BMM
Index BMM_batch_idx = blockIdx.z;
Index BMM_batch_idx = Index(blockIdx.z);
Copy link
Contributor

Choose a reason for hiding this comment

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

The "Don't Repeat Yourself" principle suggests using auto here.

Suggested change
Index BMM_batch_idx = Index(blockIdx.z);
auto BMM_batch_idx = Index(blockIdx.z);

@@ -318,7 +318,7 @@ class Tensor4DPermuteBMM0213RowMajor : public PermuteBase {
LongIndex operator()(MatrixCoord coord) const {

// The batch index for BMM
Index BMM_batch_idx = blockIdx.z;
Index BMM_batch_idx = Index(blockIdx.z);
Copy link
Contributor

@mhoemmen mhoemmen Apr 1, 2024

Choose a reason for hiding this comment

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

The "Don't Repeat Yourself" principle suggests using auto here.

Suggested change
Index BMM_batch_idx = Index(blockIdx.z);
auto BMM_batch_idx = Index(blockIdx.z);

@@ -248,7 +248,7 @@ struct alignas(2) half_t {

if (exp >= -14) {
// normal fp32 to normal fp16
exp = uint16_t(exp + uint16_t(15));
exp = exp + 15;
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks like it undoes a fix, rather than fixing a warning.

Copy link
Author

Choose a reason for hiding this comment

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

This was the only way I could find to shut the warning up. (Not even exp += 15; worked.)

No implication of this being the best solution, of course. It did need attention, however, as this was one of the top two sources of warnings in the build.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for explaining! Now that I look more closely, this makes sense, as exp is int16_t, a signed integer. Nevertheless, I would expect the compiler to warn about exp + 15 being a narrowing conversion (first exp promotes to int, then the result is int, and the assignment narrows to 16 bits). Would the following line also work?

Suggested change
exp = exp + 15;
exp = static_cast<decltype(exp)>(exp + 15);

Use of decltype(exp) here follows the Don't Repeat Yourself principle and prevents possible bugs if the type of exp later changes above.

@@ -224,7 +224,7 @@ struct alignas(2) half_t {
#endif

uint16_t sign = uint16_t((s >> 16) & 0x8000);
int16_t exp = uint16_t(((s >> 23) & 0xff) - 127);
int16_t exp = int16_t(((s >> 23) & 0xff) - 127);
Copy link
Contributor

Choose a reason for hiding this comment

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

The "Don't Repeat Yourself" principle suggests using auto here.

Suggested change
int16_t exp = int16_t(((s >> 23) & 0xff) - 127);
auto exp = int16_t(((s >> 23) & 0xff) - 127);

@@ -100,7 +100,7 @@ struct ConvertAndPack<bfloat16_t, float, N, Round> {

CUTLASS_PRAGMA_UNROLL
for (int i = 0; i < N; ++i) {
int idx = (((i << 1) & 2) | ((i >> 1) & 1) | (i & 0xfffffffc));
int idx = (((i << 1) & 2) | ((i >> 1) & 1) | (i & 0x7ffffffc));
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm guessing the intent of these two changes was to remove the sign bit; is that correct?

We're already in trouble if i rolls over to a negative number here, so this is probably OK. However, I'm generally nervous about changes to constants.

Copy link
Author

Choose a reason for hiding this comment

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

Yes, the sign bit was causing the compiler to recognize the constant as a negative signed value, but then the bit operations implied unsignedness.

My fix is focused on the warning, but you're probably better off replacing int with uint32_t.

Copy link
Contributor

Choose a reason for hiding this comment

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

Do you mean like this?

Suggested change
int idx = (((i << 1) & 2) | ((i >> 1) & 1) | (i & 0x7ffffffc));
uint32_t idx = (((i << 1) & 2u) | ((i >> 1) & 1u) | (i & 0xfffffffc));

Copy link
Author

Choose a reason for hiding this comment

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

Hmm, I think I misremembered the effect of the sign bit: it didn't cause the literal to get interpreted as negative/signed, but as unsigned, and then the complaint was with i that was signed.

Here is the full warning from the suggested code above (which I copied in verbatim):

/tmp/cutlass-git/include/cutlass/gemm/warp/mma_tensor_op.h:103:55: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
  103 | uint32_t idx = (((i << 1) & 2U) | ((i >> 1) & 1U)) | (i & 4294967292U); 
      |                                                       ^ ~
/tmp/cutlass-git/include/cutlass/gemm/warp/mma_tensor_op.h:103:39: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
  103 | uint32_t idx = (((i << 1) & 2U) | ((i >> 1) & 1U)) | (i & 4294967292U); 
      |                                     ~~^~~~  ~
/tmp/cutlass-git/include/cutlass/gemm/warp/mma_tensor_op.h:103:21: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
  103 | uint32_t idx = (((i << 1) & 2U) | ((i >> 1) & 1U)) | (i & 4294967292U); 
      |                   ~~^~~~  ~

Rather than casting i, I'll just make it uint32_t as well. The u suffixes don't appear to be needed.

Comment on lines +451 to +442
(element_C_bytes_ * size_t(problem_size.m()) * size_t(problem_size.n())) +
(element_A_bytes_ * size_t(problem_size.m()) * size_t(problem_size.k())) +
(element_B_bytes_ * size_t(problem_size.k()) * size_t(problem_size.n()));
Copy link
Contributor

@mhoemmen mhoemmen Apr 1, 2024

Choose a reason for hiding this comment

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

I'm a bit surprised that this was necessary, as the normal integer conversion rules should turn these into size_t already.

Copy link
Author

Choose a reason for hiding this comment

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

I think originally it was size_t * int * int... is conversion of the latter two in the C++ standard? I'm assuming GCC didn't warn about these as it is more lax, but I doubt Intel's compiler (which is basically a repackaged LLVM) would be stricter in a way that breaks the standard.

Copy link
Contributor

Choose a reason for hiding this comment

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

is conversion of the latter two in the C++ standard?

It's valid C++. The expression evaluates left to right. For size_t * int, size_t has higher conversion rank (assuming a 64-bit compiler), so int converts to size_t.

Compilers might still warn, though.

auto log_swizzle_size = UnderlyingParams::get_log_swizzle_size(problem_blocks.x, problem_blocks.y, max_swizzle);
problem_blocks.x = round_up(problem_blocks.x, (1 << log_swizzle_size) * cluster_shape.m());
problem_blocks.y = round_up(problem_blocks.y, (1 << log_swizzle_size) * cluster_shape.n());
auto log_swizzle_size = UnderlyingParams::get_log_swizzle_size(int(problem_blocks.x), int(problem_blocks.y), max_swizzle);
Copy link
Contributor

Choose a reason for hiding this comment

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

Note to self: Look more closely at this.

@@ -647,7 +647,7 @@ struct PersistentTileSchedulerSm90StreamKParams {

// Calculate the number of stream-K units that would be needed if each stream-K unit
// computed the minimum allowable k iterations. Truncate this to be in units of clusters.
auto cluster_size = cluster_shape.m() * cluster_shape.n();
uint64_t cluster_size = cluster_shape.m() * cluster_shape.n();
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure how these three changes (that explicitly specify uint64_t instead of using auto) would fix warnings.

cluster_shape is a GemmCoord, so m() and n() should be int. Thus, explicitly specifying uint64_t here should actually either introduce a warning (signed to unsigned conversion), or mask possible overflow in the product of two int values (by converting some negative value due to overflow to a large unsigned value).

Copy link
Author

Choose a reason for hiding this comment

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

This part of the code changed since my original push, and I'm no longer getting a warning from the plain auto. I don't recall if I was getting an overflow warning to make it 64-bit... but in any event, I've reverted this.

@@ -605,7 +605,7 @@ class TileIteratorTensorOpMixed<WarpShape_, OperatorShape_, int32_t, 32, OutputS
TensorRef const &ref,
unsigned lane_id
):
stride_(ref.stride()[0] / AccessType::kElements) {
stride_(size_t(ref.stride()[0]) / AccessType::kElements) {
Copy link
Contributor

Choose a reason for hiding this comment

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

stride_ is an int. It's not clear to me how casting to size_t would fix an integer conversion warning. Is size_t signed on your platform?

Copy link
Author

Choose a reason for hiding this comment

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

@@ -246,7 +246,7 @@ template <typename value_t>
CUTLASS_HOST_DEVICE value_t find_log2(value_t x) {
int a = int(31 - clz(x));
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm a bit surprised that you didn't have to change this line, as clz(x) returns value_t (see the clz function template immediately above this).

Copy link
Author

Choose a reason for hiding this comment

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

Note that I didn't fix all the warnings, only the ones that tripped a thousand times or more. The full list in the form that I provided is 1650 lines long. I had to draw the line somewhere :-]

(incidentally, if I filter out all -Wsign-conversion, -Wimplicit-int-conversion, and -Wimplicit-float-size-conversion warnings, I am left with eight unique warnings overall.)

@@ -365,7 +365,7 @@ struct FastDivmod {
FastDivmod(int divisor): divisor(divisor) {

if (divisor != 1) {
unsigned int p = 31 + find_log2(divisor);
unsigned int p = 31 + unsigned(find_log2(divisor));
Copy link
Contributor

Choose a reason for hiding this comment

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

This relies on "int + unsigned" implicitly converting to unsigned, and also mentions "unsigned" twice. Would you instead consider converting the entire expression to unsigned int and using auto on the left-hand side, to avoid repetition?

Suggested change
unsigned int p = 31 + unsigned(find_log2(divisor));
auto p = static_cast<unsigned int>(31 + find_log2(divisor));

@iskunk
Copy link
Author

iskunk commented Apr 1, 2024

Hi @mhoemmen, thanks for looking at this.

To help answer many of the above questions, let me provide you with an updated list of the warnings generated from my build, specifically for an unmodified Git revision f9ece1b. This was generated with grep warning: build.out | sort | uniq -c | sort -nr | grep -E '^ *[0-9]{4} ' | sed 's!/tmp/cutlass/!.../!':

   2210 .../include/cutlass/half.h:251:8: warning: implicit conversion changes signedness: 'uint16_t' (aka 'unsigned short') to 'int16_t' (aka 'short') [-Wsign-conversion]
   2210 .../include/cutlass/half.h:227:15: warning: implicit conversion changes signedness: 'uint16_t' (aka 'unsigned short') to 'int16_t' (aka 'short') [-Wsign-conversion]
   2205 .../include/cutlass/fast_math.h:376:17: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
   2205 .../include/cutlass/fast_math.h:254:8: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
   2182 .../include/cute/numeric/integral_constant.hpp:454:26: warning: implicit conversion changes signedness: 'int' to 'uint64_t' (aka 'unsigned long') [-Wsign-conversion]
   2180 .../include/cute/numeric/math.hpp:154:49: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
   1863 .../include/cutlass/numeric_conversion.h:3708:44: warning: implicit conversion loses integer precision: 'unsigned int' to 'uint8_t' (aka 'unsigned char') [-Wimplicit-int-conversion]
   1854 .../include/cutlass/arch/mma_sm60.h:88:5: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1854 .../include/cutlass/arch/mma_sm60.h:88:38: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1854 .../include/cutlass/arch/mma_sm60.h:88:18: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1854 .../include/cutlass/arch/mma_sm60.h:134:5: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1854 .../include/cutlass/arch/mma_sm60.h:134:38: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1854 .../include/cutlass/arch/mma_sm60.h:134:27: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1850 .../include/cutlass/arch/mma_sm61.h:86:22: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1850 .../include/cutlass/arch/mma_sm61.h:86:13: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1850 .../include/cutlass/arch/mma_sm61.h:133:22: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1850 .../include/cutlass/arch/mma_sm61.h:133:13: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1850 .../include/cutlass/arch/mma_sm60.h:242:56: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1850 .../include/cutlass/arch/mma_sm60.h:242:37: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1850 .../include/cutlass/arch/mma_sm60.h:242:28: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1850 .../include/cutlass/arch/mma_sm60.h:242:13: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1850 .../include/cutlass/arch/mma_sm60.h:188:7: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1850 .../include/cutlass/arch/mma_sm60.h:188:50: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1850 .../include/cutlass/arch/mma_sm60.h:188:37: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1850 .../include/cutlass/arch/mma_sm60.h:188:28: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
   1780 .../include/cutlass/predicate_vector.h:163:19: warning: implicit conversion changes signedness: 'int' to 'unsigned long' [-Wsign-conversion]
   1780 .../include/cutlass/predicate_vector.h:162:9: warning: implicit conversion changes signedness: 'int' to 'unsigned long' [-Wsign-conversion]
   1778 .../include/cutlass/layout/permute.h:517:58: warning: implicit conversion changes signedness: 'const unsigned int' to 'Index' (aka 'int') [-Wsign-conversion]
   1778 .../include/cutlass/layout/permute.h:456:58: warning: implicit conversion changes signedness: 'const unsigned int' to 'Index' (aka 'int') [-Wsign-conversion]
   1778 .../include/cutlass/layout/permute.h:384:58: warning: implicit conversion changes signedness: 'const unsigned int' to 'Index' (aka 'int') [-Wsign-conversion]
   1778 .../include/cutlass/layout/permute.h:321:58: warning: implicit conversion changes signedness: 'const unsigned int' to 'Index' (aka 'int') [-Wsign-conversion]
   1778 .../include/cutlass/gemm/warp/mma_tensor_op.h:124:48: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
   1778 .../include/cutlass/gemm/warp/mma_tensor_op.h:124:45: warning: implicit conversion changes signedness: 'unsigned int' to 'int' [-Wsign-conversion]
   1778 .../include/cutlass/gemm/warp/mma_tensor_op.h:103:48: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
   1778 .../include/cutlass/gemm/warp/mma_tensor_op.h:103:45: warning: implicit conversion changes signedness: 'unsigned int' to 'int' [-Wsign-conversion]
   1754 .../include/cutlass/epilogue/warp/tile_iterator_tensor_op_mixed.h:964:21: warning: implicit conversion changes signedness: 'Index' (aka 'long') to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
   1754 .../include/cutlass/epilogue/warp/tile_iterator_tensor_op_mixed.h:775:21: warning: implicit conversion changes signedness: 'Index' (aka 'long') to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
   1754 .../include/cutlass/epilogue/warp/tile_iterator_tensor_op_mixed.h:580:21: warning: implicit conversion changes signedness: 'Index' (aka 'long') to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
   1754 .../include/cutlass/epilogue/warp/tile_iterator_tensor_op_mixed.h:385:21: warning: implicit conversion changes signedness: 'Index' (aka 'long') to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
   1752 .../include/cutlass/gemm/threadblock/threadblock_swizzle_streamk.h:449:86: warning: implicit conversion changes signedness: 'Index' (aka 'int') to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
   1752 .../include/cutlass/gemm/threadblock/threadblock_swizzle_streamk.h:449:62: warning: implicit conversion changes signedness: 'Index' (aka 'int') to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
   1752 .../include/cutlass/gemm/threadblock/threadblock_swizzle_streamk.h:449:225: warning: implicit conversion changes signedness: 'Index' (aka 'int') to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
   1752 .../include/cutlass/gemm/threadblock/threadblock_swizzle_streamk.h:449:201: warning: implicit conversion changes signedness: 'Index' (aka 'int') to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
   1752 .../include/cutlass/gemm/threadblock/threadblock_swizzle_streamk.h:449:155: warning: implicit conversion changes signedness: 'Index' (aka 'int') to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
   1752 .../include/cutlass/gemm/threadblock/threadblock_swizzle_streamk.h:449:131: warning: implicit conversion changes signedness: 'Index' (aka 'int') to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
   1695 .../test/unit/gemm/device/testbed_universal.h:135:60: warning: implicit conversion changes signedness: '::size_t' (aka 'unsigned long') to 'int64_t' (aka 'long') [-Wsign-conversion]
   1643 .../include/cutlass/gemm/threadblock/threadblock_swizzle.h:112:88: warning: implicit conversion changes signedness: 'Index' (aka 'int') to 'unsigned int' [-Wsign-conversion]
   1643 .../include/cutlass/gemm/threadblock/threadblock_swizzle.h:112:68: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
   1643 .../include/cutlass/gemm/threadblock/threadblock_swizzle.h:112:29: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
   1621 .../include/cutlass/gemm/threadblock/threadblock_swizzle.h:112:90: warning: implicit conversion changes signedness: 'Index' (aka 'int') to 'unsigned int' [-Wsign-conversion]
   1621 .../include/cutlass/gemm/threadblock/threadblock_swizzle.h:112:70: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]
   1621 .../include/cutlass/gemm/threadblock/threadblock_swizzle.h:112:31: warning: implicit conversion changes signedness: 'int' to 'unsigned int' [-Wsign-conversion]

You might consider it worth the trouble to reproduce these with your own installation of the Intel oneAPI compiler, to cut out the middleman.

I will read through your review comments and respond/revise as appropriate. Then a test build, and (hopefully) an update to the PR.

@iskunk iskunk force-pushed the feature/fix-warnings branch 2 times, most recently from 28915a5 to 699178b Compare April 2, 2024 23:32
@iskunk
Copy link
Author

iskunk commented Apr 2, 2024

I've updated and rebased my PR. With these changes, the most frequent warning occurs 969 times.

@mhoemmen
Copy link
Contributor

mhoemmen commented Apr 3, 2024

@iskunk Thanks for your interest in CUTLASS and for all your work!

You might consider it worth the trouble to reproduce these with your own installation of the Intel oneAPI compiler, to cut out the middleman.

Please note that the Intel oneAPI compiler is not currently a supported or tested build configuration. We do support and test Clang as host compiler plus NVCC as device compiler.

Copy link

github-actions bot commented May 4, 2024

This PR has been labeled inactive-30d due to no recent activity in the past 30 days. Please close this PR if it is no longer required. Otherwise, please respond with a comment indicating any updates. This PR will be labeled inactive-90d if there is no activity in the next 60 days.

@iskunk
Copy link
Author

iskunk commented May 6, 2024

Hello @mhoemmen, have you had a chance to try out these changes? I've rebased the PR to current main.

@mhoemmen
Copy link
Contributor

mhoemmen commented May 7, 2024

@iskunk Thank you for your interest in CUTLASS!

Changes like the following, that replace int with size_t,

CUTLASS_PRAGMA_UNROLL
for (size_t k = 0; k < 2; ++k) {

cannot possibly reduce the number of warnings, given that the C++ Standard guarantees that 2 is an int literal. We test with GCC, Clang, and MSVC, and don't see build warnings when using int as the index type. Thus, I strongly suspect that something is wrong with the oneAPI compiler.

You might consider it worth the trouble to reproduce these with your own installation of the Intel oneAPI compiler, to cut out the middleman.

We do not support the Intel oneAPI compiler. We would consider code changes that happen to improve the oneAPI compiler experience as long as they improve code quality overall, but changes like the above objectively don't do that.

@iskunk
Copy link
Author

iskunk commented May 7, 2024

I think the oneAPI warnings on that bit come down to operator[] taking a size_t. Since overloading that with int doesn't appear to work, is there a way to declare that that is more forgiving on the integer type? Not least since specifying size_t can have the implication that an unsigned type is required.

@mhoemmen
Copy link
Contributor

mhoemmen commented May 8, 2024

@iskunk Thanks for the suggestion! We contemplated overloading operator[], but decided against that. The C++ Standard Library has several types with an array access operator[] with one integer parameter: std::array, std::span, std::string, std::string_view, std::valarray, and std::vector. For all of them, the parameter's type is size_t. None of them have overloads for other integer types or take the type as a template parameter.

I've implemented an example and run it through the latest icx (and the 2024 and 2023 releases).

https://godbolt.org/z/P3ch9T9x1

For std::array, std::vector, std::span, and my hand-rolled versions of these three classes (to demonstrate that the compiler doesn't treat Standard Library types specially), I could not reproduce warnings with code like the following, even with -Wall -Werror.

x[0] = 1.0f;
x[1] = 2.0f;

for (int k = 0; k < 10; ++k) {
  x[k] = static_cast<float>(k) + 1.0f;
}

Please let me know if I'm using icx incorrectly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants