Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.
7956 Discussions

Threadprivate directive doesn't work as expected

digchiko
Beginner
398 Views
I wrote a test example which resembles the situation I have in my application. The system consists of main.c, work.c and def.h files.


def.h
---------
#include  

#define STOP 4


extern int myvar;


void SetValue(int val);
int Count();
int GetValue();
int *GetAddress(void);


work.c
-----------
#include "def.h"

int myvar;
#pragma omp threadprivate(myvar)


int *GetAddress(void) { return &myvar;}

int GetValue() { return myvar;}

void SetValue(int val) { myvar = val;}

int Count()
{
myvar++;
if (myvar == STOP)
return 0;
else
return 1;
}

main.c
-----------
#include 
#include "def.h"


int main()
{
int cnt=0;

omp_set_num_threads(4);

SetValue(-1);
printf("Before parallel region: myvar address: %p value: %d ",&myvar, myvar);

#pragma intel omp parallel taskq shared(cnt)
while (Count())
{
#pragma intel omp task captureprivate(cnt)
{
SetValue(cnt);
printf("Thread %d myvar address: %p value: %d GetAddress: %p GetValue: %d ",
omp_get_thread_num(), &myvar, myvar, GetAddress(), GetValue());
}
cnt++;
}

return 1;
}


When I make and execute this I get the following output:

Before parallel region: myvar address: 0x804b83c value: -1
Thread 0 myvar address: 0x804b83c value: 0 GetAddress: 0x804b83c GetValue: 0
Thread 3 myvar address: 0x804b83c value: 0 GetAddress: 0x805c180 GetValue: 1
Thread 1 myvar address: 0x804b83c value: 0 GetAddress: 0x805c380 GetValue: 2
Thread 2 myvar address: 0x804b83c value: 0 GetAddress: 0x805c580 GetValue: 3



This is not what I expected. When threads start to execute parallel region (tasks) any reference to a myvar should be to the same, threadprivate copy of the global variable. What I got here is that if I reference myvar by its name in main.c it works with the global variable, and when I call functions defined in work.c it works with a threadprivate copies.

In my opinion this is a bug. Can you confirm this?


0 Kudos
3 Replies
Xinmin_T_Intel
Employee
398 Views

This is an user error/mis-understanding. In the def.h file, you need to mark "myvar" as threadprivate to get expected behavior. Below isthe correct usage of threadprivate for your test . In addition, you need to change the order of including def.h in work.c to get the legalsyntax of using "pragma omp threadprivate" for extern int myvar.

Xinmin Tian (Intel)

// def.h

#include
#define STOP 4

extern int myvar;
#pragma omp threadprivate(myvar)

void SetValue(int val);
int Count();
int GetValue();
int *GetAddress(void);

// work.c

int myvar;
#pragma omp threadprivate(myvar)

#include "def.h"

int *GetAddress(void) { return &myvar;}
int GetValue() { return myvar;}
void SetValue(int val) { myvar = val;}
int Count() { myvar++; if (myvar == STOP) return 0; else return 1;}

// main.c

#include
#include "def.h"
int main()
{ int cnt=0;
omp_set_num_threads(4);
SetValue(-1);
printf("Before parallel region: myvar address: %p value: %d ",&myvar, myvar);
#pragma intel omp parallel taskq shared(cnt)
while (Count()) {
#pragma intel omp task captureprivate(cnt)
{
SetValue(cnt);
printf("Thread %d myvar address: %p value: %d GetAddress: %p GetValue: %d ", omp_get_thread_num(), &myvar, myvar, GetAddress(), GetValue());
}
cnt++;
}
return 1;
}

icl -Qopenmp main.c work.c
Intel C++ Compiler for applications running on IA-32, Version Mainline Beta
Build x
Built Jan 2 2008 18:11:27 by xtian on SC12SSG005 in C:/cmplr/dev_hpo/dev
Copyright (C) 1985-2007 Intel Corporation. All rights reserved.

main.c
C: estsmain.c(10): (col. 1) remark: TASK CONSTRUCT WAS PARALLELIZED.
C: estsmain.c(8): (col. 1) remark: PARALLEL TASKQ CONSTRUCT WAS PARALLELIZED.
work.c
Microsoft Incremental Linker Version 7.10.3077
Copyright (C) Microsoft Corporation. All rights reserved.

-out:main.exe
-nodefaultlib:libguide_stats.lib
-nodefaultlib:libguide40_stats.lib
-defaultlib:libguide.lib
main.obj
work.obj
./main.exe
Before parallel region: myvar address: 0042C11C value: -1
Thread 2 myvar address: 00447B80 value: 0 GetAddress: 00447B80 GetValue: 0
Thread 1 myvar address: 00448280 value: 1 GetAddress: 00448280 GetValue: 1
Thread 0 myvar address: 0042C11C value: 3 GetAddress: 0042C11C GetValue: 3
Thread 3 myvar address: 00448380 value: 2 GetAddress: 00448380 GetValue: 2

0 Kudos
digchiko
Beginner
398 Views

Thanks for the answer!

Before I wrote this post I tried all the combinations of where to put threadprivate directive, but the trick is in the order in which I include header file.

I will test this in a few days just to confirm that everything is OK.

Have a nice time!

0 Kudos
vladimir_gajinov
Beginner
398 Views
I just want to verify that your explanation is correct.

Thanks again.


0 Kudos
Reply