AvicScalar avic_mat_add_square(const AvicMat* src) - Efficient Matrix Element Squaring and Summation
{
int src_cn = AVICCV_MAT_CN(src->type);
int depth = AVICCV_MAT_DEPTH(src->type);
int elem_size = AVICCV_ELEM_SIZE(src->type);
int size = elem_size / src_cn;
int i, j, k, size_multi_cn = 0;
double sum = 0;
AvicScalar add_square_value;
switch (depth)
{
case AVICCV_8U:
{
for (k = 0; k < src_cn; k++)
{
size_multi_cn = k * size;
sum = 0;
for (i = 0; i < src->rows; i++)
{
for (j = 0; j < src->cols; j++)
{
sum += AVIC_CV_SQR(*(unsigned char*)(src->data.ptr + (i * src->cols + j)*elem_size + size_multi_cn));
}
}
add_square_value.val[k] = sum;
}
break;
}
case AVICCV_32F:
{
if(src_cn == 3)
{
float* src_ptr = src->data.fl;
for (k = 0; k < src_cn; k++)
{
size_multi_cn = k * size;
sum = 0;
for (i = 0; i < src->rows; i++)
{
for (j = 0; j < src->cols; j++)
{
sum += AVIC_CV_SQR(*(float*)(src->data.ptr + (i * src->cols + j)*elem_size + size_multi_cn));
}
}
add_square_value.val[k] = sum;
}
}
else
{
float* src_ptr = src->data.fl;
float add[4] ={0} ;
float* add_ptr = add;
#ifndef WITH_NEON
#ifdef WITH_OMP
#pragma omp parallel for private(j)
#endif
for (k = 0; k < src_cn; k++)
{
size_multi_cn = k * size;
sum = 0;
for (i = 0; i < src->rows; i++)
{
for (j = 0; j < src->cols; j++)
{
sum += AVIC_CV_SQR(*(float*)(src->data.ptr + (i * src->cols + j)*elem_size + size_multi_cn));
}
}
add_square_value.val[k] = sum;
}
#else
#ifdef WITH_OMP
#pragma omp parallel for private(j)
#endif
for(i = 0 ; i < src->rows ; i++)
{
src_ptr = src->data.fl + i * src->cols * elem_size;
printf("1111 ");////////////////////////////
for(j = 0; j <= src->cols * src_cn - 4; j += 4)
{
float32x4_t temp = vld1q_f32(src_ptr + j * size);
float32x4_t re = vmulq_f32(temp , temp);
float32x4_t re1 = vld1q_f32(add_ptr);
vst1q_f32(add_ptr , vaddq_f32(re, re1));
}
for(; j <= src->cols * src_cn ; j ++)
{
add_square_value.val[0] += AVIC_CV_SQR(*(float*)(src->data.ptr + i * src->cols *elem_size + j * size));
}
printf("2222 ");////////////////////////////
add_square_value.val[0] += add[0];
add_square_value.val[0] += add[1];
add_square_value.val[0] += add[2];
add_square_value.val[0] += add[3];
printf("%.2f ",add_square_value.val[0]);////////////////////////////
}
#endif
}
break;
}
}
return(add_square_value);
}
分析该段代码中使用NEON和openmp优化部分有何问题内容:在分析这段代码中使用NEON和OpenMP优化部分的问题之前,首先需要了解NEON和OpenMP的基本概念和使用方式。
NEON是ARM架构下的SIMD(单指令多数据)指令集,可以在一次指令中同时处理多个数据元素,从而提高并行计算的效率。NEON的优化需要使用特定的指令和数据类型,并且需要对内存访问进行对齐操作。
OpenMP是一种并行编程模型,可以将程序的某些部分标记为并行执行的区域,然后由编译器和运行时系统来自动处理并行化的细节。OpenMP的优化需要合理地进行任务划分和负载均衡,以确保各个线程之间的工作量均衡。
在对这段代码进行分析时,可以发现以下问题:
-
NEON优化部分: a. 在使用NEON进行优化时,代码中的NEON指令使用不正确。例如,代码中使用了vld1q_f32和vst1q_f32加载和存储指令,但是加载和存储的地址计算部分存在问题,无法正确地加载和存储数据。 b. 在使用NEON指令时,需要对内存访问进行对齐操作,以保证数据的正确加载和存储。代码中没有对内存进行对齐操作,可能导致NEON指令的运行出错。
-
OpenMP优化部分: a. 在使用OpenMP进行优化时,代码中的并行化标记和任务划分存在问题。代码中使用了#pragma omp parallel for进行并行化循环,但是循环的并行化可能存在数据依赖和负载不均衡的问题。 b. 在使用OpenMP进行并行化时,需要考虑数据的共享和同步问题。代码中没有对共享数据和临界区进行合理的同步操作,可能导致并发访问的错误。
综上所述,该段代码中使用NEON和OpenMP优化部分存在NEON指令使用不正确、内存访问未对齐、OpenMP循环并行化存在数据依赖和负载不均衡等问题。需要对这些问题进行修正和改进,以确保优化的正确性和效果。
原文地址: http://www.cveoy.top/t/topic/qA9m 著作权归作者所有。请勿转载和采集!