Intel® Moderncode for Parallel Architectures
Support for developing parallel programming applications on Intel® Architecture.

[Hardware Transactional Memory] Why _xbegin() return 0

Mengxing_L_
Beginner
8,085 Views

Hello, everyone. I am trying intel RTM now.

I am confusing that _xbegin() return 0 frequently. If _xbegin failed/ abort, it should return a abort status.https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/X86-transactional-memory-intrinsics.html

Here is my test code: There are 1000 accounts in a bank; A random account transfer 1$ to another  random account each time.

for(int i=0; i<5000000; i++){
		int src = rand()%bank->size;
		int dst = rand()%bank->size;
		//printf("src %d dst %d\n", src, dst);
		while(src == dst){
			dst = rand()%bank->size;
		}

		unsigned stat = _xbegin();
		if(stat == _XBEGIN_STARTED){
			bank->accounts[src].balance--;
			bank->accounts[dst].balance++;
			_xend();
			tx[id]++;
		}else{
			_abort[id]++;
			if (stat & _XABORT_CONFLICT){
				conflict[id]++;
			}
			if (stat & _XABORT_CAPACITY){
				capacity[id]++;
			}
			if (stat & _XABORT_DEBUG){
				debug[id]++;
			}
			if (stat & _XABORT_RETRY == 0){
				failed[id]++;
			}
			if (stat & _XABORT_NESTED){
				printf("[ PANIC ] _XABORT_NESTED\n");
				exit(-1);
			}
			if (stat & _XABORT_EXPLICIT){
				printf("[ panic ] _XBEGIN_EXPLICIT\n");
				exit(-1);
			}
			if (stat == 0){
			//	printf("[ panic] stat is zero\n");
			//	exit(-1);
			}
		}
	}

 

I was wondering in which situation will the _xbegin() return 0?

0 Kudos
27 Replies
JWong19
Beginner
1,922 Views

Mengxing, I ran several times before I posted. I use vs2015 instead of g++ to build the program. Could you show disassembly of the loops to confirm whether Jim's touch code is in effect or not?

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,922 Views

>>Could you show disassembly of the loops to confirm whether Jim's touch code is in effect or not?

Confirmation should be performed. In my opinion, the code optimization should NOT consider manipulation of volatile variables in "dead code" elimination. "volatile", as one of its definitions, declares that the memory location may be observed and/or modified by an external process not visible to the compiler.

If you find the Touch code optimized out, then as a work around you will have to write asm statements to perform the touch.

Jim Dempsey

0 Kudos
JWong19
Beginner
1,922 Views

A simple trick is to print the variable 'Touch' as well, in case the compiler eliminates it...

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,922 Views

Jeremy,

If the Touch code were stripped, then the following may be better

if(zero == 999999999) printf("%d", Touch); // don't expect this to print

Jim Dempsey

0 Kudos
Mengxing_L_
Beginner
1,922 Views

Sorry for response late.

I use gdb to disassemble the code, I am sure Touch is executed.

if (stat == 0){
   0x0000000000400fc2 <+263>:	cmpl   $0x0,-0x4(%rbp)
   0x0000000000400fc6 <+267>:	jne    0x40105d <f1(Bank*, int)+418>

49			// ?? interrupt may have unmapped page holding [src] and/or [dst]
50			Touch = bank->accounts[src].balance + bank->accounts[dst].balance;
---Type <return> to continue, or q <return> to quit---
   0x0000000000400fcc <+273>:	mov    -0x18(%rbp),%rax
   0x0000000000400fd0 <+277>:	mov    (%rax),%rax
   0x0000000000400fd3 <+280>:	mov    -0x8(%rbp),%edx
   0x0000000000400fd6 <+283>:	movslq %edx,%rdx
   0x0000000000400fd9 <+286>:	shl    $0x6,%rdx
   0x0000000000400fdd <+290>:	add    %rdx,%rax
   0x0000000000400fe0 <+293>:	mov    (%rax),%rax
   0x0000000000400fe3 <+296>:	mov    %eax,%edx
   0x0000000000400fe5 <+298>:	mov    -0x18(%rbp),%rax
   0x0000000000400fe9 <+302>:	mov    (%rax),%rax
   0x0000000000400fec <+305>:	mov    -0xc(%rbp),%ecx
   0x0000000000400fef <+308>:	movslq %ecx,%rcx
   0x0000000000400ff2 <+311>:	shl    $0x6,%rcx
   0x0000000000400ff6 <+315>:	add    %rcx,%rax
   0x0000000000400ff9 <+318>:	mov    (%rax),%rax
   0x0000000000400ffc <+321>:	add    %edx,%eax
   0x0000000000400ffe <+323>:	mov    %eax,0x2061fc(%rip)        # 0x607200 <Touch>

51	     	zero[id]++;
   0x0000000000401004 <+329>:	mov    0x2061ed(%rip),%rax        # 0x6071f8 <zero>
   0x000000000040100b <+336>:	mov    -0x1c(%rbp),%edx
   0x000000000040100e <+339>:	movslq %edx,%rdx
   0x0000000000401011 <+342>:	shl    $0x3,%rdx
   0x0000000000401015 <+346>:	add    %rdx,%rax
   0x0000000000401018 <+349>:	mov    (%rax),%rdx
   0x000000000040101b <+352>:	add    $0x1,%rdx
   0x000000000040101f <+356>:	mov    %rdx,(%rax)

 

0 Kudos
JWong19
Beginner
1,922 Views

I set "src=0" and "dst=1" instead of random number in my test (https://github.com/jrmwng/like2016/blob/test/jrmwng/why_xbegin_return_0/main.cpp).

From the disassembly, the 'Touch' assignment statement is followed by the 'zero' increment statement. It is different from the order in Jim's Touch codes (https://github.com/jrmwng/like2016/blob/test_jim/jrmwng/why_xbegin_return_0/main.cpp).

In addition, it'd be much clear if you dump addresses of relevant variables (e.g. addressof(src), addressof(dst), addressof(bank), addressof(bank->account), addressof(bank->account[src]), addressof(bank->account[dst]), addressof(zero), addressof(zero[id])) when the problem happens

0 Kudos
zhang_l_1
Beginner
1,922 Views

I also meet with the issues, I am confused about two problems:

1. _xbegin return 0 in one-thread situation;

2. conflicts happens when 2 threads access the independent locations. https://github.com/natsys/blog/blob/master/tsx.cc#L153-L158 this lines show that two threads access the independent data. and '_XABORT_CONFLICT' happens frequently.

BTW, are there some detail manual about RTM programming. I am a beginner, Thanks. :)

0 Kudos
Reply