NVIDIA Optimus技术和CUDA

    Nvidia称Optimus是一个革命性的技术,它可以延长笔记本电脑续航时间,同时获得很好的性能。这种技术使得硬件能够自己选择使用那个显卡来计算。一般使用GPU计算的应用、视频、3D游戏等会被安排在高性能的NVIDIA GPU上执行,一些像Office、Web冲浪,电子邮件类似的应用会被安排在集成显卡上执行。

    如果你的笔记本有两块显卡,一块是Intel的集成显卡(IGP),一块是Nvidia的独立GPU,你的笔记本一般采用了Optimus技术。在使用CUDA的时候,务必要理解Optimus,才能很好的使用你的笔记本来开发CUDA程序。

    1、在运行自己的CUDA程序时,小心自己的程序找不到CUDA设备!(因为实现默认的是IGP奥)

    2、在使用Direct3D与CUDA、OpenGL与CUDA互操作时,开发人员要注意一些限制!

    针对以上限制,注意说明:

    1、查询CUDA设备:

// CUDA Runtime API Version
inline int cutGetMaxGflopsDeviceId() 
{ 
    int current_device   = 0, sm_per_multiproc = 0; 
    int max_compute_perf = 0, max_perf_device  = 0; 
    int device_count     = 0, best_SM_arch     = 0; 
    int arch_cores_sm[3] = { 1, 8, 32 }; 
    cudaDeviceProp deviceProp; 
 
    cudaGetDeviceCount( &device_count ); 
 
    // Find the best major SM Architecture GPU device 
    while ( current_device < device_count ) { 
        cudaGetDeviceProperties( &deviceProp, current_device ); 
        if (deviceProp.major > 0 && deviceProp.major < 9999) { 
            best_SM_arch = max(best_SM_arch, deviceProp.major); 
        } 
        current_device++; 
    } 
 
    // Find the best CUDA capable GPU device 
    current_device = 0; 
    while( current_device < device_count ) { 
        cudaGetDeviceProperties( &deviceProp, current_device ); 
        if (deviceProp.major == 9999 && deviceProp.minor == 9999) { 
            sm_per_multiproc = 1; 
        } else if (deviceProp.major <= 2) { 
            sm_per_multiproc = arch_cores_sm[deviceProp.major]; 
        } else { // Device has SM major > 2 
            sm_per_multiproc = arch_cores_sm[2]; 
        } 
 
        int compute_perf = deviceProp.multiProcessorCount *  
                           sm_per_multiproc * deviceProp.clockRate; 
 
        if( compute_perf > max_compute_perf ) { 
            // If we find GPU of SM major > 2, search only these 
            if ( best_SM_arch > 2 ) { 
                // If device==best_SM_arch, choose this, or else pass 
                if (deviceProp.major == best_SM_arch) {   
                    max_compute_perf  = compute_perf; 
                    max_perf_device   = current_device; 
                }  
            } else { 
                max_compute_perf  = compute_perf; 
                max_perf_device   = current_device; 
            } 
        } 
        ++current_device; 
    } 
 
    cudaGetDeviceProperties(&deviceProp, max_compute_perf_device); 
    printf("\nDevice %d: \"%s\"\n", max__perf_device,  
                                    deviceProp.name); 
    printf("Compute Capability   : %d.%d\n",  
            deviceProp.major, deviceProp.minor); 
    return max_perf_device; 
}

声明下哈,这个代码并不是我写的,在参考文献里粘贴的奥。这是官方给出的代码。大家可以参考着写出适合自己的代码,要是你想直接考走就用,建议你还是别看了,直接请别人给你做得了!!

2、Direct3DCUDAOpenGLCUDA互操作:

代码以蔽之!

// CUDA/Direct3D9 interop 
    // You will need to create the D3D9 context first 
IDirect3DDevice9 * g_pD3D9Device; // Initialize D3D9 rendering device 
    // After creation, bind your D3D9 context to CUDA 
cudaD3D9SetDirect3DDevice(g_pD3D9Device);


 

// CUDA/Direct3D9 interop 
    // You will need to create the D3D9 context first 
IDirect3DDevice9 * g_pD3D9Device; // Initialize D3D9 rendering device 
    // After creation, bind your D3D9 context to CUDA 
cudaD3D9SetDirect3DDevice(g_pD3D9Device);


 

// CUDA/Direct3D11 interop 
    // You will need to first create the D3D11 context first 
      ID3D11Device      * g_pD3D11Device; // Initialize D3D11 rendering device 
    // After creation, bind your D3D11 context to CUDA 
      cudaD3D11SetDirect3DDevice(g_pD3D11Device);


 

// For CUDA/OpenGL interop 
    // You will need to create the OpenGL Context first 
    // After creation, bind your D3D11 context to CUDA 
       cudaGLSetGLDevice(deviceID);


 

会写上面这些代码,并且可以熟练使用这些互操作接口后,你不一定能得到正确的结果奥,或者你的程序根本就不能运行!呵呵,这是为什么那。很可能的原因是你在使用cuda提供的互操作接口之前,DX、OpenGL的图形上下文可能已经被用在了IGP上了,所以会导致失败。解决方法:

    1.使用支持Optimus功能的笔记本用户可以在Nvidia Control panel的3DSettings->Manage3DSettings中将需要运行的程序加入到列表中,并将它们的preferred processor设置为High-performance Nvidia processor。

    2.程序编写者应该按照最新的方法修改代码。方法是首先创建一个不与设备绑定的OpenGL/D3D上下文;然后枚举所有CUDA设备并创建CUDA上下文;再把CUDA上下文所在设备与OpenGL/D3D上下文绑定;最后再将CUDA上下文与OpenGL/D3D上下文绑定。

 

参考:

【1】:NVIDIA CUDA Developer Guide for NVIDIA Optimus Platforms

【2】:http://hpcbbs.it168.com/forum.php?mod=viewthread&tid=5958&fromuid=26008496

你可能感兴趣的:(NVIDIA Optimus技术和CUDA)