I want to parallelize the following code in CUDA, but I don't know how to port it on kernel and convert its return value from bool to void for use it into global memory.
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <malloc.h>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <map>
#include <algorithm>
#define WEIGHTED 0
#define UNWEIGHTED 1
using namespace std;
class Graph {
public:
unsigned int nb_nodes;
unsigned long nb_links;
double total_weight;
vector<unsigned long> degrees;
vector<unsigned int> links;
vector<float> weights;
Graph();
Graph(char *filename, char *filename_w, int type);
Graph(int nb_nodes, int nb_links, double total_weight, int *degrees, int *links, float *weights);
void display(void);
void display_reverse(void);
void display_binary(char *outfile);
bool check_symmetry();
// return the number of neighbors (degree) of the node
inline unsigned int nb_neighbors(unsigned int node);
// return the number of self loops of the node
inline double nb_selfloops(unsigned int node);
// return the weighted degree of the node
inline double weighted_degree(unsigned int node);
// return pointers to the first neighbor and first weight of the node
inline pair<vector<unsigned int>::iterator, vector<float>::iterator > neighbors(unsigned int node);
};
inline unsigned int
Graph::nb_neighbors(unsigned int node) {
assert(node>=0 && node<nb_nodes);
if (node==0)
return degrees[0];
else
return degrees[node]-degrees[node-1];
}
inline double
Graph::nb_selfloops(unsigned int node) {
assert(node>=0 && node<nb_nodes);
pair<vector<unsigned int>::iterator, vector<float>::iterator > p = neighbors(node);
for (unsigned int i=0 ; i<nb_neighbors(node) ; i++) {
if (*(p.first+i)==node) {
if (weights.size()!=0)
return (double)*(p.second+i);
else
return 1.;
}
}
return 0.;
}
inline double
Graph::weighted_degree(unsigned int node) {
assert(node>=0 && node<nb_nodes);
if (weights.size()==0)
return (double)nb_neighbors(node);
else {
pair<vector<unsigned int>::iterator, vector<float>::iterator > p = neighbors(node);
double res = 0;
for (unsigned int i=0 ; i<nb_neighbors(node) ; i++) {
res += (double)*(p.second+i);
}
return res;
}
}
inline pair<vector<unsigned int>::iterator, vector<float>::iterator >
Graph::neighbors(unsigned int node) {
assert(node>=0 && node<nb_nodes);
if (node==0)
return make_pair(links.begin(), weights.begin());
else if (weights.size()!=0)
return make_pair(links.begin()+degrees[node-1], weights.begin()+degrees[node-1]);
else
return make_pair(links.begin()+degrees[node-1], weights.begin());
}
Graph::Graph() {
nb_nodes = 0;
nb_links = 0;
total_weight = 0;
}
Graph::Graph(char *filename, char *filename_w, int type) {
ifstream finput;
finput.open(filename,fstream::in | fstream::binary);
// Read number of nodes on 4 bytes
finput.read((char *)&nb_nodes, 4);
assert(finput.rdstate() == ios::goodbit);
// Read cumulative degree sequence: 8 bytes for each node
// cum_degree[0]=degree(0); cum_degree[1]=degree(0)+degree(1), etc.
degrees.resize(nb_nodes);
finput.read((char *)°rees[0], nb_nodes*8);
// Read links: 4 bytes for each link (each link is counted twice)
nb_links=degrees[nb_nodes-1];
links.resize(nb_links);
finput.read((char *)(&links[0]), (long)nb_links*8);
// IF WEIGHTED : read weights: 4 bytes for each link (each link is counted twice)
weights.resize(0);
total_weight=0;
if (type==WEIGHTED) {
ifstream finput_w;
finput_w.open(filename_w,fstream::in | fstream::binary);
weights.resize(nb_links);
finput_w.read((char *)&weights[0], (long)nb_links*4);
}
// Compute total weight
for (unsigned int i=0 ; i<nb_nodes ; i++) {
total_weight += (double)weighted_degree(i);
}
}
Graph::Graph(int n, int m, double t, int *d, int *l, float *w) {
/* nb_nodes = n;
nb_links = m;
total_weight = t;
degrees = d;
links = l;
weights = w;*/
}
void
Graph::display() {
/* for (unsigned int node=0 ; node<nb_nodes ; node++) {
pair<vector<unsigned int>::iterator, vector<float>::iterator > p = neighbors(node);
for (unsigned int i=0 ; i<nb_neighbors(node) ; i++) {
if (node<=*(p.first+i)) {
if (weights.size()!=0)
cout << node << " " << *(p.first+i) << " " << *(p.second+i) << endl;
else
cout << node << " " << *(p.first+i) << endl;
}
}
}*/
for (unsigned int node=0 ; node<nb_nodes ; node++) {
pair<vector<unsigned int>::iterator, vector<float>::iterator > p = neighbors(node);
cout << node << ":" ;
for (unsigned int i=0 ; i<nb_neighbors(node) ; i++) {
if (true) {
if (weights.size()!=0)
cout << " (" << *(p.first+i) << " " << *(p.second+i) << ")";
else
cout << " " << *(p.first+i);
}
}
cout << endl;
}
}
void
Graph::display_reverse() {
for (unsigned int node=0 ; node<nb_nodes ; node++) {
pair<vector<unsigned int>::iterator, vector<float>::iterator > p = neighbors(node);
for (unsigned int i=0 ; i<nb_neighbors(node) ; i++) {
if (node>*(p.first+i)) {
if (weights.size()!=0)
cout << *(p.first+i) << " " << node << " " << *(p.second+i) << endl;
else
cout << *(p.first+i) << " " << node << endl;
}
}
}
}
bool
Graph::check_symmetry() {
int error=0;
for (unsigned int node=0 ; node<nb_nodes ; node++) {
pair<vector<unsigned int>::iterator, vector<float>::iterator > p = neighbors(node);
for (unsigned int i=0 ; i<nb_neighbors(node) ; i++) {
unsigned int neigh = *(p.first+i);
float weight = *(p.second+i);
pair<vector<unsigned int>::iterator, vector<float>::iterator > p_neigh = neighbors(neigh);
for (unsigned int j=0 ; j<nb_neighbors(neigh) ; j++) {
unsigned int neigh_neigh = *(p_neigh.first+j);
float neigh_weight = *(p_neigh.second+j);
if (node==neigh_neigh && weight!=neigh_weight) {
cout << node << " " << neigh << " " << weight << " " << neigh_weight << endl;
if (error++==10)
exit(0);
}
}
}
}
return (error==0);
}
void
Graph::display_binary(char *outfile) {
ofstream foutput;
foutput.open(outfile ,fstream::out | fstream::binary);
foutput.write((char *)(&nb_nodes),4);
foutput.write((char *)(°rees[0]),4*nb_nodes);
foutput.write((char *)(&links[0]),8*nb_links);
}
This code contains vector, iterator, pair. Hence I don't know how to mapping it on the device, already I didn't use thrust for vector, etc.
Aucun commentaire:
Enregistrer un commentaire