Top.Mail.Ru
Ответы

Помогите пожалуйста решить задачу, буду благодарен

Написать программу в C++
Сгенерировать два вектора одинаковой длины и вычислить, используя потоки, скалярное произведение. Расчеты проведете на четырех, восьми и шестнадцати. Подсчитаете эффективность и ускорение вычислений. На одном потоке программа должна работать 3-4 секунды, соответственно, выбирайте большую размерность вектора.
Комментарии к заданию:
В программе ничего не вводится. Сразу прописывайте размерность массивов. Программа на одном потоке должна считать 3-4 секунды. Время выдавать в секундах и три знака миллисекунд
Исходные данные для задания многопоточно генерируем, считать время не нужно, количество потоков - количество ядер в вашей системе.
Расчет эффективности = Ускорение / количество потоков.

По дате
По рейтингу
Аватар пользователя
Новичок

Вот пример программы на C++, которая генерирует два вектора заданной длины, вычисляет скалярное произведение с помощью потоков и выводит на экран время работы, эффективность и ускорение:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
 #include <iostream> 
#include <vector> 
#include <chrono> 
#include <thread> 
 
using namespace std; 
 
// Функция, вычисляющая скалярное произведение векторов 
double dot_product(const vector<double>& a, const vector<double>& b) 
{ 
    double result = 0.0; 
    for (size_t i = 0; i < a.size(); ++i) { 
        result += a[i] * b[i]; 
    } 
    return result; 
} 
 
int main() 
{ 
    const size_t size = 10000000; // Длина векторов 
    vector<double> a(size); 
    vector<double> b(size); 
 
    // Генерация случайных значений векторов 
    for (size_t i = 0; i < size; ++i) { 
        a[i] = static_cast<double>(rand()) / RAND_MAX; 
        b[i] = static_cast<double>(rand()) / RAND_MAX; 
    } 
 
    // Вычисление скалярного произведения на 1, 2, и 4 потоках 
    for (int num_threads = 1; num_threads <= 4; num_threads *= 2) { 
        cout << "Number of threads: " << num_threads << endl; 
        auto start_time = chrono::high_resolution_clock::now(); 
        double result = 0.0; 
        vector<thread> threads(num_threads); 
        for (int i = 0; i < num_threads; ++i) { 
            threads[i] = thread([&a, &b, num_threads, i, &result]() { 
                const size_t chunk_size = a.size() / num_threads; 
                const size_t start = i * chunk_size; 
                const size_t end = (i == num_threads - 1) ? a.size() : (i + 1) * chunk_size; 
                double local_result = 0.0; 
                for (size_t j = start; j < end; ++j) { 
                    local_result += a[j] * b[j]; 
                } 
                result += local_result; 
            }); 
        } 
        for (auto& t : threads) { 
            t.join(); 
        } 
        auto end_time = chrono::high_resolution_clock::now(); 
        chrono::duration<double, milli> elapsed_time = end_time - start_time; 
        cout << "Elapsed time: " << elapsed_time.count() / 1000.0 << " s" << endl; 
        double efficiency = elapsed_time.count() / (size * log2(num_threads) * 4.0); 
        cout << "Efficiency: " << efficiency << endl; 
        double speedup = elapsed_time.count() / (num_threads == 1 ? 3.0 : (elapsed_time.count() / 3.0)); 
        cout << "Speedup: " << speedup << endl; 
        cout << endl; 
    } 
 
    return 0; 
} 
 
Аватар пользователя
Мастер
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
 #include <iostream> 
#include <vector> 
#include <chrono> 
#include <random> 
#include <omp.h> 
 
// Функция для генерации случайных чисел в указанном диапазоне 
double generate_random_number(double min, double max) 
{ 
    std::random_device rd; 
    std::mt19937 gen(rd()); 
    std::uniform_real_distribution<> dis(min, max); 
    return dis(gen); 
} 
 
// Функция для вычисления скалярного произведения векторов 
double scalar_product(const std::vector<double>& a, const std::vector<double>& b) 
{ 
    double result = 0.0; 
    #pragma omp parallel for reduction(+:result) 
    for (size_t i = 0; i < a.size(); ++i) 
    { 
        result += a[i] * b[i]; 
    } 
    return result; 
} 
 
int main() 
{ 
    // Задаем размерность векторов 
    size_t vector_size = 10000000; 
 
    // Генерируем два вектора с случайными значениями 
    std::vector<double> vector1(vector_size); 
    std::vector<double> vector2(vector_size); 
    for (size_t i = 0; i < vector_size; ++i) 
    { 
        vector1[i] = generate_random_number(1.0, 10.0); 
        vector2[i] = generate_random_number(1.0, 10.0); 
    } 
 
    // Вычисляем скалярное произведение на одном потоке 
    double start_time = omp_get_wtime(); 
    double scalar_product_single_thread = scalar_product(vector1, vector2); 
    double end_time = omp_get_wtime(); 
    double time_single_thread = end_time - start_time; 
 
    // Вычисляем скалярное произведение на многопоточности с количеством потоков равным количеству ядер 
    int num_threads = omp_get_num_procs(); 
    start_time = omp_get_wtime(); 
    double scalar_product_multithread = scalar_product(vector1, vector2); 
    end_time = omp_get_wtime(); 
    double time_multithread = end_time - start_time; 
 
    // Вычисляем эффективность и ускорение 
    double efficiency = time_single_thread / (time_multithread / num_threads); 
    double speedup = time_single_thread / time_multithread; 
 
    // Выводим результаты 
    std::cout << "Vector size: " << vector_size << std::endl; 
    std::cout << "Time on single thread: " << std::fixed << time_single_thread << " seconds" << std::endl; 
    std::cout << "Time on " << num_threads << " threads: " << std::fixed << time_multithread << " seconds" << std::endl; 
    std::cout << "Efficiency: " << std::fixed << efficiency << std::endl; 
    std::cout << "Speedup: " << std::fixed << speedup << std::endl; 
 
    return 0;