Software Archive
Read-only legacy content
17060 Discussions

Problem using locks with MIC and OpenMP

Yoel_E_
Beginner
930 Views

Hi all,

 

I'm new to this world of MIC and OpenMP. I'm trying to write a simple multithreaded program that uses a lock and it seems to give me a segmentation fault.

The code:

#include <stdio.h>
#include <omp.h>

__attribute__((target(mic))) int chk_target() {
    int retval;

    #ifdef __MIC__
        retval = 1;
    #else
        retval = 0;
    #endif

    // Return 1 if target available
    return retval;
}

int main() {
	omp_lock_t lck;
	int id;
	int mic_ok;
	
	omp_init_lock(&lck);

	#pragma offload target(mic)
	#pragma omp parallel num_threads(2) private(id) shared(lck)
	{
		mic_ok = chk_target();
		if (mic_ok == 0) {
			printf("Error offloading to MIC!\n");
		}
		else {
			printf("MIC found and running!\n");
		}

		id = omp_get_thread_num();
		omp_set_lock(&lck);
		/* only one thread at a time can execute this printf */
		printf("My thread id is %d.\n", id);
		omp_unset_lock(&lck);
	}

	omp_destroy_lock(&lck);

	return 0;
}

Compilation command:

icc -qopenmp <filename> -o <output_filename>

 

The output:

offload error: process on the device 0 was terminated by signal 11 (SIGSEGV)

When the same code is run on the host, it runs fine without issue.

 

Would love to get some help to start me up on this subject :)

 

Thanks!

0 Kudos
1 Solution
Kevin_D_Intel
Employee
930 Views

Try keeping the context of the lock exclusively within the scope of the offload. IOW, move the #pragma offload above the omp_init_lock and encapsulate the omp_init_lock/omp_destroy_lock within the scope of the offload.

Something like this works:

     #pragma offload target(mic)
     {
        omp_init_lock(&lck);

        #pragma omp parallel num_threads(2) private(id) shared(lck)
        {
                mic_ok = chk_target();
                if (mic_ok == 0) {
                        printf("Error offloading to MIC!\n");
                }
                else {
                        printf("MIC found and running!\n");
                }

                id = omp_get_thread_num();
                omp_set_lock(&lck);
                /* only one thread at a time can execute this printf */
                printf("My thread id is %d.\n", id);
                omp_unset_lock(&lck);
        }

        omp_destroy_lock(&lck);
     }  // end pragma offload

 

View solution in original post

0 Kudos
5 Replies
Kevin_D_Intel
Employee
931 Views

Try keeping the context of the lock exclusively within the scope of the offload. IOW, move the #pragma offload above the omp_init_lock and encapsulate the omp_init_lock/omp_destroy_lock within the scope of the offload.

Something like this works:

     #pragma offload target(mic)
     {
        omp_init_lock(&lck);

        #pragma omp parallel num_threads(2) private(id) shared(lck)
        {
                mic_ok = chk_target();
                if (mic_ok == 0) {
                        printf("Error offloading to MIC!\n");
                }
                else {
                        printf("MIC found and running!\n");
                }

                id = omp_get_thread_num();
                omp_set_lock(&lck);
                /* only one thread at a time can execute this printf */
                printf("My thread id is %d.\n", id);
                omp_unset_lock(&lck);
        }

        omp_destroy_lock(&lck);
     }  // end pragma offload

 

0 Kudos
Yoel_E_
Beginner
930 Views

Thanks, that did it :)

Can you explain why there's a difference?

0 Kudos
jimdempseyatthecove
Honored Contributor III
930 Views

The omp_lock_t is an opaque object (struct) and may not necessarily be copy able as POD from outside the offload to inside the offload via shared(lck).

You also have a race condition in that mic_ok is not declared as private. This race condition is benign because all threads inside the offload parallel region ought to return the same value.

Jim Dempsey

0 Kudos
Yoel_E_
Beginner
930 Views

Many thanks! :)

0 Kudos
James_C_Intel2
Employee
930 Views

Jim Dempsey is correct. The omp_lock_t may contain a pointer to additional information, in which case it cannot be copied between address spaces. 

The wider point is that if you're writing C/C++ and using OpenMP it is very helpful to follow the practice of declaring variables in the smallest possible scope. (I find this good practice anyway, but it particularly helps OpenMP since it often removes the need for private or firstprivate annotations which are easy to forget).

P.S. if your code is really all you're trying to do, there's no need to use an explicit lock. you could write the guarded printf  using omp critical and do away with all of the lock manipulation, something like this

#pragma omp critical
{
    printf("My thread id is %d.\n", id);
}

 

0 Kudos
Reply