[英]Parallel algorithm to produce all possible sequences of a set
我在嘗試產生給定字符集的所有可能字符串時遇到了困難。 令S
為符號集。 我需要處理長度為n
的S
所有可能組合。 例如,如果S={'a','b','+','-'}
和n=4
則算法應處理以下序列:
aaaa
aaab
abab
+aa-
// And all other sequences in the universe
當前,我的算法是下面描述的非有效遞歸算法。 我有兩個問題:
當前實施:(簡體)
void workhorse(vector<char> &input, vector<char>::iterator i)
{
if(i==inputs.end()) {
// process the input
return;
}
else {
for( const auto& symbol : S) {
*i=symbol;
workhorse(input, i+1);
}
}
}
您是否需要所有排列或組合? 在您的示例中,看起來好像是組合(順序無關緊要,可以重復符號),但是在您的代碼中,看起來您可能正在嘗試生成置換(通過函數名進行猜測)。 組合是簡單的以n為底數的問題-在這種情況下為4 ^ 4,而排列數要少得多4! 但是稍微復雜一點的遞歸算法,取決於您是否要保留字典順序。 無論哪種方法,算法都是計算機科學的基本支柱之一,並且已經被廣泛介紹,請嘗試以下其他Q:
您的算法看起來已經非常高效,您不會浪費任何工作。 唯一可以稍微改善的是由於遞歸導致的函數調用開銷。 但是遞歸是好的,因為它允許簡單的並行化:
#include <thread>
#include <array>
#include <string>
#include <vector>
using namespace std;
array<char,3> S = {{ 'a', 'b', 'c' }};
const int split_depth = 2;
void workhorse(string& result, int i) {
if (i == result.size()) {
// process the input
return;
}
if (i == split_depth) {
vector<thread> threads;
for (char symbol : S) {
result[i] = symbol;
threads.emplace_back([=] {
string cpy(result);
workhorse(cpy, i + 1);
});
}
for (thread& t: threads) t.join();
} else {
for (char symbol : S) {
result[i] = symbol;
workhorse(result, i + 1);
}
}
}
int main() {
string res(6, 0);
workhorse(res, 0);
}
確保使用C ++ 11功能進行編譯並啟用線程,例如
$ g++ -O3 -std=c++11 -lpthread [file].cpp
此版本的函數將枚舉長度最大為split_depth
所有前綴,然后生成一個線程以進一步處理每個前綴。 因此,它將總共啟動|S|^split_depth
線程,您可以對其進行調整以匹配您的硬件並發性。
您可以迭代地進行。 但這不會更快。
想象一下集合中的字符是數字。
'a'= 0,'b'= 1,'+'= 2,'-'= 3
您從0000開始,然后遞增直到3333。
0000、0001、0002、0003、0010、0011等...
這很容易並行化。 對於兩個線程,讓第一個線程執行從0000到1333的工作,而另一個線程執行從2000到3333的工作。顯然,這可以輕松擴展到任意數量的線程。
沒什么可做的了。 如果您的程序運行緩慢,那是因為有太多的組合可供選擇。 通過此代碼線性查找所有組合所需的時間取決於存在的組合數量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.