案例Demo
可通过JavaVectorHelper工具对单个文件/整个项目进行扫描,本章节基于单个文件提供对应可用向量化的示例代码,示例代码片段功能是对数组间运算并赋值,代码仅供参考。
- 扫描前源码文件如图1所示。
- 运行BpVectorReorderer.java文件中的For循环。图2 改造前运行结果
- 使用JavaVectorHelper工具,识别出代码块中加粗显示的代码,可替换为可用向量化代码。
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];//可替换为向量化代码 } }
- 替换为向量化代码,若代码中定义了变量名称,替换后会自动引入所需要的import语句和需要声明的常量语句。
static void vectorSubtract(float[] u, float[] v, float[] result) { int i = 0;//已替换为向量化代码 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]; } }
需要声明的常量语句:
private static final VectorSpecies<Float> FLOAT_SPECIES = FloatVector.SPECIES_PREFERRED;
import语句:
import jdk.incubator.vector.VectorSpecies; import jdk.incubator.vector.FloatVector;
- 运行BpVectorReorderer.java文件中改造后的For循环。图3 改造后运行结果
编译运行改造后的文件,运行结果保持不变,性能有所提升。
父主题: JavaVectorHelper工具简介