Showing posts with label NVIDIA. Show all posts
Showing posts with label NVIDIA. Show all posts

Inverting Large Images Using CUDA

This is a simple example of how to invert a very large image, stored as a vector using nVidia's CUDA programming environment and an EVGA GeForce GTX 260 graphics card.

A GeForce GTX 260 card should have only 24 cores on it, but the nVidia SDK deviceQuery utility reports that there are 27 multiprocessors on my GeForce GTX 260 graphics card and I am able to use all 27 of them.

$ deviceQuery
CUDA Device Query (Runtime API) version (CUDART static linking)
There is 1 device supporting CUDA

Device 0: "GeForce GTX 260"
CUDA Driver Version: 2.30
CUDA Runtime Version: 2.30
CUDA Capability Major revision number: 1
CUDA Capability Minor revision number: 3
Total amount of global memory: 938803200 bytes
Number of multiprocessors: 27
Number of cores: 216
Total amount of constant memory: 65536 bytes
Total amount of shared memory per block: 16384 bytes
Total number of registers available per block: 16384
Warp size: 32
Maximum number of threads per block: 512
Maximum sizes of each dimension of a block: 512 x 512 x 64
Maximum sizes of each dimension of a grid: 65535 x 65535 x 1
Maximum memory pitch: 262144 bytes
Texture alignment: 256 bytes
Clock rate: 1.35 GHz
Concurrent copy and execution: Yes
Run time limit on kernels: Yes
Integrated: No
Support host page-locked memory mapping: Yes
Compute mode: Default (multiple host threads can use this device simultaneously)
The application is fairly trivial. It reads in an image file in PPM P6 format, stores the image in a vector of integers, one per pixel, with 24-bits used to store the RGB values. Depending on which command line option is selected ( -c invert using CPU, -g invert using GPU), it then inverts the image vector either using the CPU or the GPU (Graphical Processing Unit). Finally it writes the image out to an output file in PPM P6 format.

It uses a block size of 16 and a single kernel called myCudaInvertPixel which works on 16 rows of the image at the time via tiling.

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <climits>

#include <unistd.h>
#include <time.h>
#include <string.h>
#include <stdio.h>

#include <cuda.h>
#include <cuda_runtime_api.h>

#define BLOCK_SIZE 16
// #define DEBUG 0

// ------------ prototypes --------------
__global__ void myCudaInvertPixel(int *, int);


class CCL {

int width;
int height;

public:

CCL() { width = height = 0; }
~CCL() { width = height = 0; }

void cuda_ccl(vector& img, int w)
{
width = w;
height = img.size()/w;

#ifdef DEBUG
cout << "Image width=" << width << " height=" << height << endl;
#endif
int result = cuda_invert(img, width, height);

return;
}

private:
int cuda_invert(vector&, int, int);

};


int
CCL::cuda_invert(vector& image, int width, int height)
{
int deviceCount = 0;
int driverVersion = 0, runtimeVersion = 0;
int globalMem;
int image_size = width * height * sizeof(int);

int *cuda_image_ptr;
cudaDeviceProp deviceProp;
cudaError_t err;

int strake_size = 0;
int last_strake_size = 0;
int strakes = 0;
int this_strake_size = 0;
int offset = 0;

if (cudaGetDeviceCount(&deviceCount) != cudaSuccess) {
printf("ERROR: cudaGetDeviceCount failed. CUDA Driver and Runtime version may be mismatched.\n");
return 1;
}

if (deviceCount == 0) {
printf("ERROR: No device supporting CUDA found\n");
return 1;
}

cudaGetDeviceProperties(&deviceProp, 0);
globalMem = deviceProp.totalGlobalMem;

#ifdef DEBUG
printf("Number of CUDA devices: %d\n\n", deviceCount);
printf("Device %d: \"%s\"\n", 0, deviceProp.name);
#if CUDART_VERSION >= 2020
cudaDriverGetVersion(&driverVersion);
cudaRuntimeGetVersion(&runtimeVersion);
printf(" CUDA Driver Version: %d.%d\n", driverVersion/1000, driverVersion%100);
printf(" CUDA Runtime Version: %d.%d\n", runtimeVersion/1000, runtimeVersion%100);
#endif
printf(" CUDA capability revision number: %d.%d\n", deviceProp.major, deviceProp.minor);
#if CUDART_VERSION >= 2000
printf(" Number of multiprocessors: %d\n", deviceProp.multiProcessorCount);
printf(" Number of cores: %d\n", 8 * deviceProp.multiProcessorCount);
printf(" Maximum number of threads per block: %d\n", deviceProp.maxThreadsPerBlock);
#endif
printf(" Clock rate: %.2f GHz\n", deviceProp.clockRate * 1e-6f);
printf(" Global memory: %d\n", globalMem);
printf(" Shared memory per block: %d\n", deviceProp.sharedMemPerBlock);
printf(" Registers per block: %d\n\n", deviceProp.regsPerBlock);
#endif

cudaSetDevice(0); // not needed - default is 0.

int rowBytes = width * 4; // size of a row
int maxrow = BLOCK_SIZE; // max rows that can be handled in global memory
strake_size = maxrow * rowBytes; // memory to allocate
strakes = image_size/strake_size + ((image_size % strake_size == 0) ? 0 : 1); // there X strakes necessary
last_strake_size = image_size - (strake_size * (strakes - 1)); // figure out size of last strake (may be smaller)
#if DEBUG
printf(" Image size %d\n", image_size);
printf(" Image vector size %d\n", image.size());
printf(" Row size %d\n", rowBytes);
printf(" Maxximum rows %d\n", maxrow);
printf(" Strake size %d\n", strake_size);
printf(" Strakes %d\n", strakes);
printf(" Last strake size %d\n\n", last_strake_size);
#endif

// uncomment if you want to using CUDA's elapsed timer
// float elapsed_time_ms = 0.0f;
// cudaEvent_t start, stop;
// cudaEventCreate( &start);
// cudaEventCreate( &stop);
// cudaEventRecord(start, 0);

dim3 dimBlock(BLOCK_SIZE, BLOCK_SIZE);
dim3 dimGrid(((width*4)/dimBlock.x) + (((width*4)%dimBlock.x)?1:0), BLOCK_SIZE);

cudaMalloc((void**)&cuda_image_ptr, strake_size);
if ((err = cudaGetLastError()) != cudaSuccess) {
fprintf(stderr, "ERROR: Cuda: %s\n", cudaGetErrorString(err));
exit(2);
}

for (int i = 0; i < strakes; i++) {
if (i > 0 && i == strakes - 1) {
this_strake_size = last_strake_size;
} else {
this_strake_size = strake_size;
}
offset = 0 + i *(strake_size/4);

cudaMemcpy(cuda_image_ptr, &image[offset], this_strake_size, cudaMemcpyHostToDevice);
if ((err = cudaGetLastError()) != cudaSuccess) {
fprintf(stderr, "ERROR: Cuda: %s\n", cudaGetErrorString(err));
exit(2);
}

// invoke CUDA kernel
myCudaInvertPixel<<<dimGrid, dimBlock>>>(cuda_image_ptr, width);
if ((err = cudaGetLastError()) != cudaSuccess) {
fprintf(stderr, "ERROR: Cuda: %s\n", cudaGetErrorString(err));
exit(2);
}

// not needed here - cudaThreadSynchronize();

cudaMemcpy( &image[offset], cuda_image_ptr, this_strake_size, cudaMemcpyDeviceToHost);
if ((err = cudaGetLastError()) != cudaSuccess) {
fprintf(stderr, "ERROR: Cuda: %s\n", cudaGetErrorString(err));
exit(2);
}
}

cudaFree(cuda_image_ptr);

// uncomment if you want to using CUDA's elapsed timer
// cudaEventRecord(stop, 0);
// cudaEventSynchronize(stop);
// cudaEventElapsedTime( &elapsed_time_ms, start, stop);
// printf("Elapsed time per CUDA: %f\n", elapsed_time_ms);

return 0;
}


// CUDA kernel definition - invert pixel
__global__ void myCudaInvertPixel(int *pixel, int width)
{
int ix = blockIdx.x * blockDim.x + threadIdx.x;
int iy = blockIdx.y * blockDim.y + threadIdx.y;
int idx = ix + iy*width;

if (ix <= width || iy >= BLOCK_SIZE) return;

pixel[idx] = 0x00FFFFFF - pixel[idx];
}


class Timer {

private:

timespec starttime, endtime;
float elapsed;

float difftime(timespec start, timespec end) {
float temp;

temp = (end.tv_sec - start.tv_sec) +
(float) (end.tv_nsec - start.tv_nsec) / 1000000000.0;

return temp;
}

public:

Timer() { elapsed = 0.00; }

void reset() { elapsed = 0.00; }

void start() {
elapsed = 0.00;
clock_gettime(CLOCK_MONOTONIC, &starttime);
}

void stop() {
clock_gettime(CLOCK_MONOTONIC, &endtime);
elapsed = elapsed + difftime(starttime, endtime);
}

void restart() { clock_gettime(CLOCK_MONOTONIC, &starttime); }

void print() { cout << "Elapsed time: " << elapsed << endl; }

};

class PPM {

protected:

int width;
int height;
int maxColor;
vector <int> image;
friend class CCL;

public:

PPM() {
width = 0;
height = 0;
maxColor = 0;
}

int read(char *filename);

int write(char* filename);

void printsize() {
cout << "Image height: " << height << endl;
cout << "Image width: " << width <<< endl;
cout << "Image vector size: " << image.size() << endl;
}

void invertpixelNoCuda() {
for (vector<int>::iterator it = image.begin(); it != image.end(); ++it) {
*it = 0x00FFFFFF - *it;
}
}

void invertpixelCuda() {
CCL ccl;
ccl.cuda_ccl(image, width);
}

int getwidth() { return width; }

};


int
PPM::read(char *filename)
{
FILE *fp = fopen(filename, "r");
int rgb, x, y;
unsigned char red, green, blue;
char buf[256];
int *pwidth = &width;
int *pheight = &height;

if (fp== NULL) return 1;

do {
fgets(buf, 256, fp);
} while(buf[0] == '#');

if (buf[0] != 'P' || buf[1] != '6') {
fclose(fp);
return 1;
}

do {
fgets(buf, 256, fp);
} while(buf[0] == '#');

sscanf(buf, "%u %u", pwidth, pheight);
fscanf(fp, "%u\n", &maxColor);

image.resize(height*width);
for (y = 0; y < height ; y++) {
for (x = 0; x < width; x++) {
fscanf(fp, "%c%c%c", &red, &green, &blue);
rgb = ((int)blue & 0x000000ff) << 16 |
((int)green & 0x000000ff ) << 8 |
((int)red & 0x000000ff) | 0x00000000;
image[y*width + x] = rgb;
}
}

fclose(fp);
return 0;
}


int
PPM::write(char* filename)
{
FILE *fp;
int y, x;
unsigned char red=0, green=0, blue=0;
int rgb;

if ((fp = fopen(filename, "w")) == NULL) {
fprintf(stderr, "ERROR: Cannot open output file\n");
return 1;
}

fprintf(fp, "P6\n");
fprintf(fp, "%d %d\n", width, height);
fprintf(fp, "255\n");

for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
rgb = image[y*width + x];
blue = (rgb & 0x00FF0000) >> 16;
green = (rgb & 0x0000FF00) >> 8;
red = (rgb & 0x000000FF);
fprintf(fp, "%c%c%c", red, green, blue);
}
}

fclose(fp);

return(0);
}


void
usage(char *name,
int mode)
{
cerr << "Usage: " << name << " [-c] [-d] [-g] infile outfile" << endl;
exit(mode);
}


int
main(int argc,
char *argv[])
{
int c;
int cflag = 0, dflag = 0, gflag = 0;
PPM ppm;
Timer timer;

if (argc == 1)
usage(argv[0], 0);

opterr = 0;
while ((c = getopt( argc, argv, "cdgh")) != -1) {
switch (c) {
case 'c':
cflag = 1;
break;
case 'd':
dflag = 1;
break;
case 'g':
gflag = 1;
break;
case '?':
case 'h':
usage(argv[0], 0);
break;
}
}

if (optind != argc-2) {
cerr << "ERROR: An input file and an output file must be specified" << endl;
usage(argv[0], 1);
}

if (ppm.read(argv[optind++])) {
cerr << "ERROR: Failed to read input file" << endl;
exit(1);
}

timer.start();

if (dflag) ppm.printsize();

if (cflag) ppm.invertpixelNoCuda();

if (gflag) ppm.invertpixelCuda();

timer.stop();

if (ppm.write(argv[optind])) {
cerr << "ERROR: Failed to write output file" << endl;
exit(1);
}

timer.print();

exit(0);
}

Well that is all there is to this application. To compile it you need to have at least the nVidia CUDA 2.3 SDK installed and the latest nVidia graphics card driver.

If you are new to CUDA programming, I suggest you download the source code, compile it and play around with it on your own computer. The man pages for Linux do not work (they are all mixed up) but good up-to-date documentation can be found online at nVidia CUDA Library Documentation.

You might also want to play around with the block (dimBlock) and grid (dimGrid) dimensions. nVidia has a useful Microsoft Excel Occupancy Calculator Spreadsheet.

P.S. I tested the application on images up to a 32000 x 32000 pixels on RHEL5.4 using the CUDA 2.3 SDK and an EVGA GeForce GTX 260 graphics card with 896Mb of memory.

Fedora 11 nVidia Twinview Support

Fedora 11 (Leonidas) ships with the nouveau nVidia graphics driver preloaded by default if a nVidia graphics card is detected at install time.  Previous versions of Fedora used the older X.Org nv driver.

The nouveau project aims at producing Open Source 3D drivers for nVidia graphics cards.  According to the nouveau project Wiki

2D-support is in fairly good shape with EXA acceleration, Xv and Randr12 (think of dual-head, rotations, etc.). Randr12 should work for all cards up to, and including, Geforce 9000 series, although some issues with Geforce 8/9 laptops may still exist, for such issues bug reports should be submitted. Randr12 is now the default. Any 3D functionality that might exist is still unsupported, do not ask for instructions to try it. Also, VT switching while X is running is considered lucky."

Well, I certainly quickly ran into the VT switching issue!  It worked but not consistently.

Unfortunately the nouveau driver currently does not support nVidia TwinView functionality and I suspect that it will be a long time before it does if ever!

To use TwinView with Fedora 11, you have to load the correct nVidia drivers from rpmfusion.org.  I described how to do this in detail in a previous post so I will not repeat that information here.

You also need to modify your grub.conf file to include the nopat kernel boot option as shown below.
title Fedora (2.6.29.4-167.fc11.x86_64)
root (hd0,1)
kernel /vmlinuz-2.6.29.4-167.fc11.x86_64 ro root=/dev/mapper/vg_ultra-lv_root rhgb quiet nopat
initrd /initrd-2.6.29.4-167.fc11.x86_64.img
The nopat option is needed for this particular kernel (2.6.29.4) as it appears to still have broken PAT functionality.

For those readers who are unaware of what PAT is, here is a brief explanation.  Traditionally page caching was controlled by a CPU feature called Memory Type Range Registers (MTRR).  A CPU has a finite and limited set of MTRRs each of which control part of the physical address space.  To overcome this limitation and provide a more flexible architecture, Intel and other x86 CPU vendors added a set of bits to page table entries to control how a CPU does page caching.  These bits are called the Page Attribute Table (PAT).  Incidentally, the 2.6.26 kernel was the first Linux kernel to support PATs.

Unless you rebuild your initial ramdisk (initrd), the nouveau driver will remain loaded in the kernel.  I prefer not to have the nouveau driver loaded in my kernel if I am not using it so I added nouveau to the list of blacklisted drivers in /etc/modprobe.d/blacklist.conf and rebuild initrd.
# mv /boot/initrd-`uname -r`.img /boot/initrd-`uname -r`.img.backup
# mkinitrd -v /boot/initrd-`uname -r`.img `uname -r`
Creating initramfs
Looking for driver for /dev/mapper/vg_ultra-lv_root in /sys/block/dm-0
Found DeviceMapper component dm-0
Looking for deps of module scsi:t-0x00
Looking for deps of module pci:v00008086d00002922sv00008086sd00005442bc01sc06i01
Looking for driver for /dev/mapper/vg_ultra-lv_swap in /sys/block/dm-1
Found DeviceMapper component dm-1
Using modules:
Building initrd in /tmp/initrd.txR0Kd
/sbin/nash -> /tmp/initrd.txR0Kd/bin/nash
/usr/lib64/libnash.so.6.0.86 -> /tmp/initrd.txR0Kd/usr/lib64/libnash.so.6.0.86
/usr/lib64/libbdevid.so.6.0.86 -> /tmp/initrd.txR0Kd/usr/lib64/libbdevid.so.6.0.86
/lib64/libdevmapper.so.1.02 -> /tmp/initrd.txR0Kd/lib64/libdevmapper.so.1.02
/lib64/libparted-1.8.so.8 -> /tmp/initrd.txR0Kd/lib64/libparted-1.8.so.8
/lib64//libparted-1.8.so.8.0.0 -> /tmp/initrd.txR0Kd/lib64//libparted-1.8.so.8.0.0
/lib64/libblkid.so.1 -> /tmp/initrd.txR0Kd/lib64/libblkid.so.1
/lib64//libblkid.so.1.0 -> /tmp/initrd.txR0Kd/lib64//libblkid.so.1.0
/lib64/libselinux.so.1 -> /tmp/initrd.txR0Kd/lib64/libselinux.so.1
/lib64/libsepol.so.1 -> /tmp/initrd.txR0Kd/lib64/libsepol.so.1
/lib64/libuuid.so.1 -> /tmp/initrd.txR0Kd/lib64/libuuid.so.1
/lib64//libuuid.so.1.2 -> /tmp/initrd.txR0Kd/lib64//libuuid.so.1.2
/lib64/libpopt.so.0 -> /tmp/initrd.txR0Kd/lib64/libpopt.so.0
/lib64//libpopt.so.0.0.0 -> /tmp/initrd.txR0Kd/lib64//libpopt.so.0.0.0
/lib64/libresolv.so.2 -> /tmp/initrd.txR0Kd/lib64/libresolv.so.2
/lib64//libresolv-2.10.1.so -> /tmp/initrd.txR0Kd/lib64//libresolv-2.10.1.so
/lib64/libc.so.6 -> /tmp/initrd.txR0Kd/lib64/libc.so.6
/lib64//libc-2.10.1.so -> /tmp/initrd.txR0Kd/lib64//libc-2.10.1.so
/lib64/ld-linux-x86-64.so.2 -> /tmp/initrd.txR0Kd/lib64/ld-linux-x86-64.so.2
/lib64//ld-2.10.1.so -> /tmp/initrd.txR0Kd/lib64//ld-2.10.1.so
/lib64/libdl.so.2 -> /tmp/initrd.txR0Kd/lib64/libdl.so.2
/lib64//libdl-2.10.1.so -> /tmp/initrd.txR0Kd/lib64//libdl-2.10.1.so
/usr/lib64/libelf.so.1 -> /tmp/initrd.txR0Kd/usr/lib64/libelf.so.1
/usr/lib64//libelf-0.141.so -> /tmp/initrd.txR0Kd/usr/lib64//libelf-0.141.so
/usr/lib64/libnl.so.1 -> /tmp/initrd.txR0Kd/usr/lib64/libnl.so.1
/usr/lib64//libnl.so.1.1 -> /tmp/initrd.txR0Kd/usr/lib64//libnl.so.1.1
/lib64/libm.so.6 -> /tmp/initrd.txR0Kd/lib64/libm.so.6
/lib64//libm-2.10.1.so -> /tmp/initrd.txR0Kd/lib64//libm-2.10.1.so
/lib64/libgcc_s.so.1 -> /tmp/initrd.txR0Kd/lib64/libgcc_s.so.1
/lib64//libgcc_s-4.4.0-20090506.so.1 -> /tmp/initrd.txR0Kd/lib64//libgcc_s-4.4.0-20090506.so.1
/lib64/libreadline.so.5 -> /tmp/initrd.txR0Kd/lib64/libreadline.so.5
/lib64//libreadline.so.5.2 -> /tmp/initrd.txR0Kd/lib64//libreadline.so.5.2
/lib64/librt.so.1 -> /tmp/initrd.txR0Kd/lib64/librt.so.1
/lib64//librt-2.10.1.so -> /tmp/initrd.txR0Kd/lib64//librt-2.10.1.so
/lib64/libpthread.so.0 -> /tmp/initrd.txR0Kd/lib64/libpthread.so.0
/lib64//libpthread-2.10.1.so -> /tmp/initrd.txR0Kd/lib64//libpthread-2.10.1.so
/lib64/libtinfo.so.5 -> /tmp/initrd.txR0Kd/lib64/libtinfo.so.5
/lib64//libtinfo.so.5.7 -> /tmp/initrd.txR0Kd/lib64//libtinfo.so.5.7
/sbin/modprobe -> /tmp/initrd.txR0Kd/bin/modprobe
/sbin/rmmod -> /tmp/initrd.txR0Kd/bin/rmmod
resolving for MODULES
and that has items of
resolving for availmodules
and that has items of
/sbin/lvm -> /tmp/initrd.txR0Kd/bin/lvm
/etc/lvm -> /tmp/initrd.txR0Kd/etc/lvm
`/etc/lvm/lvm.conf' -> `/tmp/initrd.txR0Kd/etc/lvm/lvm.conf'
/etc/sysconfig/keyboard -> /tmp/initrd.txR0Kd/etc/sysconfig/keyboard
/bin/loadkeys -> /tmp/initrd.txR0Kd/bin/loadkeys
/lib/kbd/keymaps/i386/qwerty/us.map.gz -> /tmp/initrd.txR0Kd/lib/kbd/keymaps/i386/qwerty/us.map.gz
/lib/kbd/keymaps/i386/include/qwerty-layout.inc -> /tmp/initrd.txR0Kd/lib/kbd/keymaps/i386/include/qwerty-layout.inc
/lib/kbd/keymaps/i386/include/compose.inc -> /tmp/initrd.txR0Kd/lib/kbd/keymaps/i386/include/compose.inc
/lib/kbd/keymaps/include/compose.latin4 -> /tmp/initrd.txR0Kd/lib/kbd/keymaps/include/compose.latin4
/lib/kbd/keymaps/include/compose.8859_8 -> /tmp/initrd.txR0Kd/lib/kbd/keymaps/include/compose.8859_8
/lib/kbd/keymaps/include/compose.latin1 -> /tmp/initrd.txR0Kd/lib/kbd/keymaps/include/compose.latin1
/lib/kbd/keymaps/include/compose.latin3 -> /tmp/initrd.txR0Kd/lib/kbd/keymaps/include/compose.latin3
/lib/kbd/keymaps/include/compose.8859_7 -> /tmp/initrd.txR0Kd/lib/kbd/keymaps/include/compose.8859_7
/lib/kbd/keymaps/include/compose.latin2 -> /tmp/initrd.txR0Kd/lib/kbd/keymaps/include/compose.latin2
/lib/kbd/keymaps/include/compose.latin -> /tmp/initrd.txR0Kd/lib/kbd/keymaps/include/compose.latin
/lib/kbd/keymaps/i386/include/linux-with-alt-and-altgr.inc -> /tmp/initrd.txR0Kd/lib/kbd/keymaps/i386/include/linux-with-alt-and-altgr.inc
/lib/kbd/keymaps/i386/include/linux-keys-bare.inc -> /tmp/initrd.txR0Kd/lib/kbd/keymaps/i386/include/linux-keys-bare.inc
/lib/kbd/keymaps/i386/include/euro1.map.gz -> /tmp/initrd.txR0Kd/lib/kbd/keymaps/i386/include/euro1.map.gz
/etc/sysconfig/i18n -> /tmp/initrd.txR0Kd/etc/sysconfig/i18n
/bin/setfont -> /tmp/initrd.txR0Kd/bin/setfont
/lib/kbd/consolefonts/latarcyrheb-sun16.psfu.gz -> /tmp/initrd.txR0Kd/lib/kbd/consolefonts/latarcyrheb-sun16.psfu.gz
/lib/udev/console_init -> /tmp/initrd.txR0Kd/lib/udev/console_init
/lib64/libglib-2.0.so.0 -> /tmp/initrd.txR0Kd/lib64/libglib-2.0.so.0
/lib64//libglib-2.0.so.0.2000.1 -> /tmp/initrd.txR0Kd/lib64//libglib-2.0.so.0.2000.1
probing for modules for drm device card0
Adding graphics device card0
Looking for deps of module pci:v000010DEd00000640sv00003842sd0000C959bc03sc00i00: i2c-core nvidia
Adding module i2c-core
Adding module nvidia
resolving for GRAPHICSMODS
and that has items of i2c-core nvidia
Looking for deps of module i2c-core
Looking for deps of module nvidia: i2c-core
copy from `/lib/modules/2.6.29.4-167.fc11.x86_64/kernel/drivers/i2c/i2c-core.ko' [elf64-x86-64] to `/tmp/initrd.txR0Kd/lib/modules/2.6.29.4-167.fc11.x86_64/i2c-core.ko' [elf64-x86-64]
copy from `/lib/modules/2.6.29.4-167.fc11.x86_64/extra/nvidia-173xx/nvidia.ko' [elf64-x86-64] to `/tmp/initrd.txR0Kd/lib/modules/2.6.29.4-167.fc11.x86_64/nvidia.ko' [elf64-x86-64]
/sbin/plymouthd -> /tmp/initrd.txR0Kd/bin/plymouthd
........
........
Adding module scsi_wait_scan
copy from `/lib/modules/2.6.29.4-167.fc11.x86_64/kernel/drivers/scsi/scsi_wait_scan.ko' [elf64-x86-64] to `/tmp/initrd.txR0Kd/lib/modules/2.6.29.4-167.fc11.x86_64/scsi_wait_scan.ko' [elf64-x86-64]
This initrd uses dynamic shared objects.
Adding dynamic linker configuration files.
/etc/ld.so.conf -> /tmp/initrd.txR0Kd/etc/ld.so.conf
/etc/ld.so.conf.d/kernel-2.6.29.4-167.fc11.x86_64.conf -> /tmp/initrd.txR0Kd/etc/ld.so.conf.d/kernel-2.6.29.4-167.fc11.x86_64.conf
/etc/ld.so.conf.d/mysql-x86_64.conf -> /tmp/initrd.txR0Kd/etc/ld.so.conf.d/mysql-x86_64.conf
/etc/ld.so.conf.d/nvidia-lib64.conf -> /tmp/initrd.txR0Kd/etc/ld.so.conf.d/nvidia-lib64.conf
/etc/ld.so.conf.d/xulrunner-64.conf -> /tmp/initrd.txR0Kd/etc/ld.so.conf.d/xulrunner-64.conf
/etc/ld.so.conf.d/qt-x86_64.conf -> /tmp/initrd.txR0Kd/etc/ld.so.conf.d/qt-x86_64.conf
Running ldconfig
#
After rebooting your system, if you use dmesg or lsmod, you will see that the nvidia driver was loaded instead of the nouveau driver.

You will also see that for some reason Plymouth no longer runs with a graphical splash screen if it previously did so.  Plymouth is the replacement for the old RedHat Graphical Boot (RHGB).  It was written by Ray Strode, Kristian Hogsberg and Peter Jones of Redhat and first shipped in Fedora 10.

Finally, you do not need to modify your xorg.conf file for Fedora 11.  It should just work.
 

Fedora 10 Dual Head Graphics Card

This post details how to install and configure two monitors on a single EVGA GeForce 9500 GT graphics (video) card under Fedora 10.

When I was researching dual head graphics cards for use with Fedora, I came across a lot of forum and blog entries on the subject but most of them contained obsolete or incorrect information - especially about TwinView, Xinerama and the X Window System configuration file. Hopefully this post will provide readers with some useful up-to-date information on the subject.

This particular graphics card (EVGA P/N 01G-P3-N959-TR) was of interest to me for a number of reasons but primarly because the card contains two heads each with DVI-I connectors which would allow me to move away from VGA cabling altogether since my two HP w1907 19" LCD monitors also have DVI-I connectors. In addition two heads on one graphics card enabled me to free up a PCI slot by eliminating the need for a second graphics card in my workstation.

Using TwinView was also of interest to me because it uses a single X screen, i.e. the driver conceals all information about the two separate monitors from the X server, and both monitors share the same frame buffer. This means that I can continue to use functionality such as accelerated OpenGL without a problem.

There are many graphics cards available which contain the nVidia 9500GT GPU but, to date, few of these cards come with dual DVI-I heads. In addition nVidia fully supports their graphics cards on GNU/Linux and Solaris platforms. Another feature of modern nVidia GPUs which is of great interest to me is their support for the CUDA (Compute Unified Device Architecture) architecture which I wish to experiment with a part of a project which I am currently working on for a customer.

You can use a single monitor with this card out-of-the-box using the default nv driver which comes standard with Fedora. However, to use two monitors with this card, you need to download and install the correct package for your specific kernel, i.e.
kmod-nvidia-2.6.27.19-170.2.35.fc10.x86_64-180.29-1.fc10.1.x86_64

in my particular case as my present kernel is 2.6.27.19-170.2.35. Selecting this package will cause three other packages to be also downloaded and installed on your system unless they already exist. These packages are livna-config-display-*, xorg-x11-drv-nvidia-*, and xorg-x11-drv-nvidia-libs-*.

These packages not not available in the regular Fedora repositories. You need to add the rpmfusion repositories to /etc/yum.conf or to the /etc/yum.repos.d subdirectory. Here is one way of installed the repository configuration files into /etc/yum.repos.d.
rpm -ivh http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-stable.noarch.rpm
rpm -ivh http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-stable.noarch.rpm
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-rpmfusion-*
Before you actually download these packages, make a copy of your X Server configuration file i.e. /etc/X11/xorg.conf if one exists. On Fedora 10, it may not if you have a very simple setup. Don't say that you were not warned!

You then should reboot your system and use the nVidia configuration utility either from the command line (/usr/bin/nvidia-settings) or via the /Applications/System Tools/nVidia Display Settings menu option to configure the dual monitor setup.

The following is a screenshot of the nVidia configuration utility after invocation.
and here is a screenshot of the utility showing the X Server display Configuration panel.


There are limits to how you can configure your setup. You can have only one virtual screen per graphics card. Thus zaphod mode, i.e. the ability to assign each monitor on a device to a different screen, is not supported nor can you combine monitors from multiple graphic cards into a single screen.

Unless you modify your X Server configuration file all settings will be lost upon the next reboot or restart of the X Server. For this reason the utility has options to create a new X Server configuration file (in my case /etc/X11/xorg.conf) or to merge with your existing configuration file.

For completeness, here is a copy of the /etc/X11/xorg.conf which I currently use with this configuration.
#
# FPMurphy 3/28/2009 Twinview EVGA 9500 GT
#

Section "ServerLayout"
Identifier "Layout0"
Screen 0 "Screen0" 0 0
InputDevice "Keyboard0" "CoreKeyboard"
InputDevice "Mouse0" "CorePointer"
EndSection

Section "Files"
FontPath "/usr/share/fonts/default/Type1"
ModulePath "/usr/lib64/xorg/modules/extensions/nvidia"
ModulePath "/usr/lib64/xorg/modules"

EndSection

Section "Module"
Load "dbe"
Load "extmod"
Load "type1"
Load "freetype"
Load "glx"
EndSection

Section "ServerFlags"
Option "Xinerama" "0"
EndSection

Section "InputDevice"
Identifier "Mouse0"
Driver "mouse"
Option "Protocol" "auto"
Option "Device" "/dev/input/mice"
Option "ZAxisMapping" "4 5 6 7"
EndSection

Section "InputDevice"
Identifier "Keyboard0"
Driver "kbd"
Option "XkbLayout" "us"
Option "XkbModel" "pc105"
EndSection

Section "Monitor"
Identifier "Monitor0"
VendorName "HP"
ModelName "w1907"
HorizSync 24.0 - 83.0
VertRefresh 50.0 - 76.0
Option "DPMS"
EndSection

Section "Device"
Identifier "Device0"
Driver "nvidia"
VendorName "NVIDIA Corporation"
BoardName "GeForce 9500 GT"
EndSection

Section "Screen"
Identifier "Screen0"
Device "Device0"
Monitor "Monitor0"
DefaultDepth 24
Option "TwinView" "1"
Option "TwinViewXineramaInfoOrder" "DFP-1"
Option "metamodes" "DFP-0: nvidia-auto-select +1440+0, DFP-1: nvidia-auto-select +0+0"
SubSection "Display"
Depth 24
EndSubSection
EndSection
If the nVidia GLX module loaded correctly, you should able to run /usr/bin/glxgears successfully. If it fails to run, check your /var/log/Xorg.O.log file to see if the nVidia libglx library is being loaded or not. You should see something like the following
(II) Loading /usr/lib64/xorg/modules/extensions/nvidia//libglx.so
(II) Module glx: vendor="NVIDIA Corporation"
compiled for 4.0.2, module version = 1.0.0
Module class: X.Org Server Extension
(II) NVIDIA GLX Module 173.14.18 Mon Mar 2 15:55:02 PST 2009
(II) Loading extension GLX
If you do not see that specific path for the nVidia libglx.so you need to go back and fix up the ModulePath lines in your xorg.conf. Note that the order of the ModulePath lines is important as each path is searched in turn from first to last.

With this configuration the output from the xrandr utility should be something to this:
#xrandr -q
Screen 0: minimum 2880 x 900, current 2880 x 900, maximum 2880 x 900
default connected 2880x900+0+0 0mm x 0mm
2880x900 50.0*
#
If you are unfamiliar with xrandr which is the command line interface to the X Server RandR extension, I recommend that you become familar with it as it is one of the more useful extensions in the X Window System when you have more than one head on a graphics card.

The following is a list of the nvidia-related kernel modules.
# modprobe -l | grep nvidia
/lib/modules/2.6.27.19-170.2.35.fc10.x86_64/extra/nvidia/nvidia.ko
/lib/modules/2.6.27.19-170.2.35.fc10.x86_64/kernel/drivers/video/nvidia/nvidiafb.ko
/lib/modules/2.6.27.19-170.2.35.fc10.x86_64/kernel/drivers/video/backlight/mbp_nvidia_bl.ko
# lsmod | grep nv
nvidia 8117992 20
i2c_core 29216 2 nvidia,i2c_i801
#
One thing to watch out for is the nvidia system service can change your /etc/X11/xorg.conf file without informing you. To eliminate this possibility, I strongly recommend that you turn the service off.
# chkconfig --list  nvidia
nvidia 0:off 1:off 2:on 3:on 4:on 5:on 6:off
# chkconfig nvidia off
#
Note that these instructions may not apply to Fedora 11 (aka Leonidas) as it is getting a new default driver for nVidia grahics chipsets called nouveau. The nv driver will still be installed by default and will be used as a fall-back where nouveau fails to work for whatever reason.

Because the nVidia kernel module is built specifically for each kernel release, you need to download and install a new nVidia kernel module each time your kernel is updated.  If you suddenly are confronted with a non-responsive blank screen after a reboot, this is probably what has happened.  The easiest fix in this case is to log in to one of the virtual consoles, downgrade the system to runlevel 2, remove the old kmod-nvidia-173* package, and install the new kmod-nvidia-173* package followed by a reboot.

[ Updated Apr 28 2009] Alternatively you can let your system always automatically download and install the latest nVidia kernel module whenever a new kernel is downloaded by simply installing a meta-package called kmod-nvidia-173xx-173.14.18-1.fc10.1.x86_64 instead of the kernel specific package.



Here is the relevant portion of /var/log/yum.log which shows the packages which were installed as a result of installing this meta-package
Apr 23 15:36:59 Installed: system-config-display-1.1.1-1.fc10.noarch
Apr 23 15:36:59 Installed: livna-config-display-0.0.22-1.fc10.noarch
Apr 23 15:37:00 Installed: xorg-x11-drv-nvidia-173xx-libs-173.14.18-1.fc10.x86_64
Apr 23 15:37:06 Installed: xorg-x11-drv-nvidia-173xx-173.14.18-1.fc10.x86_64
Apr 23 15:37:09 Installed: kmod-nvidia-173xx-2.6.27.21-170.2.56.fc10.x86_64-173.14.18-1.fc10.1.x86_64
Apr 23 15:37:09 Installed: kmod-nvidia-173xx-173.14.18-1.fc10.1.x86_64
As usual, I hope that this information has been of help to you. If you are a software developer, I strongly encourage you to upgrade to a dual head system as studies have consistently shown that your productivity can increase by as much as 20% with such a configuration.