Assembly 如何通过mmx计算3个整数的平均值?

Assembly 如何通过mmx计算3个整数的平均值?,assembly,nasm,mmx,sse,Assembly,Nasm,Mmx,Sse,我有个问题,希望你能帮忙。 我的任务是使用mmx、xmm或sse命令对图像(从Java发送)执行灰度缩放。我已经在C和asm中这样做了(使用逻辑获取R、G和b,然后找到avg),现在我需要使用mmx/xmm/sse并提高性能(否则,教授拒绝接受,明天是考试日) 灰度缩放是取一个像素的R、G和B,并用R、G和B的平均值替换。简单地将三个像素合并并进行idiv很容易做到这一点,但mmx中没有除法,所以我需要即兴创作,我没有任何想法 xmm的问题是,简单的“movaps xmm0,[rel v1]”会

我有个问题,希望你能帮忙。 我的任务是使用mmx、xmm或sse命令对图像(从Java发送)执行灰度缩放。我已经在C和asm中这样做了(使用逻辑获取R、G和b,然后找到avg),现在我需要使用mmx/xmm/sse并提高性能(否则,教授拒绝接受,明天是考试日)

灰度缩放是取一个像素的R、G和B,并用R、G和B的平均值替换。简单地将三个像素合并并进行idiv很容易做到这一点,但mmx中没有除法,所以我需要即兴创作,我没有任何想法

xmm的问题是,简单的“movaps xmm0,[rel v1]”会让我崩溃,而我没有时间去探索它,所以最好只通过mmx来实现

昨天我写了一些使用mmx的东西,但它比C代码慢30倍:( 好吧,我不需要史诗般的表演,也不需要工作正常的东西


有什么想法吗?也许可以通过移位或类似的方式进行除法?非常感谢您的帮助。

所附代码使用SSE优化。
实现使用C内部-无程序集

为简单起见,我假设R、G和B是三个不同的平面,
以R矩阵、G矩阵和B矩阵的形式存储在内存中,而不是以R、G、B、R、G、B、R、G、B的数据顺序存储。
代码使用定点实现以获得更好的性能。
重要注意事项:

  • 乘以(1/3)比除以3更有效
  • 整数转换前加0.5可用于对正值进行舍入
  • 通过扩展、缩放和移位执行的(1/3)缩放的定点实现。示例:平均值=(和*缩放+舍入)>>15;[当缩放=(1/3)*2^15]
  • _mm_mulhrs_epi16正在执行上述操作:(x*scl+2^14)>>15
实施意见包括更多解释:

//计算3个向量R、G和B的元素平均值,并将结果存储到J中。
//实现使用SSE内部函数进行性能优化。
//使用定点计算以获得更好的性能。
//R-红色像素的平面:rrrrrrrrrrrrrrrrrrrrrr
//G-绿色像素的平面:gggggggggggggg
//B-蓝色像素的平面:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
//图像大小:像素总数(宽度*高度)。
//J-目标灰度平面:JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
//限制:
//1.图像大小必须是16的倍数。
void RgbAverage(常量无符号字符R[],
常量无符号字符G[],
常量无符号字符B[],
int图像大小,
无符号字符J[]
{
int x;
/*
//1.普通C代码:
//--------------------
对于(x=0;xconst unsigned int scale=(unsigned int)((1.0/3.0)*(1)它必须是(R+G+B)/3吗?另外,
movaps
可能因为地址未对齐而崩溃。这个公式是错误的,它应该使用weights@harold可能公式不好,但它工作正常(至少在C中)。如果你提示我应该尝试什么,我可以尝试一些不同的方法。@stark不确定在mmx中使用浮点运算……如何放置数据以及如何执行计算?如果你被允许将G的重量比R和B重,并且你有点作弊,你可以使用pavgb(pavgb(R,B),G),否则你可以尝试旧的“乘法除法”(pmulhw由某个精心选择的常数(我认为),请注意,这需要在某个地方转换为shorts)。mmx中没有浮点。建议对平面数据进行操作。据我所知,如果要对同一图像执行多个操作,则转换的开销是值得的。否则,您可以直接从压缩的RGB数据进行灰度调整,并进行更多的混洗。或者更容易地,从RGBA数据进行灰度调整,以便轻松应用权重并执行水平求和的第一步。(此代码中缺少组件权重)。