Demo
Use JavaVectorHelper to scan a single file or the entire project. This demo showcases how to scan a single file to find vectorizable code snippets. The sample code performs calculations and assigns values between arrays.
- Check the source file before scanning. See Figure 1.
- Execute the for loop in the BpVectorReorderer.java file.Figure 2 Execution before code reconstruction
- Use JavaVectorHelper to identify the code in bold and replace it with vectorized code.
private static boolean centroidValid( float[] centroid, FloatVectorValues vectors, IntsRef ids, int count) throws IOException { // recompute centroid to check the incremental calculation float[] check = new float[centroid.length]; computeCentroid(ids, vectors, check, VectorSimilarityFunction.EUCLIDEAN); for (int i = 0; i < check.length; ++i) { float diff = Math.abs(check[i] - centroid[i]); if (diff > 1e-4) { return false; } } return true; } private static void swapIdsAndCentroids( IntsRef ids, int from, int to, int midPoint, FloatVectorValues vectors, float[] leftCentroid, float[] rightCentroid, float[] scratch, int count, VectorSimilarityFunction vectorScore) throws IOException { assert from < to; int[] idArr = ids.ints; int fromId = idArr[from]; int toId = idArr[to]; // Now update the centroids, this makes things much faster than invalidating it and having to // recompute on the next iteration. Should be faster than full recalculation if the number of // swaps is reasonable. // We want the net effect to be moving "from" left->right and "to" right->left // (1) scratch = to - from if (count <= MAX_CENTROID_UPDATES && vectorScore == VectorSimilarityFunction.EUCLIDEAN) { int relativeMidpoint = midPoint - ids.offset; vectorSubtract(vectors.vectorValue(toId), vectors.vectorValue(fromId), scratch); // we must normalize to the proper scale by accounting for the number of points contributing // to each centroid // left += scratch / size(left) vectorScalarMul(1 / (float) relativeMidpoint, scratch); VectorUtil.add(leftCentroid, scratch); // right -= scratch / size(right) vectorScalarMul(-relativeMidpoint / (float) (ids.length - relativeMidpoint), scratch); VectorUtil.add(rightCentroid, scratch); } idArr[from] = toId; idArr[to] = fromId; if (count <= MAX_CENTROID_UPDATES) { assert centroidValid( leftCentroid, vectors, new IntsRef(idArr, ids.offset, midPoint - ids.offset), count); assert centroidValid( rightCentroid, vectors, new IntsRef(ids.ints, midPoint, ids.length - midPoint + ids.offset), count); } } /** * Adds the second argument to the first * * @param u the destination * @param v the vector to add to the destination **/ static void vectorSubtract(float[] u, float[] v, float[] result) { for (int i = 0; i < u.length; i++) { result[i] = u[i] - v[i];// Can be replaced with vectorized code. } } - Replace the identified code with vectorized code. If the code contains a defined variable name, the necessary import statement and the constant declaration are automatically added after the replacement.
static void vectorSubtract(float[] u, float[] v, float[] result) { int i = 0;// Replaced with vectorized code. for (; i < FLOAT_SPECIES.loopBound(u.length); i = i + FLOAT_SPECIES.length()) { FloatVector uVector = FloatVector.fromArray(FLOAT_SPECIES, u, i); FloatVector vVector = FloatVector.fromArray(FLOAT_SPECIES, v, i); uVector.sub(vVector).intoArray(result, i); } for (; i < u.length; i++) { result[i] = u[i] - v[i]; } }Constant statement that requires declaration:
private static final VectorSpecies<Float> FLOAT_SPECIES = FloatVector.SPECIES_PREFERRED;
import statement:
import jdk.incubator.vector.VectorSpecies; import jdk.incubator.vector.FloatVector;
- Execute the reconstructed for loop in the BpVectorReorderer.java file.Figure 3 Execution after code reconstruction
Compile and execute the reconstructed file. The execution result remains unchanged while the code performance improves.
Parent topic: Introduction
