J. Jackson
J. Jackson

Reputation: 77

CUDA Makefile Include Error

I'm attempting to write a basic matrix multiplication program using CUDA and C. The code itself doesn't really do anything right now, but should at least compile. After some research on the issue, I've determined that the issue is failure to include CUDA header files, indicating an issue with my Makefile. I'm extremely inexperienced with CUDA (and C for that matter), so any help would be greatly appreciated.

Output on command: make matrixMult1

c99    -I. -I/usr/local/cuda/include -c matrixMult1.c -o matrixMult1.o
matrixMult1.c: In function 'main':
matrixMult1.c:77: warning: implicit declaration of function 'cudaMalloc'
matrixMult1.c:82: warning: implicit declaration of function 'cudaMemcpy'
matrixMult1.c:83: error: 'cudaMemcpyHostToDevice' undeclared (first use in this
function)
matrixMult1.c:83: error: (Each undeclared identifier is reported only once
matrixMult1.c:83: error: for each function it appears in.)
matrixMult1.c:106: warning: implicit declaration of function 'cudaFree'
make: *** [matrixMult1.o] Error 1

Makefile:

GCC = c99
CUDA_INSTALL_PATH := /usr/local/cuda
INCLUDES := -I. -I$(CUDA_INSTALL_PATH)/include
CUDA_LIBS := -L$(CUDA_INSTALL_PATH)/lib -lcudart

matrixMult1.o:          matrixMult1.c
                $(GCC)  $(INCLUDES) -c matrixMult1.c -o $@

matrixMult1:            matrixMult1.o
                $(GCC)  -o $@ matrixMult1.o $(CUDA_LIBS)

C Program:

//********************************************************************
// matrixMult1.c
//
// A basic matrix multiplication program.
//********************************************************************

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "cuda.h"

#define WA 3
#define HA 3
#define WB 3
#define HB WA
#define WC WB
#define HC HA

void initMatrix(float * matrix, int numIndices);

//*************
// Main Program
//*************
int main(int argc, char** argv) {

    /* Set random seed */
    srand(2013);

    /* Compute memory sizes for matrices A, B, and C */
    unsigned int sizeA = WA * HA;
    unsigned int sizeB = WB * HB;
    unsigned int sizeC = WC * HC;
    unsigned int memoryA = sizeof(float) * sizeA;
    unsigned int memoryB = sizeof(float) * sizeB;
    unsigned int memoryC = sizeof(float) * sizeC;

    /* Allocate memory for matrices A, B, and C */
    float * matrixA = (float *) malloc(memoryA);
    float * matrixB = (float *) malloc(memoryB);
    float * matrixC = (float *) malloc(memoryC);

    /* Initialize matrices A and B */
    initMatrix(matrixA, sizeA);
    initMatrix(matrixB, sizeB);

    /* Print matrix A */
    printf("\nMatrix A:\n");
    for (int i = 0; i < sizeA; i++) {
        printf("%f ", matrixA[i]);

    if (((i + 1) % WA) == 0) {
        printf("\n");
    } else {
        printf(" | ");
    }
    }

    /* Print matrix B */
    printf("\nMatrix B:\n");
    for (int i = 0; i < sizeB; i++) {
    printf("%f ", matrixB[i]);

    if (((i + 1) % WA) == 0) {
        printf("\n");
    } else {
        printf(" | ");
    }
    }

    /* Allocate device memory */
    float* deviceMemA;
    float* deviceMemB;
    float* deviceMemC;
    cudaMalloc((void**) &deviceMemA, memoryA);
    cudaMalloc((void**) &deviceMemB, memoryB);
    cudaMalloc((void**) &deviceMemC, memoryC);

    /* Copy host memory to device */
    cudaMemcpy(deviceMemA, matrixA, memoryA,
           cudaMemcpyHostToDevice);
    cudaMemcpy(deviceMemB, matrixB, memoryB,
               cudaMemcpyHostToDevice);
    cudaMemcpy(deviceMemC, matrixC, memoryC,
           cudaMemcpyHostToDevice);

    /* Print matrix C */
    printf("\nMatrix C:\n");
    for (int i = 0; i < sizeC; i++) {
    printf("%f ", matrixC[i]);

    if (((i + 1) % WC) == 0) {
        printf("\n");
    } else {
        printf(" | ");
    }
    }
    printf("\n");

    /* Free up memory */
    free(matrixA);
    free(matrixB);
    free(matrixC);
    cudaFree(deviceMemA);
    cudaFree(deviceMemB);
    cudaFree(deviceMemC);
}

//--------------------------------------------------------------------
// initMatrix - Assigns a random float value to each indice of the
//              matrix.
//
// PRE:  matrix is a pointer to a block of bytes in memory; numIndices
//       is the number of indicies in the matrix being instantiated.
// POST: Each index of the matrix has been instantiated with a random
//       float value.
//--------------------------------------------------------------------
void initMatrix(float * matrix, int numIndices) {

    /*
    Loop through the block of bytes, assigning a random float
    for each index of the matrix
    */
    for (int i = 0; i < numIndices; ++i) {

    /* Assign a random float between 0 and 1 at this byte */
    matrix[i] = rand() / (float)RAND_MAX;
    }
}

Upvotes: 0

Views: 1272

Answers (2)

talonmies
talonmies

Reputation: 72349

Two problems here:

  1. You were not including the appropriate header into your code (which you fixed)
  2. Your Makefile is, in fact, broken. It should look something like:
GCC = c99
CUDA_INSTALL_PATH := /usr/local/cuda
INCLUDES := -I. -I$(CUDA_INSTALL_PATH)/include
CUDA_LIBS := -L$(CUDA_INSTALL_PATH)/lib -lcudart

matrixMult1.o:          matrixMult1.c
                $(GCC) $(INCLUDES) -c matrixMult1.c -o $@

matrixMult1:            matrixMult1.o
                $(GCC) -o $@ matrixMult1.o  $(CUDA_LIBS)

[Disclaimer: not tested, use at own risk]

The current problem is that the include path was only specified at the linkage phase of the build.

Note that these changes also preempt the missing symbols error you will get during linkage from not linking with the CUDA runtime library. Note that depending on whether you are using a 32 or 64 bit host OS, you may need to change the library path to $(CUDA_INSTALL_PATH)/lib64 for the linkage to work correctly.

Upvotes: 1

tera
tera

Reputation: 7245

CUDA programs need to be compiled by nvcc. While your program does not yet contain any CUDA kernel yet, I believe that is what you want to achieve.

Rename your file from matrixMult1.c to matrixMult1.cu, remove the #include "cuda.h" line (programs compiled with nvcc don't need any CUDA-specific includes) and compile with nvcc instead of gcc (e.g. by setting GCC = nvcc at the beginning of the Makefile).

Upvotes: 2

Related Questions