5

我试图看看时间切片的效果。以及它如何消耗大量时间。实际上,我试图将某个工作分成多个线程并查看效果。

我有一个两核处理器。所以两个线程可以并行运行。我试图查看我是否有一个由 2 个线程完成的工作,以及我是否有 t 个线程完成的相同工作,每个线程都在做 w/t 的工作。时间切片在其中起多大作用

由于时间切片是耗时的过程,我期望当我使用双线程进程或线程进程执行相同的工作时,t 线程进程所花费的时间会更多

然而,我发现事实并非如此。我尝试使用 t=10。而且它仍然比 2 线程进程快。例如。如果我必须进行 10,000,000 次迭代,使用两个线程进程,我将让 2 个线程进行 5,000,000 次迭代,这样我们总共有 10,000,000 次迭代。如果我必须处理 10 个线程的进程,我会让每个线程进行 1,000,000 次迭代,这样我们总共也有 10,000,000 次。

我期待 10 线程进程消耗更多时间。但事实并非如此。代码中是否有任何错误?对我来说看起来不错

有什么建议么?

4

4 回答 4

1

您正在按顺序执行 10000000(1000 万)x 1000 次迭代,并为并行版本中的每个线程执行 5000000(500 万)x 1000 次迭代。以我的经验,这足以使启动开销变得微不足道。结果对我来说似乎是正确的。

对于 2 个内核和 2 个线程,不涉及时间片(至少在 2 个工作线程中),因为调度程序足够聪明,可以将线程放在单独的内核上并将它们保留在那里。

为了看到一些降级,您需要在缓存中移动一些内存,这样每个上下文切换实际上会通过导致一些数据从缓存中被逐出来惩罚性能。这是我得到的运行时间:

./a.out 2 500000000
线程数 = 2
每个线程的迭代次数 = 250000000
总耗时 = 5.931148

./a.out 1000 500000000
线程数 = 1000
每个线程的迭代次数 = 500000
总耗时 = 6.563666

./a.out 2000 500000000
线程数 = 2000
每个线程中的迭代次数 = 250000
总时间 = 7.087449

这是代码。我基本上是在给定线程之间划分一个大数组并对数组中的每个项目进行平方:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

long* array;
int length;
int threads;

void *tfunc(void *arg) {
  int n = (int)arg;
  int i;
  int j;
  int x;
  long sum = 0;
  //printf("%d\n",*n);
  int start = n * (length / threads);
  int end = (n + 1) * (length / threads);

  for (i=start; i<end; i++) {
    array[i] = array[i] * array[i];
    //printf("%d\n",i);
  }
  return(0);

}

double timestamp() {
  struct timeval tp;
  gettimeofday(&tp, NULL);
  return (double)tp.tv_sec + tp.tv_usec / 1000000.;
}

int main(int argc, char *argv[]) {
  int numberOfIterations = atoi(argv[2]);
  int numberOfThreads = atoi(argv[1]);
  int i;
  printf("Number of threads = %d\n",numberOfThreads);
  printf("Number of iterations in each thread = %d \n", numberOfIterations / numberOfThreads);
  pthread_t workerThreads[numberOfThreads];
  int *arg = &numberOfIterations;

  array = (long*)malloc(numberOfIterations * sizeof(long));
  length = numberOfIterations;
  threads = numberOfThreads;
  int result[numberOfThreads];

  double timeTaken;
  timeTaken = timestamp();

  for(i=0; i<numberOfThreads; i++) {
    result[i] = pthread_create(workerThreads+i, NULL, tfunc, (void*)i);
  }

  for(i=0; i<numberOfThreads; i++) {
    pthread_join(workerThreads[i], NULL);
  }

  timeTaken = timestamp() - timeTaken;
  printf("Total time taken = %f\n", timeTaken);
  /*printf("The results are\n");
  for(i=0; i<numberOfThreads; i++) {
    printf("%d\n",result[i]);
  }*/

  free(array);
  exit(0);
}
于 2012-09-01T20:00:58.980 回答
1

要让应用程序在线程数多于处理器的情况下表现出显着的、易于测量的减速,您必须努力:

1)线程必须是CPU密集型的,即。不要阻塞 I/O 或彼此。如果您使用的是简单的计数循环(听起来像您),那么是的,已经完成了。

2) 您必须安排每个线程处理足够大的数据,以便 L1 缓存在上下文交换时需要大量刷新。如果您只增加一个整数,则不会发生这种刷新,并且上下文切换开销将太小(与计时器驱动的调度运行之间的间隔相比),无法轻松演示。

Windows 示例数据,最小缓存刷新,i7,4/8 内核:

8 tests,
400 tasks,
counting to 10000000,
using 8 threads:
Ticks: 2199
Ticks: 2184
Ticks: 2215
Ticks: 2153
Ticks: 2200
Ticks: 2215
Ticks: 2200
Ticks: 2230
Average: 2199 ms

8 tests,
400 tasks,
counting to 10000000,
using 32 threads:
Ticks: 2137
Ticks: 2121
Ticks: 2153
Ticks: 2138
Ticks: 2137
Ticks: 2121
Ticks: 2153
Ticks: 2137
Average: 2137 ms

8 tests,
400 tasks,
counting to 10000000,
using 128 threads:
Ticks: 2168
Ticks: 2106
Ticks: 2184
Ticks: 2106
Ticks: 2137
Ticks: 2122
Ticks: 2106
Ticks: 2137
Average: 2133 ms

8 tests,
400 tasks,
counting to 10000000,
using 400 threads:
Ticks: 2137
Ticks: 2153
Ticks: 2059
Ticks: 2153
Ticks: 2168
Ticks: 2122
Ticks: 2168
Ticks: 2138
Average: 2137 ms
于 2012-09-02T09:22:49.527 回答
0

你的机器上有多少个 CPU 内核?关于 CPU 绑定线程的问题是,即使设置和调度只有一个线程时不存在的线程可能会有开销,但如果这些线程实际上可以同时执行(而不是仅仅出现同时执行),那么线程仍然可以产生大于开销成本的增益。

于 2012-09-01T17:36:43.770 回答
0

如果您有多个逻辑核心,您的线程将并行执行。

要检验您的假设,您需要将它们固定到单个逻辑核心。

于 2012-09-01T17:44:19.937 回答