diff --git a/java/src/main/java/ai/rapids/cudf/ColumnVector.java b/java/src/main/java/ai/rapids/cudf/ColumnVector.java index a15817f250f2..465294ab97d4 100644 --- a/java/src/main/java/ai/rapids/cudf/ColumnVector.java +++ b/java/src/main/java/ai/rapids/cudf/ColumnVector.java @@ -819,42 +819,6 @@ public ColumnVector castTo(DType type) { return super.castTo(type); } - /** - * Replace the null mask of a column. The resultant null mask is the bitwise {@code mergeOp} of - * null masks in the columns given as arguments, AND-ed with this column's existing null mask. - * - * If applying the null mask would be a no-op, the original column is returned with incremented - * refcount. Otherwise, a deep copy of the column is made. - * - * For STRUCT columns the new mask is also pushed down into every descendant column, to - * stay consistent with the parent. For LIST/STRING columns the resultant offsets are - * sanitized to not contain any non-empty nulls. - * - * If {@code columns} is empty, the column is returned unchanged (no-op). - * - * @param mergeOp binary operator (either BITWISE_AND or BITWISE_OR) - * @param columns array of columns whose null masks are merged, must have identical number of rows. - * @return the new ColumnVector with merged null mask. - */ - @Override - public ColumnVector mergeAndSetValidity(BinaryOp mergeOp, ColumnView... columns) { - assert mergeOp == BinaryOp.BITWISE_AND || mergeOp == BinaryOp.BITWISE_OR : "Only BITWISE_AND and BITWISE_OR supported right now"; - long[] columnViews = new long[columns.length]; - long size = getRowCount(); - - for (int i = 0; i < columns.length; i++) { - assert columns[i] != null : "Column vectors passed may not be null"; - assert columns[i].getRowCount() == size : "Row count mismatch, all columns must be the same size"; - columnViews[i] = columns[i].getNativeView(); - } - - long mergeOutput = bitwiseMergeAndSetValidity(getNativeView(), columnViews, mergeOp.nativeId); - if (mergeOutput == 0) { // no-op, the current column is unchanged - return incRefCount(); - } - return new ColumnVector(mergeOutput); - } - ///////////////////////////////////////////////////////////////////////////// // NATIVE METHODS ///////////////////////////////////////////////////////////////////////////// @@ -878,19 +842,6 @@ private static native long makeListFromOffsets(long childHandle, long offsetsHan private static native long concatenate(long[] viewHandles) throws CudfException; - /** - * Native method to replace a column's null mask. The null mask is the - * bitwise merge of the null masks in the columns given as arguments. - * - * @param baseHandle column view of the column whose null mask is being replaced. - * @param viewHandles array of views whose null masks are merged, must have identical row counts. - * @param mergeOp native id of the binary op (BITWISE_AND or BITWISE_OR) used to merge the null masks. - * @return native handle of the resulting column, or 0 when the original is unchanged - * (a no-op) and no copied column was produced. - */ - private static native long bitwiseMergeAndSetValidity(long baseHandle, long[] viewHandles, - int mergeOp) throws CudfException; - /** * Native method to concatenate columns of lists horizontally (row by row), combining a row * from each column into a single list. diff --git a/java/src/main/java/ai/rapids/cudf/ColumnView.java b/java/src/main/java/ai/rapids/cudf/ColumnView.java index 4c00bf3c4e5d..cbbc1cf78397 100644 --- a/java/src/main/java/ai/rapids/cudf/ColumnView.java +++ b/java/src/main/java/ai/rapids/cudf/ColumnView.java @@ -883,9 +883,9 @@ public final ColumnVector normalizeNANsAndZeros() { * Replace the null mask of a column. The resultant null mask is the bitwise {@code mergeOp} of * null masks in the columns given as arguments, AND-ed with this column's existing null mask. * - * If applying the null mask would be a no-op, the original column is returned with incremented - * refcount. Otherwise, a deep copy of the column is made (for a non-owning ColumnView, a deep copy - * must be made in either case). + * If applying the null mask would be a no-op and this is a {@link ColumnVector}, the original + * column is returned with incremented refcount. Otherwise, a deep copy of the column is made. + * For a non-owning ColumnView, a deep copy must be made in either case. * * For STRUCT columns the new mask is also pushed down into every descendant column, to * stay consistent with the parent. For LIST/STRING columns the resultant offsets are @@ -896,10 +896,8 @@ public final ColumnVector normalizeNANsAndZeros() { * @param mergeOp binary operator (either BITWISE_AND or BITWISE_OR) * @param columns array of columns whose null masks are merged, must have identical number of rows. * @return the new ColumnVector with merged null mask. - * @deprecated Use {@link ColumnVector#mergeAndSetValidity(BinaryOp, ColumnView...)} instead. */ - @Deprecated - public ColumnVector mergeAndSetValidity(BinaryOp mergeOp, ColumnView... columns) { + public final ColumnVector mergeAndSetValidity(BinaryOp mergeOp, ColumnView... columns) { assert mergeOp == BinaryOp.BITWISE_AND || mergeOp == BinaryOp.BITWISE_OR : "Only BITWISE_AND and BITWISE_OR supported right now"; long[] columnViews = new long[columns.length]; long size = getRowCount(); @@ -912,6 +910,8 @@ public ColumnVector mergeAndSetValidity(BinaryOp mergeOp, ColumnView... columns) long mergeOutput = bitwiseMergeAndSetValidity(getNativeView(), columnViews, mergeOp.nativeId); if (mergeOutput == 0) { // no-op, the current column is unchanged + // For a ColumnVector, copyToColumnVector() is simply an incRefCount(), making this + // zero-copy. Otherwise for a ColumnView, we must materialize an owning column. return copyToColumnVector(); } return new ColumnVector(mergeOutput); diff --git a/java/src/main/native/src/ColumnVectorJni.cpp b/java/src/main/native/src/ColumnVectorJni.cpp index e42dc9a4e1cd..866fc58ce6a6 100644 --- a/java/src/main/native/src/ColumnVectorJni.cpp +++ b/java/src/main/native/src/ColumnVectorJni.cpp @@ -7,11 +7,9 @@ #include "dtype_utils.hpp" #include "jni_utils.hpp" -#include #include #include #include -#include #include #include #include @@ -22,7 +20,6 @@ #include #include #include -#include #include #include @@ -432,56 +429,6 @@ JNIEXPORT jlong JNICALL Java_ai_rapids_cudf_ColumnVector_sha1(JNIEnv* env, JNI_CATCH(env, 0); } -JNIEXPORT jlong JNICALL Java_ai_rapids_cudf_ColumnVector_bitwiseMergeAndSetValidity( - JNIEnv* env, jobject j_object, jlong base_column, jlongArray column_handles, jint bin_op) -{ - JNI_NULL_CHECK(env, base_column, "base column native handle is null", 0); - JNI_NULL_CHECK(env, column_handles, "array of column handles is null", 0); - JNI_TRY - { - cudf::jni::auto_set_device(env); - cudf::column_view* original_column = reinterpret_cast(base_column); - cudf::jni::native_jpointerArray n_cudf_columns(env, column_handles); - - auto const op = static_cast(bin_op); - if (op != cudf::binary_operator::BITWISE_AND && op != cudf::binary_operator::BITWISE_OR) { - JNI_THROW_NEW(env, cudf::jni::ILLEGAL_ARG_EXCEPTION_CLASS, "Unsupported merge operation", 0); - } - - // If we have no columns to merge, return the original column unchanged. - // 0 signals to the caller that this was a no-op. - if (n_cudf_columns.size() == 0) { return 0; } - - // Merge the null masks of the provided columns using the binary op. - auto const cudf_columns = n_cudf_columns.get_dereferenced(); - auto const input_table = cudf::table_view{cudf_columns}; - auto [merge_mask, merge_null_count] = op == cudf::binary_operator::BITWISE_AND - ? cudf::bitmask_and(input_table) - : cudf::bitmask_or(input_table); - - // If the merge null count is 0, the merged mask is all-valid - either the binop returned - // an empty mask or the mask was allocated but had no nulls. - // in either case this is a no-op on the original mask and we can return as-is. - if (merge_null_count == 0) { return 0; } - - auto copy = std::make_unique(*original_column); - - // Now apply the merged mask to the original by AND-ing it into - // the parent's null mask. This will also push it down through any - // descendants for STRUCTs so that child masks stay consistent , - // and fix offsets for LIST/STRINGs by purging non-empty nulls. - auto result = cudf::structs::detail::superimpose_and_sanitize_nulls( - static_cast(merge_mask.data()), - merge_null_count, - std::move(copy), - cudf::get_default_stream(), - cudf::get_current_device_resource_ref()); - - return release_as_jlong(result); - } - JNI_CATCH(env, 0); -} - //////// // Native methods specific to cudf::column. These either take or return a cudf::column // instead of a cudf::column_view so they need to be used with caution. These should