-3

Parallel.Foreach を使用している場合でも、完了までに 7 分以上かかる次のコードがあります。私が反復するリスト「final_products」には、約 7000 個の製品が含まれています。

 public void GenerateTreeFromAllFinalProducts()
    {
        XmlSerializer serializer = new XmlSerializer(typeof(ImageFeature<float>[]));
        DSTableAdapters.Products_UniqueTableAdapter pft = new DSTableAdapters.Products_UniqueTableAdapter();
        DSTableAdapters.Products_Unique_SURFTableAdapter pus = new DSTableAdapters.Products_Unique_SURFTableAdapter();
        DS.Products_UniqueDataTable final_products = pft.GetData();

        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();

        Parallel.ForEach(final_products.AsParallel(), row =>
        {                 
            //Get SURF data for all images found similar to this image
            Types.Products_Unique_SURFRow surfData = GetDataByUniqueProductID(row.id);

            ImageFeature<float>[] row_features = (ImageFeature<float>[])serializer.Deserialize(new StringReader(Decompress(surfData.SURF)));
            if (row_features != null)
                flann.AddSurfDescriptors(row_features, row.id);                       
        });

        stopwatch.Stop();
        Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);
    }

この時間がかかるのは正常ですか? そうでない場合、どうすればコードを最適化できますか?

GetDataByUniqueProductID(row.id) は、1 行を返すデータベースへの呼び出しです。

private static Types.Products_Unique_SURFRow GetDataByUniqueProductID(int rowid)
    {
        Types.Products_Unique_SURFRow ret = new Types.Products_Unique_SURFRow();

        string sqlText = "SET ROWCOUNT 1 SELECT SURF from Products_Unique_SURF WHERE unique_product_id =" + rowid;

        using (SqlConnection myConn = new SqlConnection(global::SCBot.Properties.Settings.Default.DataConnectionString))
        {
            myConn.Open();

            SqlCommand cmd = new SqlCommand(sqlText, myConn);
            try
            {
                cmd.CommandType = CommandType.Text;

                SqlDataReader reader = cmd.ExecuteReader();
                while (reader.Read())
                {
                    Types.Products_Unique_SURFRow row = new Types.Products_Unique_SURFRow();
                    row.SURF = Convert.ToString(reader["SURF"]);

                    ret = row;
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
        }
        return ret;
    }

私の最初のコードは次のとおりでした

 public void GenerateTreeFromAllFinalProducts()
    {
        XmlSerializer serializer = new XmlSerializer(typeof(ImageFeature<float>[]));
        DSTableAdapters.Products_UniqueTableAdapter pft = new DSTableAdapters.Products_UniqueTableAdapter();
        DSTableAdapters.Products_Unique_SURFTableAdapter pus = new DSTableAdapters.Products_Unique_SURFTableAdapter();
        DS.Products_UniqueDataTable final_products = pft.GetData();

        foreach (DS.Products_UniqueRow row in final_products)
        {
            //Get SURF data for all images found similar to this image
            List<DS.Products_Unique_SURFRow> surfData = pus.GetDataByUniqueProductID(row.id).ToList();

            foreach (DS.Products_Unique_SURFRow data in surfData)
            {
                ImageFeature<float>[] row_features = (ImageFeature<float>[])serializer.Deserialize(new StringReader(Decompress(data.SURF)));
                flann.AddSurfDescriptors(row_features, row.id);
            }
        }
    }

しかし、これは遅すぎたので、Parallel.Foreach を実行しようとしました。

4

1 に答える 1

0

内部コードにかかる時間を測定する必要があります。Parallel は内部コードを高速化しません。メソッド Decompress/Deserialize をネストする代わりに、それらを個別に測定できます。

編集後:

各スレッドは新しい接続を作成します。これは、高速化として並列を使用しない方法の良い例だと思います。ただし、アルゴリズムを変更すると、さらに役立ちます。異なる接続/スレッドで単一の行をクエリすると、それらすべて (または選択) をクエリして単一のスレッドで foreach ループするよりも時間がかかるためです。

私の見解:

final_products enemration のすべての ID を収集し、stringbuilder を使用して文字列を構築します。

StringBuilder sb = new StringBuiler();
bool isFirst = true;

sb.Append("(");
foreach(var prod in final_products)
{
    if(isFirst)
        isFirst = false;
    else
        sb.Append(", ");

    sb.Append(prod.Id);
}
sb.Append(")");

string query = "SELECT SURF FROM Products_Unique_SURF WHERE Id in "+sb.ToString();

// execute the query

// foreach row, decompress, deserialize etc...
于 2013-08-08T09:44:57.283 に答える