我遇到了一点麻烦。我不确定我是否能理解它。 所以,我有一些代码。我正在尝试在代码中为一些循环添加#pragma loop(hint_parallel(8))语句。 当我使用必要的编译选项编译它时,实际上是这样的:
gcc -w -funroll-loops -O2 -fno-inline -fipa-pta -msse2 -funsafe-math-optimizations -ftree-vectorizer-verbose = 1 -fopt-info-optimized = logs / optOpt.txt -shared -fPIC singleThread.cpp
我得到分段错误。
fish:'。/ a.out'由信号SIGSEGV(地址边界错误)终止
关键是我不知道为什么会这样。我怀疑在这些循环中使用的常量可能是个问题。但我不认为这是相关的。如果我只是使用-O0优化编译这个代码它可以正常工作(因为编译器没有向我推测的东西)。
请您查看下面的代码,并建议我应该检查哪个方向。 感谢。
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <random>
#include <cstdio>
#include <set>
#include <fstream>
#include <cstdint>
#include <climits>
using namespace std;
const int STRING_HASH_SIZE = 32;
int convert(vector<string> &inputVector, const char **outputArray);
void printCollisions(const char **charArray, int size);
void printArray(const char **arrayToPrint, int size);
int getHashCode(const char *characters, unsigned long size);
string getRandomString();
void writeFileIfNeeded(vector<string> &vector, bool needToWrite);
vector<string> generateStringsVector(int size, bool isNeedToWriteFile);
/**
* main method is present to test these native code.
* to perform some external operation we should use another method.
* @return
*/
int main() {
/**
* The constant represents number of strings that will be generated
* in the string vector generation.
*/
const int STRING_NUMBERS = 100000;
vector<string> inputVector = generateStringsVector(STRING_NUMBERS, false);
#pragma pack 8
const char *charArray[inputVector.size()];
int hashResult = convert(inputVector, charArray);
if (hashResult != 0) {
return 0;
}
printCollisions(charArray, STRING_NUMBERS);
}
/**
* Converts an input vector to char array.
* Getting a hash of
* Returns 0 if conversion from vector to array has been successfully performed.
* @param inputVector [ input array reference ]
* @param outputArray [ a char array that would contain char sequences from vector ]
* @return [ hash sum (int)]
*/
int convert(vector<string> &inputVector, const char **outputArray) {
int hashSum = 0;
#pragma loop(hint_parallel(8))
for (int i = 0; i < inputVector.size(); i++) {
outputArray[i] = inputVector[i].c_str();
}
#pragma loop(hint_parallel(8))
for (auto &i : inputVector) {
hashSum += getHashCode(i.c_str(), i.length());
}
int stringHashSize = STRING_HASH_SIZE;
#pragma loop(hint_parallel(8))
for (int i = 0; i < inputVector.size(); i++) {
hashSum -= getHashCode(outputArray[i], stringHashSize);
}
if (hashSum != 0) {
cout << "\nConversion isn't succeeded, hash = " << hashSum << endl;
} else {
cout << "\nConversion succeeded" << endl;
}
return hashSum;
}
/**
* Prints count and percentage of collisions in array hash codes
* @param charArray
* @param size
*/
void printCollisions(const char **charArray, int size) {
set<int> setOfHashes;
int stringHashSize = STRING_HASH_SIZE;
#pragma loop(hint_parallel(8))
for (int i = 0; i < size; i++) {
setOfHashes.insert(getHashCode(charArray[i], stringHashSize));
}
unsigned long collisions = size - setOfHashes.size();
cout << collisions << "/" << size << " " << 100.0 * collisions / size << "% of collisions";
}
/**
* Prints input char array
* @param arrayToPrint
*/
void printArray(const char **arrayToPrint, int size) {
cout << "\nPrinted array size = " << size << endl;
for (int i = 0; i < size; i++) {
cout << arrayToPrint[i] << ":" << getHashCode(arrayToPrint[i], STRING_HASH_SIZE) << endl;
}
}
/**
*
* @param characters
* @return
*/
int getHashCode(const char *characters, unsigned long size) {
int hash = 0;
#pragma loop(hint_parallel(8))
for (int i = 0; i < size; i++) {
hash = (31 + hash) * (characters[i]);
}
return hash;
}
/**
* Get a random String from alphabetical char sequence.
* @return a randomized string according to an alphabet.
*/
string getRandomString() {
string str("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
random_device rd;
mt19937 generator(rd());
shuffle(str.begin(), str.end(), generator);
return str.substr(0, STRING_HASH_SIZE);
}
/**
* Generates a vector with random strings
* @param size - an int value that will be used as size of a generated vector
* @return reference to generated vector.
*/
vector<string> generateStringsVector(int size, bool isNeedToWriteFile) {
vector<string> charArray;
#pragma loop(hint_parallel(8))
for (int i = 0; i < size; i++) {
string str = getRandomString();
charArray.push_back(str);
}
writeFileIfNeeded(charArray, isNeedToWriteFile);
return charArray;
}
/**
* Writes file with name according to vector size (e.g. 100000.csv)
* if needToWrite is true
* @param vector
* @param needToWrite
*/
void writeFileIfNeeded(vector<string> &vector, bool needToWrite) {
if (needToWrite) {
ofstream csvFile;
string filename = to_string(vector.size()) + ".csv";
csvFile.open(filename, fstream::out);
for (const auto &i : vector) {
csvFile << i << "\n";
}
csvFile.close();
}
}
答案 0 :(得分:4)
导致细分错误的原因是您编译代码的方式而不是编译指示(无论如何都不会对gcc产生任何影响,见下文):
gcc -w -funroll-loops -O2 -fno-inline -fipa-pta -msse2 -funsafe-math-optimizations -ftree-vectorizer-verbose = 1 -fopt-info-optimized = logs / optOpt.txt -shared -fPIC singleThread.cpp
-shared -fPIC
创建DSO(动态共享对象)。如果您尝试执行此文件,您将获得一台无效的PC(程序计数器),您的程序将立即崩溃。您必须编译代码而不 -shared -fPIC
(如果您需要与位置无关的可执行文件,请使用-pie -fPIE
。g++
代替gcc
。-Wall
添加到您的编译选项中,gcc将显示相应的警告。-fopenmp
编译)。这样,您就可以更接近编写与编译器无关的代码了。#pragma omp parallel for reduction(+: sum)
是您在OpenMP中的朋友(reference sheet)。免责声明:我在x86_64(CentOS Linux)上使用过gcc 7.3.0。