I have been trying to develop a code that counts character frequency (for Huffman Tree calculation). In my Kernel function, I want devFreq array to update the count every time a specific character is found. For example, if a space " " is found in devCharsFromFile array, then devFreq[0] += 1. In the end, we can access the array to see how many spaces are in the text.
When I run my code, devFreq array is assigned to just 1 and cannot increment any further. I have been working on this code for 12 hours and I thought I could use help from a third eye. Thank you in advance. The code is as follow:
#include <stdio.h>
#include <time.h>
#include <cuda_runtime.h>
#include <cassert>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string.h>
#define CUDA_CALL(x) do { if((x)!=cudaSuccess) { \
printf("Error at %s:%d\n", __FILE__,__LINE__); \
return EXIT_FAILURE;}} while(0)
#define CHECK(x) do { if((x)!=cudaSuccess) { \
printf("Error at %s:%d\n", __FILE__, __LINE__); \
return EXIT_FAILURE;}} while(0)
// This constant can be avoided by explicitly
// calculating height of Huffman Tree
#define MAX_TREE_HT 100
#define MAXCHAR 1000
#define CHARLIMIT 96
__global__ void countCharFreqOnGPU(int *devFreq, const char *devCharsFromFile) {
int idx = blockDim.x * blockIdx.x + threadIdx.x;
int i = 0;
if(devCharsFromFile[idx] != '\0'){
i = devCharsFromFile[idx] - ' ';
devFreq[i] += 1;
printf("devFreq[%d] = %d\n", i, devFreq[i]);
}
}
void countCharFreqCPU(char const *fn, int *count, bool printFreq) {
FILE *fp;
char str[MAXCHAR];
fp = fopen(fn, "r");
int c = 0;
int x = 0;
if (fp == NULL)
printf("Could not open file %s", fn);
while (fgets(str, MAXCHAR, fp) != NULL){
while (str[c] != '\0') {
x = str[c] - ' ';
count[x] ++;
c ++;
}
c=0;
}
if(printFreq == true) {
for (int i = 0; i < 96; i++){
if(count[i]!=0)
printf("%c : %d \n", i + ' ', count[i]);
}
printf("0 if not mentioned.\n");
}
fclose(fp);
}
void storeCharsFromFile(char const *fn, char *hostCharsFromFile) {
FILE *fp;
char str[MAXCHAR];
fp = fopen(fn, "r");
int c = 0;
int x = 0;
if (fp == NULL)
printf("Could not open file %s", fn);
while (fgets(str, MAXCHAR, fp) != NULL){
while (str[c] != '\0') {
hostCharsFromFile[x] = str[c] - ' ';
c ++;
x ++;
}
c=0;
}
fclose(fp);
}
int main() {
// initial device setup
int dev = 0;
cudaDeviceProp deviceProp;
CHECK(cudaGetDeviceProperties(&deviceProp, dev));
printf("Using Device %d, %s\n", dev, deviceProp.name);
CHECK(cudaSetDevice(dev));
char const *filename = "ThreeMusks.txt";
int *hostFreq;
char *hostCharsFromFile;
// assign all the characters in hostCharsArr
hostFreq = (int *) malloc(CHARLIMIT * sizeof(int));
hostCharsFromFile = (char *) malloc (MAXCHAR * sizeof(char));
for (int i = 0; i < CHARLIMIT; i++)
hostFreq[i] = 0;
storeCharsFromFile(filename, hostCharsFromFile);
// The file is now stored in hostCharsFromFile as an array of Char.
int *devFreq;
char *devCharsFromFile;
cudaMalloc( &devFreq, MAXCHAR * sizeof(int) );
cudaMalloc( &devCharsFromFile, MAXCHAR * sizeof(char) );
cudaMemcpy( devFreq, hostFreq, MAXCHAR * sizeof(int), cudaMemcpyHostToDevice);
cudaMemcpy( devCharsFromFile, hostCharsFromFile, MAXCHAR * sizeof(char), cudaMemcpyHostToDevice);
dim3 block (100);
dim3 grid (10);
countCharFreqOnGPU <<< grid, block >>> (devFreq, devCharsFromFile);
cudaMemcpy( hostFreq, devFreq, CHARLIMIT * sizeof(int), cudaMemcpyDeviceToHost);
/** CPU test **/
char const *filename1 = "ThreeMusks.txt";
int freq[CHARLIMIT] = {0};
countCharFreqCPU( filename1, freq, false);
printf("Character Frequency\n");
for (int j = 0; j < CHARLIMIT; j++){
printf("freq[%d] = %d hostFreq[%d] = %d. \n", j, freq[j], j, hostFreq[j]);
}
free(hostFreq);
free(hostCharsFromFile);
cudaFree(devFreq);
cudaFree(devCharsFromFile);
return 0;
}