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

[BUG] String to float casting mismatch with cpu in different way from compatibility doc #10037

Closed
thirtiseven opened this issue Dec 13, 2023 · 0 comments · Fixed by #10156
Closed
Assignees
Labels
documentation Improvements or additions to documentation

Comments

@thirtiseven
Copy link
Collaborator

thirtiseven commented Dec 13, 2023

Describe the bug

Our compatibility doc is outdated after we switched string to float to new kernel.

The results of current code mismatch slightly with cpu but in different way from compatibility doc. I'm not sure if we are aware of this. I think the cpu did things correctly because the cpu results are also matched with python.

Steps/Code to reproduce bug
Compatibility doc:

### String to Float

Casting from string to floating-point types on the GPU returns incorrect results when the string
represents any number in the following ranges. In both cases the GPU returns `Double.MaxValue`. The
default behavior in Apache Spark is to return `+Infinity` and `-Infinity`, respectively.

- `1.7976931348623158E308 <= x < 1.7976931348623159E308`
- `-1.7976931348623159E308 < x <= -1.7976931348623158E308`

Also, the GPU does not support casting from strings containing hex values.

This configuration is enabled by default. To disable this operation on the GPU set
[`spark.rapids.sql.castStringToFloat.enabled`](additional-functionality/advanced_configs.md#sql.castStringToFloat.enabled) to `false`.
My test code

Hack into DoubleGen to make it produce string:

class DoubleGen(DataGen):
    """Generate doubles, which some built in corner cases."""
    def __init__(self, min_exp=DOUBLE_MIN_EXP, max_exp=DOUBLE_MAX_EXP, no_nans=False,
            nullable=True, special_cases = None):
        self._min_exp = min_exp
        self._max_exp = max_exp
        self._no_nans = no_nans
        self._use_full_range = (self._min_exp == DOUBLE_MIN_EXP) and (self._max_exp == DOUBLE_MAX_EXP)
        if special_cases is None:
            special_cases = [
                self.make_from(1, self._max_exp, DOUBLE_MAX_FRACTION),
                self.make_from(0, self._max_exp, DOUBLE_MAX_FRACTION),
                self.make_from(1, self._min_exp, DOUBLE_MAX_FRACTION),
                self.make_from(0, self._min_exp, DOUBLE_MAX_FRACTION)
            ]
            if self._min_exp <= 0 and self._max_exp >= 0:
                special_cases.append(0.0)
                special_cases.append(-0.0)
            if self._min_exp <= 3 and self._max_exp >= 3:
                special_cases.append(1.0)
                special_cases.append(-1.0)
            if not no_nans:
                special_cases.append(float('inf'))
                special_cases.append(float('-inf'))
                special_cases.append(float('nan'))
                special_cases.append(NEG_DOUBLE_NAN_MAX_VALUE)
-      super().__init__(DoubleType(), nullable=nullable, special_cases=special_cases)
+      super().__init__(StringType(), nullable=nullable, special_cases=special_cases)

    def _cache_repr(self):
        return super()._cache_repr() + '(' + str(self._min_exp) + ',' + str(self._max_exp) + ',' + str(self._no_nans) + ')'

    @staticmethod
    def make_from(sign, exp, fraction):
        sign = sign & 1 # 1 bit
        exp = (exp + 1023) & 0x7FF # add bias and 11 bits
        fraction = fraction & DOUBLE_MAX_FRACTION
        i = (sign << 63) | (exp << 52) | fraction
        p = struct.pack('L', i)
        ret = struct.unpack('d', p)[0]
        return ret

    def _fixup_nans(self, v):
        if self._no_nans and (math.isnan(v) or v == math.inf or v == -math.inf):
            v = None if self.nullable else 0.0
        return v

    def start(self, rand):
        if self._use_full_range:
            def gen_double():
                i = rand.randint(LONG_MIN, LONG_MAX)
                p = struct.pack('l', i)
-              return self._fixup_nans(struct.unpack('d', p)[0])
+              return str(self._fixup_nans(struct.unpack('d', p)[0]))
            self._start(rand, gen_double)
        else:
            def gen_part_double():
                sign = rand.getrandbits(1)
                exp = rand.randint(self._min_exp, self._max_exp)
                fraction = rand.getrandbits(52)
-              return self._fixup_nans(self.make_from(sign, exp, fraction))
+              return str(self._fixup_nans(self.make_from(sign, exp, fraction)))
            self._start(rand, gen_part_double)

and run test:

def test_cast_string_to_double():
    assert_gpu_and_cpu_are_equal_collect(
        lambda spark: unary_op_df(spark, DoubleGen()).selectExpr("cast(a as double)"),
        conf = {"spark.rapids.sql.castStringToFloat.enabled": True})
Results (part)
------------------------------------- Captured stdout call -------------------------------------
### CPU RUN ###
### GPU RUN ###
### COLLECT: GPU TOOK 0.7212874889373779 CPU TOOK 3.1057026386260986 ###
--- CPU OUTPUT
+++ GPU OUTPUT
@@ -4,17 +4,17 @@
 Row(a=-2.444938694383766e+286)
 Row(a=-5.7584082229265876e-18)
 Row(a=1.574944514174226e+43)
-Row(a=-1.4650819429118621e-127)
+Row(a=-1.465081942911862e-127)
 Row(a=-7.75440264752919e+269)
 Row(a=2.7620954776080103e-86)
 Row(a=2.506675047410682e-42)
-Row(a=-1.48853526504395e-11)
+Row(a=-1.4885352650439498e-11)
 Row(a=-3.43240182714965e-178)
 Row(a=inf)
 Row(a=-2.7190128283058926e-168)
-Row(a=-3.2943333374066515e+156)
+Row(a=-3.294333337406652e+156)
 Row(a=7.463662720127636e-240)
-Row(a=-8.540050848524817e-232)
+Row(a=-8.540050848524818e-232)
 Row(a=1.7976931348623157e+308)
 Row(a=8.263702939928063e-69)
 Row(a=None)
@@ -22,93 +22,93 @@
 Row(a=-7.865537250753515e+272)
 Row(a=-2.514831252461456e+126)
 Row(a=-4.7896272228726344e-250)
-Row(a=-1.6514316325970003e+42)
+Row(a=-1.6514316325970006e+42)
 Row(a=None)
 Row(a=8.045078032082626e-107)
 Row(a=8.880334404284274e-166)
 Row(a=-3.805850739666648e+305)
 Row(a=None)
-Row(a=2.9508008807315855e+296)
-Row(a=-5.17912046297054e-213)
-Row(a=-5.678542704554978e+76)
+Row(a=2.950800880731586e+296)
+Row(a=-5.1791204629705395e-213)
+Row(a=-5.678542704554979e+76)
 Row(a=1.0)
-Row(a=1.3662155151282655e-12)
+Row(a=1.3662155151282657e-12)
 Row(a=-2.3041080882412546e+285)
 Row(a=-1.7064141837290472e-93)
 Row(a=-1.7209261466767005e-141)
-Row(a=6.153874993929035e+221)
-Row(a=-1.9523248958527442e-41)
-Row(a=4.8504608452517354e-60)
+Row(a=6.1538749939290354e+221)
+Row(a=-1.952324895852744e-41)
+Row(a=4.850460845251735e-60)
 Row(a=-7.340795276278201e+109)
-Row(a=-1.4741991231472253e+242)
+Row(a=-1.474199123147225e+242)
 Row(a=1.7976931348623157e+308)
 Row(a=-2.3033715538534124e-196)
 Row(a=-2.7679085498913265e-115)
-Row(a=3.684860973603985e+140)
-Row(a=4.4501477170144023e-308)
-Row(a=-5.238087265542425e-102)
-Row(a=4.083675965437869e+98)
-Row(a=5.667700294110108e-178)
+Row(a=3.6848609736039846e+140)
+Row(a=4.450147717014402e-308)
+Row(a=-5.2380872655424245e-102)
+Row(a=4.0836759654378693e+98)
+Row(a=5.667700294110107e-178)
 Row(a=7.516125161953722e-142)
 Row(a=-4.7970013557641394e-188)
 Row(a=-3.6813417309176673e-50)
 Row(a=-8.513295515982125e-209)
 Row(a=-3.6658695241704135e-52)
-Row(a=-1.627450612708682e-257)
+Row(a=-1.6274506127086822e-257)
 Row(a=2.4462371056476875e-134)
 Row(a=-6.5323324224403105e-164)
 Row(a=-5.5817046352192334e-217)
-Row(a=2.901226594440994e+203)
-Row(a=2.7412284262316342e-251)
+Row(a=2.9012265944409942e+203)
+Row(a=2.7412284262316346e-251)
 Row(a=None)
 Row(a=2.513617208453495e-53)
 Row(a=1.0127183423706363e-10)
-Row(a=-2.4267107459303328e+243)
-Row(a=-1.1076001338869503e+179)
+Row(a=-2.426710745930333e+243)
+Row(a=-1.1076001338869505e+179)
 Row(a=2.7453487882698745e+71)
 Row(a=-1.291354755907272e-33)
 Row(a=3.3329412626980284e-47)
-Row(a=1.0371044719189557e+256)
-Row(a=2.4340586250245606e-247)
+Row(a=1.0371044719189555e+256)
+Row(a=2.434058625024561e-247)
 Row(a=-7.385293468971211e-302)
 Row(a=4.449176862434377e-84)
 Row(a=-3.306487448329129e-41)
-Row(a=-2.506619782481997e-120)
+Row(a=-2.5066197824819972e-120)
 Row(a=5.620645430768326e+137)
 Row(a=-8.639506985412191e-269)
 Row(a=None)
-Row(a=-6.1744384134096995e-220)
+Row(a=-6.174438413409699e-220)
 Row(a=inf)
 Row(a=-4.3427259082918814e-192)
 Row(a=4.977188453132103e+98)
 Row(a=-1.1210490827648647e+197)
 Row(a=None)
-Row(a=-2.3707776970906663e+129)
-Row(a=-4.656853405813435e+256)
-Row(a=10866077750.339087)
+Row(a=-2.3707776970906666e+129)
+Row(a=-4.6568534058134355e+256)
+Row(a=10866077750.339088)
 Row(a=-0.0)
 Row(a=1.0942100092394046e-116)
-Row(a=-1.7726429734988672e-90)
+Row(a=-1.772642973498867e-90)
 Row(a=-3.5557391852660547e-22)
-Row(a=-1.167597451577837e-151)
-Row(a=1.557577390551627e+116)
+Row(a=-1.1675974515778368e-151)
+Row(a=1.5575773905516269e+116)
 Row(a=7.508138672445844e-178)
 Row(a=-1.1119140526777427e+197)
 Row(a=None)
 Row(a=-2.9863434162694357e-189)
 Row(a=0.0)
-Row(a=4.921534325965825e-191)
+Row(a=4.9215343259658247e-191)
 Row(a=-8.516977110855943e+92)
 Row(a=-4.253488048758416e-123)
 Row(a=2.9918407544363216e-282)
 Row(a=1.2397221609902193e+201)
 Row(a=None)
-Row(a=-3.379188842468723e-176)
-Row(a=1.609881725640588e-121)
+Row(a=-3.3791888424687235e-176)
+Row(a=1.6098817256405882e-121)
 Row(a=-1.3370589664670525e+235)
 Row(a=-2.0174133864490337e+35)
 Row(a=5.426259688369346e+192)
-Row(a=1.196234961412452e+271)
+Row(a=1.1962349614124521e+271)
 Row(a=-5.954852315194037e-291)
 Row(a=2.344390797125135e+269)
 Row(a=-2.0319762991013286e-138)
@@ -117,22 +117,22 @@
 Row(a=inf)
 Row(a=None)
 Row(a=-2.7827893151210605e+85)
-Row(a=-6.655392632858402e-223)
-Row(a=-6.5746109383224925e+252)
-Row(a=1.7071127170594405e+128)
-Row(a=1.2095508002494765e-239)
+Row(a=-6.6553926328584016e-223)
+Row(a=-6.574610938322493e+252)
+Row(a=1.7071127170594404e+128)
+Row(a=1.2095508002494763e-239)
 Row(a=-4.220687287151834e+63)
 Row(a=1.7976931348623157e+308)
-Row(a=9.167195839100168e-181)
+Row(a=9.167195839100169e-181)
 Row(a=-1.6062983379106216e+53)
-Row(a=-2.178331034417628e-14)
-Row(a=None)
-Row(a=-7.111231129842083e-43)
+Row(a=-2.1783310344176277e-14)
+Row(a=None)
+Row(a=-7.111231129842084e-43)
 Row(a=-4.4829324631771155e+251)
-Row(a=2.5619910020305246e-175)
+Row(a=2.561991002030525e-175)
 Row(a=3.458784645664513e-252)
 Row(a=-1.9957040121199044e+236)
-Row(a=6.439593546943697e+276)
+Row(a=6.439593546943696e+276)
 Row(a=-1.7976931348623157e+308)
 Row(a=5.7924144535247705e+87)
 Row(a=7.628478435428954e+236)
@@ -141,14 +141,14 @@
 Row(a=1.4500280441827833e-180)
 Row(a=1.5624792575692676e+68)
 Row(a=7.534744933666472e+138)
-Row(a=4.530654892147572e-86)
+Row(a=4.5306548921475725e-86)
 Row(a=None)
 Row(a=2.2738527704315084e+33)
 Row(a=-3.6165828499406312e-62)
-Row(a=4.221878157848311e-271)
+Row(a=4.2218781578483106e-271)
 Row(a=0.8893291790421467)
 Row(a=-3.885162553158353e-222)
-Row(a=-4.5770669429086804e+83)
+Row(a=-4.57706694290868e+83)
 Row(a=3.502003343948888e+147)
 Row(a=-2.452541399898191e+125)
 Row(a=-749265.7514116293)
@@ -156,39 +156,39 @@
 Row(a=6.611429781969025e-303)
 Row(a=-8.950270296481439e+33)
 Row(a=2.3647540446635172e+63)
-Row(a=8.781904009628652e-207)
+Row(a=8.781904009628653e-207)
 Row(a=5.154215708999913e-199)
 Row(a=-0.0)
 Row(a=-0.0)
-Row(a=-1.3617859638086872e-111)
+Row(a=-1.361785963808687e-111)
 Row(a=5.169880548381539e+31)
 Row(a=3.1755691192645254e+103)
-Row(a=1.113112495210162e+87)
-Row(a=-4.000807959029876e+264)
-Row(a=-8.169762018067182e+71)
+Row(a=1.1131124952101619e+87)
+Row(a=-4.0008079590298755e+264)
+Row(a=-8.169762018067183e+71)
 Row(a=-inf)
 Row(a=-8.977644760998437e+96)
-Row(a=-1.666497502504461e-284)
+Row(a=-1.6664975025044608e-284)
 Row(a=-1.1366088306214133e+183)
 Row(a=2.243149336108745e-177)
-Row(a=-3.213854097619208e-231)
+Row(a=-3.2138540976192076e-231)
 Row(a=nan)
 Row(a=6.547388116127832e+160)
 Row(a=1.5254723288457914e+28)
 Row(a=7.565575071372013e-70)
-Row(a=2.4001687718546542e+48)
+Row(a=2.4001687718546545e+48)
 Row(a=5.089511464499697e+161)
 Row(a=-6.514392323163265e+86)
-Row(a=-2.2417550821133338e-253)
+Row(a=-2.2417550821133335e-253)
 Row(a=-1.7976931348623157e+308)
 Row(a=-6.9948998437040944e-12)
-Row(a=1.0698487807057677e-10)
+Row(a=1.0698487807057676e-10)
 Row(a=2.422085805933065e-35)
 Row(a=8.171354150098198e+23)
 Row(a=1.4884059037085738e-240)
 Row(a=1.6765940308663088e-174)
 Row(a=1.4408719880897215e+289)
-Row(a=-2.77532626370512e+180)
+Row(a=-2.7753262637051204e+180)
 Row(a=-7.943422349876187e-100)
 Row(a=-1.7976931348623157e+308)
 Row(a=-6.334067836915482e+138)
@@ -198,37 +198,37 @@
 Row(a=-3.0107518518093684e-201)
 Row(a=7.317364874449711e-145)
 Row(a=-inf)
-Row(a=7.366189170788555e+133)
-Row(a=-6.1493924915122924e+215)
-Row(a=5.6733875431420956e+32)
-Row(a=-3.6825945696485052e+25)
-Row(a=-0.00028072021479159996)
-Row(a=3.1425340938563156e-211)
-Row(a=4.064422438002872e-150)
+Row(a=7.366189170788554e+133)
+Row(a=-6.149392491512293e+215)
+Row(a=5.673387543142096e+32)
+Row(a=-3.6825945696485057e+25)
+Row(a=-0.0028072021479159997)
+Row(a=3.1425340938563152e-211)
+Row(a=4.0644224380028723e-150)
 Row(a=1.6163370185528936e+84)
 Row(a=-1.0454277307942211e-157)
 Row(a=7.798801388054893e+84)
 Row(a=2.290222068453895e-135)
 Row(a=-6.771851095573596e+258)
-Row(a=2.0667969905244359e+248)
-Row(a=9.001560063763786e-91)
+Row(a=2.066796990524436e+248)
+Row(a=9.001560063763785e-91)
 Row(a=-2.6944240753121314e-262)
 Row(a=None)
 Row(a=-6.4121655386426414e+289)
-Row(a=-6.969102633738303e-152)
+Row(a=-6.969102633738302e-152)
 Row(a=2.0535281030094401e-178)
-Row(a=1.382008748800463e+283)
-Row(a=-4.7455144983372153e-29)
+Row(a=1.3820087488004629e+283)
+Row(a=-4.745514498337215e-29)
 Row(a=-3.3009419756139006e-136)
-Row(a=-4.679946395996019e+198)
+Row(a=-4.6799463959960195e+198)
 Row(a=1.0)
-Row(a=1.61413525523654e-114)
-Row(a=-9.829942584821753e+165)
+Row(a=1.6141352552365399e-114)
+Row(a=-9.829942584821751e+165)
 Row(a=-1.2664671631639414e+307)
 Row(a=2.8746710834914848e+17)
 Row(a=0.0)
-Row(a=-3.066942612994425e+71)
-Row(a=-7.703491708886962e-34)
+Row(a=-3.0669426129944254e+71)
+Row(a=-7.703491708886963e-34)
 Row(a=4.481641017876088e+79)
 Row(a=1.860738064378745e-248)
 Row(a=7.685354716382759e-293)
@@ -236,68 +236,68 @@
 Row(a=1.4888495862001094e+247)
 Row(a=8.117651931128959e-78)
 Row(a=1.14791251032072e+161)
-Row(a=-3.6322236354962854e+61)
+Row(a=-3.632223635496286e+61)
 Row(a=-2.651097358154928e+275)
 Row(a=4.634010153714723e-122)
-Row(a=5.582118135067105e-179)
-Row(a=1.0117761531437894e+121)
+Row(a=5.5821181350671056e-179)
+Row(a=1.0117761531437893e+121)
 Row(a=4.3782872140953233e+133)
 Row(a=-8.469628501376688e-274)
 Row(a=3.1908531879398566e-97)
 Row(a=-3.7558433335821584e+71)
 Row(a=-1.851294012235031e+115)
 Row(a=2.7541580078395727e-22)
-Row(a=6.181301535394411e+291)
+Row(a=6.181301535394412e+291)
 Row(a=-2.9417354572406184e-36)
 Row(a=1.5856428044505228e-287)
 Row(a=5.358067516866644e+35)
-Row(a=3.3303065678712876e+199)
-Row(a=8.035322254903415e+180)
+Row(a=3.330306567871288e+199)
+Row(a=8.035322254903414e+180)
 Row(a=0.0)
 Row(a=1.475449885904613e+210)
 Row(a=1.696147149874758e+140)
 Row(a=-3.1144214107700516e+194)
 Row(a=5.066144730819082e+22)
-Row(a=-3.119766292749619e+305)
+Row(a=-3.1197662927496193e+305)
 Row(a=nan)
 Row(a=1.0)
 Row(a=9.794481246526591e+168)
-Row(a=5.719448325818015e+169)
+Row(a=5.7194483258180154e+169)
 Row(a=8.077779304470655e-144)
 Row(a=-1.6097312985047952e+282)
 Row(a=-3.5392137665840267e-121)
-Row(a=-7.664407409617414e-284)
-Row(a=inf)
-Row(a=-4.4501477170144023e-308)
-Row(a=-6.2388245174258005e+305)
+Row(a=-7.664407409617413e-284)
+Row(a=inf)
+Row(a=-4.450147717014402e-308)
+Row(a=-6.238824517425801e+305)
 Row(a=3.2318028698575853e+199)
 Row(a=-7.203731798403974e-280)
-Row(a=-8.311728052456158e-54)
-Row(a=-3.8635116323207874e-220)
+Row(a=-8.311728052456157e-54)
+Row(a=-3.863511632320787e-220)
 Row(a=4.396367214904539e+147)
-Row(a=6.0807658220623955e+90)
+Row(a=6.080765822062395e+90)
 Row(a=-8.231747489926172e-53)
 Row(a=2.4969536589253004e-289)
-Row(a=-9.366461106677521e-85)
+Row(a=-9.36646110667752e-85)
 Row(a=3.122448403726651e-65)
 Row(a=-1.8441634003273365e+184)

Expected behavior
At least we can note how it mismatches with cpu in the compatibility doc. We may also want to fix it to fully match cpu one day.

@thirtiseven thirtiseven added bug Something isn't working ? - Needs Triage Need team to review and classify labels Dec 13, 2023
@mattahrens mattahrens added documentation Improvements or additions to documentation and removed bug Something isn't working labels Dec 19, 2023
@mattahrens mattahrens removed the ? - Needs Triage Need team to review and classify label Dec 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants