Skip to content
This repository has been archived by the owner on Feb 2, 2024. It is now read-only.

Fix for head_index_parallel test failing if executed twice and with MPI #127

Merged

Conversation

kozlov-alexey
Copy link
Contributor

No description provided.

kozlov-alexey and others added 13 commits July 18, 2019 16:18
[BUG] Fixed problems with generation parquet files (IntelPython#93)
Fixing issue with named series handling in fillna (IntelPython#95)
Merging commits from public repo
Add tests for Series arithmetic and comparison methods and fix Series…
The test 'test_series_head_index_parallel2' from TestSeries was hanging
when executed twice on Windows with MPI run and number of processors equal to 3:
	mpiexec -n 3 python -u -m unittest $TESTS_TO_RUN
	where TESTS_TO_RUN="hpat.tests.TestSeries.test_series_head_parallel1 unittest hpat.tests.TestSeries.test_series_head_parallel1"

The problem was in wrong calculation of n_chars in const_slice_getitem
overload for StringArrayType, which was not correctly reduced by all
processors and had wrong value in some cases. The fix is to simplify the
implementation and to have workers decide whether their part of the array
has to be sent or not basing on the position of their subset in the total
array and the size of requested slice.
Copy link
Contributor

@shssf shssf left a comment

Choose a reason for hiding this comment

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

Please, next time, do not intermix code style changes with PR changes.

@kozlov-alexey
Copy link
Contributor Author

@shssf OK, next time I won't. I just started fixing newly introduced issues and forgot to stop. :)

displs = np.empty(1, np.int32)
displs_char = np.empty(1, np.int32)
displs = np.empty(n_loc, np.int32)
displs_char = np.empty(n_loc, np.int32)

Copy link
Contributor

Choose a reason for hiding this comment

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

displs and displs_char are needed on root only and will be set properly in the following if-condition.
This is just a dummy for all other ranks to keep the code simple.

A proper solution would make c_gatherv accept None or 0 for non-root ranks. This might require some extra work like casting...

BTW: n_loc is definitely not the right value anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@fschlimb Yes, I left it accidentally, it's not needed at all. I can change it to 0 size array, since the size doesn't really matter, or we can even remove these two lines as redundant. I'm not sure I got how to update c_gatherv. It accepts void*, but in gatherv_overload we have to keep the type consistent, so if we assign something to displs it it should have the same type as in the root branch. Shall I remove these lines?

Copy link
Contributor

@fschlimb fschlimb Aug 29, 2019

Choose a reason for hiding this comment

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

I don't think you can remove them because you need something type-stable to pass it to c_gatherv. If a zero-sized array works that'd be great.

If numba does not automatically cast 0 to a pointer when the C-function expects a void* you can write an intrinsic which returns a ((void*)0) and use that in the function you @jit/@overload. Maybe like this

@intrinsic
def mk_int32_null(typingctx):
    def codegen(context, builder, sig, args):
        zero = context.get_constant(types.int32, 0)
        return builder.inttoptr(zero, llvmlite.ir.IntType(32))
    return numba.types.int32, codegen

It's probably not worth the effort, though. You will probably need yet another layer between the caller and the ExternFunction. In particular if passing an empty array works we should just use that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It looks like else branch can be remove (I tried and test still passes). Inserting "print(my_arr)" into it shows empty array on non root ranks (i.e. it's not even needed to assign something in the else branch), looks like Numba default constructs the object, once it's able to infer the type? I failed to find where the magic comes from in the IR. I suggest keeping latest commit with zero size array which works too.

hpat/distributed_api.py Show resolved Hide resolved
@@ -872,14 +859,38 @@ def test_impl(S):
self.assertEqual(count_array_REPs(), 0)
self.assertEqual(count_parfor_REPs(), 0)

def test_series_dist_input2(self):
def test_impl(S):
Copy link
Contributor

Choose a reason for hiding this comment

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

Pls add a doc-string saying what it's testing.

self.assertEqual(count_array_REPs(), 0)
self.assertEqual(count_parfor_REPs(), 0)

def test_series_dist_input3(self):
Copy link
Contributor

Choose a reason for hiding this comment

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

Pls add a doc-string saying what it's testing.

# get total characters for allocation
n_chars = np.uint64(0)
if k > count:
if k > start:
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like the code from if-statement is also valid for else-statement. I mean we can avoid if-else branching here and leave only code from the if-statement.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@densmirn That's true, thank you. But I think keeping if statement simplifies code. I will remove the redundant "max(k - start, 0)" in the first branch though, i.e. will make it this:

        if k > start:
            # if slice end is beyond the start of this subset we have to send our elements
            my_end = min(count, k - start)
            my_arr = arr[:my_end]
        else:
            my_arr = arr[:0]

@kozlov-alexey kozlov-alexey force-pushed the feature/fix_head_index_parallel branch from 1ace757 to 8dc13c7 Compare August 29, 2019 10:16
@fschlimb
Copy link
Contributor

manually triggered azure succeeded: https://dev.azure.com/IntelPython/HPAT/_build/results?buildId=45

@kozlov-alexey kozlov-alexey deleted the feature/fix_head_index_parallel branch October 4, 2019 14:47
kozlov-alexey added a commit to kozlov-alexey/sdc that referenced this pull request Oct 4, 2019
…PI (IntelPython#127)

* Fix for Series.head and distribution of StringArrayType as a const_slice
  (fixing wrong calculation of n_chars in const_slice_getitem)
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants