いくつかの整数の短いソート配列があり、定義済みの定数以上の交差を見つける必要があります。ここにコードがあり、それは私がやりたいことを示しており、言葉で説明できます。問題はSPEEDです。私のコードは非常に遅く動作しています。2000要素の配列(私の遅いマシンでは)で約15秒かかります。もちろん、独自の交差メソッドを実装してコードを並列化することはできますが、改善は非常に限られています。実行時間は N^2 程度に増加し、すでに 500k 配列の場合、非常に長い時間がかかります。では、パフォーマンスを向上させるためにアルゴリズムを書き直すにはどうすればよいでしょうか? 私はc#言語に限定されていません.おそらくCPUまたはGPUには、そのような仕事のための特別な指示があります.
Example:
Input:
1,3,7,8
2,3,8,10
3,10,11,12,13,14
minSupport = 1
Output:
1 and 2: 2, 8
1 and 3: 3
2 and 3: 3, 10
var minSupport = 2;
var random = new Random(DateTime.Now.Millisecond);
// Numbers is each array are unique
var sortedArrays = Enumerable.Range(0,2000)
.Select(x => Enumerable.Range(0,30).Select(t => random.Next(1000)).Distinct()
.ToList()).ToList();
var result = new List<int[]>();
var resultIntersection = new List<List<int>>();
foreach (var array in sortedArrays)
{
array.Sort();
}
var sw = Stopwatch.StartNew();
//****MAIN PART*****//
for (int i = 0; i < sortedArrays.Count-1; i++)
{
for (int j = i+1; j < sortedArrays.Count; j++)
{
var intersect = sortedArrays[i].Intersect(sortedArrays[j]).ToList();
if(intersect.Count()>=minSupport)
{
result.Add( new []{i,j});
resultIntersection.Add(intersect);
}
}
}
//*****************//
sw.Stop();
Console.WriteLine(sw.Elapsed);
編集:
2000 要素の古いアルゴリズムでは 15 秒に対して約 9 秒かかります。うーん...もちろん、十分な速さではありません。
//****MAIN PART*****//
// This number(max value which array can contains) is known
var maxValue = 1000;
var reverseIndexDict = new Dictionary<int,List<int>>();
for (int i = 0; i < maxValue; i++)
{
reverseIndexDict[i] = new List<int>();
}
for (int i = 0; i < sortedArrays.Count; i++)
{
for (int j = 0; j < sortedArrays[i].Count; j++)
{
reverseIndexDict[sortedArrays[i][j]].Add(i);
}
}
var tempArr = new List<int>();
for (int i = 0; i < sortedArrays.Count; i++)
{
tempArr.Clear();
for (int j = 0; j < sortedArrays[i].Count; j++)
{
tempArr.AddRange(reverseIndexDict[j]);
}
result.AddRange(tempArr.GroupBy(x => x).Where(x => x.Count()>=minSupport).Select(x => new[]{i,x.Key}).ToList());
}
result = result.Where(x => x[0]!=x[1]).ToList();
for (int i = 0; i < result.Count; i++)
{
resultIntersection.Add(sortedArrays[result[i][0]].Intersect(sortedArrays[result[i][1]]).ToList());
}
//*****************//
編集:
若干改善。
//****MAIN PART*****//
// This number(max value which array can contains) is known
var maxValue = 1000;
var reverseIndexDict = new List<int>[maxValue];
for (int i = 0; i < maxValue; i++)
{
reverseIndexDict[i] = new List<int>();
}
for (int i = 0; i < sortedArrays.Count; i++)
{
for (int j = 0; j < sortedArrays[i].Count; j++)
{
reverseIndexDict[sortedArrays[i][j]].Add(i);
}
}
for (int i = 0; i < sortedArrays.Count; i++)
{
var tempArr = new Dictionary<int, List<int>>();
for (int j = 0; j < sortedArrays[i].Count; j++)
{
var sortedArraysij = sortedArrays[i][j];
for (int k = 0; k < reverseIndexDict[sortedArraysij].Count; k++)
{
if(!tempArr.ContainsKey(reverseIndexDict[sortedArraysij][k]))
{
tempArr[reverseIndexDict[sortedArraysij][k]] = new[]{sortedArraysij}.ToList();
}
else
{
tempArr[reverseIndexDict[sortedArraysij][k]].Add(sortedArrays[i][j]);
}
}
}
for (int j = 0; j < reverseIndexDict.Length; j++)
{
if(reverseIndexDict[j].Count>=minSupport)
{
result.Add(new[]{i,j});
resultIntersection.Add(reverseIndexDict[j]);
}
}
}
// and here we are filtering collections
//*****************//