SSE多线程不运算问题

EndDuke 2007-09-11 05:46:48
我实在搞不定了,我最近要用我原来写的游戏引擎做个多线程的交互式仿真软件,修改了下,引擎基本可以正常运行了,也不会报错

但是我在Vector和Matrix里面我内嵌了SSE的汇编代码。原来是正常的,但是现在根本不计算。不报错,运行时也不会出现非法操作。但就是运算不改变结果。

比如拿比较简单的Vector4::operator +=来说
其中
__asm
{
mov esi,this
mov edi,v
movaps xmm0,[esi]
addps xmm0,[edi]
movaps [esi],xmm0
}
单线程运行正常
比如V1=1,0,0,1; V2=0,1,0,1; V1+=V2;后V1变成 1,1,0,2
但是现在在多线程下,运行V1+=V2后V1依然是,1,0,0,1

我跟踪了 esi,edi 寄存器都正常啊~~~ 那为什么最后一步
movaps [esi],xmm0

不能把xmm0放回到this中呢~小生实在是搞不定了~~拿出来请教大家,谢谢

PS:如果屏蔽SSE用普通的C代码的话运行是正常的,说明系统结构上不会出现问题。
...全文
143 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
EndDuke 2007-09-17
  • 打赏
  • 举报
回复
问题已经解决了,排列的确不同。
我修改后的定义如下
union
{

__declspec(align(16)) float v[4];

struct {
float x,y,z,w;
};
}

我想是不是也可以定义成(没有试验)
__declspec(align(16)) struct
{
float x,y,z,w;
}
不过没有上面那个方便

declspec(align(16)) float x,y,z,w 把x,y,z,w都按16位对齐了产生了错误

感谢mydo这些天的关注,引导我解决了问题。现在我就结贴 呵呵
大熊猫侯佩 2007-09-13
  • 打赏
  • 举报
回复
vs2003没用过,vs2005在调试时可以打开寄存器窗口,然后在窗口上选择 xmm寄存器 即可。
EndDuke 2007-09-13
  • 打赏
  • 举报
回复
继续说,(上面的代码运行正常)

我跟踪原来的工程,可以跟踪到
__asm
{
mov esi,this
mov edi,a
movaps xmm0,[esi]
addps xmm0,[edi]
movaps [esi],xmm0
}
这段汇编码。
我察看了 esi 和 edi 的值在mov esi,this 和 mov edi,a 都正确的改变了
而到movaps xmm0,[esi]开始 于我不会察看xmm0的值(我不知道能不能察看,至少在VS2003里面没有找到)
我就不知道他是否正确的运行了
一直到结束,才知道movaps [esi],xmm0没有改变this的值,比较郁闷
我也搞不清楚 其中的盲点太多了 不知道有没有方法可以跟踪 xmm0的值呢
EndDuke 2007-09-13
  • 打赏
  • 举报
回复
我自己从新写了一个精简的代码,因为原来的代码是我把游戏引擎和MFC整合过的,特别大我都不知道怎么精简才好。
不过我重新写了这样一个代码。结果完全正常。可是我原来的代码用跟踪的话可以跟踪的汇编码,
#include <iostream>
#include <windows.h>
#include <process.h>

#pragma pack(16)

class v
{
public:
__declspec(align(16)) float f[4];
void operator +=(v& a)
{
v* p = &a;
__asm
{
mov esi,this
mov edi,a
movaps xmm0,[esi]
addps xmm0,[edi]
movaps [esi],xmm0
}
}
};

void myfunc( void )
{
v v1;
v v2;
v1.f[0] = 1.0f;
v1.f[1] = 0.0f;
v1.f[2] = 0.0f;
v1.f[3] = 1.0f;

v2.f[0] = 0.0f;
v2.f[1] = 1.0f;
v2.f[2] = 0.0f;
v2.f[3] = 1.0f;

cout<<"v1:"<<v1.f[0]<<v1.f[1]<<v1.f[2]<<v1.f[3]<<endl
<<"v2:"<<v2.f[0]<<v2.f[1]<<v2.f[2]<<v2.f[3]<<endl;
while (1){
v1+=v2;
cout<<"v1:"<<v1.f[0]<<v1.f[1]<<v1.f[2]<<v1.f[3]<<endl
<<"v2:"<<v2.f[0]<<v2.f[1]<<v2.f[2]<<v2.f[3]<<endl;
Sleep(1000);

}
}

int main(int argc, char* argv[])
{
HANDLE thd;
unsigned long tid;
v c;
v d;
thd = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)myfunc,NULL,0,&tid);
while (1){
int a;
int b;
a=1;
b=2;
a*=b;
b+=a;
a-=b;
b/=a;
c+=d;
}
system("pause");
if( thd != NULL )
{
CloseHandle( thd );
}
system("pause");
}
大熊猫侯佩 2007-09-13
  • 打赏
  • 举报
回复
你看看两种方法实际的地址排列有什么异同?
EndDuke 2007-09-13
  • 打赏
  • 举报
回复
我想问题找到了,类的向量定义成

__declspec(align(16)) float f[4];
就正常
定义成
__declspec(align(16)) float x,y,z,w;
在传入
movaps xmm0,[esi]
时就只能将x的值传入

为什么会这样,不应该啊。
x,y,z,w的数据在内存上也应该是连续的才对啊。。难道不是么
EndDuke 2007-09-13
  • 打赏
  • 举报
回复
一个新问题,计算结果如下
1,0,0,1 + 1,0,0,1 = 2,0,0,1
1,0,0,1 + 0,1,0,1 = 1,0,0,1

向量的后几位不计算啊=。=
EndDuke 2007-09-13
  • 打赏
  • 举报
回复
果然2003也能打开=。=
EndDuke 2007-09-13
  • 打赏
  • 举报
回复
这样啊 ~ 我找找2003有没有 头一次跟踪xmm积存器~~谢谢你哦
大熊猫侯佩 2007-09-11
  • 打赏
  • 举报
回复
你最好能将关键代码抽取出来,我的意思是把所有无关的东西全clear掉,
重写一个短小的测试代码,这样可以抓住重点。不知你是否明白我的意思?
如果还不行,请将精简后的代码贴出或者QQ找我。
EndDuke 2007-09-11
  • 打赏
  • 举报
回复
回 mydo:
0 不是,我的是P4的。不过多线程不是很早就有了么?双核在程序上会有什么不同
PS:这个程序最终是在4核机上运行的,现在我在我自己的计算机上编写,会有不同么?

1 我测试过了,10000的循环的+= 速度飞快,但是依然不改变结果

2 不是很明白,能详细说明一下么?谢谢
大熊猫侯佩 2007-09-11
  • 打赏
  • 举报
回复
0 你的电脑是双核么?

1 用大数量执行测试,在多次测试下(10000+),是否每次都不改变结果?

2 在进入汇编区以前用临界区包裹,强制同步。

21,458

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧