繪製julia集的曲線--GPU高性能編程CUDA實戰4.2.2

#include "../common/book.h"
#include "../common/cpu_bitmap.h"
//自學的一個CUDA比較有趣的編程,我也來寫寫註釋
#define DIM 1000

struct cuComplex {
    float   r;
    float   i;
//這裏的話就是原來少些了個__device__,這是結構體的構造函數,在julia()裏使用了,然後Julia()是設備端的函數,所以這裏也需要加上,要不然沒有辦法運行的
    __device__ cuComplex( float a, float b ) : r(a), i(b)  {}
//這個函數是求複數的模
    __device__ float magnitude2( void ) {
        return r * r + i * i;
    }
//這裏定義了一個*運算,和下面的+運算,用來執行復數運算的
    __device__ cuComplex operator*(const cuComplex& a) {
        return cuComplex(r*a.r - i*a.i, i*a.r + r*a.i);
    }
    __device__ cuComplex operator+(const cuComplex& a) {
        return cuComplex(r+a.r, i+a.i);
    }
};
//設備端調用,在設備端運行的都要加__device__,如果是在主機端調用,設備端執行的,那就是Kernel函數,用的是__global__
__device__ int julia( int x, int y ) {
//這裏是爲了讓圖像更大,選擇了1.5倍,還有下面的兩句爲了是圖像開始時候位於窗口的中心
    const float scale = 1.5;
    float jx = scale * (float)(DIM/2 - x)/(DIM/2);
    float jy = scale * (float)(DIM/2 - y)/(DIM/2);
//這裏的常數C在書上寫着:這個值剛好能生成一張有趣的圖片
    cuComplex c(-0.8, 0.156);
    cuComplex a(jx, jy);
//執行迭代運算,判斷該像素點是不是屬於Julia集,是的返回值是1,
    int i = 0;
    for (i=0; i<200; i++) {
        a = a * a + c;
        if (a.magnitude2() > 1000)
            return 0;
    }

    return 1;
}

__global__ void kernel( unsigned char *ptr ) {
//這裏是索引,dim3裏定義的是二維線程格(其實是三維的,最後一維默認爲1)所以裏面的block裏有x和y兩維索引
    // map from blockIdx to pixel position
    int x = blockIdx.x;
    int y = blockIdx.y;
    int offset = x + y * gridDim.x;
//一開始我還不是很明白,後來在看頭文件的時候慢慢的明白了些,不過還是迷亂,這裏是沒個像素有4個字節,所以索引之後要乘以4才能找到對應像素的位置,然後這四個字節表示的是RGBA模型,第一個是代表紅色
<div style="text-indent: 28px;">//第二個代表綠色,第三個代表藍色,也就是說如果是在Julia集上,會顯示藍色,0-255代表的是亮度,255就是藍色。其餘的就是黑色的,黑色是哪裏來的我還不是很清楚,如果有看到的可以給我解釋一下嘛,哈哈,<span style="font-size:12px;">最後的</span>一個字節表示的是<span style="font-family:arial, 宋體, sans-serif;font-size:12px;color:#333333;"><span style="line-height: 24px; ">不透明參數,值在0-1直接,1的話就是不透明的。</span></span></div>
    // now calculate the value at that position
    int juliaValue = julia( x, y );
    ptr[offset*4 + 0] = 0;
    ptr[offset*4 + 1] = 0;
    ptr[offset*4 + 2] =255* juliaValue;
    ptr[offset*4 + 3] = 1;
}

//這裏在書裏是沒有的,bitmap()函數裏也沒有第三個參數,書上的很好理解,這裏突然出現兩個一樣的指針聽迷惑的,於是就去cpu_bitmap.h裏看一看,裏面僅有的一個構造函數是三個參數的
// globals needed by the update routine,結構體就相當於類,看起來挺棒,之前我怎麼不知道。
struct DataBlock {
    unsigned char   *dev_bitmap;
};
//剩下的都是頭文件裏的函數可以直接調用,沒什麼好說的,其實關於裏面的GLUT我想知道的還有很多呢。。。
int main( void ) {
    DataBlock   data;
    CPUBitmap bitmap( DIM, DIM, &data );
    unsigned char    *dev_bitmap;

    HANDLE_ERROR( cudaMalloc( (void**)&dev_bitmap, bitmap.image_size() ) );
    data.dev_bitmap = dev_bitmap;

    dim3    grid(DIM,DIM);
    kernel<<<grid,1>>>( dev_bitmap );

    HANDLE_ERROR( cudaMemcpy( bitmap.get_ptr(), dev_bitmap,
                              bitmap.image_size(),
                              cudaMemcpyDeviceToHost ) );
                              
    HANDLE_ERROR( cudaFree( dev_bitmap ) );
                              
    bitmap.display_and_exit();
}

運行出來的結果是這樣的,很好看的


那麼 問題就來了,我想要分享一下這個程序,調試出來之後生成的應用程序不是可以直接打開嘛,然後在別的電腦上打開就會告訴我運行出現錯誤

有幾個問題,第一個是我把.exe文件單獨拉出了運行,告訴我缺少glut.dll文件,我知道我在SYSTEM文件夾裏存了這個,我調試用的32位,運行的時候我用把這個文件放到了SysWOW64文件夾裏,然後可以運行了,其實後來直接把他們直接放在一個文件夾裏就好了

於是第二個問題,我打包發給朋友,然後運行缺少cudart.dll於是我把這個文件也放在了一個文件夾下,就是下圖


然後不會報錯了,只是運行一閃,看到兩行代碼,然後不會出現照片,正常的情況是直接出來個框框,然後緊接着出來上面的圖像纔對,我改怎麼辦才能在別的電腦上運行呢???

我好想知道,存疑,還沒有解決!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章