I am trying to translate some C# code which creates N threads at a time and runs a function in each thread.
I have two problems:
-How do I limit N threads at a time?
-My linker doesnt appear to be recognising the static ints FastestMemory and SlowestMemory when I refer to them in my main method (when I print the values out at the end).
Could somebody please help?
So far I have:
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <vector>
#include <ctime>
using namespace std;
class Test{
public:
static unsigned int FastestMemory;
static unsigned int SlowestMemory;
public:
Test(unsigned a, unsigned b){
FastestMemory = a;
SlowestMemory = b;
}
struct thread_data
{
int m_id;
thread_data(int id) : m_id(id) {}
};
static DWORD WINAPI thread_func(LPVOID lpParameter)
{
thread_data *td = (thread_data*)lpParameter;
int RepetitionNumber = td->m_id;
printf("thread with id = " + RepetitionNumber + '\n');
unsigned int start = clock();
vector<byte> list1;
vector<byte> list2;
vector<byte> list3;
for(int i=0; i<10000000; i++){
list1.push_back(57);
}
for (int i = 0; i < 20000000; i=i+2)
{
list2.push_back(56);
}
for (int i = 0; i < 10000000; i++)
{
byte temp = list1[i];
byte temp2 = list2[i];
list3.push_back(temp);
list2[i] = temp;
list1[i] = temp2;
}
unsigned int timetaken = clock()-start;
printf(RepetitionNumber + " Time taken in millisecs: " + timetaken);
if(timetaken < FastestMemory){
FastestMemory = timetaken;
}
if(timetaken > SlowestMemory){
SlowestMemory = timetaken;
}
return 0;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Test* t = new Test(2000000,0);
for (int i=0; i< 10; i++)
{
CreateThread(NULL, 0, Test::thread_func, new Test::thread_data(i) , 0, 0);
}
printf("Fastest iteration:" + Test::FastestMemory + '\n'); //Linker not recognising
printf("Slowest iteration:" + Test::SlowestMemory + '\n'); //Linker not recognising
int a;
cin >> a;
}
I'm not sure what you mean about "limit N threads at a time". Do you mean you want (for example) to only use, say, 5 threads to execute the 10 tasks in your question?
If so, you might want to use a thread pool of some sort. Windows has something like three separate thread pool APIs, along with I/O completion ports, which can also act as thread pools. It's also pretty easy to write a thread pool of your own if you find them lacking -- but the structure is quite a bit different from what you've posted.
The static unsigned int FastestMemory; declares but does not define the variable. You need to define it outside of the class definition:
class Test {
static unsigned int FastestMemory;
static unsigned int SlowestMemory;
// ...
};
unsigned int Test::FastestMemory = 0;
unsigned int Test::SlowestMemory = 0;
You are declaring but not defining your static ints.
Try:
class Test{
public:
static unsigned int FastestMemory;
static unsigned int SlowestMemory;
// ...
};
unsigned int Test::FastestMemory = 0;
unsigned int Test::SlowestMemory = 0;
As for defining N threads, looking at what you have so far, try using CreateThread to create individual threads and scale up as needed. Of course just doing this will give you a very basic and probably not very useful threading model. I suggest reading up on thread pools.
Related
I am trying to use p_thread to print out numbers in order like:
0
1
2
3
4
Without using a global variable, just local variable, but I met deadlock and I don't know how to fix it yet.
This is my code:
#include <pthread.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
static pthread_mutex_t bsem; // Mutex semaphore
static pthread_cond_t waitTurn = PTHREAD_COND_INITIALIZER; // Condition variable to control the turn
//static int turn; // Index to control access to the turn array
static int nthreads; // Number of threads from input
struct SFE{
int turn;
int thread;
};
void *thread_function(void *void_ptr_argv)
{
SFE *threadNum = (SFE *) void_ptr_argv;
pthread_mutex_lock(&bsem);
// if its not our turn then wait
while(threadNum->turn != threadNum->thread){
pthread_cond_wait(&waitTurn, &bsem);
}
pthread_mutex_unlock(&bsem);
std::cout << "I am Thread " << threadNum->turn << std::endl;
pthread_mutex_lock(&bsem);
threadNum->turn++;
pthread_cond_broadcast(&waitTurn);
pthread_mutex_unlock(&bsem);
return nullptr;
}
int main()
{
std::cin >> nthreads;
pthread_mutex_init(&bsem, NULL); // Initialize bsem to 1
pthread_t *tid= new pthread_t[nthreads];
SFE threadNumber;
threadNumber.turn = 0;
for(int i=0;i<nthreads;i++)
{
// initialize the thread number here (remember to follow the rules from the specifications of the assignment)
threadNumber.thread = i;
pthread_create(&tid[i], nullptr, thread_function, (void*)&threadNumber);
}
for(int i = 0; i < nthreads; i++)
{
pthread_join(tid[i], nullptr);
}
return 0;
}
I am expecting a simple way to solve my problem
Think about threadNum->thread. threadNum is an unique object, thus each thread gets an unspecified number threadNum->thread between 0 and nthreads. Only the last thread gets the correct number nthreads - 1 .
You should update
struct SFE{
int *turn;
int thread;
};
Allocate the array SFE threadNum[nthread] and pass &threadNum[i] to i-th thread.
int turn = 0;
for(int i=0;i<nthreads;i++)
{
// initialize the thread number here (remember to follow the rules from the specifications of the assignment)
threadNumber[i].turn = &turn;
threadNumber[i].thread = i;
pthread_create(&tid[i], nullptr, thread_function, &threadNumber[i]);
}
Your code is C-ism. This code w/o iostream and new is a clean C. If you use C++, all will be much easier.
I'm implement about the data process in multi thread.
I want to process data in class DataProcess and merge the data in class DataStorage.
My problem is when the data is add to the vector sometimes occurs the exception error.
In my opinions, there have a different address class
Is it a problem to create a new data handling class and process each data?
Here is my code.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <thread>
#include <vector>
#include <mutex>
using namespace::std;
static std::mutex m;
class DataStorage
{
private :
std::vector<long long> vecData;
public:
DataStorage()
{
}
~DataStorage()
{
}
void SetDataVectorSize(int size)
{
vecData.clear();
vecData.resize(size);
}
void DataInsertLoop(void* Data, int start, int end)
{
m.lock();
std::vector<long long> const * _v1 = static_cast<std::vector<long long> const *>(Data);
long long num = 0;
for (int idx = start; idx < _v1->size(); ++idx)
{
vecData[idx] = _v1->at(idx);
}
m.unlock();
}
};
class DataProcess
{
private:
int m_index;
long long m_startIndex;
long long m_endIndex;
int m_coreNum;
long long num;
DataStorage* m_mainStorage;
std::vector<long long> m_vecData;
public :
DataProcess(int pindex, long long startindex, long long endindex)
: m_index(pindex), m_startIndex(startindex), m_endIndex(endindex),
m_coreNum(0),m_mainStorage(NULL), num(0)
{
m_vecData.clear();
}
~DataProcess()
{
}
void SetMainAdrr(DataStorage* const mainstorage)
{
m_mainStorage = mainstorage;
}
void SetCoreInCPU(int num)
{
m_coreNum = num;
}
void DataRun()
{
for (long long idx = m_startIndex; idx < m_endIndex; ++idx)
{
num += rand();
m_vecData.push_back(num); //<- exception error position
}
m_mainStorage->DataInsertLoop(&m_vecData, m_startIndex, m_endIndex);
}
};
int main()
{
//auto beginTime = std::chrono::high_resolution_clock::now();
clock_t beginTime, endTime;
DataStorage* main = new DataStorage();
beginTime = clock();
long long totalcount = 200000000;
long long halfdata = totalcount / 2;
std::thread t1,t2;
for (int t = 0; t < 2; ++t)
{
DataProcess* clsDP = new DataProcess(1, 0, halfdata);
clsDP->SetCoreInCPU(2);
clsDP->SetMainAdrr(main);
if (t == 0)
{
t1 = std::thread([&]() {clsDP->DataRun(); });
}
else
{
t2 = std::thread([&]() {clsDP->DataRun(); });
}
}
t1.join(); t2.join();
endTime = clock();
double resultTime = (double)(endTime - beginTime);
std::cout << "Multi Thread " << resultTime / 1000 << " sec" << std::endl;
printf("--------------------\n");
int value = getchar();
}
Interestingly, if none of your threads accesses portions of vecData accessed by another thread, DataInsertLoop::DataInsertLoop should not need to be synchonized at all. That should make processsing much faster. That is, after all bugs are fixed... This also means, you should not need a mutex at all.
There are other issues with your code... The most easily spotted is a memory leak.
In main:
DataStorage* main = new DataStorage(); // you call new, but never call delete...
// that's a memory leak. Avoid caling
// new() directly.
//
// Also: 'main' is kind of a reserved
// name, don't use it except for the
// program entry point.
// How about this, instead ?
DataStorage dataSrc; // DataSrc has a very small footprint (a few pointers).
// ...
std::thread t1,t2; // why not use an array ?
// as in:
std::vector<std::tread> thrds;
// ...
// You forgot to set the size of your data set before starting, by calling:
dataSrc.SetDataVectorSize(200000000);
for (int t = 0; t < 2; ++t)
{
// ...
// Calling new again, and not delete... Use a smart pointer type
DataProcess* clsDP = new DataProcess(1, 0, halfdata);
// Also, fix the start and en indices (NOTE: code below works for t < 2, but
// probably not for t < 3)
auto clsDP = std::make_unique<DataProcess>(t, t * halfdata, (t + 1) * halfdata);
// You need to keep a reference to these pointers
// Either by storing them in an array, or by passing them to
// the threads. As in, for example:
thrds.emplace_back([dp = std::move(clsDP)]() {clsDP->DataRun(); });
}
//...
std::for_each(thrds.begin(), thrds.end(), [](auto& t) { t.join(); });
//...
More...
You create a mutex on your very first line of executable code. That's good... somewhat...
static std::mutex m; // a one letter name is a terrible choice for a variable with
// file scope.
Apart form the name, it's not in the right scope... If you want to use a mutex to protect DataStorage::vecData, this mutex should be declared in the same scope as DataStorage::vecData.
One last thing. Have you considered using iterators (aka pointers) as arguments to DataProcess::DataProcess() ? This would simplify the code quite a bit, and it would very likely run faster.
I'm having some trouble writing a circular buffer in C++. Here is my code base at the moment:
circ_buf.h:
#ifndef __CIRC_BUF_H__
#define __CIRC_BUF_H__
#define MAX_DATA (25) // Arbitrary size limit
// The Circular Buffer itself
struct circ_buf {
int s; // Index of oldest reading
int e; // Index of most recent reading
int data[MAX_DATA]; // The data
};
/*** Function Declarations ***/
void empty(circ_buf*);
bool is_empty(circ_buf*);
bool is_full(circ_buf*);
void read(circ_buf*, int);
int overwrite(circ_buf*);
#endif // __CIRC_BUF_H__
circ_buf.cpp:
#include "circ_buf.h"
/*** Function Definitions ***/
// Empty the buffer
void empty(circ_buf* cb) {
cb->s = 0; cb->e = 0;
}
// Is the buffer empty?
bool is_empty(circ_buf* cb) {
// By common convention, if the start index is equal to the end
// index, our buffer is considered empty.
return cb->s == cb->e;
}
// Is the buffer full?
bool is_full(circ_buf* cb) {
// By common convention, if the start index is one greater than
// the end index, our buffer is considered full.
// REMEMBER: we still need to account for wrapping around!
return cb->s == ((cb->e + 1) % MAX_DATA);
}
// Read data into the buffer
void read(circ_buf* cb, int k) {
int i = cb->e;
cb->data[i] = k;
cb->e = (i + 1) % MAX_DATA;
}
// Overwrite data in the buffer
int overwrite(circ_buf* cb) {
int i = cb->s;
int k = cb->data[i];
cb->s = (i + 1) % MAX_DATA;
}
circ_buf_test.cpp:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include "circ_buf.h"
int main(int argc, char** argv) {
// Our data source
std::string file = "million_numbers.txt";
std::fstream in(file, std::ios_base::in);
// The buffer
circ_buf buffer = { .s = 0, .e = 0, .data = {} };
for (int i = 0; i < MAX_DATA; ++i) {
int k = 0; in >> k; // Get next int from in
read(&buffer, k);
}
for (int i = 0; i < MAX_DATA; ++i)
std::cout << overwrite(&buffer) << std::endl;
}
The main issue I'm having is getting the buffer to write integers to its array. When I compile and run the main program (circ_buf_test), it just prints the same number 25 times, instead of what I expect it to print (the numbers 1 through 25 - "million_numbers.txt" is literally just the numbers 1 through 1000000). The number is 2292656, in case this may be important.
Does anyone have an idea about what might be going wrong here?
Your function overwrite(circ_buf* cb) returns nothing (there are no return in it's body). So the code for printing of values can print anything (see "undefined behavior"):
for (int i = 0; i < MAX_DATA; ++i)
std::cout << overwrite(&buffer) << std::endl;
I expect you can find the reason of this "main issue" in the compilation log (see lines started with "Warning"). You can fix it this way:
int overwrite(circ_buf* cb) {
int i = cb->s;
int k = cb->data[i];
cb->s = (i + 1) % MAX_DATA;
return k;
}
#include <iostream>
#include <string.h>
#include <time.h>
using namespace std;
struct MyID
{
char FirstName[10]; // array for lenight of the word.
char LastName[10]; // array for lenight of the word.
int IdNumber;
};
void InitializeArray(MyID IDNumber[], int Size);
//void SortTheArray(MyID IDNumber[], int Size);
int main(){
const int Size = 100;
MyID IDNumber[Size];
strcpy_s(IDNumber[Size].FirstName, "Aziz");
strcpy_s(IDNumber[Size].LastName, "LEGEND");
// I believe the error is around here.
InitializeArray(IDNumber, Size);
//SortTheArray(IDNumber, Size);
}
void InitializeArray(MyID IDNumber[], int Size){
//srand(time(0));
for (int i = 0; i < Size; i++){
//IDNumber[i].IdNumber = rand() %100 ;
cout<<IDNumber[i].FirstName<<endl;
IDNumber[i].LastName;
}
}
I have this problem, every time I want to test my function and struct, this error will prompt. Also, I want to see if my name will print correctly before continue to write rest program. The idea is I want to print same name every time without ask user to print name every time.
Also, I have upload the picture of result if you want to see it.
Because you are using arrays, you are experiencing buffer overrun error:
const int Size = 100;
MyID IDNumber[Size];
strcpy_s(IDNumber[Size].FirstName, "Aziz");
strcpy_s(IDNumber[Size].LastName, "LEGEND");
The expression IDNumber[Size] is equivalent to IDNumber[100].
In C++, array slot indices go from 0 to Size - 1. You are accessing one past the end of the array.
Edit 1: Initializing an array
Based on your comment, you can use a loop to initialize the slots in an array (vector):
struct Person
{
std::string first_name;
std::string last_name;
};
const unsigned int CAPACITY = 100;
int main()
{
std::vector<Person> database(CAPACITY);
Person p;
std::ostringstream name_stream;
for (unsigned int i = 0; i < CAPACITY; ++i)
{
name_stream << "Aziz" << i;
database[i].first_name = name_stream.str();
database[i].last_name = "LEGEND";
}
return 0;
}
I am trying to build a Async application to allow processing of large lists in parallel, and after two days of learning C++ through googling I have come up with the title error, from the following code:
//
// main.cpp
// ThreadedLearning
//
// Created by Andy Kirk on 19/01/2016.
// Copyright © 2016 Andy Kirk. All rights reserved.
//
#include <iostream>
#include <thread>
#include <vector>
#include <chrono>
#include <future>
typedef struct {
long mailing_id;
char emailAddress[100];
} emailStruct ;
typedef struct {
long mailing_id = 0;
int result = 0;
} returnValues;
returnValues work(emailStruct eMail) {
returnValues result;
std::this_thread::sleep_for(std::chrono::seconds(2));
result.mailing_id = eMail.mailing_id;
return result;
}
int main(int argc, const char * argv[]) {
std::vector<emailStruct> Emails;
emailStruct eMail;
// Create a Dummy Structure Vector
for (int i = 0 ; i < 100 ; ++i) {
std::snprintf(eMail.emailAddress,sizeof(eMail.emailAddress),"user-%d#email_domain.tld",i);
eMail.mailing_id = i;
Emails.push_back(eMail);
}
std::vector<std::future<returnValues>> workers;
int worker_count = 0;
int max_workers = 11;
for ( ; worker_count < Emails.size(); worker_count += max_workers ){
workers.clear();
for (int inner_count = 0 ; inner_count < max_workers ; ++inner_count) {
int entry = worker_count + inner_count;
if(entry < Emails.size()) {
emailStruct workItem = Emails[entry];
auto fut = std::async(&work, workItem);
workers.push_back(fut);
}
}
std::for_each(workers.begin(), workers.end(), [](std::future<returnValues> & res) {
res.get();
});
}
return 0;
}
Really not sure what I am doing wrong, and have found limited answers searching. Its on OSX 10 if that is relevant, and XCode 7.
The future class has its copy constructor deleted, because you really don't want to have multiple copies of it.
To add it to the vector, you have to move it instead of copying it:
workers.push_back(std::move(fut));
This error can also be raised if you are passing a future object (within a thread) to a function which expects a pass by value.
For example, this would raise an error when you pass the future:
void multiplyForever(int x, int y, std::future<void> exit_future);
multiplyForever(3, 5, fut);
You can fix it by passing the future by reference:
void multiplyForever(int x, int y, std::future<void>& exit_future);
multiplyForever(3, 5, fut);