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 compilation of uniform int distribution #2284

Merged
merged 5 commits into from
Oct 11, 2023

Conversation

apwojcik
Copy link
Collaborator

@apwojcik apwojcik commented Oct 3, 2023

See the comment in the header file and https://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution.
The standard library from Microsoft Visual C++ is strict about that - it fails compilation when unsigned char and signed char are used as deduced type/template parameters.
The Clang compiler on Windows uses the standard library from MSFT Visual C++.

@apwojcik apwojcik added the Windows Related changes for Windows Environments label Oct 3, 2023
@apwojcik apwojcik requested review from pfultz2 and bpickrel October 3, 2023 23:40
@codecov
Copy link

codecov bot commented Oct 4, 2023

Codecov Report

Merging #2284 (c07322e) into develop (adfc74a) will increase coverage by 0.00%.
Report is 2 commits behind head on develop.
The diff coverage is 100.00%.

❗ Current head c07322e differs from pull request most recent head 7b08c13. Consider uploading reports for the commit 7b08c13 to get more accurate results

@@           Coverage Diff            @@
##           develop    #2284   +/-   ##
========================================
  Coverage    91.45%   91.45%           
========================================
  Files          433      433           
  Lines        16175    16177    +2     
========================================
+ Hits         14793    14795    +2     
  Misses        1382     1382           
Files Coverage Δ
src/include/migraphx/op/random_uniform.hpp 100.00% <100.00%> (ø)

... and 6 files with indirect coverage changes

// for the generator is not one of short, int, long, long long, unsigned short,
// unsigned int, unsigned long, or unsigned long long. See
// https://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution.
&& !(std::is_same_v<type, unsigned char> || std::is_same_v<type, signed char>)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
&& !(std::is_same_v<type, unsigned char> || std::is_same_v<type, signed char>)
&& !(std::is_same_v<type, uint8_t> || std::is_same_v<type, int8_t>)

This should work i think

Copy link
Member

Choose a reason for hiding this comment

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

So it will evaluate to false for int8 and uint8 and would try to generate real random numbers.

This requires some more changes.

@umangyadav
Copy link
Member

This change puts restriction on what data types random uniform operator can support and should better be checked at compute_shape()

@@ -75,7 +75,16 @@ struct random_uniform

result.visit([&](auto output) {
using type = typename decltype(output)::value_type;
if constexpr(std::is_integral<type>{})
if constexpr(
std::is_integral_v<type>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should be std::is_integral<type>{}.

Copy link
Collaborator Author

@apwojcik apwojcik Oct 4, 2023

Choose a reason for hiding this comment

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

Why do we need to instantiate the static check? That is a compile-time property check from the static-if and not a runtime check. std::is_integral_v<> evaluates to std::integral<>::value, which is true for integral types and false for others. Honestly, I have not seen someone instantiating static checks.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we need to instantiate the static check?

You are instantiating the template in both cases.

  1. By constructing it we get an integral_constant instead of bool which is more powerful in some cases(such as passing this to an intermediate function).
  2. Not all type traits provide variable templates, so we need to write it like that
  3. Consistency. We shouldnt need to think about whether we will pass it to a function or whether it supports a variable template. We write it the same way everytime.

// for the generator is not one of short, int, long, long long, unsigned short,
// unsigned int, unsigned long, or unsigned long long. See
// https://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution.
&& !(std::is_same_v<type, unsigned char> || std::is_same_v<type, signed char>)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This will produce wrong results for int8 on windows. When we are using an unsupported type then we need to use a supported one and then clamp it to the supported:

template<class T>
using uniform_int_distribution = std::uniform_int_distribution<std::conditional_t<sizeof(T) == 1, int, T>>;

And then clamp it when we construct it:

uniform_int_distribution<type> dis(0, std::numeric_limits<type>::max());
std::generate(output.begin(), output.end(), [&] { return dis(gen); });

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That make sense. I will try it and let you know the result.

Copy link
Member

@umangyadav umangyadav Oct 4, 2023

Choose a reason for hiding this comment

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

Then we need to use a supported one and then clamp it to the supported:

That would violate how a random uniform should work. It should produce uniformly distributed numbers across the range.

I think we can just not support it for int8 for now. ONNX only supports for real values.

or otherwise we would need to scale it down to range of int8 and then quantize/round it to nearest int

Copy link
Collaborator

Choose a reason for hiding this comment

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

That would violate how a random uniform should work. It should produce uniformly distributed numbers across the range.

Yea "clamping" was probably a poor choice of words.

or otherwise we would need to scale it down to range of int8 and then quantize/round it to nearest int

We dont need to do that, we can pass the range we want to the constructor. This should produce the same results.

Originally we were relying on the default constructor to set the range based on the data type, but since we are using a different generator type then we need to pass the range to the constructor.

Copy link
Contributor

Choose a reason for hiding this comment

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

I strongly recommend not trying to support anything not already supported by STL or other libraries. There will be a mess of special and edge cases to consider, and any shortcoming will create subtle statistical biases that could turn into problems for our future customers at runtime. Coding statistical library functions is a specialized field that we do not want to dabble in.

Copy link
Contributor

Choose a reason for hiding this comment

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

A little more reading in StackOverflow indicates that the C++ committee never gave a mathematical reason for disallowing int8 types for uniform_int_distribution. So it could be implemented by instantiating uniform_int_distribution with range arguments(0, 255) in the contructor and then assigning to the desired type.

@migraphx-bot
Copy link
Collaborator

migraphx-bot commented Oct 4, 2023

Test Batch Rate new
2582b4
Rate old
a3cf99
Diff Compare
torchvision-resnet50 64 2,323.88 2,324.01 -0.01%
torchvision-resnet50_fp16 64 5,340.36 5,360.36 -0.37%
torchvision-densenet121 32 1,846.75 1,849.40 -0.14%
torchvision-densenet121_fp16 32 3,420.28 3,416.34 0.12%
torchvision-inceptionv3 32 1,294.02 1,295.53 -0.12%
torchvision-inceptionv3_fp16 32 2,539.94 2,542.43 -0.10%
cadene-inceptionv4 16 620.32 620.07 0.04%
cadene-resnext64x4 16 588.70 588.76 -0.01%
slim-mobilenet 64 7,211.05 7,202.96 0.11%
slim-nasnetalarge 64 236.41 236.42 -0.00%
slim-resnet50v2 64 2,555.02 2,557.15 -0.08%
bert-mrpc-onnx 8 825.63 825.82 -0.02%
bert-mrpc-tf 1 390.33 388.06 0.59%
pytorch-examples-wlang-gru 1 295.79 298.74 -0.99%
pytorch-examples-wlang-lstm 1 312.71 316.37 -1.16%
torchvision-resnet50_1 1 546.08 551.75 -1.03%
torchvision-inceptionv3_1 1 302.44 303.60 -0.38%
cadene-dpn92_1 1 353.52 355.10 -0.45%
cadene-resnext101_1 1 220.47 220.42 0.02%
slim-vgg16_1 1 224.37 224.28 0.04%
slim-mobilenet_1 1 1,499.36 1,527.30 -1.83%
slim-inceptionv4_1 1 216.59 214.59 0.93%
onnx-taau-downsample 1 306.69 306.04 0.21%
dlrm-criteoterabyte 1 21.68 21.68 -0.00%
dlrm-criteoterabyte_fp16 1 40.73 40.72 0.05%
agentmodel 1 5,822.55 5,878.03 -0.94%
unet_fp16 2 55.16 55.19 -0.06%
resnet50v1_fp16 1 758.32 764.94 -0.87%
bert_base_cased_fp16 64 970.69 970.80 -0.01%
bert_large_uncased_fp16 32 305.07 305.06 0.00%
bert_large_fp16 1 167.25 166.95 0.18%
distilgpt2_fp16 16 1,352.61 1,352.32 0.02%

This build is OK for merge ✅

@migraphx-bot
Copy link
Collaborator


    :white_check_mark:bert-mrpc-onnx: PASSED: MIGraphX meets tolerance

    :white_check_mark:bert-mrpc-tf: PASSED: MIGraphX meets tolerance

    :white_check_mark:pytorch-examples-wlang-gru: PASSED: MIGraphX meets tolerance

    :white_check_mark:pytorch-examples-wlang-lstm: PASSED: MIGraphX meets tolerance

    :white_check_mark:torchvision-resnet50_1: PASSED: MIGraphX meets tolerance

    :white_check_mark:torchvision-inceptionv3_1: PASSED: MIGraphX meets tolerance

    :white_check_mark:cadene-dpn92_1: PASSED: MIGraphX meets tolerance

    :white_check_mark:cadene-resnext101_1: PASSED: MIGraphX meets tolerance

    :white_check_mark:slim-vgg16_1: PASSED: MIGraphX meets tolerance

    :white_check_mark:slim-mobilenet_1: PASSED: MIGraphX meets tolerance

    :white_check_mark:slim-inceptionv4_1: PASSED: MIGraphX meets tolerance

    :white_check_mark:dlrm-criteoterabyte: PASSED: MIGraphX meets tolerance

    :white_check_mark:agentmodel: PASSED: MIGraphX meets tolerance

    :white_check_mark:unet: PASSED: MIGraphX meets tolerance

    :white_check_mark:resnet50v1: PASSED: MIGraphX meets tolerance

🔴bert_base_cased_fp16: FAILED: MIGraphX is not within tolerance - check verbose output


🔴bert_large_uncased_fp16: FAILED: MIGraphX is not within tolerance - check verbose output


    :white_check_mark:bert_large: PASSED: MIGraphX meets tolerance

🔴distilgpt2_fp16: FAILED: MIGraphX is not within tolerance - check verbose output

Copy link
Contributor

@bpickrel bpickrel left a comment

Choose a reason for hiding this comment

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

Can add a check here if the input type is one of the disallowed ones (int8, etc.) and throw an exception.

@pfultz2
Copy link
Collaborator

pfultz2 commented Oct 6, 2023

Can add a check here if the input type is one of the disallowed ones (int8, etc.) and throw an exception.

No, our reference implementation should support all types.

// for the generator is not one of short, int, long, long long, unsigned short,
// unsigned int, unsigned long, or unsigned long long. See
// https://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution.
if constexpr(std::is_same_v<type, unsigned char> || std::is_same_v<type, signed char>)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This could be written as std::is_integral<type>{} and sizeof(type) == 1, which I think is simpler.

If not, then it should be std::is_same<type, unsigned char>{} or std::is_same<type, signed char>{} to match the style used throughout migraphx.

@apwojcik apwojcik requested a review from pfultz2 October 9, 2023 15:00
@causten causten merged commit 136df3d into develop Oct 11, 2023
@causten causten deleted the windows_random_distribution branch October 11, 2023 03:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Windows Related changes for Windows Environments
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants