0

私はジュニアプログラマーで、課題を解決しようとしています。c#.net 4.0を使用して、フォルダーを実行し、すべての* .xmlファイルを選択し、各ファイルを新しい拡張子*.binの新しいフォルダーに書き込みます。書く前のファイルごとに、別のプログラマーによって書かれたアルゴリズムを適用していますが、それが実現されているかどうかはわかりません。

そこで、*。xmlファイルを読み取り、逆シリアル化して、新しい*.binファイルに書き込みます。並列プログラミングを使用していないときは、2000ファイルで1分かかりました。そして今、私はTaskで並列プログラミングを適用することにしました。ここで、ファイルごとに新しいタスクを作成し(すべての処理(読み取り-逆シリアル化-書き込み)は1つのタスクに含まれます)、40秒になります。しかし、並列プログラミングは時間を25〜30秒に短縮するのに役立ったと思います。

私が間違っていることと、これをどのように実現しなければならないかについて、コメントをお願いします。ありがとう。

byte[] buffer;
using (Stream stream = new FileInfo(file).OpenRead())
{
    buffer = new byte[stream.Length];
    stream.Read(buffer, 0, (int)stream.Length);
}

foreach (var culture in supportedCultures)
{
    CultureInfo currentCulture = culture;
    Tasks.Add(Task.Factory.StartNew(() =>
    {
        var memoryStream = new MemoryStream(buffer);
        Task<object> serializeTask = Task.Factory.StartNew(() =>
        {
            return typesManager.Load(memoryStream, currentCulture);
        }, TaskCreationOptions.AttachedToParent);

        string currentOutputDirectory = null;
        if (outputDirectory != null)
        {
            currentOutputDirectory = outputDirectory.Replace(PlaceForCultureInFolderPath,
                                                                 currentCulture
                                                                     .ToString());
            Directory.CreateDirectory(currentOutputDirectory);
        }

        string binFile = Path.ChangeExtension(Path.GetFileName(file), ".bin");
        string binPath = Path.Combine(
            currentOutputDirectory ?? Path.GetDirectoryName(file),
            binFile);

        using (FileStream outputStream = File.OpenWrite(binPath))
        {
            try
            {
                new BinaryFormatter().Serialize(outputStream,serializeTask.Result);
            }
            catch (SerializationException e)
            {
                ReportCompilationError(e.Message, null);
            }
        }
    }));
}
4

3 に答える 3

3

コードを見たり、タスクが実際に何をしているのかを知らなくても、私たちにできることは、かなり一般的なアドバイスと診断を提供することだけです。

コードはCPUバウンドですか、それともIOバウンドですか?(パフォーマンスモニターを見て、コードの実行中にCPUがどれだけビジーであるかを確認することで、これを知ることができるはずです。)

コードがIOバウンドであり、単一の物理的な非SSDドライブに複数のファイルがある場合、ドライブヘッドにドットを付け続けるように強制するため、作業を並列化するとさらに悪化する可能性があります。場所。

コードがCPUにバインドされている場合は、並列化が役立つはずです(これらは独立したタスクのように聞こえます)-繰り返しますが、最初に並列化せずにコードを実行し、次に並列化て実行することで、どちらの場合もCPUグラフを見てこれを伝えることができます。 。シリアルバージョンでは、一度に1つのCPUのみが「ビジー」になると予想されますが、パラレルバージョンでは、すべてのCPUがビジーである必要があります。

于 2012-12-06T08:15:24.647 に答える
2

Task.Factory

var task1 = Task.Factory.StartNew(() =>
    {
       //some oepratation
    });
     var task2 = Task.Factory.StartNew(() =>
    {
       //some operations
    });
    Task.WaitAll(task1, task2);

ただし、これは、使用可能なスレッドを使用し、ジョブをスケジュールするか、使用可能なスレッドにタスクを割り当てるだけなので、すべてのタスクに新しいスレッドを保証するものではありません。したがって、使用することをお勧めします。Parallel.ForEach

var options = new ParallelOptions { MaxDegreeOfParallelism = 2 // or more };
Parallel.ForEach ( list, options, a=> { } );

http://msdn.microsoft.com/en-us/library/system.threading.tasks.parallel.foreach.aspx

于 2012-12-06T08:17:25.543 に答える
1

初め。TPLがパフォーマンスに影響を与えるという保証はありません。
Jonが言うように、HDDへの書き込みは、OSが後でシーケンシャル書き込みのためにこれらのファイルをキャッシュしない限り、パフォーマンスを低下させる可能性があります。確かにキャッシュサイズには限界があります。

2番。デフォルトのスケジューラーはCPUコアを利用するように設計されているため、複数のタスクのみが並行して処理され、他のタスクはキューで待機する可能性があります。このデフォルトは、クエリを明示的に設定ParallelOptions.MaxDegreeOfParallelismまたは呼び出すことで変更できます。WidthDegreeOfParallelism()それでも、並行して実行するタスクの数を決定するのはスケジューラーです。

.netにマルチスレッドに関する素敵な無料の本があります

于 2012-12-06T08:48:35.973 に答える