MIC offload using C++

MIC offload using C++

Hello,

I am trying to port a C++ code using the offload mic directives. I have developed a toy code,

but I cannot manage offload computations using member classes. The code I am working on is provided below.

main.cpp:

#include "foo.h"
int main()

	{

	        foo fo(2,2,2);

	        fo.transfer_on_mic();

	        fo.compute();

	}

foo.cpp:

#include "foo.h"

	#include "work.h"

	foo::foo(int size1_,int size2_,int size3_):size1(size1_),size2(size2_),size3(size3_)

	{

	        p_simple=new float[size1*size2*size3];
        for(int i=0;i<size1;i++)

	                for(int j=0;j<size2;j++)

	                        for(int k=0;k<size3;k++)

	                                p_simple[i*size3*size2+j*size3+k] = 23.F;

	}
void foo::transfer_on_mic()

	{

	#pragma offload_transfer target(mic:1) in(p_simple:length(size1*size2*size3) alloc_if(1) free_if(0))

	}
void foo::compute()

	{

	#pragma offload target(mic:1) in(p_simple:length(0) alloc_if(0) free_if(0))

	        {

	                work_simple(p_simple,size1,size2,size3);

	        }
}

work.cpp

#include <stdio.h>

	#include "work.h"
__declspec(target(mic)) void work_simple(float *field,int maxi,int maxj ,int maxk)

	{

	        for(int i=0;i<maxi;i++)

	                for(int j=0;j<maxj;j++)

	                        for(int k=0;k<maxk;k++)

	                                printf("%f n", field[i*maxk*maxj+j*maxk+k]);
}

#ifndef FOO_H

	#define FOO_H

	#pragma offload_attribute (push,target(mic))

	struct foo{

	        foo(int ,int ,int);
        void transfer_on_mic();

	        void compute();
        float *p_simple;
        int size1,size2,size3;

	};

	#pragma offload_attribute (pop)

	#endif

#ifndef WORK_H

	#define WORK_H

	__declspec(target(mic)) void work_simple(float *field,int,int,int);

	#endif

The offload_trasfer seems to work, while the offloaded computation results in a sigsegv error.

Thanks,

Francesco

7 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

foo.cpp fails to compile. I believe the code I have is what was provided but I'll check again.

$ icpc -c foo.cpp
foo.cpp(16): error: invalid entity for this variable list in
  #pragma offload_transfer target(mic:1) in(p_simple : lengt
 alloc_if(1) free_if(0))
                                            ^

foo.cpp(21): error: invalid entity for this variable list in
  #pragma offload target(mic:1) in(p_simple : length(0) allo
                                   ^

compilation aborted for foo.cpp (code 2)

I cannot find the problem, this is foo.cpp

#include "foo.h"
#include "work.h"
using namespace std;

foo::foo(int size1_,int size2_,int size3_):size1(size1_),size2(size2_),size3(size3_)
{
        p_simple=new float[size1*size2*size3];

        for(int i=0;i<size1;i++)
                for(int j=0;j<size2;j++)
                        for(int k=0;k<size3;k++)
                                p_simple[i*size3*size2+j*size3+k] = 23.F;
}

void foo::transfer_on_mic()
{
#pragma offload_transfer target(mic:1) in(p_simple:length(size1*size2*size3) alloc_if(1) free_if(0))
}

void foo::compute()
{
#pragma offload target(mic:1) in(p_simple:length(0) alloc_if(0) free_if(0))
        {
                work_simple(p_simple,size1,size2,size3);
        }

}

Francesco

Development’s guidance is that p_simple is a data member of the class, we don't support its usage in offload clauses, and we started diagnosing this in 14.0, which is why I suffered the compilation error. I confirmed this code compiled successfully with 13.1 but suffers the seg-fault you noted.

We have an open feature request for this support in a future release (internal tracking id below) and I will keep this thread updated on the availability of that support in a future release as I learn it.

There is a work around available of using a temporary pointer. This is accomplished with the following changes:

In foo.h, after line 16, add the following declaration:

       static float *p_tmp;

In foo.cpp, make the following changes:

1. After line 22 (before the offload_transfer), add this assignment:

        p_tmp = p_simple;

2. On lines 23, 30, and 34, change the reference for p_simple to p_tmp.

These changes are using with both 13.1 and 14.0 compilers.

(Internal tracking id: DPD200356158)
(Resolution Update on 09/16/2014): This defect is fixed in the Intel® Parallel Studio XE 2015 Initial Release (2015.0.090 - Linux)

What exactly is the requirement for p_simple? Just not a class member?

In my case a global variable would be not so nice. So I tried it with a method local variable. In this example I just put

float *p_tmp = p_simple;

in front of the offloads in transfer_on_mic and compute, and removed the

static float *p_tmp;

from the header. And it does work. Is this supposed to work, or do I have to be careful here?

I want to use it for a slightly more complicated problem, but I probably start a new thread for that.

In your original code, on the host, what you see in the source code is p_simple, what you are actually using is this->p_simple. On the offload side, the code is only seeing p_simple without a corresponding this object. By making it a local variable (float *p_tmp = p_simple;) you've removed the hidden "this->".

Jim Dempsey

www.quickthreadprogramming.com

Feature support for using a data member of the class within the offload clause is now available in the latest Intel® Parallel Studio XE 2015 initial release for both Linux and Windows.

The test case in the original post successfully compiles and produces expected results using the Intel® Parallel Studio XE 2015 Initial Release (2015.0.090 - Linux).

Leave a Comment

Please sign in to add a comment. Not a member? Join today