我正在尝试实现huffman'a压缩算法。现在我正在研究构建序列表的算法部分。 我们的想法是减少每个字母在文本中出现的次数。我的案例中的文本由一个从文件中读取的字符串表示。我想要做的是使字母的计数平行。我给每个帖子提供相同数量的字母。不幸的是我没有得到任何加速。我不知道可能是什么原因。我使用pthread_spinlock但是使用它应该没有问题,因为数组很小。 参见:
#include <string>
#include <streambuf>
#include <vector>
#include <pthread.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <fstream>
#include <memory>
#include <errno.h>
#include <time.h>
using namespace std;
void parse_arguments(int argc, char* const* const argv, bool& random_edges, int& vertex_count, int& threads_count, char* &input_file, char* &output_file, bool& enable_logging);
pthread_t * threads;
bool* used_threads;
int used_threads_count;
pthread_spinlock_t lock;
struct dfs_args *thread_args;
int threads_count;
struct params
{
std::string text;
unsigned long long offset;
unsigned long long length;
};
const int NUM_LETTERS = 28;
unsigned long long arr[NUM_LETTERS];
void *parallel_huffman(void* args)
{
unsigned long long arr_local[NUM_LETTERS];
memset(arr_local, 0, sizeof(arr_local));
struct params* params = (struct params*)args;
unsigned long long start = params->offset;
unsigned long long length = params->length;
const string text = params->text;
for (unsigned long long i = start; i < (start + length) && i < (long long)text.size(); ++i)
{
if(text[i] >= 'a' && text[i] <= 'z')
{
int letter_offset = text[i] - 'a';
arr_local[letter_offset]++;
}
if(text[i] >= 'A' && text[i] <= 'Z')
{
int letter_offset = text[i] - 'A';
arr_local[letter_offset]++;
}
}
pthread_spin_lock(&lock);
for( int i = 0; i < NUM_LETTERS; ++i)
{
arr[i] += arr_local[i];
}
pthread_spin_unlock(&lock);
}
int main(int argc, char* argv[])
{
double time_spent;
clock_t begin, end;
begin = clock();
threads_count = 0;
int cur_threads, vertex_count;
char* input_file = NULL, *output_file = NULL;
bool random_edges = false, enable_logging = true;;
memset(arr, 0, sizeof(arr));
vector<pthread_t> threads;
vector<params> parameters;
string text;
int ret = pthread_spin_init(&lock, PTHREAD_PROCESS_SHARED);
if (ret != 0)
{
printf("Failed to init spin lock errno = %d\n", errno);
return -1;
}
parse_arguments(argc, argv, random_edges, vertex_count, threads_count, input_file, output_file, enable_logging);
ifstream input(input_file);
input.seekg(0, ios::end);
text.reserve(input.tellg());
input.seekg(0, ios::beg);
text.assign((istreambuf_iterator<char>(input)), istreambuf_iterator<char>());
//cout << text << endl;
input.close();
if (threads_count > 1) {
threads.reserve(threads_count);
parameters.reserve(threads_count);
unsigned long long len = text.size() / threads_count;
pthread_t thread;
struct params param;
unsigned long long i;
for (i = 0; i < threads_count; ++i)
{
struct params param;
param.text = text;
param.offset = i*len;
param.length = len;
parameters.push_back(param);
threads.push_back(thread);
}
long long last = parameters.size();
long long text_size = text.size();
parameters[last-1].length = text_size - parameters[last-1].offset;
for (int i = 0; i < threads_count; ++i)
{
if (enable_logging)
printf("Starting thread number %d\n", i);
if( pthread_create(&threads[i], NULL, parallel_huffman, ¶meters[i]) )
{
printf("Failed to create thread");
break;
}
}
} else {
struct params param;
param.text = text;
param.offset = 0;
param.length = text.size();
parallel_huffman(¶m);
}
for (int i = 0; i < threads_count; ++i)
{
if (enable_logging)
printf("Awaiting thread number %d\n", i);
pthread_join(threads[i], NULL);
}
for( int i = 0; i < NUM_LETTERS; ++i)
{
if (enable_logging)
printf("%c %llu\n", char('A' + i), arr[i]);
}
end = clock();
time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
if (enable_logging)
printf("Total execution time of the program -> %f\n", time_spent);
return 0;
}
void parse_arguments(int argc, char* const* const argv, bool& random_edges, int& vertex_count, int& threads_count, char* &input_file, char* &output_file, bool& enable_logging)
{
for (int i = 0; i < argc; ++i)
{
if (0 == strcmp("-n", argv[i]) )
{
vertex_count = atoi(argv[i+1]);
random_edges = true;
} else if (0 == strcmp("-t", argv[i]) )
{
threads_count = atoi(argv[i+1]);
} else if (0 == strcmp("-f", argv[i]) )
{
input_file = argv[i+1];
} else if (0 == strcmp("-o", argv[i]) )
{
output_file = argv[i+1];
} else if (0 == strcmp("-q", argv[i]) )
{
enable_logging = false;
}
}
}