---
title: 向量化源码修改建议
description: "**表1 向量化源码修改建议**"
url: https://www.hikunpeng.com/document/detail/zh/kunpengdevps/development/affinityanalyzer/DevKit_Affinity_0021.html
sourcePath: /source/zh/kunpengdevps/development/affinityanalyzer/DevKit_Affinity_0021.html
indexId: d3cfdd10db661bef635cf1daafc9bc3ccc5de897f60b39db6cfbab49a0feeb6b78
---
# 向量化源码修改建议


**表1 向量化源码修改建议**

| 向量化建议 | 无法向量化原因 | 修改方案 | 修改样例 |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 提取循环控制变量 | for循环的循环控制变量为结构体的成员，编译器无法确定循环结束条件，导致无法自动向量化循环。 | 将循环控制变量提取到循环外。 | 代码样例如下： 1 2 3 for (i = 0; i < data\->len; i++) { vecC[i] = vecA[i] + vecB[i]; } 修改方式样例如下： 1 2 3 4 int len = data\->len; // 将循环控制变量提取到循环外. for (i = 0; i < len; i++) { vecC[i] = vecA[i] + vecB[i]; } | 1 2 3 | for (i = 0; i < data\->len; i++) { vecC[i] = vecA[i] + vecB[i]; } | 1 2 3 4 | int len = data\->len; // 将循环控制变量提取到循环外. for (i = 0; i < len; i++) { vecC[i] = vecA[i] + vecB[i]; } |
| 1 2 3 | for (i = 0; i < data\->len; i++) { vecC[i] = vecA[i] + vecB[i]; } |  |  |  |  |  |  |
| 1 2 3 4 | int len = data\->len; // 将循环控制变量提取到循环外. for (i = 0; i < len; i++) { vecC[i] = vecA[i] + vecB[i]; } |  |  |  |  |  |  |
| 修改循环控制条件 | clang 15支持向量化，clang 15版本以下无法支持自动向量化实现。 | 循环条件从<=改成<，循环长度从len改成len+1。 | 代码样例如下： 1 2 3 for (i = 0; i <= data\->len; i++) { vecC[i] = vecA[i] + vecB[i]; } 修改方式样例如下： 1 2 3 4 // 循环条件从"<="改成"<"，循环长度从len改成len+1 for (i = 0; i < data\->len + 1; i++) { vecC[i] = vecA[i] + vecB[i]; } | 1 2 3 | for (i = 0; i <= data\->len; i++) { vecC[i] = vecA[i] + vecB[i]; } | 1 2 3 4 | // 循环条件从"<="改成"<"，循环长度从len改成len+1 for (i = 0; i < data\->len + 1; i++) { vecC[i] = vecA[i] + vecB[i]; } |
| 1 2 3 | for (i = 0; i <= data\->len; i++) { vecC[i] = vecA[i] + vecB[i]; } |  |  |  |  |  |  |
| 1 2 3 4 | // 循环条件从"<="改成"<"，循环长度从len改成len+1 for (i = 0; i < data\->len + 1; i++) { vecC[i] = vecA[i] + vecB[i]; } |  |  |  |  |  |  |
| 增加自动向量化编译指示 | 编译器评估向量化收益后采用保守策略，不进行自动向量化。 | 添加pragma编译指示强行对代码进行自动向量化。 | 代码样例如下： 1 2 3 for (i = 0; i < data\->len; i++) { vecC[i] = vecA[i] + vecB[i]; } 修改方式样例如下： 1 2 3 4 5 // 添加pragma编译指示强行对代码进行自动向量化 \#pragma clang loop vectorize(enable) for (i = 0; i < data\->len; i++) { vecC[i] = vecA[i] + vecB[i]; } | 1 2 3 | for (i = 0; i < data\->len; i++) { vecC[i] = vecA[i] + vecB[i]; } | 1 2 3 4 5 | // 添加pragma编译指示强行对代码进行自动向量化 \#pragma clang loop vectorize(enable) for (i = 0; i < data\->len; i++) { vecC[i] = vecA[i] + vecB[i]; } |
| 1 2 3 | for (i = 0; i < data\->len; i++) { vecC[i] = vecA[i] + vecB[i]; } |  |  |  |  |  |  |
| 1 2 3 4 5 | // 添加pragma编译指示强行对代码进行自动向量化 \#pragma clang loop vectorize(enable) for (i = 0; i < data\->len; i++) { vecC[i] = vecA[i] + vecB[i]; } |  |  |  |  |  |  |
| 明确指针指向的内存不会被其他指针引用 | 无法确定指针指向的内存是否被其他指针引用，编译器将放弃自动向量化。 | 添加restrict关键字修饰指针变量。 | 代码样例如下： 1 2 3 4 5 void func(int \*A, struct Data \*data) { data\->a = A[0]; data\->b = A[1]; } 修改方式样例如下： 1 2 3 4 5 6 // Add restrict to the argument <A>. void func(int \*restrict A, struct Data \*data) { data\->a = A[0]; data\->b = A[1]; } | 1 2 3 4 5 | void func(int \*A, struct Data \*data) { data\->a = A[0]; data\->b = A[1]; } | 1 2 3 4 5 6 | // Add restrict to the argument <A>. void func(int \*restrict A, struct Data \*data) { data\->a = A[0]; data\->b = A[1]; } |
| 1 2 3 4 5 | void func(int \*A, struct Data \*data) { data\->a = A[0]; data\->b = A[1]; } |  |  |  |  |  |  |
| 1 2 3 4 5 6 | // Add restrict to the argument <A>. void func(int \*restrict A, struct Data \*data) { data\->a = A[0]; data\->b = A[1]; } |  |  |  |  |  |  |
| 保持数据类型长度一致 | 类型不匹配，编译器无法进行自动向量化。 | 改变变量的类型，从long型变为int型。 | 代码样例如下： 1 2 3 4 5 6 7 void func(int \*vec) { long b = 1; int i; for (i = 0; i < 64; i++) { vec[i] = (b << i); } } 修改方式样例如下： 1 2 3 4 5 6 7 8 void func(int \*vec) { // 改变变量的类型，从long型变为int型 int b = 1; int i; for (i = 0; i < 64; i++) { vec[i] = (b << i); } } | 1 2 3 4 5 6 7 | void func(int \*vec) { long b = 1; int i; for (i = 0; i < 64; i++) { vec[i] = (b << i); } } | 1 2 3 4 5 6 7 8 | void func(int \*vec) { // 改变变量的类型，从long型变为int型 int b = 1; int i; for (i = 0; i < 64; i++) { vec[i] = (b << i); } } |
| 1 2 3 4 5 6 7 | void func(int \*vec) { long b = 1; int i; for (i = 0; i < 64; i++) { vec[i] = (b << i); } } |  |  |  |  |  |  |
| 1 2 3 4 5 6 7 8 | void func(int \*vec) { // 改变变量的类型，从long型变为int型 int b = 1; int i; for (i = 0; i < 64; i++) { vec[i] = (b << i); } } |  |  |  |  |  |  |
| 循环拆分 | 循环中的运算左值空间为固定空间，存在循环依赖关系，编译器无法进行向量化。 | 拆分循环，将每一轮循环运算左值独立存储再归并。 | 代码样例如下： 1 2 3 4 for( int i = 0; i < 4; i++ ) { ...... sum += a0 + a1 + a2 + a3; } 修改方式样例如下： 1 2 3 4 5 6 7 8 9 // Declare an array, // and assign element in each iteration, // and finally accumulate elements in the array. uint32\_t sumTmp[4]; for( int i = 0; i < 4; i++ ) { ...... sumTmp[i] = a0 + a1 + a2 + a3; } sum = sumTmp[0] + sumTmp[1] + sumTmp[2] + sumTmp[3]; | 1 2 3 4 | for( int i = 0; i < 4; i++ ) { ...... sum += a0 + a1 + a2 + a3; } | 1 2 3 4 5 6 7 8 9 | // Declare an array, // and assign element in each iteration, // and finally accumulate elements in the array. uint32\_t sumTmp[4]; for( int i = 0; i < 4; i++ ) { ...... sumTmp[i] = a0 + a1 + a2 + a3; } sum = sumTmp[0] + sumTmp[1] + sumTmp[2] + sumTmp[3]; |
| 1 2 3 4 | for( int i = 0; i < 4; i++ ) { ...... sum += a0 + a1 + a2 + a3; } |  |  |  |  |  |  |
| 1 2 3 4 5 6 7 8 9 | // Declare an array, // and assign element in each iteration, // and finally accumulate elements in the array. uint32\_t sumTmp[4]; for( int i = 0; i < 4; i++ ) { ...... sumTmp[i] = a0 + a1 + a2 + a3; } sum = sumTmp[0] + sumTmp[1] + sumTmp[2] + sumTmp[3]; |  |  |  |  |  |  |
| 简化条件分支内的代码逻辑 | 在条件分支语句中存在较复杂的运算，导致无法自动向量化。 | 将运算语句提取到条件分支之外。 | 代码样例如下： 1 2 3 4 5 6 7 for( int i = 0; i < len; i++ ) { if (flag[i]) vecC[i] = vecA[i] + vecB[i]; else vecC[i] = vecA[i] \- vecB[i]; sum += vecC[i]; } 修改方式样例如下： 1 2 3 4 5 6 7 8 9 10 for( int i = 0; i < len; i++ ) { // Extract all expressions outside the branch. int ifTrue = vecA[i] + vecB[i]; int ifFalse = vecA[i] \- vecB[i]; if (flag[i]) vecC[i] = ifTrue; else vecC[i] = ifFalse; sum += vecC[i]; } | 1 2 3 4 5 6 7 | for( int i = 0; i < len; i++ ) { if (flag[i]) vecC[i] = vecA[i] + vecB[i]; else vecC[i] = vecA[i] \- vecB[i]; sum += vecC[i]; } | 1 2 3 4 5 6 7 8 9 10 | for( int i = 0; i < len; i++ ) { // Extract all expressions outside the branch. int ifTrue = vecA[i] + vecB[i]; int ifFalse = vecA[i] \- vecB[i]; if (flag[i]) vecC[i] = ifTrue; else vecC[i] = ifFalse; sum += vecC[i]; } |
| 1 2 3 4 5 6 7 | for( int i = 0; i < len; i++ ) { if (flag[i]) vecC[i] = vecA[i] + vecB[i]; else vecC[i] = vecA[i] \- vecB[i]; sum += vecC[i]; } |  |  |  |  |  |  |
| 1 2 3 4 5 6 7 8 9 10 | for( int i = 0; i < len; i++ ) { // Extract all expressions outside the branch. int ifTrue = vecA[i] + vecB[i]; int ifFalse = vecA[i] \- vecB[i]; if (flag[i]) vecC[i] = ifTrue; else vecC[i] = ifFalse; sum += vecC[i]; } |  |  |  |  |  |  |
| 数据类型改为无符号类型 | 数据类型不一致，编译器无法向量化。 | 改变数据的类型，从signed型变为unsigned型。 | 代码样例如下： 1 2 3 4 5 6 int sum; for( int i = 0; i < len; i++ ){ b0 = abs2(a0 + a4) + abs2(a0 \- a4); sum += (uint16\_t)b0; } return sum; 修改方式样例如下： 1 2 3 4 5 6 7 "// Change the type of <sum> from signed to unsigned. unsigned int sum; for( int i = 0; i < len; i++ ){ b0 = abs2(a0 + a4) + abs2(a0 \- a4); sum += (uint16\_t)b0; } return sum; | 1 2 3 4 5 6 | int sum; for( int i = 0; i < len; i++ ){ b0 = abs2(a0 + a4) + abs2(a0 \- a4); sum += (uint16\_t)b0; } return sum; | 1 2 3 4 5 6 7 | "// Change the type of <sum> from signed to unsigned. unsigned int sum; for( int i = 0; i < len; i++ ){ b0 = abs2(a0 + a4) + abs2(a0 \- a4); sum += (uint16\_t)b0; } return sum; |
| 1 2 3 4 5 6 | int sum; for( int i = 0; i < len; i++ ){ b0 = abs2(a0 + a4) + abs2(a0 \- a4); sum += (uint16\_t)b0; } return sum; |  |  |  |  |  |  |
| 1 2 3 4 5 6 7 | "// Change the type of <sum> from signed to unsigned. unsigned int sum; for( int i = 0; i < len; i++ ){ b0 = abs2(a0 + a4) + abs2(a0 \- a4); sum += (uint16\_t)b0; } return sum; |  |  |  |  |  |  |
| 降低计算精度 | 计算精度高，编译器为保障计算精度不进行自动向量化。 | 降低计算结果的精度。 | 代码样例如下： 1 2 3 DO K = 1,KM vecC(k)= (vecA(K) + vecB(K + 1))\*0.5D0 END DO 修改方式样例如下： 1 2 3 DO K = 1,KM vecC(k)= (vecA(K) + vecB(K + 1))\*0.5 END DO | 1 2 3 | DO K = 1,KM vecC(k)= (vecA(K) + vecB(K + 1))\*0.5D0 END DO | 1 2 3 | DO K = 1,KM vecC(k)= (vecA(K) + vecB(K + 1))\*0.5 END DO |
| 1 2 3 | DO K = 1,KM vecC(k)= (vecA(K) + vecB(K + 1))\*0.5D0 END DO |  |  |  |  |  |  |
| 1 2 3 | DO K = 1,KM vecC(k)= (vecA(K) + vecB(K + 1))\*0.5 END DO |  |  |  |  |  |  |
| 循环拆分 | 循环内的语句较多，编译器无法判断变量的依赖关系，不进行向量化。 | 将循环内容的多个语句拆分到多个循环中。 | 代码样例如下： 1 2 3 4 5 6 7 8 9 10 DO A = 1,AM DO K = 1,KM DO J = 3,JMT DO I = 3,IMT V1 (I,J,K,A)= V2 (I,J,K,A) + V3 (I,J,K,A)\* D U1 (I,J,K,A)= U2 (I,J,K,A) + U3 (I,J,K,A)\* D END DO END DO END DO END DO 修改方式样例如下： 1 2 3 4 5 6 7 8 9 10 11 12 DO A = 1,N DO K = 1,KM DO J = 3,JMT DO I = 3,IMT V1 (I,J,K,A)= V2 (I,J,K,A) + V3 (I,J,K,A)\* D END DO DO I = 3,IMT U1 (I,J,K,A)= U2 (I,J,K,A) + U3 (I,J,K,A)\* D END DO END DO END DO END DO | 1 2 3 4 5 6 7 8 9 10 | DO A = 1,AM DO K = 1,KM DO J = 3,JMT DO I = 3,IMT V1 (I,J,K,A)= V2 (I,J,K,A) + V3 (I,J,K,A)\* D U1 (I,J,K,A)= U2 (I,J,K,A) + U3 (I,J,K,A)\* D END DO END DO END DO END DO | 1 2 3 4 5 6 7 8 9 10 11 12 | DO A = 1,N DO K = 1,KM DO J = 3,JMT DO I = 3,IMT V1 (I,J,K,A)= V2 (I,J,K,A) + V3 (I,J,K,A)\* D END DO DO I = 3,IMT U1 (I,J,K,A)= U2 (I,J,K,A) + U3 (I,J,K,A)\* D END DO END DO END DO END DO |
| 1 2 3 4 5 6 7 8 9 10 | DO A = 1,AM DO K = 1,KM DO J = 3,JMT DO I = 3,IMT V1 (I,J,K,A)= V2 (I,J,K,A) + V3 (I,J,K,A)\* D U1 (I,J,K,A)= U2 (I,J,K,A) + U3 (I,J,K,A)\* D END DO END DO END DO END DO |  |  |  |  |  |  |
| 1 2 3 4 5 6 7 8 9 10 11 12 | DO A = 1,N DO K = 1,KM DO J = 3,JMT DO I = 3,IMT V1 (I,J,K,A)= V2 (I,J,K,A) + V3 (I,J,K,A)\* D END DO DO I = 3,IMT U1 (I,J,K,A)= U2 (I,J,K,A) + U3 (I,J,K,A)\* D END DO END DO END DO END DO |  |  |  |  |  |  |
| 减少循环内的函数调用 | 循环内存在函数调用，编译器无法进行向量化。 | 将函数调用相关的计算提取到循环外。 | 代码样例如下： 1 2 3 4 5 6 7 for( int i = 0; i < len; i++ ) { delta = \-0.5 + (2\*m+1)/(2.0\*n); vecA[k].dx = delta\*length\*cos(theta); vecA[k].dy = delta\*length\*sin(theta); k++; } 修改方式样例如下： 1 2 3 4 5 6 7 8 9 // Extract math lib call outside the loop. double cosNum = cos(theta); double sinNum = sin(theta); for( int i = 0; i < len; i++ ) { delta = \-0.5 + (2\*m+1)/(2.0\*n); vecA[k].dx = delta\*length\*cosNum; vecA[k].dy = delta\*length\*sinNum; k++; } | 1 2 3 4 5 6 7 | for( int i = 0; i < len; i++ ) { delta = \-0.5 + (2\*m+1)/(2.0\*n); vecA[k].dx = delta\*length\*cos(theta); vecA[k].dy = delta\*length\*sin(theta); k++; } | 1 2 3 4 5 6 7 8 9 | // Extract math lib call outside the loop. double cosNum = cos(theta); double sinNum = sin(theta); for( int i = 0; i < len; i++ ) { delta = \-0.5 + (2\*m+1)/(2.0\*n); vecA[k].dx = delta\*length\*cosNum; vecA[k].dy = delta\*length\*sinNum; k++; } |
| 1 2 3 4 5 6 7 | for( int i = 0; i < len; i++ ) { delta = \-0.5 + (2\*m+1)/(2.0\*n); vecA[k].dx = delta\*length\*cos(theta); vecA[k].dy = delta\*length\*sin(theta); k++; } |  |  |  |  |  |  |
| 1 2 3 4 5 6 7 8 9 | // Extract math lib call outside the loop. double cosNum = cos(theta); double sinNum = sin(theta); for( int i = 0; i < len; i++ ) { delta = \-0.5 + (2\*m+1)/(2.0\*n); vecA[k].dx = delta\*length\*cosNum; vecA[k].dy = delta\*length\*sinNum; k++; } |  |  |  |  |  |  |
| 利用Fortran关键字 | 未充分利用Fortran语言特性。 | 使用数组赋值代替循环来实现多个数据的操作。 | 代码样例如下： 1 2 3 do i = 1, maxI type1%array1(i)=array3(type1%array2(i)) enddo 修改方式样例如下： 1 type1%array1=array3(type1%array2) | 1 2 3 | do i = 1, maxI type1%array1(i)=array3(type1%array2(i)) enddo | 1 | type1%array1=array3(type1%array2) |
| 1 2 3 | do i = 1, maxI type1%array1(i)=array3(type1%array2(i)) enddo |  |  |  |  |  |  |
| 1 | type1%array1=array3(type1%array2) |  |  |  |  |  |  |
| 明确指针指向的内存不会被其他指针引用，同时添加编译标识 | 无法确定指针指向的内存是否被其他指针引用，编译器将放弃自动向量化。 | 添加restrict关键字修饰指针变量。 | 代码样例如下： 1 2 3 4 for (int i=0;i<len;++i) { a[i] = b[index[i]]; } 修改方式样例如下： 1 2 3 4 5 6 7 8 void func(int \*a, int \*\_\_restrict\_\_ b, int \*index, int len) { \#pragma clang loop vectorize(enable) for (int i=0;i<len;++i) { a[i] = b[index[i]]; } } | 1 2 3 4 | for (int i=0;i<len;++i) { a[i] = b[index[i]]; } | 1 2 3 4 5 6 7 8 | void func(int \*a, int \*\_\_restrict\_\_ b, int \*index, int len) { \#pragma clang loop vectorize(enable) for (int i=0;i<len;++i) { a[i] = b[index[i]]; } } |
| 1 2 3 4 | for (int i=0;i<len;++i) { a[i] = b[index[i]]; } |  |  |  |  |  |  |
| 1 2 3 4 5 6 7 8 | void func(int \*a, int \*\_\_restrict\_\_ b, int \*index, int len) { \#pragma clang loop vectorize(enable) for (int i=0;i<len;++i) { a[i] = b[index[i]]; } } |  |  |  |  |  |  |
