把你的代码卸载到GPU(用GPU编程):如何开始

本文翻译自:http://goparallel.sourceforge.net/offload-your-code-to-your-gpu-how-to-get-started/

水平有限,还望各路大侠指点一二。


在写这篇文章的时候大部分PC都已经有独立显卡了而且还都是多核处理器这些牛逼的显卡能够支持更高级的图形效果但是大部分时间他们都处在空闲状态直到有图形显示程序译者比如游戏开起来他们才起作用过去人们努力尝试使用显卡上的处理器核心的进展不大但是,Intel的平行工作室(Parallel Studio)却让它变得简单然后我就打算在我以后的软件开发项目中使用这项技术这篇博客向你展示了使用平行工作室的图形技术的基本方法


简单的例子程序


在开始前我们需要一个普通的程序来展示如何使用Intel的图形技术为了让东西简单点我创建了一个程序用来把RGB值转成灰度值

#define _NUMCOLORS 256*256*256
void RGBToGray(int &nRGB, int &nGray)
{
	int nRed = nRGB >> 16;
	int nGreen = (nRGB >> 8) & 0xff;
	int nBlue = nRed & 0xff;
	double dRedPortion = (double)nRed * 0.21;
	double dGreenPortion = (double)nGreen * 0.72;
	double dBluePortion = (double)nBlue * 0.07;
	nGray = (int)dRedPortion + (int)dGreenPortion + (int)dBluePortion;
}

void CreateInBufferValues(int *InBuffer)
{
	for (int i = 0; i < _NUMCOLORS; i++)
	{
		InBuffer[i] = i;
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	int *InBuffer = new int[_NUMCOLORS];
	int *OutBuffer = new int[_NUMCOLORS];

	CreateInBufferValues(InBuffer);

	for (int i = 0; i < _NUMCOLORS; i++)
	{
		RGBToGray(InBuffer[i], OutBuffer[i]);
	}

	return 0;
}

清单1用来探索用GPU编程的示例程序


我们可以用并行化for循环的方法来让这段程序优化很多事实上在我们把程序卸载到GPU之前我们就是需要先并行化程序的所以清单2中所改的地方就是上述的优化项并且为卸载到GPU上做准备

for (int i = 0; i < _NUMCOLORS; i++)
{
	RGBToGray(InBuffer[i], OutBuffer[i]);
}
改成

cilk_for(int i = 0; i < _NUMCOLORS; i++)
{
	RGBToGray(InBuffer[i], OutBuffer[i]);
}
清单2:并行化代码为放到GPU上所做的准备工作


同步卸载(offload)


卸载有2种类型。1种是同步另一种是异步同步中有2第一步是被调用的函数必须用__declspec(target(gfx))修饰第二步是必须在并行的for循环前加上#pragma offload清单3展示了清:1中的代码的改进版

#define _NUMCOLORS 256*256*256

__declspec (target(gfx))
void RGBToGray(int &nRGB, int &nGray)
{
	int nRed = nRGB >> 16;
	int nGreen = (nRGB >> 8) & 0xff;
	int nBlue = nRGB & 0xff;
	double dRedPortion = (double)nRed * 0.21;
	double dGreenPortion = (double)nGreen * 0.72;
	double dBluePortion = (double)nBlue * 0.07;
	nGray = (int)dRedPortion + (int)dGreenPortion + (int)dBluePortion;
}

void CreateInBufferValues(int *InBuffer)
{
	for (int i = 0; i < _NUMCOLORS; i++)
	{
		InBuffer[i] = i;
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	int *InBuffer = new int[_NUMCOLORS];
	int *OutBuffer = new int[_NUMCOLORS];
	CreateInBufferValues(InBuffer);

#pragma offload target(gfx) pin(InBuffer, OutBuffer:length(_NUMCOLORS))
	cilk_for(int i = 0; i < _NUMCOLORS; i++)
	{
		RGBToGray(InBuffer[i], OutBuffer[i]);
	}

	return 0;
}
清单 3: 1 中的代码的改进版

重新来看下同步卸载的步骤首先卸载的循环必须并行化在例子中这里用了cilk_for。第二卸载的函数必须被__declspec(target(gfx))修饰第三并行化的for循环前必须加上卸载的pragma。


异步卸载(offload)


从软件开发的立场来说同步和异步最大的不同就是同步是一种基于pragma的方法而异步是一种基于API的方法

在开始前我们需要写一个包含并行化for循环的函数它是自己被卸载的清单4显示了我们用作异步卸载的例子在函数前加了一句__declspec(target(gfx_kernel))

__declspec(target(gfx_kernel))
void offload(int *InBuffer, int *OutBuffer)
{
	cilk_for(int i = 0; i < _NUMCOLORS; i++)
	{
		RGBToGray(InBuffer[i], OutBuffer[i]);
	}
}
清单 4 将会被卸载的函数

第一个例子中的RGBToGray()函数一直都放在__declspec (target(gfx))之后最后清单5中的代码展示了所有异步卸载和执行所需要的东西

__GFX_share(InBuffer, sizeof(int)*_NUMCOLORS);

__GFX_share(OutBuffer, sizeof(int)*_NUMCOLORS);

__GFX_enqueue("offload", InBuffer, OutBuffer);

__GFX_wait();

__GFX_unshare(InBuffer);

__GFX_unshare(OutBuffer);
清单5:卸载和执行的代码

总结


如你所见在使用平行工作室Parallel Studio把代码卸载到GPU是很直接很简单的探索如何让你的程序表现的更好真的是个很有挑战的技术活


===============================================================================================================================================================


自言自语:

文中的几个概念

cilk_for:for的并行化版本,可以看http://blog.csdn.net/gengshenghong/article/details/7235125这篇文章,大神们早已探过路了

offload:转移讲代码转移到GPU上运行

并行化并行计算中的内容详细可以搜mic编程


另外,关于这篇文章,其实我也没看懂多少,只是在翻译过程中大概搜了下上面的概念,所以翻译的肯定不一定正确,还望各位大侠们不吝赐教,跪谢~~~






  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值