1

VPR (Versatile Place and Route) ツールでの配置 (配置配線) に使用されるシミュレーテッド アニーリング アルゴリズムを並列化するプロジェクトに取り組んでいます。

基本的に、ツールで使用される多くの C ファイルの 1 つの一部を CUDA C に変換する必要があります。コードの 1 つのセグメント全体を複数のコアで並行して実行する必要があるだけです。各コアは、データの個別のコピーで動作する必要があります。したがって、データをホストからデバイスメモリにコピーする必要があると思います。

コードを 1 行ずつ変更せずに、このプロセス全体を実行することは可能ですか?

Janisz が示唆するように、私が興味を持っているコードの部分を添付しています。

while (exit_crit(t, cost, annealing_sched) == 0) 
{
//Starting here,I require this part to run on different cores. 
//Not the entire while loop.
av_cost = 0.;//These variables should be a local copy for each core.
av_bb_cost = 0.;
av_delay_cost = 0.;
av_timing_cost = 0.;
sum_of_squares = 0.;
success_sum = 0;
inner_crit_iter_count = 1;

for (inner_iter=0; inner_iter < move_lim; inner_iter++) {
//This function try_swap also has to run on different cores and also needs 
//to be run on a local copy of data, ie each core needs to completely 
//operate on its own data. And this function calls other functions which also have 
//the same requirements.
  if (try_swap(t, &cost, &bb_cost, &timing_cost, 
     rlim, pins_on_block, placer_opts.place_cost_type,
         old_region_occ_x, old_region_occ_y, placer_opts.num_regions,
         fixed_pins, placer_opts.place_algorithm, 
     placer_opts.timing_tradeoff, inverse_prev_bb_cost, 
     inverse_prev_timing_cost, &delay_cost) == 1) {
success_sum++;
av_cost += cost;
av_bb_cost += bb_cost;
av_timing_cost += timing_cost;
av_delay_cost += delay_cost;
sum_of_squares += cost * cost;
  }

#ifdef VERBOSE
      printf("t = %g  cost = %g   bb_cost = %g timing_cost = %g move = %d dmax = %g\n",
         t, cost, bb_cost, timing_cost, inner_iter, d_max);
      if (fabs(bb_cost - comp_bb_cost(CHECK, placer_opts.place_cost_type, 
                  placer_opts.num_regions)) > bb_cost * ERROR_TOL) 
exit(1);
#endif 
}

moves_since_cost_recompute += move_lim;
if (moves_since_cost_recompute > MAX_MOVES_BEFORE_RECOMPUTE) {
   new_bb_cost = recompute_bb_cost (placer_opts.place_cost_type, 
                 placer_opts.num_regions);       
   if (fabs(new_bb_cost - bb_cost) > bb_cost * ERROR_TOL) {
      printf("Error in try_place:  new_bb_cost = %g, old bb_cost = %g.\n",
          new_bb_cost, bb_cost);
      exit (1);
   }
   bb_cost = new_bb_cost;

   if (placer_opts.place_algorithm ==BOUNDING_BOX_PLACE) {
 cost = new_bb_cost;
   }
   moves_since_cost_recompute = 0;
}

tot_iter += move_lim;
success_rat = ((float) success_sum)/ move_lim;
if (success_sum == 0) {
   av_cost = cost;
   av_bb_cost = bb_cost;
   av_timing_cost = timing_cost;
   av_delay_cost = delay_cost;
}
else {
   av_cost /= success_sum;
   av_bb_cost /= success_sum;
   av_timing_cost /= success_sum;
   av_delay_cost /= success_sum;
}
std_dev = get_std_dev (success_sum, sum_of_squares, av_cost);

#ifndef SPEC
    printf("%11.5g  %10.6g %11.6g  %11.6g  %11.6g %11.6g %11.4g %9.4g %8.3g  %7.4g  %7.4g  %10d  ",t, av_cost, av_bb_cost, av_timing_cost, av_delay_cost, place_delay_value, d_max, success_rat, std_dev, rlim, crit_exponent,tot_iter);
#endif
//the while loop continues, but till here is what needs to run on different cores.

要約すると、ここに示すコードと関数呼び出しは、多くのコアで同時に実行する必要があります。つまり、コードを複数回実行し、それぞれ別のコアで実行する必要があります。

4

2 に答える 2

3

コードを 1 行ずつ変更したくない場合は、OpenACCを使用してみてください。

OpenACC を使用すると、基礎となるコード自体を変更または適合させることなく、コンパイラ ディレクティブによって従来の科学的および技術的な Fortran および C コードを簡単に並列化できます。高速化するコードの領域を特定し、コンパイラ ディレクティブを挿入するだけで、コンパイラは元の順次計算を並列アクセラレータにマッピングするジョブを実行します。

私はそれについて個人的な経験はありませんが、私が出席したいくつかの会議のプレゼンテーションから、並列化の容易さはパフォーマンスで少し支払われます.

于 2013-06-30T17:02:39.963 に答える
0

各コアは、データの個別のコピーで動作する必要があります。したがって、データをホストからデバイスメモリにコピーする必要があると思います。

はい、そうします。「小さい」行列の場合、ターゲット CUDA (または OpenCL) デバイスの読み取り専用部分に収まる場合があります。これにより、パフォーマンスが大幅に向上する可能性があります。そうでない場合でも、ターゲットの CUDA デバイスは、既存のターゲットよりもはるかに高速なメモリ アクセスを持っている可能性があります。

コードを 1 行ずつ変更せずに、このプロセス全体を実行することは可能ですか?

ほとんどの場合、はい。反復アプローチの主要な軸を取り、代わりに単一のループの本体に巧妙なインデックスを使用して入力をロードしたり、結果を保存したりする場合、ポートの課題の大部分はそこにあります。移植するコードの複雑さに依存する可能性がありますが、十分に単純なアルゴリズムであれば、大きな課題にはなりません。

于 2013-07-01T04:42:56.670 に答える