OpenCL通过引用传递不同的地址空间
短篇故事: 我有一个输出变量的传递引用函数OpenCL通过引用传递不同的地址空间,opencl,pass-by-reference,Opencl,Pass By Reference,短篇故事: 我有一个输出变量的传递引用函数 void acum( float2 dW, float4 dFE, float2 *W, float4 *FE ) 如果满足某些条件,则假定增量变量*W,*FE,乘以dW,dFE。 我想将此函数设置为通用-输出变量可以是本地变量,也可以是全局变量 acum( dW, dFE, &W , &FE ); // __local acum acum( W, FE, &Wout[idOut], &FEout[idOut]
void acum( float2 dW, float4 dFE, float2 *W, float4 *FE )
如果满足某些条件,则假定增量变量*W,*FE,乘以dW,dFE。
我想将此函数设置为通用-输出变量可以是本地变量,也可以是全局变量
acum( dW, dFE, &W , &FE ); // __local acum
acum( W, FE, &Wout[idOut], &FEout[idOut] ); // __global acum
当我试图编译它时,我得到了一个错误
error: illegal implicit conversion between two pointers with different address spaces
有没有可能以某种方式做到这一点???我在想我是否可以用宏代替函数(但我不太熟悉C语言中的宏)
另一种可能性可能是:
//====函数::FF_vdW-莱纳德·琼斯·范德瓦尔斯力场
浮动4 FF_vdW(浮动3 R){
常数浮点C6=1.0;
常量浮点C12=1.0;
浮动ir2=1.0/点(R,R);
浮动ir6=ir2*ir2*ir2;
浮动ir12=ir6*ir6;
浮点数E6=C6*ir6;
浮点数E12=C12*ir12;
申报表(4)(
(6*E6-12*E12)*ir2*R
,E12-E6
);}
//====函数::FF_弹簧-谐波力场
浮动4 FF_弹簧(浮动3 R){
常数float3k=(float3)(1.0,1.0,1.0);
float3f=k*R;
申报表(4)(F),
0.5*点(F,R)
);}
//====函数::EtoW-计算统计权重
浮动2 EtoW(浮动EkT){
浮动Wexp=地板(EkT);
返回(浮动2)(经验(EkT-Wexp)
,Wexp
); }
//====程序:addExpInplace—使用统计权重dW计算F,E
无效acum(浮动2 dW、浮动4 dFE、浮动2*W、浮动4*FE)
{
float dExp=dW.y-(*W.y;//log(dW)-log(W)
如果(dExp>-22){//e^22=2^32,则单浮点数=2^+64
浮点数fac=exp(dExp);
if(dExp logWcut
float kT//应取样的最大能量
) {
int id=get_global_id(0);//在潜在网格点上循环
int idx=id/nV.x;
int3 iV=(int3)(idx/nV.y)
,idx%nV.y
,id%nV.x);
浮点数V=Vsurf[id];
浮动3 RXe=dV*iV;
如果(VOK,下面是OpenCL手册页中发生的事情:
如果对象的类型由地址空间名称限定,则该对象在指定的地址名称中分配;否则,该对象在通用地址空间中分配
程序中函数的参数或函数的局部变量的通用地址空间名为_私有。所有函数参数都应在_私有地址空间中
因此,acum(…)函数参数位于_私有地址空间中
因此,编译器的说法是正确的
acum(..&Wout[idOut]、&FEout[idOut])
在全局addrress空间中使用&Wout和&FEout调用,而函数args必须位于专用地址空间中
解决方案是在全局和私有之间进行转换
创建两个私有临时变量以接收结果
用这些变量调用acum(…)
调用acum(..)后,将临时私有值指定给全局值
代码看起来有点混乱
请记住,在GPU上有许多地址空间,您不能通过强制转换在它们之间神奇地跳转。您必须通过赋值在地址空间之间显式移动数据。您还可以将全局限定符添加到必要的accum(…)函数args。但是您将得到两个函数,一个带全局函数,一个不带。并且您需要不同的名称,因为在ISOC99中没有函数名重载。
// ===== function :: FF_vdW - Lenard-Jones Van Der Waals forcefield
float4 FF_vdW ( float3 R ){
const float C6 = 1.0;
const float C12 = 1.0;
float ir2 = 1.0/ dot( R, R );
float ir6 = ir2*ir2*ir2;
float ir12 = ir6*ir6;
float E6 = C6*ir6;
float E12 = C12*ir12;
return (float4)(
( 6*E6 - 12*E12 ) * ir2 * R
, E12 - E6
);}
// ===== function :: FF_spring - harmonic forcefield
float4 FF_spring( float3 R){
const float3 k = (float3)( 1.0, 1.0, 1.0 );
float3 F = k*R;
return (float4)( F,
0.5*dot(F,R)
);}
// ===== function :: EtoW - compute statistical weight
float2 EtoW( float EkT ){
float Wexp = floor( EkT);
return (float2)( exp(EkT - Wexp)
, Wexp
); }
// ===== procedure : addExpInplace -- acumulate F,E with statistical weight dW
void acum( float2 dW, float4 dFE, float2 *W, float4 *FE )
{
float dExp = dW.y - (*W).y; // log(dW)-log(W)
if(dExp>-22){ // e^22 = 2^32 , single_float = 2^+64
float fac = exp(dExp);
if (dExp<0){ // log(dW)<log(W)
dW.x *= fac;
(*FE) += dFE*dW.x;
(*W ).x += dW.x;
}else{ // log(dW)>log(W)
(*FE) = dFE + fac*(*FE);
(*W ).x = dW.x + fac*(*W).x;
(*W ).y = dW.y;
}
}
}
// ===== __kernel :: sampler
__kernel void sampler(
__global float * Vsurf, // in : surface potential (including vdW) // may be faster to precomputed endpoints positions like float8
__global float4 * FEout, // out : Fx,Fy,Fy, E
__global float2 * Wout, // out : W_digits, W_exponent
int3 nV ,
float3 dV ,
int3 nOut ,
int3 iOut0 , // shift of Fout in respect to Vsurf
int3 nCopy , // number of copies of
int3 nSample , // dimension of sampling in each dimension around R0 +nSample,-nSample
float3 RXe0 , // postion Xe relative to Tip
float EcutSurf ,
float EcutTip ,
float logWcut , // accumulate only when log(W) > logWcut
float kT // maximal energy which should be sampled
) {
int id = get_global_id(0); // loop over potential grid points
int idx = id/nV.x;
int3 iV = (int3)( idx/nV.y
, idx%nV.y
, id %nV.x );
float V = Vsurf[id];
float3 RXe = dV*iV;
if (V<EcutSurf){
// loop over tip position
for (int iz=0;iz<nOut.z;iz++ ){
for (int iy=0;iy<nOut.y;iy++ ){
for (int ix=0;ix<nOut.x;ix++ ){
int3 iTip = (int3)( iz, iy, ix );
float3 Rtip = dV*iTip;
float4 FE = 0;
float2 W = 0;
// loop over images of potential
for (int ix=0;ix<nCopy.x;ix++ ){
for (int iy=0;iy<nCopy.y;iy++ ){
float3 dR = RXe - Rtip;
float4 dFE = FF_vdW( dR );
dFE += FF_spring( dR - RXe0 );
dFE.w += V;
if( dFE.w < EcutTip ){
float2 dW = EtoW( - FE.w / kT );
acum( dW, dFE, &W , &FE ); // __local acum
}
}
}
if( W.y > logWcut ){ // accumulate force
int idOut = iOut0.x + iOut0.y*nOut.x + iOut0.z*nOut.x*nOut.y;
acum( W, FE, &Wout[idOut], &FEout[idOut] ); // __global acum
}
}}}}
}